使用 Redis bitmap 在微擎内做公众号的签到活动

先说下业务规则 首次签到可获得奖励 以及连续2天签到可获得奖励
因为使用的是openid 而非用户的uid
因此 此处的设计的key 为 openid 而判断用户是否签到 的偏移量 为以某个起始时间 未开始的便宜来那个计算
另外还有一种方案是 以当天的日期为key 而偏移量 则为用户的 uid (此处不采用的原因为 我们的业务uid 总量不算大 但是 间隔比较大 可能造成很大的 0 间隔)

redis 事件记录 RedisManager
获取 单例 getRedisConn
签到 setSignUser($openid)
判断今天签到 getTodaySign($openid)
判断某天签到 getThisDaySign($openid,$date)
计算总的签到数 countAllSignDay($openid)
计算连续签到数 countContinueSignDay($openid)
计算还差几次签到可抽奖 getAwardNeedDays($openid)
鉴定今天是否能抽奖 decide_award($openid)

class RedisManager
{
    private static $redisInstance;

    const SIGNSTARTDATA="2019-01-03";
    const CANAWARD=2002;
    const NOTAWARD=2004;
    const SIGNDAYSCANAWARD=2006;
    const SIGNDAYSCANNOTAWARD=2007;
    const FISRTSIGN=2008;
    const REPEATSIGN=2009;
    const SUFFIX="_2019";
    const PREFIX="sign_";

    private function __construct(){}

     static public function getRedisConn(){
        if(!self::$redisInstance instanceof self){
            self::$redisInstance = new self;
        }
        $temp = self::$redisInstance;
        return $temp->connRedis();
    }

    static  function connRedis()
    {     
        try {
            $redis_ocean = new Redis();
            $redis_ocean->connect("127.0.0.1","6333");
            $redis_ocean->auth("Zdklingchen");

        }catch (Exception $e){
            echo $e->getMessage().'<br/>';
        }
        return $redis_ocean;
    }

    static function setSignUser($openid){//签到
        $redis=RedisManager::getRedisConn();
        $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX;
        $startDate = RedisManager::SIGNSTARTDATA;
        $todayDate = date("Y-m-d");       
        $startTime = strtotime($startDate);
        $todayTime = strtotime($todayDate);
        $offset = floor(($todayTime - $startTime) / 86400);
       return  $redis->setBit($cacheKey, $offset, 1);
    }

     static function getTodaySign($openid){//判断某个openid 今天
        $redis=RedisManager::getRedisConn();
        $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX;
        $startDate = RedisManager::SIGNSTARTDATA;
        $todayDate = date("Y-m-d");       
        $startTime = strtotime($startDate);
        $todayTime = strtotime($todayDate);
        $offset = floor(($todayTime - $startTime) / 86400);
        $bitStatus = $redis->getBit($cacheKey, $offset);
        return $bitStatus;
    }

    static function getThisDaySign($openid,$date){//判断某个openid 是否在某天签到 0/1
        $redis=RedisManager::getRedisConn();
       $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX;
        $startDate = RedisManager::SIGNSTARTDATA;
        $todayDate = $date;       
        $startTime = strtotime($startDate);
        $todayTime = strtotime($todayDate);
        $offset = floor(($todayTime - $startTime) / 86400);
        $bitStatus = $redis->getBit($cacheKey, $offset);
        return $bitStatus;
    }

    static  function countAllSignDay($openid){//计算累计签到次数
        $redis=RedisManager::getRedisConn();
        $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX;
       return  $redis->bitCount($cacheKey);
    }

    static  function countContinueSignDay($openid){//计算连续签到次数
        $redis=RedisManager::getRedisConn();
        $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX;             
        $todayIsSign=RedisManager::getTodaySign($openid);
        if ($todayIsSign == 0) {
          $todayDate=date("Y-m-d",strtotime("-1 day"));       
        }else{
          $todayDate = date("Y-m-d"); 
        }
        $startDate = RedisManager::SIGNSTARTDATA;
        $startTime = strtotime($startDate);  
        $todayTime = strtotime($todayDate);

        $offset = floor(($todayTime - $startTime) / 86400);

        $countContinueSignDayNum=0;
        for ($i=$offset; $i >= 0; $i--) {            
            $BitRes=$redis->getBit($cacheKey, $i);
            if ($BitRes == 1) {
                $countContinueSignDayNum++;
                continue;
            }else{
                break;
            }
        }
        return $countContinueSignDayNum;
    }

