123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 |
- <?php
- defined('IN_WEB') or die('Include Error!');
- /**
- * 成就系统
- */
- class ModelAchievement
- {
- public $contypes = array(
- 'com', // '普通场对局'
- 'allin', // 'All In次数'
- 'win', // '胜利次数'
- 'swinchips', // 单局赢多少筹码
- 'winchips', // 累计赢多少筹码
- 'maxchips', // 最大拥有筹码数
- 'straight', // 顺子胜利次数
- 'flush', // 同花胜利次数
- 'straight_flush', // 同花顺胜利次数
- 'matchwin', // 比赛场获得名次
- 'recall', // 成功召回好友
- 'playslots', // 玩老虎机次数
- 'sendfn', // 赠送好友游戏币次数
- 'senddealer', // 打赏荷官
- 'invites', // 成功邀请好友数
- 'paid', // 累计充值
- 'hlu', //葫芦
- 'stiao', //四条
- );
- public $notIncContypes = array('win', 'maxchips', 'paid');
- public $achievementConfig = array();
- public $errCode = 0;
- public function __construct() {
- $this->dbToConfig();
- }
- /**
- * 获取成就列表
- * @param int $uid
- * @return array
- */
- public function getList($uid) {
- $data = array('code' => -1, 'list' => []);
- if (!$uid || !$this->achievementConfig) {
- return $data;
- }
- $ret = $this->achievementConfig;
- $rewardedStr = $this->getRewarded($uid);
- $rewarded = str_split($rewardedStr);
- $conKeys = array();
- foreach ($ret as $id => &$v) {
- if (!isset($v['subtask']) || !is_array($v['subtask'])) {
- unset($v);
- continue;
- }
- $status = isset($rewarded[$id - 1]) ? (int) $rewarded[$id - 1] : 0;
- foreach ($v['subtask'] as $subid => &$task) {
- $task['num'] = (int) $task[0];
- $task['reward'] = (int) $task[1];
- // 匹配用户已完成的子任务
- if ($status & (1 << $subid - 1)) {
- $task['rewarded'] = 1;
- } else {
- $task['rewarded'] = 0;
- }
- unset($task[0], $task[1]);
- }
- $conKeys[] = $v['contype'];
- unset($v['zh_name']);
- }
- $condition = $this->getCondition($uid, $conKeys);
- // 数据重组
- foreach ($ret as $id => &$v) {
- $v['cur'] = (int) $condition[$v['contype']];
- }
- $data['code'] = 1;
- $data['list'] = $ret;
- return $data;
- }
- /**
- * 获取用户领取情况
- * @param int $uid
- * @return array
- */
- public function getRewarded($uid) {
- if (!$uid) return array();
- $cacheKey = okeys::achi($uid);
- $cache = oo::commonOprRedis('userinfo')->get($cacheKey);
- if (!is_null($cache) && $cache !== false) {
- return $cache;
- }
- $tb = otable::achi($uid);
- $query = "select rewarded from {$tb} where uid='{$uid}' limit 1";
- $row = oo::commonOprDb('common')->getOne($query, MYSQLI_ASSOC);
- if ($row) {
- $rewarded = !empty($row['rewarded']) ? $row['rewarded'] : $this->getDefault();
- } else {
- $rewarded = $this->getDefault();
- $query = "insert into {$tb} (uid,rewarded) values ('{$uid}','{$rewarded}')";
- $flg = oo::commonOprDb('common')->query($query);
- if (!$flg)
- return array();
- }
- oo::commonOprRedis('userinfo')->setex($cacheKey, $rewarded, oo::redisRandomExpire(7 * 86400));
- return $rewarded;
- }
- /**
- * 获取用户当前缓存状态
- * @param int $uid
- * @param array $types
- * @return array
- */
- public function getCondition($uid, $types = array()) {
- if (!$uid || !$types || !is_array($types)) {
- return array();
- }
- $cacheKey = okeys::achi($uid.'-');
- if (!oo::commonOprRedis('usercache')->exists($cacheKey)) { // 没有缓存
- $ret = $this->getConditionFromDB($uid, true);
- } else {
- $ret = oo::commonOprRedis('usercache')->hMget($cacheKey, $types);
- }
- $property = array();
- // if (isset($ret['paid'])) {
- // $ret['paid'] = $ret['paid']; // 泰铢
- // }
- if (in_array('maxchips', $types)) {
- $property or $property = oo::commonOprModel('member')->getUserAssetsInfo($uid);
- $ret['maxchips'] = $property['money'];
- }
- return $ret;
- }
- /**
- * 默认串
- * @return string
- */
- public function getDefault() {
- $maxId = max(array_keys($this->achievementConfig));
- return str_pad('', $maxId, '0');
- }
- /**
- * 获取条件值的数据库记录,或更新至缓存
- * @param int $uid
- * @param bool $toCache
- * @return array
- */
- public function getConditionFromDB($uid, $toCache = false) {
- if (!$uid)
- return array();
- $tb = otable::achi($uid.'-');
- $query = "select * from {$tb} where uid='{$uid}' limit 1";
- $data = oo::commonOprDb('common')->getOne($query, MYSQLI_ASSOC);
- if ($toCache) {
- oo::commonOprRedis('usercache')->delete(okeys::achi($uid));
- unset($data['rewarded']);
- oo::commonOprRedis('usercache')->hMget(okeys::achi($uid), $data);
- }
- return $data;
- }
- /**
- * 设置已领奖励缓存
- * @param int $uid
- * @param int $id
- * @param int $subid
- * @return bool
- */
- public function setRewarded($uid, $id, $subid) {
- if (!$uid || !$id || !$subid) {
- $this->errCode = -201;
- return false;
- }
- $rewardedStr = $this->getRewarded($uid);
- // 如果有新成就则可以补全
- $maxId = max(array_keys($this->achievementConfig));
- $rewardedStr = str_pad($rewardedStr, $maxId, '0');
- $rewarded = str_split($rewardedStr);
- $idx = $id - 1; // ** 重要,存储的字符串是要ID-1
- if (!isset($rewarded[$idx])) {
- $this->errCode = -201;
- return false;
- }
- if ($rewarded[$idx] & (1 << $subid - 1)) { // 已经设置过
- $this->errCode = -202;
- return false;
- }
- $rewarded[$idx] |= 1 << $subid - 1;
- return $this->updateRewarded($uid, implode('', $rewarded));
- }
- /**
- * 更新领取情况
- * @param int $uid
- * @param string $rewarded
- * @return bool
- */
- public function updateRewarded($uid, $rewarded) {
- if (!$uid || empty($rewarded)) {
- return false;
- }
- $rewarded = oo::functions()->escape($rewarded);
- oo::commonOprRedis('userinfo')->delete(okeys::achi($uid));
- $tb = otable::achi($uid);
- $query = "update {$tb} set rewarded='{$rewarded}' where uid='{$uid}' limit 1";
- return oo::commonOprDb('common')->query($query);
- }
- /**
- * 累加条件缓存
- * @param int $uid
- * @param string $type
- * @param int $num
- * @return bool
- */
- public function incCondition($uid, $type, $num = 1) {
- if (!$uid || !in_array($type, $this->contypes)) {
- return false;
- }
- $cacheKey = okeys::achi($uid.'-');
- $curCondition = $this->getCondition($uid, [$type]);
- if ($type == 'winchips' && $curCondition['winchips'] > 100000000) { // 已经超过最大值了
- return false;
- }
- $diffCacheKey = okeys::achiDiff($uid);
- if ($type == 'swinchips') {
- if ($num <= $curCondition['swinchips']) {
- return false;
- } else {
- oo::commonOprRedis('usercache')->hSet($diffCacheKey, $type, $num);
- return oo::commonOprRedis('usercache')->hSet($cacheKey, $type, $num);
- }
- }
- oo::commonOprRedis('usercache')->hIncrBy($diffCacheKey, $type, $num);
- $ret = oo::commonOprRedis('usercache')->hIncrBy($cacheKey, $type, $num);
- return $ret;
- }
- /**
- * 成就用户数据值入库落地(放在用户登录的时候,落地一次)
- * loginHandler.php
- * @param array $arr
- * @return bool
- */
- public function recordCondition($arr) {
- $uid = (int) $arr['uid'];
- if (!$uid)
- return false;
- $cacheKey = okeys::achiDiff($uid);
- $cache = oo::commonOprRedis('usercache')->hGetAll($cacheKey);
- if ($cache === false) { // 没有缓存
- return false;
- }
- oo::commonOprRedis('usercache')->delete($cacheKey); // 删除差值,重新累加
- $tb = otable::achi($uid);
- if (!is_array($cache) || !$cache)
- return false;
- $insert = "";
- $update = "";
- foreach ($cache as $k => $v) {
- $v = (int) $v;
- if (!in_array($k, $this->contypes) || ($v <= 0)) {
- continue;
- }
- $insert .= "`{$k}`='{$v}',";
- if ($k == 'swinchips') { // 更新不累加
- $update .= "`{$k}`='{$v}',";
- } else {
- $update .= "`{$k}`=`{$k}`+'{$v}',";
- }
- }
- if (empty($insert))
- return false;
- $insert = rtrim($insert, ',');
- $update = rtrim($update, ',');
- $query = "insert into {$tb} set uid='{$uid}',{$insert} on duplicate key update {$update}";
- return oo::commonOprDb('achi')->query($query);
- }
- /**
- * 数据库内容读入配置文件
- */
- public function dbToConfig()
- {
- $key = okeys::achievementConfig();
- $cacheData = oo::commonOprRedis('config')->get($key);
- if ($cacheData) {
- $tempArr = json_decode($cacheData, 1);
- foreach ($tempArr as $id => &$info) {
- $info['name'] = oo::getLang('achievement_'.$info['contype']);
- $info['desc'] = oo::getLang('achievement_desc_'.$info['contype']);
- }
- $this->achievementConfig = $tempArr;
- return;
- }
- $table = otable::achievementConfig();
- $sql = "SELECT * FROM {$table} ORDER BY aid ASC ";
- $list = oo::commonOprDb('common')->getAll($sql, 1);
- $i = 1;
- $taskList = array();
- foreach ($list as $ke => $value) {
- $value['id'] = $taskid = intval($value['id']);
- $value['sort'] = intval($value['sort']);
- $value['name'] = oo::getLang('achievement_'.$value['contype']);
- $value['desc'] = oo::getLang('achievement_desc_'.$value['contype']);
- $subtask = json_decode($value['subtask'], 1);
- $value['subtask'] = $subtask;
- $taskList[$taskid] = $value;
- $i++;
- }
- $taskListJson = json_encode($taskList);
- oo::commonOprRedis('config')->set($key, $taskListJson, 3600);
- $this->achievementConfig = $taskList;
- return $taskList;
- }
- /**
- * 配置文件写入数据库
- */
- public function configToDb()
- {
- $table = otable::achievementConfig();
- foreach ($this->achievementConfig as $key => $info) {
- $name = $info['name'];
- $zh_name = $info['zh_name'];
- $contype = $info['contype'];
- $image = $info['image'];
- $sort = $info['sort'];
- $desc = $info['desc'];
- $subtask = json_encode( $info['subtask'] );
- $sql = "INSERT INTO {$table} VALUES({$key}, '{$name}', '{$zh_name}', '{$contype}', '{$image}', {$sort}, '{$desc}', '{$subtask}')";
- oo::commonOprDb('common')->query($sql);
- echo $key."\r\n";
- }
- }
- // -----------------------------------------------------------------------------------------------------------------
- /**
- * 成就配置
- * @param string $aid
- * @return mixed
- * Created by: Owen
- * Created on: 2019/6/13 17:50
- * Description:
- */
- public function getAchieveConfig($aid = ''){
- $cacheKey = okeys::AchieveConfig();
- $arrJson = oo::commonOprRedis('config')->hGetAll($cacheKey);
- $arr = funs::getArrFromJsonArr($arrJson);
- if(empty($arr)||($aid!==''&&empty($arr[$aid]))){
- $tb = otable::achievementConfig();
- $sql = "SELECT * FROM {$tb}";
- $ret = oo::commonOprDb('config')->getAll($sql,1);
- if(!empty($ret)){
- foreach ($ret as $k=>$v){
- $arr[$v['aid']] = $v;
- $cache[$v['aid']] = json_encode($v);
- }
- oo::commonOprRedis('config')->hMset($cacheKey,$cache);
- oo::commonOprRedis('config')->expire($cacheKey,oo::redisRandomExpire(7*86400));
- }
- }
- $data = $aid===''?$arr:$arr[$aid];
- return $data;
- }
- /**
- * 成就列表
- * @param $uid
- * @return array
- * Created by: Owen
- * Created on: 2020/4/7 18:27
- */
- public function getAchieveList($uid){
- $achieveConfig = self::getAchieveConfig();
- $achieveUser = self::getUserAchieve($uid);
- $achieve = [];
- $lang = oo::getDefinedLang($uid);
- foreach ($achieveConfig as $row){
- $reward = json_decode($row['reward']);
- $stage = explode(',',$row['stage']);
- $i = 0;
- $process = ($achieveUser[$row['aid']]['process'])??0;
- foreach ($stage as $k){
- if($process>=$k){
- $i++;
- }
- }
- $userStage = ($achieveUser[$row['aid']]['stage'])??0;
- if($userStage >= count($stage)){
- $userStage = $userStage - 1;
- }
- if($lang == 'zh'){
- $designation = $row['designation'];
- $content = $row['content'];
- }else{
- $designation = $row['designation_'.$lang];
- $content = $row['content_'.$lang];
- }
- $temp = [
- 'id' =>$row['aid'],
- 'rewardTimes' =>$i,
- 'name' =>$designation,
- 'desc' =>$content,
- 'spinsNum' =>$reward[$userStage]->spin,
- 'coinsNum' =>$reward[$userStage]->coin,
- 'progress' =>$process,
- 'target' =>$stage[$userStage],
- 'curRewardTimes'=>($achieveUser[$row['aid']]['stage'])??0
- ];
- $achieve[] = $temp;
- }
- return $achieve;
- }
- /**
- * 获取用户成就
- * @param $uid
- * @param $aid
- * @return mixed
- * Created by: Owen
- * Created on: 2019/6/13 17:50
- * Description:
- */
- public function getUserAchieve($uid,$aid = ''){
- $cacheKey = okeys::UserAchieve($uid);
- $data = oo::commonOprRedis('Usercache')->hGetAll($cacheKey);
- if(empty($data)){
- $tb = otable::achievement($uid);
- $data = oo::commonOprDb('achievement')->getAll("SELECT * FROM {$tb} WHERE uid={$uid}",MYSQLI_ASSOC);
- if(empty($data)){
- if($aid !== ''){
- return self::InsertUserAchieve($uid,$aid);
- }else if($aid == ''){
- return [];
- }
- }
- foreach ($data as $row){
- oo::commonOprRedis('Usercache')->hSetNx($cacheKey,$row['aid'],json_encode($row));
- }
- oo::commonOprRedis('Usercache')->expire($cacheKey,oo::redisRandomExpire(3*2*60*60));
- }else{
- $data = funs::getArrFromJsonArr($data);
- }
- $out = [];
- foreach ($data as $key=>$row){
- if($key == $aid && $aid !== ''){
- return $row;
- }
- $out[$key] = $row;
- }
- if($aid === ''){
- return $out;
- }else{
- return self::InsertUserAchieve($uid,$aid);
- }
- }
- /**
- * 插入成就
- * @param $uid
- * @param $aid
- * @return array
- * Created by: Owen
- * Created on: 2020/7/3 14:52
- */
- public function InsertUserAchieve($uid,$aid){
- $cacheKey = okeys::UserAchieve($uid);
- $ret = [
- 'uid' => $uid,
- 'aid' => $aid,
- 'process' => 0,
- 'stage' => 0
- ];
- $res = oo::commonOprRedis('Usercache')->hSetNx($cacheKey,$aid,json_encode($ret));
- if($res){//并发锁
- $tb = otable::achievement($uid);
- oo::commonOprDb('achievement')->query("INSERT INTO {$tb} (uid,aid,process) VALUES ({$uid},{$aid},0)",false);
- }
- return $ret;
- }
-
- /**
- * 更新成就缓存
- * @param $uid
- * @param $aid
- * @param $ret
- * @return bool
- * Created by: Owen
- * Created on: 2020/4/7 18:19
- */
- public function updateUserAchieve($uid,$aid,$ret){
- $cacheKey = okeys::UserAchieve($uid);
- $ret['isLanding'] = 1;
- $bool = oo::commonOprRedis('Usercache')->hSet($cacheKey,$aid,json_encode($ret));
- oo::commonOprRedis('Usercache')->expire($cacheKey,oo::redisRandomExpire(3*2*60*60));
- /** 数据落地标识 */
- oo::commonOprRedis('Usercache')->zAdd(okeys::Landing("ACHIEVE", $uid),time(),$uid);
- return $bool;
- }
- /**
- * 更新成就数值
- * @param $uid
- * @param $aid
- * @param int $num
- * @param string $opt
- * @return bool
- * Created by: Owen
- * Created on: 2020/4/7 10:42
- */
- public function updateAchi($uid,$aid,$num = 1,$opt = '+'){
- $ret = self::getUserAchieve($uid,$aid);
- if($opt == '+'){
- $ret['process'] = $ret['process'] + $num;
- }else if($opt == '='){
- $ret['process'] = $num;
- }
- self::updateUserAchieve($uid,$aid,$ret);
- $ret = self::getAchieveConfig($aid);
- $stage = explode(',',$ret['stage']);
- if($ret['process'] <= $stage[count($stage)-1]){
- if(count($stage) > $ret['stage'] && $ret['process'] >= $stage[$ret['stage']]){
- $is_push = oo::commonOprRedis('Usercache')->hGet(okeys::redPointLock($uid,'Achi-'.$aid),$ret['stage']+1);
- if(!$is_push){
- oo::commonOprModel('Workerman')->push($uid,ocmd::$redPoint,['type'=>10]);
- oo::commonOprRedis('Usercache')->hSet(okeys::redPointLock($uid,'Achi-'.$aid),$ret['stage']+1,1);
- oo::commonOprRedis('usercache')->expire(okeys::redPointLock($uid,'Achi-'.$aid),oo::redisRandomExpire(7*86400));
- }
- }
- }
- return ($ret)?true:false;
- }
- /**
- * 领取成就奖品
- * @param $uid
- * @param $aid
- * @return array
- * Created by: Owen
- * Created on: 2019/6/13 18:33
- * Description:
- */
- public function getAchieveReward($uid,$aid){
- $achieve = self::getUserAchieve($uid,$aid);
- if(empty($achieve)){
- return ['code'=>-1,'msg'=>'未达标,无法领取奖品'];
- }
- $rewardStage = $achieve['stage'];
- $config = self::getAchieveConfig($aid);
- $configStage = explode(',',$config['stage']);
- if(count($configStage) == $rewardStage){
- return ['code'=>-1,'msg'=>'已领取最高等级奖励'];
- }
- $lang = oo::getDefinedLang($uid);
- if($configStage[$rewardStage]<=$achieve['process']){
- $achieve['stage'] = $rewardStage + 1;
- $ret = self::updateUserAchieve($uid,$aid,$achieve);
- if($ret){
- $reward = json_decode($config['reward'],true);
- $nextReward = $reward[$rewardStage+1];
- $rewardTemp = $reward[$rewardStage];
- $reward = [
- 'spins' => $rewardTemp['spin'],
- 'money' => $rewardTemp['coin'],
- ];
- oo::commonOprModel('member')->optProperty($uid,$reward,'+',102,'领取成就奖励:'.$aid.'-'.$rewardStage);
- $i = 0;
- $process = $achieve['process'];
- $stage = explode(',',$config['stage']);
- foreach ($stage as $k){
- if($process>$k){
- $i++;
- }
- }
- $data = [
- 'coin' =>$reward['money'],
- 'coins'=>$reward['money'],
- 'spins'=>$reward['spins'],
- ];
- if($lang == 'zh'){
- $designation = $config['designation'];
- $content = $config['content'];
- }else{
- $designation = $config['designation_'.$lang];
- $content = $config['content_'.$lang];
- }
- $data['achieve'] = [
- 'id' =>$aid,
- 'rewardTimes' =>$i,
- 'name' =>$designation,
- 'desc' =>$content,
- 'spinsNum' =>$nextReward['spin']??0,
- 'coinsNum' =>$nextReward['coin']??0,
- 'progress' =>$process,
- 'target' =>$stage[$rewardStage+1]??0,
- 'curRewardTimes'=>($rewardStage+1)
- ];
- oo::commonOprRedis('Usercache')->hDel(okeys::redPointLock($uid,'Achi-'.$aid),$rewardStage+1);
- return ['code'=>1,'msg'=>'领取奖品成功','data'=>$data];
- }
- }else{
- return ['code'=>-1,'msg'=>'未达标,无法领取奖品'];
- }
- }
- /**
- * 1.5.0 新版配置 --------------------------------------------------------------------------------------------------
- */
- /**
- * 成就列表
- * @param $uid
- * @return array
- * Created by: Owen
- * Created on: 2020/4/7 18:27
- */
- public function getAchieveList2($uid){
- $achieveConfig = self::getAchieveConfig();
- $achieveUser = self::getUserAchieve($uid);
- $achieve = [];
- foreach ($achieveConfig as $row){
- $process = ($achieveUser[$row['aid']]['process'])??0;
- $temp = [
- 'id' =>$row['aid'],
- 'progress' =>$process,
- 'curRewardTimes'=>($achieveUser[$row['aid']]['stage'])??0
- ];
- $achieve[] = $temp;
- }
- return $achieve;
- }
- }
|