Создание динамической системы оценки квестов и значков на 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)

Я работаю над платформой для социальных сетей, где пользователи могут зарабатывать награды (квесты и значки) на основе своих действий. Моя цель - создать гибкую систему, которая могла бы оценивать эти награды динамически, без необходимости жестко задавать новые условия каждый раз, когда мы вводим новый квест или значок.

Что мы сделали до сих пор:

  1. Модели для квестов и значков: Мы определили модели для Quest, Badge, UserQuestProgress и UserBadgeProgress, которые отслеживают прогресс пользователя.
  2. Критерии JSON: Мы используем JSON для определения критериев для каждого квеста или бейджа. Например:
    {
        "Post": {
            "reaction_type_within_timeframe": ["dislike", 30, 50]
        }
    }
    
  3. Функция оценки: У нас есть функция evaluate_quest, которая обрабатывает JSON критериев для вычисления прогресса пользователя:
    def evaluate_quest(user, criteria):
        # Evaluate criteria and calculate progress
    
  4. Задача Целери: Когда пользователь переходит на страницу квеста или бейджа, запускается задача 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
          }
      }
      

Рабочий процесс:

  1. Когда пользователь переходит на страницу квеста или бейджа, запускается задача Celery.
  2. Задача использует get_or_create(user, quest|badge) для обеспечения экземпляра прогресса.
  3. Вызывается функция evaluate_quest для вычисления текущих и целевых значений.
  4. Модели UserQuestProgress и UserBadgeProgress имеют переопределенные методы save для отметки завершения, если текущее значение соответствует или превышает целевое значение.
  5. После сохранения сигнал post_save уведомляет пользователя через WebSocket о завершении квеста или бейджа.

Текущая evaluate_quest функция:

Опасения:

  • Текущая реализация по-прежнему требует от нас жесткого кодирования определенных условий в функции evaluate_quest.
  • Мы хотим более динамичный подход, который может обрабатывать неизвестные будущие сценарии, не требуя изменений в коде.

Просьба о помощи:

  • Как сделать функцию evaluate_quest более динамичной для обработки различных сложных условий без жесткого кодирования каждого нового сценария?
  • Есть ли в Django какие-либо существующие библиотеки или паттерны, которые могут помочь достичь такой гибкости?
  • Примеры сложных условий, которые нам необходимо обработать:
    • Размещение обновления статуса в первый раз.
    • Заполнение всех полей информации профиля.
    • Поставить 50 лайков и/или любовных реакций на сообщения подписчиков.
    • Получение 100+ лайков и 50+

комментарии к одному сообщению.

  • Реагируя первым на сообщения 50+ друзей.

Текущий рабочий процесс:

  1. Пользователь переходит на страницу квеста или бейджа, вызывая задачу Celery.
  2. Задача оценивает все квесты или бейджи для пользователя с помощью get_or_create(user, quest|badge).
  3. Вызывается функция evaluate_quest для вычисления прогресса.
  4. Прогресс обновляется на основе ответа от функции evaluate_quest.
  5. Метод save в UserQuestProgress и UserBadgeProgress автоматически отмечает завершение, если текущее значение соответствует или превышает целевое значение.
  6. Сигнал post_save уведомляет пользователя через WebSocket о завершении квеста или бейджа.

Любые соображения или предложения, чтобы сделать эту систему более надежной и динамичной, будут высоко оценены. Спасибо!

Вернуться на верх