Как реализовать функцию snap chat streak like?

У меня не получается построить логику относительно функции streak, аналогичной Snapchat. Вот как подсчитывается полоса в snapchat. проблема в следующем. если пользователь добавляет новую запись данных раз в 24 часа, то полоса равна единице, независимо от того, сколько записей он добавляет, и полоса равна 0, если он не добавляет записи в следующий период времени и добавляет по +1 в следующие 24 часа с момента последней добавленной записи.

Я пробовал этот код на django, но любая помощь на любом языке будет ценной

class ModelAnswer(BaseModel):
    questions = models.ForeignKey(
        to=Questions,
        on_delete=models.CASCADE
    )
    answer = models.TextField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    current_streak = models.PositiveIntegerField(
        null=True,
        blank=True,
        default=0,
        editable=False

    )

вот моя основная логическая часть, которая не работает в соответствии с требованиями

def save(self, *args, **kwargs):

    today = timezone.now()
    yesterday = today - timedelta(days=1)
    print(today,yesterday)

    # get the categories created yesterday to maintain the streak
    answers_created_yesterday = ModelAnswer.objects.filter(
        Q(created_at__gte=yesterday),
        Q(created_at__lt=today),
        user=self.user
    ).order_by('-id').last()

    if answers_created_yesterday is not None:
        self.current_streak = answers_created_yesterday.current_streak + 1
    else:
        self.current_streak = 1
    print(self.current_streak)
    super(ModelAnswer, self).save(args, kwargs)

Поскольку вы сказали, что помощь на любом языке будет ценной, я буду отвечать на английском.

  1. У вас должно быть поле DateTime с вашим ответом
  2. .
  3. streak может быть Dict {"start":last_week, "current":whenever_check_function_runs}
  4. Просто получите доступ к последнему ответу (order_by("-AnswerDate").last()) и вычислите дельту с timezone.now() и покажите streak_count, если дельта меньше 24 часов и установите streak["current"] в timezone.now().
  5. Вам не нужны все ответы, вам нужен последний ответ пользователя.
  6. Если дельта превышает 24 часа, установите streak["start"], streak["current"] в timezone.now()
  7. Возвращаем счетчик streak_count путем вычисления дельты от (streak["start"], streak["current"]) +1

Надеюсь, это поможет.

Я создал приложение для ведения журнала с похожей системой полос.

Метод, который я использовал, заключался в добавлении поля last_answered в модель пользователя/профиля. Каждый раз, когда пользователь загружал журнал, last_answered устанавливалось текущее время. Затем, чтобы гарантировать, что полоса не останется на уровне (например) 2, пока пользователь не отправит следующий пост, каждый раз, когда пользователь просматривает свою полосу, выполняется проверка, не осталось ли до last_answered более 24 часов.

Кроме того, как указал @Art в комментариях, current_streak должен сохраняться на модели пользователя/профиля.

Чтобы добавить эти два поля в модель пользователя, вы должны расширить модель пользователя моделью профиля следующим образом:

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    last_answered = models.DateTimeField(null=True)
    streak = models.IntegerField(default=0)

Тогда каждый раз, когда пользователь просматривает полосу - или, если вы хотите сэкономить ресурсы, вы можете использовать метод, упомянутый @Art, и запускать функцию с помощью celery - вы должны запускать эту проверку

from datetime import datetime, timedelta

def update_streak(self):
    current = datetime.now()
    delta = current - self.last_answered

    if delta > timedelta(1)
        self.streak = 0
    return True

Конечно, вы также можете использовать ваш метод, ища последний ответ и проверяя, в какое время он был отправлен, но тогда вы должны сохранять точное время отправки в ModalAnswer.

Наконец, при отправке необходимо инкрементировать полосу. Эта функция гарантирует, что наступил новый день, чтобы пользователь не мог злоупотребить полосой, отправив кучу записей. Если вы хотите более точно имитировать Snapchat, установите порог потери полоски в вышеприведенной функции на 36 часов, чтобы дать пользователям некоторую свободу действий.

def save(self, *args, **kwargs):
    today = datetime.now().date()
    last_submitted = self.request.user.profile.last_answered
    delta = today - last_submitted.date()

    if delta > timedelta(1):
        self.request.user.profile.increment_streak()    

Затем в модале Profile:

def increment_streak():
    self.streak += 1

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

Одним из существенных недостатков является то, что если пользователь решит не спать в 11:59 вечера, технически он может увеличить свою полосу на 2 за несколько минут.

после долгих проб и ошибок я сделал вот так:

today = timezone.now()
        yesterday = today - timedelta(days=1)

        # get the categories created yesterday to maintain the streak
        last_24_hours_entries = ModelAnswer.objects.filter(
            Q(created_at__gte=yesterday),
            Q(created_at__lt=today),
            user=self.user
        ).first()
        last_48_hours = today - timedelta(days=2)

        if last_24_hours_entries is None:
            last__48_hour_streak = ModelAnswer.objects.filter(
                Q(created_at__gte=last_48_hours),
                Q(created_at__lt=today),
                user=self.user
            ).last()
            if last__48_hour_streak is not None:
                self.current_streak = last__48_hour_streak.current_streak + 1
            else:
                self.current_streak = 1
        else:
            self.current_streak = last_24_hours_entries.current_streak
Вернуться на верх