📝 Python

Система достижений на Python

P
Автор
PyLand Team
📅
Опубликовано
03.04.2026
⏱️
Время чтения
2 мин
👁️
Просмотров
398
🌱
Уровень
Начальный

Gamification увеличивает вовлечённость пользователей на 30–40%. Достижения — простой способ это реализовать.


Базовый класс Achievement

from datetime import datetime

class Achievement:
    """Одно достижение."""

    def __init__(self, id, name, description, points, condition):
        self.id = id
        self.name = name
        self.description = description
        self.points = points
        self.condition = condition  # функция (user_data) -> bool
        self.unlocked = False
        self.unlocked_at = None

    def check(self, user_data):
        """Проверить условие и разблокировать. Возвращает True при новом unlock."""
        if self.unlocked:
            return False
        if self.condition(user_data):
            self.unlocked = True
            self.unlocked_at = datetime.now()
            return True
        return False

    def __str__(self):
        status = "unlocked" if self.unlocked else "locked"
        return f"[{status}] {self.name} ({self.points} pts)"

Типы достижений

def create_milestone(name, stat_key, threshold, points):
    """За достижение числового порога."""
    return Achievement(
        id=f"{stat_key}_{threshold}",
        name=name,
        description=f"Достигни {threshold} {stat_key}",
        points=points,
        condition=lambda data: data.get(stat_key, 0) >= threshold
    )

def create_streak(days, points):
    """За дни подряд."""
    return Achievement(
        id=f"streak_{days}",
        name=f"{days} дней подряд",
        description=f"Заходи {days} дней подряд",
        points=points,
        condition=lambda data: data.get("streak", 0) >= days
    )

# Примеры тиров
milestones = [
    create_milestone("Новичок",  "lessons_finished",  1,  10),
    create_milestone("Ученик",   "lessons_finished",  5,  50),
    create_milestone("Эксперт",  "lessons_finished", 20, 200),
    create_milestone("Мастер",   "lessons_finished", 50, 500),
]

streaks = [
    create_streak( 3,   30),
    create_streak( 7,  100),
    create_streak(30,  500),
    create_streak(100, 2000),
]

Уровни (Tiers)

TIERS = [
    {"name": "Новичок", "min_points":    0},
    {"name": "Ученик",  "min_points":  100},
    {"name": "Эксперт", "min_points":  500},
    {"name": "Мастер",  "min_points": 1000},
    {"name": "Легенда", "min_points": 5000},
]

def get_tier(points):
    """Текущий уровень пользователя."""
    tier = TIERS[0]
    for t in TIERS:
        if points >= t["min_points"]:
            tier = t
    return tier

def progress_to_next(points):
    """Прогресс до следующего уровня в %."""
    current = get_tier(points)
    next_tier = next((t for t in TIERS if t["min_points"] > points), None)
    if not next_tier:
        return 100
    earned = points - current["min_points"]
    needed = next_tier["min_points"] - current["min_points"]
    return (earned / needed) * 100

Интеграция: AchievementManager

class AchievementManager:
    """Центральная система управления достижениями."""

    def __init__(self, achievements):
        self.achievements = achievements
        self.user_stats = {}   # {user_id: stats_dict}
        self.user_unlocked = {}  # {user_id: [achievement_id, ...]}

    def get_stats(self, user_id):
        if user_id not in self.user_stats:
            self.user_stats[user_id] = {
                "logins": 0, "lessons_finished": 0,
                "tasks_completed": 0, "streak": 0, "points_earned": 0
            }
            self.user_unlocked[user_id] = []
        return self.user_stats[user_id]

    def record_action(self, user_id, action, value=1):
        """Записать действие и проверить достижения."""
        stats = self.get_stats(user_id)
        if action in stats:
            stats[action] += value

        newly_unlocked = []
        for ach in self.achievements:
            if ach.id not in self.user_unlocked[user_id] and ach.check(stats):
                self.user_unlocked[user_id].append(ach.id)
                stats["points_earned"] += ach.points
                newly_unlocked.append(ach)
                print(f"Achievement unlocked: {ach.name} (+{ach.points} pts)")

        return newly_unlocked

# Использование
all_achievements = milestones + streaks
manager = AchievementManager(all_achievements)

manager.record_action(user_id=1, action="lessons_finished")   # -> "Новичок" unlock
manager.record_action(user_id=1, action="lessons_finished")
manager.record_action(user_id=1, action="lessons_finished")
manager.record_action(user_id=1, action="lessons_finished")
manager.record_action(user_id=1, action="lessons_finished")   # -> "Ученик" unlock

stats = manager.get_stats(1)
tier = get_tier(stats["points_earned"])
print(f"Уровень: {tier['name']}, очков: {stats['points_earned']}")

Баланс системы

Тип Сложность Очки Цель
Первые шаги Очень легко 10–50 Onboarding
Milestone Средне 50–200 Retention
Streak Требует регулярности 100–500 Habit loop
Эпические Сложно 500–2000 Престиж

Первые достижения должны разблокироваться быстро — иначе пользователь уйдёт раньше, чем увлечётся.

Ваша реакция на статью

💬 Комментарии (0)

🔐 Войдите в систему, чтобы оставить комментарий
🚪 Войти
💭

Комментариев пока нет

Станьте первым, кто поделится мнением об этой статье!

🔗 Похожие

Похожие статьи

Продолжите изучение с этими материалами

📝

if __name__ == "__main__": точка входа Python

Конструкция if name == "main" определяет точку входа Python-программы: она помогает отличить прямой запуск файла...

📅 14.08.2026 👁️ 44
📝

strip() и lower(): подготавливаем пользовательски…

Пользователь может ввести правильное слово с лишними пробелами или буквами другого регистра. Для Python строки...

📅 11.08.2026 👁️ 50
📝

ord(), chr() и циклический сдвиг букв в Python 🔐

Строка состоит из символов, но компьютер хранит каждый символ как числовой код. Python позволяет переходить...

📅 09.08.2026 👁️ 89

Понравилась статья?

Подпишитесь на наши обновления и получайте новые статьи первыми. Развивайтесь вместе с PyLand!