• 利用redis的bitmap实现用户签到功能


    一、场景需求

    适用场景如签到送积分、签到领取奖励等,大致需求如下:

    • 比如签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等。
    • 如果连续签到中断,则重置计数,每月初重置计数。
    • 显示用户某个月的签到次数和首次签到时间。
    • 在日历控件上展示用户每月签到情况,可以切换年月显示……等等。

    二、代码

    以下代码没有积分逻辑,只有签到

    import datetime
    import redis
    
    class Redis(object):
        def __init__(self):
            self.redis_store = redis.Redis(
                host="127.0.0.1",
                port="6379",
                db="8"
            )
    
    
    class RedisSignIn(Redis):
        @staticmethod
        def GetDaliySignKey(time=datetime.datetime.now()):
            # 拼接redis的key
            bitmap_key_daily_sign = "daily_sign_{date}"
            return bitmap_key_daily_sign.format(date=time.date())
    
        def UserDailySign(self, session):
            user_id = session.get("user")
            if not user_id:
                print( "验证失败")
                return
            if self.UserDaliySignByUserId(user_id):
                rec = self.GetSignRecordByUserId(user_id, 7)
                l = len(rec.split('0')[0])
                print(l)
                # 连续签到
                if l > 1:
                    pass
                if l > 6:
                    pass
            return
        # 获取每月的签到记录
        def GetUserDailySignRecordMonthly(self, session):
            user_id = session.get("user")
            if not user_id:
                print( "验证失败")
                return
            res = self.GetSignRecordByUserId(user_id)
            print(int(res, 2))
            # 二进制数据转换为10进制,拿到的10进制数返回到前端,前端再解析成二进制数进行判断
            return int(res, 2)
    
    
        def GetSignRecordByUserId(self, user_id, days=30):
            # 开启管道模拟事务
            with self.redis_store.pipeline(True) as p:
                for i in range(days):
                    # 获取key对应值的二进制表示中的某位的值
                    p = p.getbit(self.GetDaliySignKey(datetime.datetime.now() - datetime.timedelta(days=i)), user_id)
                # execute返回命令执行结果列表
                res = p.execute()
                # res是一个[1,0,0,0...]的列表
                print(res)
                # 转成字符串的二进制
                return ''.join([str(x) for x in res])
    
        # 通过user_id用户做每日签到
        def UserDaliySignByUserId(self, user_id):
            if self.GetDailySignByUserId(user_id):
                print( "今天您已签到")
                return
            key = self.GetDaliySignKey()
            # key就是签到日期,将该user_id在key对应的位置上设置为1,表示签到了
            self.redis_store.setbit(key, user_id, 1)
            # 设置key的过期时间
            self.redis_store.expire(key, 60 * 60 * 24 * 30)
            return True
    
        # 通过user_id获取用户每日签到信息
        def GetDailySignByUserId(self, user_id):
            return self.redis_store.getbit(self.GetDaliySignKey(), user_id)
    
    
    if __name__ == '__main__':
        session={"user":1003}
        sign=RedisSignIn()
        sign.UserDailySign(session)
        sign.GetUserDailySignRecordMonthly(session)
  • 相关阅读:
    LFU
    poj 3581 -- 后缀数组
    leetcode 679
    poj 两条线段接雨水
    poj 1696极角排序
    判断平面上是否有一条直线与所有线段相交
    洛谷P3808 【模板】AC自动机(简单版)
    Most Distant Point from the Sea UVA
    P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包
    P2249
  • 原文地址:https://www.cnblogs.com/angelyan/p/11208370.html
Copyright © 2020-2023  润新知