You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似Snapchat的连续答题Streak功能?

如何实现类似Snapchat的连续答题Streak功能?

需求规则

  • 用户每24小时至少提交1条答案,无论提交多少条,Streak维持当前数值;
  • 若超过24小时未提交,Streak清零;
  • 清零后再次提交,Streak从1开始,后续若在距上次提交的24小时内提交,Streak递增1。

当前Django实现问题

你将current_streak存储在ModelAnswer模型中(每个答案对应一个streak值),且核心逻辑用自然日区间判断提交行为,导致同一天内多次提交会重复递增streak,不符合“维持streak”的规则,同时streak作为用户全局属性,存储在答案模型中设计不合理。

当前模型代码

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)

优化解决方案(Django)

1. 调整模型设计

将streak相关字段移到User模型中(streak是用户的全局属性):

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    current_streak = models.PositiveIntegerField(default=0)
    last_submission_time = models.DateTimeField(null=True, blank=True)

2. 修正提交逻辑

修改ModelAnswer的save方法,基于用户上次提交的时间差判断streak变化,避免同一周期内重复递增:

from django.utils import timezone
from datetime import timedelta

def save(self, *args, **kwargs):
    user = self.user
    now = timezone.now()
    # 获取用户最近的一条提交记录
    last_answer = ModelAnswer.objects.filter(user=user).order_by('-created_at').first()

    if not last_answer:
        # 首次提交,streak设为1
        user.current_streak = 1
    else:
        time_since_last = now - last_answer.created_at
        if time_since_last > timedelta(hours=24):
            # 超过24小时未提交,重置streak
            user.current_streak = 1
        else:
            # 检查本次提交是否是当前24小时周期内的第一次提交
            has_recent_submission = ModelAnswer.objects.filter(
                user=user,
                created_at__gt=last_answer.created_at,
                created_at__lt=now
            ).exists()
            if not has_recent_submission:
                # 周期内首次提交,streak递增
                user.current_streak += 1

    # 更新用户的上次提交时间
    user.last_submission_time = now
    user.save()

    # 保存当前答案
    super().save(*args, **kwargs)

通用逻辑实现(伪代码/JavaScript)

如果不用Django,可通过以下逻辑计算streak:

// 假设userSubmissions是用户的提交记录数组,每个元素含createdAt时间戳
function calculateUserStreak(userSubmissions) {
    if (userSubmissions.length === 0) return 0;

    // 按提交时间倒序排序
    userSubmissions.sort((a, b) => b.createdAt - a.createdAt);
    
    let streak = 1;
    let lastSubmitTime = userSubmissions[0].createdAt;
    const ONE_DAY = 24 * 60 * 60 * 1000; // 24小时的毫秒数

    for (let i = 1; i < userSubmissions.length; i++) {
        const currentSubmitTime = userSubmissions[i].createdAt;
        const timeDiff = lastSubmitTime - currentSubmitTime;

        if (timeDiff > ONE_DAY) {
            // 超过24小时,streak中断
            break;
        }

        // 检查是否跨了新的24小时周期
        const cycleEnd = currentSubmitTime + ONE_DAY;
        if (lastSubmitTime > cycleEnd) {
            streak++;
        }

        lastSubmitTime = currentSubmitTime;
    }

    return streak;
}

内容的提问来源于stack exchange,提问作者lord stock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 00:15:59