先说下业务规则 首次签到可获得奖励 以及连续 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().'
';
}
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(){}
}