Создание динамической системы оценки квестов и значков на Django
Модели
Квест
class Quest(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    criteria = models.JSONField()  # Store criteria as JSON
    reward_points = models.IntegerField(default=0)
    def __str__(self):
        return self.name
Значок
class Badge(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    criteria = models.JSONField()  # Store criteria as JSON
    reward_points = models.IntegerField(default=0)
    def __str__(self):
        return self.name
UserQuestProgress
class UserQuestProgress(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    quest = models.ForeignKey(Quest, on_delete=models.CASCADE)
    current_value = models.IntegerField(default=0)
    target_value = models.IntegerField()
    completed = models.BooleanField(default=False)
    completed_at = models.DateTimeField(null=True, blank=True)
    def save(self, *args, **kwargs):
        if self.current_value >= self.target_value:
            self.completed = True
            if not self.completed_at:
                self.completed_at = timezone.now()
        super().save(*args, **kwargs)
UserBadgeProgress
class UserBadgeProgress(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    badge = models.ForeignKey(Badge, on_delete=models.CASCADE)
    current_value = models.IntegerField(default=0)
    target_value = models.IntegerField()
    completed = models.BooleanField(default=False)
    completed_at = models.DateTimeField(null=True, blank=True)
    def save(self, *args, **kwargs):
        if self.current_value >= self.target_value:
            self.completed = True
            if not self.completed_at:
                self.completed_at = timezone.now()
        super().save(*args, **kwargs)
Я работаю над платформой для социальных сетей, где пользователи могут зарабатывать награды (квесты и значки) на основе своих действий. Моя цель - создать гибкую систему, которая могла бы оценивать эти награды динамически, без необходимости жестко задавать новые условия каждый раз, когда мы вводим новый квест или значок.
Что мы сделали до сих пор:
- Модели для квестов и значков: Мы определили модели для 
Quest,Badge,UserQuestProgressиUserBadgeProgress, которые отслеживают прогресс пользователя. - Критерии JSON: Мы используем JSON для определения критериев для каждого квеста или бейджа. Например:
{ "Post": { "reaction_type_within_timeframe": ["dislike", 30, 50] } } -  Функция оценки: У нас есть функция 
evaluate_quest, которая обрабатывает JSON критериев для вычисления прогресса пользователя:def evaluate_quest(user, criteria): # Evaluate criteria and calculate progress -  Задача Целери: Когда пользователь переходит на страницу квеста или бейджа, запускается задача Celery для оценки его прогресса и обновления 
UserQuestProgressилиUserBadgeProgress. 
Текущие задачи:
-  Жесткое кодирование сценариев: Текущая реализация по-прежнему требует от нас жесткого кодирования новых сценариев в функции 
evaluate_quest. Мы стремимся динамически обрабатывать различные сложные условия, но испытываем трудности с неизвестными будущими сценариями. - Примерные сценарии:
-  Впервые разместите обновление статуса или любое другое сообщение:
{ "Post": { "first_post": true } } - Вы заполнили все поля информации о своем профиле:
{ "Profile": { "complete_profile": true } } -  Выставите 50 лайков и/или любовных реакций на сообщения ваших подписчиков:
{ "Reaction": { "reaction_type": ["like", "love"], "count": 50, "on_followers_posts": true } } -  Получили 100+ лайков и 50+ комментариев к одному посту:
{ "Post": { "likes": 100, "comments": 50, "single_post": true } } -  Пользователь первым отреагировал на 50+ постов друзей:
{ "Reaction": { "first_reaction": true, "on_friends_posts": true, "count": 50 } } 
 -  Впервые разместите обновление статуса или любое другое сообщение:
 
Рабочий процесс:
- Когда пользователь переходит на страницу квеста или бейджа, запускается задача Celery.
 -  Задача использует 
get_or_create(user, quest|badge)для обеспечения экземпляра прогресса. -  Вызывается функция 
evaluate_questдля вычисления текущих и целевых значений. -  Модели 
UserQuestProgressиUserBadgeProgressимеют переопределенные методыsaveдля отметки завершения, если текущее значение соответствует или превышает целевое значение. -  После сохранения сигнал 
post_saveуведомляет пользователя через WebSocket о завершении квеста или бейджа. 
 Текущая evaluate_quest функция: 
Опасения:
-  Текущая реализация по-прежнему требует от нас жесткого кодирования определенных условий в функции 
evaluate_quest. - Мы хотим более динамичный подход, который может обрабатывать неизвестные будущие сценарии, не требуя изменений в коде.
 
Просьба о помощи:
-  Как сделать функцию 
evaluate_questболее динамичной для обработки различных сложных условий без жесткого кодирования каждого нового сценария? - Есть ли в Django какие-либо существующие библиотеки или паттерны, которые могут помочь достичь такой гибкости?
 -  Примеры сложных условий, которые нам необходимо обработать:
- Размещение обновления статуса в первый раз.
 - Заполнение всех полей информации профиля.
 - Поставить 50 лайков и/или любовных реакций на сообщения подписчиков.
 - Получение 100+ лайков и 50+
 
 
комментарии к одному сообщению.
- Реагируя первым на сообщения 50+ друзей.
 
Текущий рабочий процесс:
- Пользователь переходит на страницу квеста или бейджа, вызывая задачу Celery.
 -  Задача оценивает все квесты или бейджи для пользователя с помощью 
get_or_create(user, quest|badge). -  Вызывается функция 
evaluate_questдля вычисления прогресса. -  Прогресс обновляется на основе ответа от функции 
evaluate_quest. -  Метод 
saveвUserQuestProgressиUserBadgeProgressавтоматически отмечает завершение, если текущее значение соответствует или превышает целевое значение. -  Сигнал 
post_saveуведомляет пользователя через WebSocket о завершении квеста или бейджа. 
Любые соображения или предложения, чтобы сделать эту систему более надежной и динамичной, будут высоко оценены. Спасибо!