    static function getAwardNeedDays($openid){
        $todayIsSign=RedisManager::getTodaySign($openid);
        $totalCountSign=RedisManager::countAllSignDay($openid);

         if ($totalCountSign == 1 && $todayIsSign == 1) {//今天还没签到
             $data=array(
                     "code"=>RedisManager::FISRTSIGN,
                     "needsDays"=>2,
                     "msg"=> "First sign has sign,can get arawd",
                 );
             return $data;
         }

        if ($totalCountSign == 0 && $todayIsSign == 0) {//今天还没签到
             $data=array(
                     "code"=>RedisManager::FISRTSIGN,
                     "needsDays"=>0,
                     "msg"=> "First sign has  not sign",
                 );
             return $data;

        }else{
             $YesterDay=date("Y-m-d",strtotime("-1 day"));
            $YesterDaySignData=RedisManager::getThisDaySign($openid,$YesterDay);
            if ($YesterDaySignData == 0) {//昨日没签到
                   if ($todayIsSign == 0) {
                         $data=array(
                             "code"=>RedisManager::SIGNDAYSCANAWARD,
                             "needsDays"=>2,
                            "msg"=> "Today is  not sign And YesterDay is not sign ",
                             );
                        return $data;
                   }else{
                        $data=array(
                             "code"=>RedisManager::SIGNDAYSCANAWARD,
                             "needsDays"=>1,
                            "msg"=> "Today  has  sign But YesterDay is not sign  ",
                             );
                        return $data;
                   }
            }else{
               $continueSignNum=RedisManager::countContinueSignDay($openid);
                if ($totalCountSign == $continueSignNum && $totalCountSign > 0 ) {//签到一直没间断
                        if ($todayIsSign == 0) {
                                if ($totalCountSign%2 == 0 ) {
                                         $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                            "needsDays"=>1,
                                            "msg"=> "Today is  not sign  But sign is continue  ",
                                        );
                                        return $data;
                                }else{
                                     $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                             "needsDays"=>2,
                                            "msg"=> "Today is  not sign  But sign is continue   ",
                                             );
                                 return $data;
                                }

                        }else{//今天签到了
                                  if ($totalCountSign%2 == 0 ) {
                                         $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                            "needsDays"=>1,
                                            "msg"=> "Today has sign And sign is continue  ",
                                        );
                                        return $data;
                                }else{
                                     $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                             "needsDays"=>2,
                                            "msg"=> "Today has sign And sign is continue  ",
                                             );
                                 return $data;
                                }
                        }
                }else{
                      if ($todayIsSign == 0) {
                            if ($continueSignNum%2 == 0 ) {
                                 $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                             "needsDays"=>1,
                                            "msg"=> "Today is  not sign But sign is not  continue  ",
                                             );
                                 return $data;
                            }else{
                                $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                             "needsDays"=>2,
                                            "msg"=> "Today is  not sign  But sign is not  continue   ",
                                             );
                                 return $data;
                            }
                      }else{
                         if ($continueSignNum%2 == 0 ) {
                                 $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                             "needsDays"=>2,
                                            "msg"=> "Today is  has  sign  But sign is not  continue   ",
                                             );
                                 return $data;
                            }else{
                                $data=array(
                                            "code"=>RedisManager::SIGNDAYSCANAWARD,
                                             "needsDays"=>1,
                                            "msg"=> "Today is  has  sign  But sign is not  continue   ",
                                             );
                                 return $data;
                            }
                      }
                }
            }
        }
    }

    static function decide_award($openid){ //返回一个数组 2004 不抽奖 2002抽奖      
        $todayIsSign=RedisManager::getTodaySign($openid);
        $totalCountSign=RedisManager::countAllSignDay($openid);
        if ($todayIsSign == 0) {//今天没签到
             $data=array(
                     "code"=>RedisManager::NOTAWARD,
                     "msg"=>"今日还没签到",
                 );
            return $data;
        }
        if ($todayIsSign == 1 && $totalCountSign == 1) {//首次签到 今天签到 +总签到数=1
            $data=array(
                "code"=>RedisManager::CANAWARD,
                "msg"=>"首次签到",
            );
            return $data;
        }else{
            $YesterDay=date("Y-m-d",strtotime("-1 day"));
            $YesterDaySignData=RedisManager::getThisDaySign($openid,$YesterDay);
            if ($YesterDaySignData == 0) {  //昨天没签到
                $data=array(
                     "code"=>RedisManager::NOTAWARD,
                     "msg"=>"签到成功,但是您昨天没签到,明天继续签到可获得奖励",
                 );
                 return $data;
            }else{//因为今天已经签到 所以 连续签到从今天算 最小为1
               $continueSignNum=RedisManager::countContinueSignDay($openid);
                if ($totalCountSign == 2 &&  $continueSignNum == 2 ) {//总签到 跟连续签到 都为2 则说明昨天是首次签到
                     $data=array(
                            "code"=>RedisManager::NOTAWARD,
                            "msg"=>"签到成功,明天继续签到可获得奖励",
                        );
                         return $data;
                }else{//昨天签到不是首次签到 
                    if ($totalCountSign == $continueSignNum && $totalCountSign > 0 ) {//首次签到一直没断
                        if ($totalCountSign%2 == 0 ) {
                            //偶数次不发
                              $data=array(
                                    "code"=>RedisManager::NOTAWARD,
                                    "msg"=>"签到成功,明天继续签到可获得奖励",
                                 );
                         return $data;
                        }else{
                             $data=array(
                                    "code"=>RedisManager::CANAWARD,
                                        "msg"=>"签到成功,今天可抽奖",
                               );
                              return $data;
                        }
                    }else{
                        if ($continueSignNum%2 == 0 ) {
                            //偶数次发
                           $data=array(
                                    "code"=>RedisManager::CANAWARD,
                                        "msg"=>"签到成功,今天可抽奖",
                               );

                            return $data;
                        }else{
                             $data=array(
                                    "code"=>RedisManager::NOTAWARD,
                                    "msg"=>"签到成功,明天继续签到可获得奖励",
                                 );
                              return $data;
                        }
                    }
                }        
            }
        }
    }

    private function __clone(){}

}
本作品采用《CC 协议》,转载必须注明作者和本文链接
MrHou
hou3749887
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 1

if else 好多,搞不懂

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!