<?php
class statisticsModel extends CI_Model
{
	/********新注册玩家key(newPlayerAndroidFb newPlayIosVisitor)******/
	protected $maxLevel = 120;
    protected $newPlayerKeyList = array(
        1 => array(//玩家类型1FB 2游客 3LINE 4华为
            1 => 'NPAFB', //1安卓 2IOS
            2 => 'NPIFB',
        ),
        2 => array(
            1 => 'NPAV', //1安卓 2IOS
            2 => 'NPIV',
        ),
        3 => array(
            1 => 'NPAL', //1安卓 2IOS
            2 => 'NPIL',
        ),
        4 => array(
            1 => 'NPAH',//华为
            2 => 'NPIH',
        ),
        5 => array(
            1 => 'NPAK',//靠谱
            2 => 'NPIK'
        ),
        6 => array(
            1 => 'NPAVK',//俄语的安卓VK
            2 => 'NPIVK' //俄语的苹果VK
        ),
        7 => array(
            1 => 'NPAOS',//华为海外
            2 => 'NPIOS'
        )
    );
    //设备列表
    private $sidList = [1, 2];

	//统计玩家等级,筹码区间
	private $moneyRange = array(
		array(0, 1000),
		array(1000, 2000),
		array(2000, 4000),
		array(4000, 10000),
		array(10000, 20000),
		array(20000, 40000),
		array(40000, 60000),
		array(60000, 100000),
		array(100000, 200000),
		array(200000, 400000),
		array(400000, 600000),
		array(600000, 1000000),
		array(1000000, 2000000),
		array(2000000, 3000000),
		array(3000000, 6000000),
		array(6000000, 10000000),
		array(10000000, 20000000),
		array(20000000, 1000000000),
	);

	private $diamondRange = [
        //[0, 1], 
        [1, 2], 
        [2, 3], 
        [3, 4], 
        [4, 5], 
        [5, 6], 
        [6, 7], 
        [7, 8], 
        [8, 9], 
        [10, 11], 
        [11, 12], 
        [12, 13], 
        [13, 14], 
        [14, 15], 
        [15, 16], 
        [16, 17], 
        [17, 18], 
        [18, 19], 
        [19, 20], 
        [20, 21], 
        [21, 24], 
        [24, 27], 
        [27, 30], 
        [30, 34], 
        [34, 38], 
        [38, 42], 
        [42, 47], 
        [47, 52], 
        [52, 57], 
        [57, 100],
        [100, 200],
        [200, 500],
        [500, 1000],
        [1000, 3000],
        [3000, 8000],
        [8000, 1000000000],
    ];

    /********新注册玩家key END ******/

    /********登陆玩家key(loginAndroidFb loginIosVisitor)*****/
    protected $loginPlayerKeyList = array(
        1 => array(//玩家类型1FB 2游客 3LINE 4华为
            1 => 'LIAFB', //1安卓 2IOS
            2 => 'LIIFB',
        ),
        2 => array(//
            1 => 'LIAV', //1安卓 2IOS
            2 => 'LIIV',
        ),
        3 => array(
            1 => 'LIAL', //1安卓 2IOS
            2 => 'LIIL',
        ),
        4 => array(
            1 => 'LIAH',
            2 => 'LIIH',
        ),
        5 => array(
            1 =>'LIAK',//靠谱
            2 => 'LIIK'
        ),
        6 => array(
            1 => 'LIAVK',//俄语的安卓VK
            2 => 'LIIVK' //俄语的苹果VK
        ),
        7 => array(
            1 => 'LIAOS',//华为海外
            2 => 'LIIOS'
        )
    );
    /********登陆玩家key END *****/

    protected $trackers = [
        "2xgabxp"=>"Facebook",
        "53ece3e"=>"Organic_all",
        "a9nv7dj"=>"Organic_all",
        "cwvjh9o"=>"Facebook",
        "g1b8nag"=>"Organic_all",
        "j6gwegb"=>"Organic_all",
        "k1qjyjr"=>"Facebook",
        "m6tz7ra"=>"Organic_all",
        "n6mofty"=>"Organic_all",
        "oss8d1v"=>"Facebook",
        "u69nimr"=>"Unity",
        "ussdj6t"=>"Google_ads",
        "vjjyyf2"=>"IronSource",
    ];
    
	public function __construct(){
        parent::__construct();
        $this->load->model('okeys');
		$this->load->model('otable');
		$this->load->model('oo');
		
		if (file_exists(APPPATH.'config/reason.php')) {
			$this->reason = include APPPATH.'config/reason.php';
		}
    }
    
    public function getMaxLevel(){
        $maxLevel = (int)oo::commonOprRedis('games')->hGet(okeys::shareBaseConfig(), 'basic-curMaxLevel');
        return $maxLevel??250;
    }

    /**
     * 获取资源配置英文
     * @return array
     */
    public function getResources() {
        return [ 'money', 'spins', 'level', 'diamond', ];
    }

    /**
     * 根据英文名获取中文内容
     */
    public function getNameByResource($type = 'money') {
        $names = [
            'money'   => '金币',
            'spins'   => '体力',
            'level'   => '等级',
            'diamond' => '钻石',
        ];
        return isset($names[$type]) ? $names[$type] : $names;
    }

    /**
     * 获取所有等级列表
     * @return array
     */
    public function getLevelRange(){
        $levelRange =[];
        $maxLevel = oo::commonOprModel("statistics")->getMaxLevel();
        for($i=1;$i<=$maxLevel;$i++){
            $levelRange[] =$i;
        }
        return $levelRange;
    }

    /**
     * 钻石/金币/体力分布统计
     * @param int $type (1:活跃用户,other:所有)
     * @param array $sidList 设备列表(1安卓,2IOS)
     * @return array
     */
    public function resourceLevelStatic($type = '', $sidList = [999]) {
	    $levelRange = $this->getLevelRange();
		$data = array('range' => [], 'rangeList' => []);
	    $tb = otable::gh_gameserver(1);
        switch($type){
            case 'diamond':
                $data['range'] = $this->diamondRange;
                foreach ($this->diamondRange as $key=>$row){
                    $sql = "SELECT count(*) as count FROM {$tb} WHERE diamond BETWEEN {$row[0]} AND {$row[1]}";
                    $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                    $data['rangeList'][] = intval($ret['count']);
                }
                break;
            case 'money':
                $data['range'] = $this->moneyRange;
                foreach ($this->moneyRange as $key=>$row){
                    $sql = "SELECT count(*) as count FROM {$tb} WHERE money BETWEEN {$row[0]} AND {$row[1]}";
                    $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                    $data['rangeList'][] = intval($ret['count']);
                }
                break;
            case 'level':
                $data['range'] = $levelRange;
                if(in_array(999, $sidList)) {
                    foreach ($levelRange as $key=>$row){
                        $sql = "SELECT count(*) as count FROM {$tb} WHERE levelId={$row}";
                        $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                        $data['rangeList'][] = intval($ret['count']);
                    }
                }else{
                    $login_plat = 1;
                    if(!empty($sidList) && is_array($sidList)){
                        $login_plat = implode(',',$sidList);
                    }
                    $tbUserinfo = otable::userinfo(1);
                    foreach ($levelRange as $key=>$row){
                        $sql = "SELECT count(*) as count FROM {$tb} AS a INNER JOIN {$tbUserinfo} AS b WHERE b.login_plat in ({$login_plat}) AND b.uid = a.mid AND a.levelId={$row}";
                        $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                        $data['rangeList'][] = intval($ret['count']);
                    }
                }
                break;
            case 'spins':
                for ($i=0;$i<=50;$i++){
                    $sql = "SELECT count(*) as count FROM {$tb} WHERE spins={$i}";
                    $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                    $data['rangeList'][] = intval($ret['count']);
                }

                //新加的体力区间
                $spinsRange = array(
                    '0'=>[51,100],
                    '1'=>[101,500],
                    '2'=>[501,1000],
                    '3'=>[1001,5000],
                    '4'=>[5001,9999999],
                );
                $data['range'] = $spinsRange;
                foreach($spinsRange as $k => $v){
                    $start = $v[0];
                    $end = $v[1];
                    $sql = "SELECT count(*) as count FROM {$tb} WHERE spins<={$end} AND spins >= {$start}";
                    $ret = oo::commonOprDb('common')->getOne($sql,1);
                    $data['rangeList'][] = intval($ret['count']);
                }
                break;
        }
        return json_encode($data);
    }
	
	//事件统计
	public function newGuideLost(){
        $keys = [10002,10003,10004,10005,10006,10007];
        /*
        $tb = otable::EventTitle();
        $sql = "SELECT * FROM {$tb}";
        $query = oo::commonOprDb('statistics')->query($sql);
        $EventTitle = $query->result_array();
        $keys = [];
        foreach($EventTitle as $k => $v){
        	$keys[] = $v['id'];
        }
        */
        
        foreach ($keys as $eventId){
            if($eventId == 10002 || $eventId == 10003){
                continue;
            }
            $data = [
                'time'=>date('Y-m-d'),
                'event_id'=>$eventId,
                'data'=>[],
                'total'=>0,
                'success_total'=>0,
                'other'=>[],
                'version'=>0,
            ];
            
            //FB
            $dataFb = [
                'time'=>date('Y-m-d'),
                'event_id'=>$eventId,
                'data'=>[],
                'total'=>0,
                'success_total'=>0,
                'version'=>0,
            ];
            
            //游客
            $dataVisitor = [
                'time'=>date('Y-m-d'),
                'event_id'=>$eventId,
                'data'=>[],
                'total'=>0,
                'success_total'=>0,
            ];

            $eventData = oo::commonOprRedis("Statistics")->hGetAll(okeys::Report($eventId));
            $data['total'] = count($eventData);
            
            $Users = [];//总用户
            $fbUsers = [];//fb用户
            $visitorUsers = [];//游客
            foreach ($eventData as $key=>$row){
                if($row<24){
                    $data['data'][$row] = $data['data'][$row] + 1;
                }
                
                //10005事件 区分FB、游客 
                if($eventId == 10005 || $eventId == 10006 || $eventId == 10007){
                	$Users[] = $key;
                	if(oo::commonOprModel('member')->isVistor($key) == 1){
                		//游客
                		$visitorUsers[] = $key;
                		$dataVisitor['data'][$row] = $dataVisitor['data'][$row] + 1;
                	}else{
                		//FB
                		$fbUsers[] = $key;
                		$dataFb['data'][$row] = $dataFb['data'][$row] + 1;
                	}
                }
            }
            $dataFb['total'] = count($fbUsers);//FB总流失数 包括通过的
            $dataVisitor['total'] = count($visitorUsers);//游客总流失数 包括通过的
            
            //最后一个事件人数减去通过新手的人数
            if($eventId == 10005 || $eventId == 10006 || $eventId == 10007){
            	//所有当天注册玩家
            	$successUsersCount = 0;
            	if(!empty($Users)){
            		$Users = array_filter($Users);
            		$UidStr = empty($Users) ? '' : " AND mid IN (".implode(',', $Users).") ";
			        //所有通过新手任务的玩家
			    	//for($i = 0; $i < 100; $i ++){
			    		$slTable = otable::gh_gameserver(1);
				        $sql = " SELECT count(*) AS count FROM {$slTable} WHERE beginGuide = 19 {$UidStr}";
				        $result = oo::commonOprDb('slavedb')->getOne($sql,1);

						$successUsersCount +=$result['count'];
			    	//}
            	}
		        $data['success_total'] = $successUsersCount;
		        
		        //FB的通过数
		        $successUsersCountFb = 0;
            	if(!empty($fbUsers)){
            		$fbUsers = array_filter($fbUsers);
            		$UidStrFb = empty($fbUsers) ? '' : " AND mid IN (".implode(',', $fbUsers).") ";
			        //所有通过新手任务的玩家
			    	//for($i = 0; $i < 100; $i ++){
			    		$slTable = otable::gh_gameserver(1);
				        $sql = " SELECT count(*) AS count FROM {$slTable} WHERE beginGuide = 19 {$UidStrFb}";
				        $result = oo::commonOprDb('slavedb')->getOne($sql,1);
						$successUsersCountFb +=$result['count'];
			    	//}
            	}
		        $dataFb['success_total'] = $successUsersCountFb;
		        
		        //游客的通过数
		        $successUsersCountVisitor = 0;
            	if(!empty($visitorUsers)){
            		$visitorUsers = array_filter($visitorUsers);
            		$UidStrVisitor = empty($visitorUsers) ? '' : " AND mid IN (".implode(',', $visitorUsers).") ";
			        //所有通过新手任务的玩家
			    	//for($i = 0; $i < 100; $i ++){
			    		$slTable = otable::gh_gameserver(1);
				        $sql = " SELECT count(*) AS count FROM {$slTable} WHERE beginGuide = 19 {$UidStrVisitor}";
				        $result = oo::commonOprDb('slavedb')->getOne($sql,1);
						$successUsersCountVisitor +=$result['count'];
			    	//}
            	}
		        $dataVisitor['success_total'] = $successUsersCountVisitor;
            }
            
            $data['data'] = json_encode($data['data'],JSON_NUMERIC_CHECK);
            
            
            //插入游客 统计结果
            //$dataVisitor['data'] = json_encode($dataVisitor['data'],JSON_NUMERIC_CHECK);
            
            $data['other']['fb'] = $dataFb;
            $data['other']['visitor'] = $dataVisitor;
            $data['other'] = json_encode($data['other'],JSON_NUMERIC_CHECK);
            $tb = otable::newGuideLost();
            $value = array_values($data);
            $value = implode("','",$value);
            $value = "'{$value}'";
            $sql = "INSERT INTO {$tb} VALUES({$value})";
            oo::commonOprDb('default')->query($sql);
            
            //插入FB 统计结果
            $dataFb['data'] = json_encode($dataFb['data'],JSON_NUMERIC_CHECK);
            $tb = otable::newGuideLostFb();
            $value = array_values($dataFb);
            $value = implode("','",$value);
            $value = "'{$value}'";
            $sql = "INSERT INTO {$tb} VALUES({$value})";
            oo::commonOprDb('default')->query($sql);
            
            oo::commonOprRedis("Statistics")->delete(okeys::Report($eventId));
        }
    }

    /**
     * 每日宝箱活动不同宝箱id数据统计
     */
    public function saveDailyChest($day = 0) {
        if(empty($day)){
            $day = date('Ymd', strtotime('-1 days 0:0:0'));
        }
        $key = okeys::daliyChestLog($day);
        $tmp = oo::commonOprRedis('Statistics')->hGetAll($key);
        if(empty($tmp)){
            return true;
        }
        $tb = otable::daliyChestLog();
        $sql = "REPLACE INTO {$tb} (id, day, chest1,chest2,chest3,chest4,chest5,chest6,chest7,chest8,chest9,chest10) VALUES(null,{$day}";
        for($i = 1; $i <= 10; $i++){
            $sql .= isset($tmp[$i]) ? ",{$tmp[$i]}" : ",0";
        }
        $sql .= ")";
        $ret = oo::commonOprDb('default')->query($sql);
        if($ret){
            oo::commonOprRedis('Statistics')->delete($key);
        }
        return $ret;
    }
    
	/**
     * 支付上报 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/6/11 11:17
     */
    public function savePayReportSta(){
    	$date = date('Ymd', strtotime("-1 day"));
    	
    	$sidList = [1,2];
    	//总次数
    	foreach($sidList as $sid){
    		$ret = oo::commonOprRedis("Statistics")->hGetAll(okeys::payReport($sid));
	        $data['sid'][$sid] = $ret;
	        $data["total"][$sid] = array_sum($ret);
	        
	        //统计后重置
			oo::commonOprRedis("Statistics")->delete(okeys::payReport($sid));
    	}
    	
    	$event = [10009,10010,10011];
    	//支付成功、支付取消、支付失败
    	foreach($event as $event_id){
    		foreach($sidList as $sid){
	    		$ret = oo::commonOprRedis("Statistics")->hGetAll(okeys::payReport($sid,$event_id));
		        $data[$event_id]['sid'][$sid] = $ret;
		        $data[$event_id]["total"][$sid] = array_sum($ret);
		        
		        //统计后重置
				oo::commonOprRedis("Statistics")->delete(okeys::payReport($sid,$event_id));
	    	}
    	}
		
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'payReport';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
	
	/**
     * adJust 統計
     * Created by: Owen
     * Created on: 2020/6/17 16:10
     */
    public function adJustSta(){
        foreach ([1=>'android',2=>'ios'] as $key=>$row){
            $list = oo::commonOprRedis("Statistics")->hGetAll(okeys::Report(10012,$key));
            if(empty($list)){
                continue;
            }
            $sql = "INSERT IGNORE INTO %s (uid,{$row}) VALUES ";
            $num = ceil(count($list) / 5000);
            for($i = 0; $i <= $num; $i++){
                $sqlArr = [];
            	$tempList = array_slice($list,$i * 5000,5000,true);
                if(empty($tempList)){
                    continue;
                }
                foreach ($tempList as $uid=>$data){
                    $tb = otable::AdJustSta($uid);
                    if(!isset($sqlArr[$tb])){
                        $sqlArr[$tb] = sprintf($sql, $tb);
                    }
                    oo::commonOprRedis('games')->delete(okeys::isPushCoinsUser($uid));
                    $sqlArr[$tb] .= "('{$uid}','{$data}'),";
                }
                //批量插入多表
                foreach($sqlArr as $v){
                    $v = trim($v,",");
                    oo::commonOprDb('games')->query($v);
                }
            }
            oo::commonOprRedis("Statistics")->delete(okeys::Report(10012,$key));
        }
    }
    
    /**
     * 广告统计
     * @return string
     * Created by: Owen
     * Created on: 2019/10/21 17:22
     */
    public function advertisement(){
        $date = date('Ymd');
        $sid = [1=>'android',2=>'ios'];
        $successSid = [];
        foreach ($sid as $x=>$y){
            $userCountList = oo::commonOprRedis("games")->hGetAll(okeys::advertisementRemainCount($x));
            $success = [];
            foreach ($userCountList as $key=>$row){
                $temp = explode('-',$key);
                $success[$temp[1]] += $row;
            }
            $successSid[$y] = $success;
        }
        $success = json_encode($successSid);
        
        $clickSid = [];
    	foreach ($sid as $x=>$y){
	        $userCountList = oo::commonOprRedis("Statistics")->hGetAll(okeys::Report(10002,$x));
	        $click = [];
	        foreach ($userCountList as $key=>$row){
	            $temp = explode('-',$key);
	            $click[$temp[1]] += $row;
	        }
	        $clickSid[$y] = $click;
    	}
        $clickSid = json_encode($clickSid);
        
        $playSid = [];
        foreach ($sid as $x=>$y){
	        $userCountList = oo::commonOprRedis("Statistics")->hGetAll(okeys::Report(10003,$x));
	        $play = [];
	        foreach ($userCountList as $key=>$row){
	            $temp = explode('-',$key);
	            $play[$temp[1]] += $row;
	        }
	        $playSid[$y] = $play;
        }
        $playSid = json_encode($playSid);
        $tb = otable::advertisementSta();
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$success}', '{$clickSid}','{$playSid}',1)";
        oo::commonOprDb('default')->query($sql);

        oo::commonOprRedis("games")->delete(okeys::advertisementRemainCount());
        oo::commonOprRedis("games")->delete(okeys::advertisementRemainCount(1));
        oo::commonOprRedis("games")->delete(okeys::advertisementRemainCount(2));
        oo::commonOprRedis("Statistics")->delete(okeys::Report(10002,1));
        oo::commonOprRedis("Statistics")->delete(okeys::Report(10002,2));
        oo::commonOprRedis("Statistics")->delete(okeys::Report(10003,1));
        oo::commonOprRedis("Statistics")->delete(okeys::Report(10003,2));
    }

    /**
     * 从环形表中取表数据
     * @param string $sql
     * @param int $circleId(1-10)
     * @return array
     */
    private function assetsLogFromSql($sql, $date = '', $circleId = -1) {
        $sql = sprintf($sql, otable::Assetslog($date, $circleId));
        return oo::commonOprDb('log')->getAll($sql,1);
    }

    /**
     * 从数据表取单条记录(适用select count or limit 1)
     * @param string $sql
     * @param string $date
     * @param int $circleId
     * @return array
     */
    private function assetsLogOneFromSql($sql, $date = '', $circleId = -1) {
        $sql = sprintf($sql, otable::Assetslog($date, $circleId));
    	return oo::commonOprDb('log')->getOne($sql,1);
    }

    /**
     * 合并新加入的分表数据
     * @param array $data
     * @param string $date
     * @param array $newArr
     * @return array
     */
    private function mergeAssetsLogFromData(array $data = [], array $newArr = []) {
        return $newArr ? array_merge($data, $newArr) : $data;
    }

    /**
     * 汇总合并几张分表数据
     * @param string $sql
     * @param string $date
     * @param string $type (one|all)
     * @return array
     */
    public function getAssLogsWithAllTable($sql, $date = '', $type = 'all') {
        $data = [];
        for($i = 0; $i < 10; $i++){
            $tmp = $type == 'all' ? 
                $this->assetsLogFromSql($sql, $date, $i) : $this->assetsLogOneFromSql($sql, $date, $i);
            $data = $this->mergeAssetsLogFromData($data, $tmp);
        }
        return $data;
    }

    /**
     * 获取总记录数
     * @param string $sql
     * @param string $date
     * @return int
     */
    public function getAssLogCountAllTable($sql, $date = '', $field = 'count') {
        $arr = $this->getAssLogsWithAllTable($sql, $date, 'all');
        $total = 0;
        foreach($arr as $v){
            $total += (empty($v[$field]) ? 0 : $v[$field]);
        }
        return $total;
    }
    
    //金币体力发放消耗统计
    public function savePropertyStatistics($date = '', $returnBack = true, $start_level = 0, $end_level = 0, $sHourMinute = 0, $eHourMinute = 0){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
        $where = ' 1=1 ';
        if($start_level){
            $where .= " AND levelId >= {$start_level}";
        }
        if($end_level){
            $where .= " AND levelId <= {$end_level}";
        }
        if($sHourMinute){
            $time = strtotime($date ." " .$sHourMinute.":00");
            $where .= " AND time >= {$time}";
        }
        if($eHourMinute){
            $time = strtotime($date ." " .$eHourMinute.":00");
            $where .= " AND time <= {$time}";
        }
        $payWhiteList = oo::commonOprModel("payment")->payWhiteList();
        if(empty(!$payWhiteList)){
            $payWhiteListTemp = implode(",",$payWhiteList);
            $where .= " AND uid not in({$payWhiteListTemp})";
        }
//    	$sql = "SELECT rid,type,crease,SUM(num) AS num FROM %s WHERE {$where} GROUP BY rid,type,crease";
//        $tmp = $this->getAssLogsWithAllTable($sql, $date);
        $sql = $this->getAllLogSql($date,"rid,type,crease,SUM(num) AS num",$where,"","GROUP BY rid,type,crease");
        $tmp = oo::commonOprDb('log')->getAll($sql,1);
        $data = [];
        foreach($tmp as $v){
            $key = $v['rid'].$v['type'].$v['crease'];
            if(empty($data[$key])){
                $data[$key] = $v;
            }else{
                $data[$key]['num'] += $v['num'];
            }
        }
        $data = array_values($data);
        
        $pos = $total = 0;//宝藏活动
        foreach($data as $k => $v){
        	if(in_array($v['rid'],[1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028]) && $v['crease'] == '+' && $v['type'] == 'money'){
        		$total += $v['num'];
        	}
        	if($v['rid'] == 1002){
        		$pos = $k;
        	}
        }
        if($pos){
        	$data[$pos]['num'] = $total;
        }else{
        	$treasure = array(
        		'rid'=>1002,
        		'type'=>'money',
        		'crease'=>'+',
        		'num'=>$total,
        	);
        	$data[] = $treasure;
        }

        if($returnBack){
            $tbKey[] = 'date';
            $tbVal[] = $date;
            $tbKey[] = 'data';
            $tbVal[] = json_encode($data);
            $tbSta = otable::AssetsSta();
            $tbKey = implode(',',$tbKey);
            $tbVal = implode("','",$tbVal);
            $tbVal = "'".$tbVal."'";
            $sql = "INSERT INTO {$tbSta} ($tbKey) VALUES ({$tbVal})";
            oo::commonOprDb('statistics')->query($sql);
        }
        
        //每日转动&体力消耗
        $actArr = ["+"=>"add","-"=>"low"];
        //$keyArr = ["money", "spins", "shield", "star", "levelId","slotCount"];
        $keyArr = ["money", "spins", "shield", "star"];
        $temp = [];
        
        foreach($data as $k => $v){
        	foreach ($actArr as $key=>$row){
	            foreach ($keyArr as $x){
	            	if(!isset($temp[$row][$x])){
	            		$temp[$row][$x] = 0;
	            	}
	            	if($v['type'] == $x && $v['crease'] == $key){
	            		$temp[$row][$x] += $v['num'];
	            	}
	            }
	        }
        }
        foreach ($actArr as $key=>$row){
            foreach ($keyArr as $x){
            	if(!isset($temp[$row][$x])){
            		$temp[$row][$x] = 0;
            	}
            }
        }

        $where = '';
        if(!empty($payWhiteListTemp)){
            $where .= " AND uid not in({$payWhiteListTemp})";
        }
        //$temp['add']['slotCount'] = $this->getAssLogCountAllTable("SELECT count(*) AS count FROM %s WHERE rid = 1 AND type = 'spins' AND crease = '-' {$where}", $date);
        $sql = $this->getAllLogSql($date,"count(*) AS count","rid = 1 AND type = 'spins' AND crease = '-' {$where}");
        $slotCountRet = oo::commonOprDb('log')->getAll($sql,1);
        $slotCount = 0;
        foreach($slotCountRet as $row){
            $slotCount += $row['count'];
        }
        $temp['add']['slotCount'] = $slotCount;

        if($returnBack){
            $insertDate = date('Y-m-d',strtotime($date));
            $tableAdd = otable::PropertyAdd();
            $sql = " INSERT INTO {$tableAdd}(date,money,spins,shield,star,levelId,slotCount) VALUES('{$insertDate}',{$temp['add']['money']},{$temp['add']['spins']},{$temp['add']['shield']},{$temp['add']['star']},0,{$temp['add']['slotCount']})";
            oo::commonOprDb('statistics')->query($sql);
            $tableAdd = otable::Propertylow();
            $sql = " INSERT INTO {$tableAdd}(date,money,spins,shield,star) VALUES('{$insertDate}',{$temp['low']['money']},{$temp['low']['spins']},{$temp['low']['shield']},{$temp['low']['star']})";
            oo::commonOprDb('statistics')->query($sql);

            $this->assetsStaRealityPeople(date('Ymd',strtotime($date)),true, $start_level, $end_level, $sHourMinute, $eHourMinute); //消耗、发放、实际参与人数
        }

        if(!$returnBack){
            return $data;
        }else{
            return false;
        }
    }

    /**
     * Notes:消耗、发放、实际参与人数
     * User: Hss
     * Time: 2021/1/21 10:44
     */
    public function assetsStaRealityPeople($date = '',$insert = true, $start_level = 0, $end_level = 0, $sHourMinute = 0, $eHourMinute = 0){
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }
        $where = " type in('money','spins','diamond') ";
        if($start_level){
            $where .= " AND levelId >= {$start_level}";
        }
        if($end_level){
            $where .= " AND levelId <= {$end_level}";
        }
        if($sHourMinute){
            $time = strtotime($date ." " .$sHourMinute.":00");
            $where .= " AND time >= {$time}";
        }
        if($eHourMinute){
            $time = strtotime($date ." " .$eHourMinute.":00");
            $where .= " AND time <= {$time}";
        }
        $sql = $this->getAllLogSql($date,"uid,rid,type,crease",$where,"","GROUP BY uid,rid,type,crease");
        $sql = "SELECT rid,type,crease,count(*) AS count FROM ({$sql}) AS a GROUP BY rid,type,crease";
        $ret = oo::commonOprDb('log')->getAll($sql,MYSQLI_ASSOC);
        $data = json_encode($ret,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
        $type = 'assetsStaRealityPeople';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        if($insert){
            oo::commonOprDb('statistics')->query($sql);
        }else{
            return $data;
        }
    }
    
    //老虎机统计
    public function slotStatistics($date = ''){
        $tb = otable::slotStatistics();
        if(empty($date)){
        	$date = date('Y-m-d',strtotime('-1 day'));
        }
        
        $money = $this->slotTb($date,1);
        $spins = $this->slotTb($date,2);
        $steal = $this->slotTb($date,3);
        $attack = $this->slotTb($date,4);
        $shield = $this->slotTb($date,5);
        $activity = $this->slotTb($date,6);
        $count = $this->slotTb($date,0);
        $nothing = $count - $money - $spins - $steal - $attack - $shield - $activity;
        
        //金币细分
        $money1 = $this->slotTb($date,11);
        $money2 = $this->slotTb($date,12);
        $money3 = $this->slotTb($date,13);
        $money4 = $this->slotTb($date,14);
        $money5 = $this->slotTb($date,15);
        $money6 = $this->slotTb($date,16);
        
        $sql = " INSERT INTO {$tb}(date,slot,money,spins,shield,steal,attack,activity,nothing,money1,money2,money3,money4,money5,money6) VALUES('{$date}',{$count},{$money},{$spins},{$shield},{$steal},{$attack},{$activity},{$nothing},{$money1},{$money2},{$money3},{$money4},{$money5},{$money6})";
        oo::commonOprDb('statistics')->query($sql);
    }
    
    public function slotTb($date,$type,$uid = 0,$levelId = 0){
    	$where = '';
    	$field = '';
    	if(!empty($uid)){
    		$where = " AND uid = {$uid}";
    	}
    	if(!empty($levelId)){
    		//$where = " AND levelId = {$levelId}";
    		$where .= " GROUP BY {$levelId}";
    		$field = "levelId,";
    	}
    	switch ($type) {
    		case 1:
    			//金币
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'money' AND crease = '+' {$where}";
    			break;
    		case 2:
    			//体力
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'spins' AND crease = '+' {$where}";
    			break;
    		case 3:
    			//偷
    			//4偷到 9偷到机器人
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid in(4,9) AND type = 'money' AND crease = '+' {$where}";
    			break;
    		case 4:
    			//打
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid between 2 and 3 AND type = 'money' AND crease = '+' AND reason <> '攻击宠物技能获得金币' {$where}";
    			break;
    		case 5:
    			//盾牌
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE ((rid = 5 AND type = 'spins') OR (rid = 1 AND type = 'shield')) AND crease = '+' {$where}";
    			break;
    		case 6:
    			//活动
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1001 AND type = 'actCurrency' AND crease = '+' {$where}";
    			break;
    		case 0:
    			//摇奖次数
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'spins' AND crease = '-' {$where}";
    			break;
    		case 11:
    			//1个金币
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'money' AND crease = '+' AND reason	= '摇奖奖励金币:1' {$where}";
    			break;
    		case 12:
    			//2个金币
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'money' AND crease = '+' AND reason	= '摇奖奖励金币:2' {$where}";
    			break;
    		case 13:
    			//3个金币
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'money' AND crease = '+' AND reason	= '摇奖奖励金币:3' {$where}";
    			break;
    		case 14:
    			//1个金袋
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'money' AND crease = '+' AND reason	= '摇奖奖励金币:4' {$where}";
    			break;
    		case 15:
    			//2个金袋
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'money' AND crease = '+' AND reason	= '摇奖奖励金币:5' {$where}";
    			break;
    		case 16:
    			//3个金袋
    			$sql = "SELECT {$field}count(*) AS count FROM %s WHERE rid = 1 AND type = 'money' AND crease = '+' AND reason	= '摇奖奖励金币:6' {$where}";
    			break;
    		default:
    			return 0;
    			break;
    	}
        
        $date = date("Ymd",strtotime($date));
    	//$tbSta = otable::Assetslog(date("Ymd",strtotime($date)));
        if(!empty($levelId)){
            $ret = $this->getAssLogsWithAllTable($sql, $date);
        	//$ret = oo::commonOprDb('log')->getAll($sql,1);
        	$temp = [];
	        foreach($ret as $key => $val){
	        	$temp[$val['levelId']] = $val['count'];
	        }
        	return $temp;
        }else{
            $ret = $this->getAssLogsWithAllTable($sql, $date);
        	//$ret = oo::commonOprDb('log')->getOne($sql,1);
        	//return intval($ret['count']);
            $count = 0;
            foreach($ret as $v){
                $count = empty($v['count']) ? $count : $count+$v['count'];
            }
            return $count;
        }
    }
    
    /**
     * 网络重连上报统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/7/22 18:28
     */
    public function saveNetworkReportSta(){
    	$date = date('Ymd', strtotime("-1 day"));
    	
    	$sidList = [0,1,2];
    	//总次数
    	foreach($sidList as $sid){
    		$ret = oo::commonOprRedis("statistics")->hGetAll(okeys::NetworkReport($sid));
	        $data['sid'][$sid] = $ret;

	        //统计后重置
			oo::commonOprRedis("statistics")->delete(okeys::NetworkReport($sid));
    	}
		
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'NetworkReport';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 新手步骤统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2019/12/24 10:41
     */
    public function saveNoviceStepsSta(){
    	$date = date('Ymd');

        $data = array();
        $data['statistics'] = oo::commonOprRedis('statistics')->hgetall(okeys::noviceStepsSta());
        $data['statisticsFb'] = oo::commonOprRedis('statistics')->hgetall(okeys::noviceStepsSta(1));
        
        //统计后重置
        oo::commonOprRedis('statistics')->delete(okeys::noviceStepsSta());
        oo::commonOprRedis('statistics')->delete(okeys::noviceStepsSta(1));
        
        $data = json_encode($data);
        
        $tb = otable::noviceStepsSta();
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$data}')";
        oo::commonOprDb('statistics')->query($sql);
    }
    
    /**
     * 登陆事件上报 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/7/28 10:29
     */
    public function saveLoginEventSta(){
    	$date = date('Ymd');

        $data = array();
        $sidList = [1,2];
        foreach($sidList as $sid){
        	$data['sid'][$sid] = oo::commonOprRedis('Statistics')->hgetall(okeys::LoginEventSta($sid));
        	
        	//统计后重置
        	oo::commonOprRedis('Statistics')->delete(okeys::LoginEventSta($sid));
        }

        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'LoginEventSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 打概率统计 击中率（损毁建筑） & 摧毁率（岛被打光）& 打到盾概率
     * @return string
     * Created by: hss
     * Created on: 2020/8/10 12:26
     */
    public function attackChanceSta(){
    	$date = date('Ymd', strtotime("-1 day"));
    	//$tbSta = otable::Assetslog(date("Ymd",strtotime($date)));
    	$where = '';
    	$sql = "SELECT count(*) AS count FROM %s WHERE rid between 2 and 3 AND type = 'money' AND crease = '+' {$where}";
    	//$ret = oo::commonOprDb('log')->getOne($sql,1);
        //$attackTotal = intval($ret['count']);//打总次数
        $attackTotal = $this->getAssLogCountAllTable($sql, date("Ymd",strtotime($date)));
        
        $sql = "SELECT count(*) AS count FROM %s WHERE rid = 2 AND type = 'money' AND crease = '+' AND reason like '损毁建筑%' {$where}";
    	//$ret = oo::commonOprDb('log')->getOne($sql,1);
        //$attackSun = intval($ret['count']);//损毁建筑打总次数 建筑被损毁
        $attackSun = $this->getAssLogCountAllTable($sql, date("Ymd",strtotime($date)));
        
        $sql = "SELECT count(*) AS count FROM %s WHERE rid = 2 AND type = 'money' AND crease = '+' AND reason like '摧毁建筑%' {$where}";
    	//$ret = oo::commonOprDb('log')->getOne($sql,1);
        //$attackCui = intval($ret['count']);//摧毁建筑打总次数 建筑被摧毁
        $attackCui = $this->getAssLogCountAllTable($sql, date("Ymd",strtotime($date)));//摧毁建筑打总次数 建筑被摧毁
        
        $sql = "SELECT count(*) AS count FROM %s WHERE rid = 2 AND type = 'money' AND crease = '+' AND reason like '%(岛被打光)%' {$where}";
    	//$ret = oo::commonOprDb('log')->getOne($sql,1);
        //$attackOver = intval($ret['count']);//岛被打光
        $attackOver = $this->getAssLogCountAllTable($sql, date("Ymd",strtotime($date)));//岛被打光
        
        $sql = "SELECT count(*) AS count FROM %s WHERE rid = 3 AND type = 'money' AND crease = '+' {$where}";
    	//$ret = oo::commonOprDb('log')->getOne($sql,1);
        //$attackShield = intval($ret['count']);//打到盾牌
        $attackShield = $this->getAssLogCountAllTable($sql, date("Ymd",strtotime($date)));//打到盾牌
        
        $sql = "SELECT sum(num) AS sum FROM %s WHERE rid = 5 {$where}";
    	//$ret = oo::commonOprDb('log')->getOne($sql,1);
        //$spins = intval($ret['sum']);//盾转体力的个数
        $spins = $this->getAssLogCountAllTable($sql, date("Ymd",strtotime($date)));//盾转体力的个数
        
        $sql = "SELECT sum(num) AS sum FROM %s WHERE rid = 1 AND type = 'shield' AND crease = '+' {$where}";
        //$ret = oo::commonOprDb('log')->getOne($sql,1);
        //$shield = intval($ret['sum']);//转到盾的数量（真实盾量） 不包含盾转体力
        //转到盾的数量（真实盾量） 不包含盾转体力
        $shield = $this->getAssLogCountAllTable($sql, date("Ymd",strtotime($date)));
        
        $data = array(
        	'attackTotal'=>$attackTotal,
        	'attackSun'=>$attackSun,
        	'attackOver'=>$attackOver,
        	'attackShield'=>$attackShield,
        	'attackCui'=>$attackCui,
        	'spins'=>$spins,
        	'shield'=>$shield,
        );
        
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'attackChanceSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 当天用户分组人数
     * @return string
     * Created by: hss
     * Created on: 2020/8/11 10:11
     */
    public function todayUserGroupSta(){
    	$date = date('Ymd', strtotime("-1 day"));
    	$ret = oo::commonOprModel('config')->getUserGroupConfig();
    	
    	$tb = otable::UserDynamicsData();
    	//总数
    	$sql = "SELECT groupId,count(*) AS count FROM {$tb} GROUP BY groupId";
    	$userGroupRet = oo::commonOprDb('slavedb')->getAll($sql,1);
    	$userGroup = [];
    	foreach($userGroupRet as $key => $val){
    		$userGroup[$val['groupId']] = $val['count'];
    	}
    	$out = [];
    	foreach($ret as $key => $row){
    		$out[$row['id']] = empty($userGroup[$row['id']])?0:$userGroup[$row['id']];
    	}
    	
    	$data['group'] = $out;
    	
    	//当天活跃人数
    	$activeUser = oo::commonOprModel('statistics')->getAllPlayer($date, 2);
    	$activeUserStr = implode(",",$activeUser);
    	if(!empty($activeUserStr)){
    		$sql = "SELECT groupId,count(*) AS count FROM {$tb} WHERE uid in({$activeUserStr}) GROUP BY groupId";
	    	$userGroupRet = oo::commonOprDb('slavedb')->getAll($sql,1);
	    	$userGroup = [];
	    	foreach($userGroupRet as $key => $val){
	    		$userGroup[$val['groupId']] = $val['count'];
	    	}
	    	$out = [];
	    	foreach($ret as $key => $row){
	    		$out[$row['id']] = empty($userGroup[$row['id']])?0:$userGroup[$row['id']];
	    	}
	    	$data['groupActive'] = $out;
    	}

    	//新用户分组数据 用户分组中加入统计 付费率 arpu arppu 充值总额 并每日记录
        $config = oo::commonOprModel('config')->getUserGroupConfig2();
        array_multisort(array_column($config,'sort'),SORT_ASC,$config);
        $list = [];
        $tb   = otable::UserGroupSta();
        $summarylist = otable::summarylist();
        $payWhiteList = oo::commonOprModel("payment")->payWhiteList();
        $where = '';
        if(empty(!$payWhiteList)){
            $payWhiteList = implode(",",$payWhiteList);
            $where .= " AND sl_uid not in({$payWhiteList})";
        }
        foreach ($config as $key=>$row){
            $id = $row['id'];
            $like = "%#{$id}#%";
            $sql = "SELECT uid FROM {$tb} WHERE date='{$date}' AND groupId LIKE '{$like}'";
            $ret = oo::commonOprDb('statistics')->getAll($sql, MYSQLI_ASSOC);
            if(!empty($ret)){
                $uids = [];
                foreach($ret as $vo){
                    $uids[] = $vo['uid'];
                }
//                $uids = array_unique($uids);
                $uidStr = implode(",",$uids);
                $dau = count($ret);
                $stime = strtotime($date);
                $sql = "SELECT sl_uid,sum(sl_pusd) as total FROM {$summarylist} WHERE sl_pay_time >= {$stime} AND sl_pay_time <= {$stime} + 86400 AND sl_status = 2 AND sl_sid <> -1 AND sl_uid in({$uidStr}) {$where} group by sl_uid";
                $summarylistRet = oo::commonOprDb('slavedb')->getAll($sql,1);
                $payTotal = array_sum(array_map(function($val){return $val['total'];}, $summarylistRet));
                $payNum = count($summarylistRet);
                $list[$id]['payTotal'] = number_format($payTotal,2,".","");//付费总额
                $list[$id]['ARPU'] = number_format($payTotal / $dau,2,".","");//ARPU = 付费金额 / DAU
                $list[$id]['ARPPU'] = number_format($payTotal / $payNum,2,".","");//ARPPU = 付费金额 / 付费人数
                $list[$id]['payRate'] = number_format($payNum / $dau * 100,2,".","");
                $list[$id]['payNum'] = $payNum;
            }
        }
        $data['list'] = $list;
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'todayUserGroupSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 用户留存 统计 游客 / FB
     * @return string
     * Created by: hss
     * Created on: 2020/8/11 15:42
     */
    public function recordDataFB($day = ''){
    	if(empty($day)){
    		$day = date('Ymd', strtotime("-1 day"));
    	}
    	
        $now = time();
        $table = otable::remainStatistics2();
        $sidList = [1,2];//1安卓 2IOS

    	$data = $this->getRemainData($day,$sidList);

    	//全部
        $sql = "INSERT INTO {$table} (date, day1Remain, day3Remain, day7Remain, day30Remain, day60Remain, day90Remain, day120Remain, day1ActRemain, day3ActRemain, day7ActRemain, day30ActRemain, day60ActRemain, day90ActRemain, day120ActRemain, createtime, is_fb) VALUES({$day}, {$data['day1Remain']}, {$data['day3Remain']}, {$data['day7Remain']}, {$data['day30Remain']}, {$data['day60Remain']}, {$data['day90Remain']}, {$data['day120Remain']}, {$data['day1ActRemain']}, {$data['day3ActRemain']}, {$data['day7ActRemain']}, {$data['day30ActRemain']}, {$data['day60ActRemain']}, {$data['day90ActRemain']}, {$data['day120ActRemain']}, {$now}, 0)";
        $ret = oo::commonOprDb('default')->query($sql);
        //游客
        $sql = "INSERT INTO {$table} (date, day1Remain, day3Remain, day7Remain, day30Remain, day60Remain, day90Remain, day120Remain, day1ActRemain, day3ActRemain, day7ActRemain, day30ActRemain, day60ActRemain, day90ActRemain, day120ActRemain, createtime, is_fb) VALUES({$day}, {$data['day1RemainGuest']}, {$data['day3RemainGuest']}, {$data['day7RemainGuest']}, {$data['day30RemainGuest']}, {$data['day60RemainGuest']}, {$data['day90RemainGuest']}, {$data['day120RemainGuest']}, {$data['day1ActRemainGuest']}, {$data['day3ActRemainGuest']}, {$data['day7ActRemainGuest']}, {$data['day30ActRemainGuest']}, {$data['day60ActRemainGuest']}, {$data['day90ActRemainGuest']}, {$data['day120ActRemainGuest']}, {$now}, 1)";
        $ret = oo::commonOprDb('default')->query($sql);
        //FB
        $sql = "INSERT INTO {$table} (date, day1Remain, day3Remain, day7Remain, day30Remain, day60Remain, day90Remain, day120Remain, day1ActRemain, day3ActRemain, day7ActRemain, day30ActRemain, day60ActRemain, day90ActRemain, day120ActRemain, createtime, is_fb) VALUES({$day}, {$data['day1RemainFb']}, {$data['day3RemainFb']}, {$data['day7RemainFb']}, {$data['day30RemainFb']}, {$data['day60RemainFb']}, {$data['day90RemainFb']}, {$data['day120RemainFb']}, {$data['day1ActRemainFb']}, {$data['day3ActRemainFb']}, {$data['day7ActRemainFb']}, {$data['day30ActRemainFb']}, {$data['day60ActRemainFb']}, {$data['day90ActRemainFb']}, {$data['day120ActRemainFb']}, {$now}, 2)";
        $ret = oo::commonOprDb('default')->query($sql);
        //Vivo
        $sql = "INSERT INTO {$table} (date, day1Remain, day3Remain, day7Remain, day30Remain, day60Remain, day90Remain, day120Remain, day1ActRemain, day3ActRemain, day7ActRemain, day30ActRemain, day60ActRemain, day90ActRemain, day120ActRemain, createtime, is_fb) VALUES ({$day},";
        foreach ([1,3,7,30,60,90,120] as $num){
            $sql = $sql . $data['day'.$num.'RemainVivo'].",";
        }
        foreach ([1,3,7,30,60,90,120] as $num){
            $sql = $sql . $data['day'.$num.'ActRemainVivo'].",";
        }
        $sql .= "{$now},3)";
        oo::commonOprDb('default')->query($sql);
        return true;
    }
    
    public function remainFunc($todayUser,$lastUser){
    	$intersectPlay = array_intersect($todayUser, $lastUser);//交集玩家
        $tempRemain = empty(count($lastUser)) ? 0 : count($intersectPlay) / count($lastUser);//次日留存率
        $remain = round($tempRemain, 4)*100;//留存率
        return $remain;
    }
    
    public function getRemainData($day, $sidList=[1,2]){
        $days1ago = $day;
        $arr['1'] = date('Ymd', strtotime($day.'-1 day'));
        $arr['3'] = date('Ymd', strtotime($day.'-3 days'));
        $arr['7'] = date('Ymd', strtotime($day.'-7 days'));
        $arr['30'] = date('Ymd', strtotime($day.'-30 days'));
        $arr['60'] = date('Ymd', strtotime($day.'-60 days'));
        $arr['90'] = date('Ymd', strtotime($day.'-90 days'));
        $arr['120'] = date('Ymd', strtotime($day.'-120 days'));
        
        //次日新增留存
        $yesterdayPlayer = oo::commonOprModel('statistics')->getAllPlayer($days1ago, 2, $sidList);//登陆玩家
        $vivoYesterdayPlayer = [];
//        foreach($yesterdayPlayer as $uid){
//            $temp = oo::commonOprModel('member')->getUserInfo($uid);
//            if($temp['channel'] == 1){
//                $vivoYesterdayPlayer[] = $uid;
//            }
//        }
        //次日活跃留存
        $yesterdayLoginPlayer = oo::commonOprModel('statistics')->getAllPlayer($days1ago, 2, $sidList);//登陆玩家
        
        $yesterdayPlayerGuest = $yesterdayPlayerFb = [];
        $yesterdayPlayerGuest = oo::commonOprModel('statistics')->getAllPlayer($days1ago, 2, $sidList, 2);//登陆玩家 优化
        $yesterdayPlayerFb    = oo::commonOprModel('statistics')->getAllPlayer($days1ago, 2, $sidList, 1);//登陆玩家 优化
        /*
        foreach($yesterdayPlayer as $uid){
        	if(oo::commonOprModel('member')->isVistor($uid)){
        		$yesterdayPlayerGuest[] = $uid;
        	}else{
        		$yesterdayPlayerFb[] = $uid;
        	}
        }
        */
        
        $yesterdayLoginPlayerGuest = $yesterdayLoginPlayerFb = [];
        $yesterdayLoginPlayerGuest = oo::commonOprModel('statistics')->getAllPlayer($days1ago, 2, $sidList, 2);//登陆玩家 优化
        $yesterdayLoginPlayerFb	   = oo::commonOprModel('statistics')->getAllPlayer($days1ago, 2, $sidList, 1);//登陆玩家 优化
        /*
        foreach($yesterdayLoginPlayer as $uid){
        	if(oo::commonOprModel('member')->isVistor($uid)){
        		$yesterdayLoginPlayerGuest[] = $uid;
        	}else{
        		$yesterdayLoginPlayerFb[] = $uid;
        	}
        }
        */
        
        foreach($arr as $k => $days){
        	//新增留存
        	$lastdaysPlayer = oo::commonOprModel('statistics')->getAllPlayer($days, 1, $sidList);//新增玩家
	        $data['day'.$k.'Remain'] = $this->remainFunc($yesterdayPlayer,$lastdaysPlayer);//次日留存率
	        $lastdaysPlayerGuest = $lastdaysPlayerFb = [];
	        $lastdaysPlayerGuest = oo::commonOprModel('statistics')->getAllPlayer($days, 1, $sidList, 2);//新增玩家 优化
	        $lastdaysPlayerFb    = oo::commonOprModel('statistics')->getAllPlayer($days, 1, $sidList, 1);//新增玩家 优化
	        /*
	        foreach($lastdaysPlayer as $uid){
	        	if(oo::commonOprModel('member')->isVistor($uid)){
	        		$lastdaysPlayerGuest[] = $uid;
	        	}else{
	        		$lastdaysPlayerFb[] = $uid;
	        	}
	        }
	        */
	        $data['day'.$k.'RemainGuest'] = $this->remainFunc($yesterdayPlayerGuest,$lastdaysPlayerGuest);//次日留存率 游客
	        $data['day'.$k.'RemainFb'] = $this->remainFunc($yesterdayPlayerFb,$lastdaysPlayerFb);//次日留存率 FB

//            //vivo新增留存
//            $vivoNewPlayer = [];
//            foreach($lastdaysPlayer as $uid){
//                $temp = oo::commonOprModel('member')->getUserInfo($uid);
//                if($temp['channel'] == 1){
//                    $vivoNewPlayer[] = $uid;
//                }
//            }
//            $data['day'.$k.'RemainVivo'] = $this->remainFunc($vivoYesterdayPlayer,$vivoNewPlayer);
            $data['day'.$k.'RemainVivo'] = 0;

	        //活跃留存
	        $lastdaysLoginPlayer = oo::commonOprModel('statistics')->getAllPlayer($days, 2, $sidList);//登陆玩家
	        $data['day'.$k.'ActRemain'] = $this->remainFunc($yesterdayLoginPlayer,$lastdaysLoginPlayer);//次日留存率
	        $lastdaysLoginPlayerGuest = $lastdaysLoginPlayerFb = [];
	        $lastdaysLoginPlayerGuest = oo::commonOprModel('statistics')->getAllPlayer($days, 2, $sidList, 2);//登陆玩家 优化
	        $lastdaysLoginPlayerFb    = oo::commonOprModel('statistics')->getAllPlayer($days, 2, $sidList, 1);//登陆玩家 优化
	        /*
	        foreach($lastdaysLoginPlayer as $uid){
	        	if(oo::commonOprModel('member')->isVistor($uid)){
	        		$lastdaysLoginPlayerGuest[] = $uid;
	        	}else{
	        		$lastdaysLoginPlayerFb[] = $uid;
	        	}
	        }
	        */
	        $data['day'.$k.'ActRemainGuest'] = $this->remainFunc($yesterdayLoginPlayerGuest,$lastdaysLoginPlayerGuest);//次日留存率 游客
	        $data['day'.$k.'ActRemainFb'] = $this->remainFunc($yesterdayLoginPlayerFb,$lastdaysLoginPlayerFb);//次日留存率 FB

//            //vivo活跃留存
//            $vivoLoginPlayer = [];
//            foreach($lastdaysLoginPlayer as $uid){
//                $temp = oo::commonOprModel('member')->getUserInfo($uid);
//                if($temp['channel'] == 1){
//                    $vivoLoginPlayer[] = $uid;
//                }
//            }
//            $data['day'.$k.'ActRemainVivo'] = $this->remainFunc($vivoYesterdayPlayer,$vivoLoginPlayer);
            $data['day'.$k.'ActRemainVivo'] = 0;
        }

        return $data;
    }
    
    //老虎机关卡概率统计
    public function slotLevelStatistics($date = '',$range = 1){
        if(empty($date)){
        	$date = date('Ymd',strtotime('-1 day'));
        }
        
        $out = [];
    	$money = $this->slotTb($date,1,0,1);
        $spins = $this->slotTb($date,2,0,1);
        $steal = $this->slotTb($date,3,0,1);
        $attack = $this->slotTb($date,4,0,1);
        $shield = $this->slotTb($date,5,0,1);
        $activity = $this->slotTb($date,6,0,1);
        $count = $this->slotTb($date,0,0,1);
        //$nothing = $count - $money - $spins - $steal - $attack - $shield - $activity;
        
        //金币细分
        $money1 = $this->slotTb($date,11,0,1);
        $money2 = $this->slotTb($date,12,0,1);
        $money3 = $this->slotTb($date,13,0,1);
        $money4 = $this->slotTb($date,14,0,1);
        $money5 = $this->slotTb($date,15,0,1);
        $money6 = $this->slotTb($date,16,0,1);
        
        for($i = 1; $i <= 120; $i++){
        	$nothing = (empty($count[$i])?0:$count[$i]) - (empty($money[$i])?0:$money[$i]) - (empty($spins[$i])?0:$spins[$i]) - (empty($steal[$i])?0:$steal[$i]) - (empty($attack[$i])?0:$attack[$i]) - (empty($shield[$i])?0:$shield[$i]) - (empty($activity[$i])?0:$activity[$i]);
        	$out[$i] = array(
	        	'money'=>(empty($money[$i])?0:$money[$i]),
	        	'spins'=>(empty($spins[$i])?0:$spins[$i]),
	        	'steal'=>(empty($steal[$i])?0:$steal[$i]),
	        	'attack'=>(empty($attack[$i])?0:$attack[$i]),
	        	'shield'=>(empty($shield[$i])?0:$shield[$i]),
	        	'activity'=>(empty($activity[$i])?0:$activity[$i]),
	        	'count'=>(empty($count[$i])?0:$count[$i]),
	        	'nothing'=>$nothing,
	        	'money1'=>(empty($money1[$i])?0:$money1[$i]),
	        	'money2'=>(empty($money2[$i])?0:$money2[$i]),
	        	'money3'=>(empty($money3[$i])?0:$money3[$i]),
	        	'money4'=>(empty($money4[$i])?0:$money4[$i]),
	        	'money5'=>(empty($money5[$i])?0:$money5[$i]),
	        	'money6'=>(empty($money6[$i])?0:$money6[$i]),
	        );
        }

        $data['list'] = $out;
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'slotLevelStatistics';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 宝藏探索数据统计
     * @return string
     * Created by: hss
     * Created on: 2020/8/11 15:42
     */
    public function treasureSlotSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	
    	$type = ['slot'=>1011,'king3'=>1012,'fox'=>1013,'king2'=>1014,'crown3'=>1015,'king1'=>1016,'spade3'=>1017,'heart3'=>1018,'block3'=>1019,'spade_heart_block'=>1020,'none'=>1021,'slot1'=>1022,'slot2'=>1023,'slot3'=>1024,'slot4'=>1025,'slot5'=>1026,'slot6'=>1027,'slot7'=>1028];
    	$ret = [];
    	foreach($type as $key => $val){
    		$ret[$key] = $this->treasureSlotTb($date,$val);
    	}
    	
    	$out = [];
    	$progres = 10;
    	for($i = 1; $i <= $progres; $i++){
    		foreach($type as $key => $val){
	    		$out[$i][$key] = empty($ret[$key][$i])?0:$ret[$key][$i];
	    	}
    	}
    	
    	$data['list'] = $out;
    	
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'treasureSlotSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    public function treasureSlotTb($date,$type,$uid = 0){
    	//$tbSta = otable::Assetslog(date("Ymd",strtotime($date)));
    	$where = '';
    	if(!empty($uid)){
    		$where = " AND uid = {$uid}";
    	}
    	if(!empty($levelId)){
    		$where = " AND levelId = {$levelId}";
    	}

    	//if(in_array($type,[1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028])){
    	//	$sql = "SELECT reason,count(*) as count FROM {$tbSta} WHERE rid = {$type} AND type = 'money' AND crease = '+' {$where} GROUP BY reason";
    	//}else{
    	//	return [];
    	//}

    	if(!in_array($type,[1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028])){
            return [];
        }

    	$sql = "SELECT reason,count(*) as count FROM %s WHERE rid = {$type} AND type = 'money' AND crease = '+' {$where} GROUP BY reason";
        //$ret = oo::commonOprDb('log')->getAll($sql,1);

        $ret = $this->getAssLogsWithAllTable($sql, date("Ymd",strtotime($date)));
    	
        $temp = [];
        foreach($ret as $key => $val){
            if(!isset($temp[$val['reason']])){
                $temp[$val['reason']] = $val['count'];
            }
            $temp[$val['reason']] += $val['count'];
        }
        return $temp;
    }
    
    /**
     * 宝藏探索关卡统计
     * @return string
     * Created by: hss
     * Created on: 2020/8/11 15:42
     */
    public function treasureSlotLevelSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	//$tbSta = otable::Assetslog($date);
    	//$sql = "SELECT reason,count(*) as count FROM (SELECT uid,max(reason) AS reason FROM {$tbSta} WHERE rid in(1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028) AND type = 'money' AND crease = '+' GROUP BY uid) AS a GROUP BY reason";
    	//$ret = oo::commonOprDb('log')->getAll($sql,1);
    	$sql = "SELECT reason,count(*) as count FROM (SELECT uid,max(cast(reason as UNSIGNED INTEGER)) AS reason FROM %s WHERE rid in(1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028) AND type = 'money' AND crease = '+' GROUP BY uid) AS a GROUP BY reason";
        $ret = $this->getAssLogsWithAllTable($sql, $date);
    	
    	$out = [];
    	foreach($ret as $key => $row){
            $out[$row['reason']] += $row['count'];
    	}
    	
    	$data['list'] = $out;
    	
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'treasureSlotLevelSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 规则礼包统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/8/26 11:52
     */
    public function GiftEventSta($date = ''){ 
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	
    	$out = [];
    	$types = [1=>'入口点击',2=>'自动弹出',3=>'购买点击',4=>'购买成功',5=>'购买失败'];
    	foreach([1,2] as $sid){
    		foreach($types as $type => $name){
    			$out[$sid][$type] = oo::commonOprRedis("Statistics")->hgetall(okeys::GiftEventSta($sid,$type));
    			
    			oo::commonOprRedis("Statistics")->delete(okeys::GiftEventSta($sid,$type));
    		}
    	}
    	
    	$data['list'] = $out;
    	
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'GiftEventSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 邀请事件上报 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/8/26 11:52
     */
    public function inviteEventSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	
    	$out = [];
    	$types = [1=>'邀请按钮点击',2=>'发送邀请',3=>'邀请成功'];
    	foreach($this->sidList as $sid){
    		foreach($types as $type => $name){
    			$out[$sid][$type] = oo::commonOprRedis("Statistics")->hgetall(okeys::inviteEventSta($sid,$type));
    			oo::commonOprRedis("Statistics")->delete(okeys::inviteEventSta($sid,$type));
    		}
    	}
    	
    	$data['list'] = $out;
    	
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'inviteEventSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }

    /**
     * 分享事件上报 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/8/26 11:52
     */
    public function shareEventSta($date = ''){
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }
        $out = [];
        $types = [1=>'FB',2=>'MESSAGE'];//FB MESSAGE
        foreach($this->sidList as $sid){
            foreach($types as $type => $name){
                foreach([1=>"分享按钮点击",2=>"发送分享",3=>"领奖"] as $event => $say){
                    $out[$sid][$type][$event] = oo::commonOprRedis("Statistics")->hgetall(okeys::shareEventSta($sid,$type,$event));
                    oo::commonOprRedis("Statistics")->delete(okeys::shareEventSta($sid,$type,$event));
                }
            }
        }
        $data['list'] = $out;
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
        $type = 'shareEventSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 关卡分布统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/9/2 12:08
     */
    public function levelSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd');
    	}

    	//累计
    	$tb = otable::gh_gameserver(1);
    	$sql = "SELECT levelId,COUNT(*) AS count FROM {$tb} GROUP BY levelId";
    	$ret = oo::commonOprDb('slavedb')->getAll($sql,1);
    	$out = [];
    	foreach($ret as $row){
    		$out[$row['levelId']] = $row['count'];
    	}
    	$data['list'] = $out;

        //活跃
        $ret = oo::commonOprModel('statistics')->getAllPlayer($date, 2);
        $where = '';
        if(!empty($ret)){
            $uidStr = implode(",",$ret);
            $where .= " AND mid in($uidStr)";
        }
        $sql = "SELECT levelId,COUNT(*) AS count FROM {$tb} WHERE 1=1 {$where} GROUP BY levelId";
        $ret = oo::commonOprDb('slavedb')->getAll($sql,1);
        $out = [];
        foreach($ret as $row){
            $out[$row['levelId']] = $row['count'];
        }
        $data['listActive'] = $out;
    	
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'levelSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 每日金币、体力、盾牌存量统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/9/4 10:27
     */
    public function todayStockSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	
    	$tb = otable::gh_gameserver(1);
    	$sql = "SELECT sum(money) AS sumMoney,sum(spins) AS sumSpins,sum(shield) AS sumShield,avg(money) AS avgMoney,avg(spins) AS avgSpins,avg(shield) AS avgShield,sum(diamond) as sumDiamond,avg(diamond) AS avgDiamond FROM {$tb}";
    	$ret = oo::commonOprDb('slavedb')->getOne($sql,1);
    	
    	$data['sumMoney'] = $ret['sumMoney'];
    	$data['sumSpins'] = $ret['sumSpins'];
        $data['sumShield'] = $ret['sumShield'];
        $data['sumDiamond'] = $ret['sumDiamond'];
    	$data['avgMoney'] = $ret['avgMoney'];
    	$data['avgSpins'] = $ret['avgSpins'];
        $data['avgShield'] = $ret['avgShield'];
        $data['avgDiamond'] = $ret['avgDiamond'];

    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'todayStockSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 小丑卡统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/10/20 11:12
     */
    public function jokerCardSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	
    	$data['list'] = oo::commonOprRedis("Statistics")->hgetall(okeys::JokerCardSta());
    	
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'jokerCardSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
        
        //统计后重置
        oo::commonOprRedis('Statistics')->delete(okeys::JokerCardSta());
    }
    
    /**
     * 统计-体力分布统计（活跃） 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/10/27 12:18
     */
    public function todaySpinsSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	$tb = otable::gh_gameserver(1);
    	$spinsRange = array(
        	[1,50],
        	[51,100],
        	[101,500],
        	[501,1000],
        	[1001,2000],
        	[2001,3000],
        	[3001,4000],
        	[4001,5000],
        	[5001,10000],
        	[10001,20000],
        	[20001,30000],
        	[30001,100000000],
        );
        $type =2;
        $ret = oo::commonOprModel('statistics')->getAllPlayer($date, $type, []);
		$uidStr = implode(",",$ret);
		
        $out = $out2 = [];
        foreach($spinsRange as $key => $row){
        	$start = $row[0];
        	$end = $row[1];
        	$sql = "SELECT count(*) as count FROM {$tb} WHERE spins<={$end} AND spins >= {$start} AND mid in(".$uidStr.")";
	        $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
        	$out[$start."-".$end] = intval($ret['count']);
            $sql = "SELECT count(*) as count FROM {$tb} WHERE spins<={$end} AND spins >= {$start}";
            $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
            $out2[$start."-".$end] = intval($ret['count']);
        }

        $data['list'] = $out;
        $data['listTotal'] = $out2;
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'todaySpinsSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }
    
    /**
     * 商城促销统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/11/2 14:27
     */
    public function shopDiscountSta($date = ''){
    	if(empty($date)){
    		$date = date('Ymd',strtotime('-1 day'));
    	}
    	$ret = oo::commonOprRedis("Statistics")->hgetall(okeys::shopDiscountSta());
    	$ret2 = oo::commonOprRedis("Statistics")->hgetall(okeys::shopDiscountSta('price'));
    	$data['number'] = count($ret);//人数
    	$data['count'] = array_sum($ret);//商品次数
    	$data['price'] = array_sum($ret2);//商品金额
    	
    	$data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
    	$type = 'shopDiscountSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
        
        //统计后重置
        oo::commonOprRedis('Statistics')->delete(okeys::shopDiscountSta());
        oo::commonOprRedis('Statistics')->delete(okeys::shopDiscountSta('price'));
    }

    /**
     * 每日体力盈亏统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/12/5 15:26
     */
    public function todaySpinsAddLowSta($date = '',$start_level = 0,$end_level = 0){
        if(empty($date)){
            $date = date("Ymd",time());
        }
        $sql = "set time_zone='+0:00'";
        oo::commonOprDb('log')->query($sql);

        $where = '';
        if($start_level && $end_level){
            $where .= " AND levelId >= {$start_level} AND levelId <= {$end_level}";
        }

        $sql = $this->getAllLogSql($date,"uid,last_num,max(time)","type = 'spins' {$where}","","GROUP BY uid");
        $endRet = oo::commonOprDb('log')->getAll($sql,MYSQLI_ASSOC);

        $sql = $this->getAllLogSql($date,"uid,last_num,num,min(time),crease","type = 'spins' {$where}","","GROUP BY uid");
        $startRet = oo::commonOprDb('log')->getAll($sql,MYSQLI_ASSOC);

        $endNumArr = [];
        foreach($endRet as $row){
            $uid = $row['uid'];
            $endNumArr[$uid] = $endRet['last_num'];
        }

        $moveArr = [];
        foreach($startRet as $row){
            $uid = $row['uid'];
            if($row['crease'] == '+'){
                $number = $row['last_num'] - $row['num'];
            }else{
                $number = $row['last_num'] + $row['num'];
            }
            $moveNum = $endNumArr[$uid] - $number;
            $moveArr[$uid] = $moveNum;
        }
        //筛选区间
        $section = [-50000,-10000,-5000,-1000,-500,-200,-100,-50,50,100,200,500,1000,5000,10000,50000];
        $sectionTotal = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
        $sectionPeople = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
        foreach($moveArr as $uid => $num){
            foreach($section as $k => $endNum){
                if($num <= $endNum){
                    $sectionTotal[$k] += $num;
                    $sectionPeople[$k]++;
                    break;
                }
            }
        }

        return ['section'=>$section,'sectionTotal'=>$sectionTotal,'sectionPeople'=>$sectionPeople];
    }

    /**
     * 每日体力盈亏统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/12/5 15:26
     */
    public function todaySpinsAddLowSta2($date = ''){
        ini_set('memory_limit', '4048M');
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }
        $tb = otable::gh_gameserver(1);
        $sql = "SELECT mid as uid,spins,levelId,money,diamond,shield FROM {$tb}";
        $ret = oo::commonOprDb('slavedb')->getAll($sql,MYSQLI_ASSOC);

        $mode = 10;
        if(count($ret) >= 1000000){
            $mode = 1000;
        }else if(count($ret) >= 10000000){
            $mode = 10000;
        }
        $data = [];
        foreach($ret as $row){
            $uid = $row['uid'];
            $k = $uid % $mode;
            $data[$k][$uid]['num'] = $row['spins'];
            $data[$k][$uid]['levelId'] = $row['levelId'];
            $data[$k][$uid]['money'] = $row['money'];
            $data[$k][$uid]['diamond'] = $row['diamond'];
            $data[$k][$uid]['shield'] = $row['shield'];
        }
        $tb = otable::TodaySpinsLog($date);
        for($i = 0; $i < $mode; $i++){
            $sql = "INSERT INTO {$tb} (uid,num,levelId,money,diamond,shield) VALUES ";
            foreach ($data[$i] as $uid => $row){
                $num = $row['num'];
                $levelId = $row['levelId'];
                $money = $row['money'];
                $diamond = $row['diamond'];
                $shield = $row['shield'];
                $sql .= "('{$uid}','{$num}','{$levelId}','{$money}','{$diamond}','{$shield}'),";
            }
            $sql = trim($sql,",");
            oo::commonOprDb('log')->query($sql);
        }
    }

    /**
     * 每日卡片发放产出统计 保存到数据库 & 金卡每日发放
     * @return string
     * Created by: hss
     * Created on: 2020/12/8 11:52
     */
    public function cardGrantSta($date = ''){
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }

        //msg:Got a packet bigger than 'max_allowed_packet' bytes; #原因是插入数据库数据太大
        //set global max_allowed_packet = 1048576*10 #我现在设置临时的 数据库重启失效

        $tb = otable::cardinfo_config();
        $sql = "SELECT * FROM {$tb}";
        $ret = oo::commonOprDb('slavedb')->getAll($sql,1);
        $arr = [];
        foreach ($ret as $k=>$v){
            $arr[$v['ciid']] = $v;
        }

        $select = 'reason';
        $where = 'rid = 3001 ';
        $sql = $this->getAllLogSql($date,$select,$where);
        $ret = oo::commonOprDb('log')->getAll($sql,MYSQLI_ASSOC);
        $out = $outGold = [];
        foreach($ret as $row){
            if(strpos($row['reason'],':')!==false){
                $reason = explode(":",$row['reason']);
                $temp = explode(",",$reason[1]);
            }else{
                $temp = explode(",",$row['reason']);
            }

            foreach($temp as $ciid){
                $out[$ciid]++;
                if($arr[$ciid]['grade'] == 2){
                    $outGold[$ciid]++;
                }
            }
        }
        $data['card'] = $out;//所有卡片每日发放统计
        $data['cardGold'] = $outGold;//金卡每日发放统计

        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
        $type = 'cardGrantSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('statistics')->query($sql);
    }

    /**
     * 好友召回统计 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/12/17 11:27
     */
    public function friendRecallSta($date = ''){
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }
        //1点击召回按钮数量 2点击消息数量 3成功召回数量
        $ret = oo::commonOprRedis("Statistics")->hGetAll(okeys::friendRecallSta(1));
        $data['clickBtnSum'] = array_sum($ret);
        $ret = oo::commonOprRedis("Statistics")->hGetAll(okeys::friendRecallSta(2));
        $data['clickMessSum'] = array_sum($ret);
        $ret = oo::commonOprRedis("Statistics")->hGetAll(okeys::friendRecallSta(3));
        if($ret){
            $data['successSum'] = array_sum($ret);
            $data['uids'] = $ret;
        }else{
            $data['successSum'] = 0;
            $data['uids'] = [];
        }

        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
        $type = 'friendRecallSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('statistics')->query($sql);

        oo::commonOprRedis('Statistics')->delete([
            okeys::friendRecallSta(1),
            okeys::friendRecallSta(2),
            okeys::friendRecallSta(3)
        ]);
    }

    /**
     * 好友召回留存统计
     * @return string
     * Created by: hss
     * Created on: 2020/12/17 11:27
     */
    public function friendRecallremainSta($date = ''){
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }
        $tb = otable::staData();
        $data = [];
        foreach([1,3,7,30] as $dayNum){
            $days = date("Ymd",strtotime($date . " -{$dayNum} day"));
            $loginUser = oo::commonOprModel('statistics')->getAllPlayer($date, 2);
            $sql = "SELECT * FROM {$tb} WHERE date = '{$days}' AND type = 'friendRecallSta'";
            $ret = oo::commonOprDb('statistics')->getOne($sql,MYSQLI_ASSOC);
            $ret['data'] = json_decode($ret['data'],true);

            if(!empty($ret['data']['uids'])){
                $uids = array_keys($ret['data']['uids']);
                $intersect = array_intersect($loginUser, $uids);//交集玩家
                $remain = empty(count($uids)) ? 0 :  count($intersect) / count($uids);//留存率
                $remain = round($remain, 4) * 100;//留存率
            }else{
                $remain = 0;
            }
            $data['remain_'.$dayNum] = $remain;
        }

        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
        $type = 'friendRecallremainSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('statistics')->query($sql);
    }

    /**
     * 当天人均通关数（当天通关数 / 当天登陆用户数） 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/1/15 18:33
     */
    public function saveTodayUpLvelSta(){
        $date = date('Ymd');
        //通过人数 以及 关卡数
        $ret = oo::commonOprRedis('games')->hGetAll(okeys::todayDataRank('level'));
        $data = $uidArr = [];
//        foreach($ret as $uid => $v){
//            $uidArr[] = $uid;
//        }
        if(!empty($ret)){
//            $uidStr = implode(",",$uidArr);//在考虑用不用，还是都查询出来
            $sql = $this->getAllLogSql($date,"uid,min(levelId) as levelId","1=1",'','GROUP BY uid');
            $logRet = oo::commonOprDb('log')->getAll($sql,MYSQLI_ASSOC);
            $uidMinLevel = [];
            foreach($logRet as $row){
                $uidMinLevel[$row['uid']] = $row['levelId'];
            }
            $total = $count = 0;
            //新增的区间统计
            $section = [
                [1,1],
                [2,2],
                [3,3],
                [4,5],
                [6,10],
                [11,20],
                [21,30],
                [31,60],
                [61,90],
                [91,120],
                [121,150],
            ];
            $out = [];
            foreach($ret as $uid => $num){
                $total += $num;
                $count++;
                $uidLevel = $uidMinLevel[$uid];
                foreach($section as $key => $row){
                    if($uidLevel >= $row[0] && $uidLevel <= $row[1]){
                        $out[$key]['total'] += $num;
                        $out[$key]['count']++;
                        break;//只会跳出当前循环
                    }
                }
            }
            $data['total'] = $total;
            $data['count'] = $count;
            $data['list'] = $out;
        }
        $data = json_encode($data);
        $tb = otable::saveTodayUpLvelSta();
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$data}')";
        oo::commonOprDb('statistics')->query($sql);
    }

    /**
     * 统计特殊收集活动的特殊道具概率 保存到数据库
     * @return string
     * Created by: hss
     * Created on: 2020/1/18 15:50
     */
    public function superCollectSta($date = ''){
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }
        $tb = otable::activityConf();
        $sql = "SELECT * FROM {$tb} WHERE type = 'super_collect' ORDER BY id DESC LIMIT 1";
        $activityConfRet = oo::commonOprDb('slavedb')->getOne($sql,1);
        $data = [];
        //预先添加多了活动的时候无法判断
        //if($date <= date("Ymd",$activityConfRet['end_time']) && $date >= date("Ymd",$activityConfRet['start_time'])){
            $i = 3;
            while($i){
                $sql = $this->getAllLogSql($date,"COUNT(*) as count,levelId","rid = 204 AND reason LIKE '%super_collect获得进度值:{$i}'","","GROUP BY levelId");
                $ret = oo::commonOprDb('log')->getAll($sql,1);
                foreach($ret as $row){
                    $data['superCollect_'.$i][$row['levelId']] += $row['count'];
                }
                $i--;
            }
        //}
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
        $type = 'superCollectSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('statistics')->query($sql);
    }

    public function getAllLogSql($date = '',$select = '',$where = '',$order = '',$group = '',$exc = []){
        $tb = otable::Assetslog($date);
        $sql = '';
        if(empty($where)){
            $where = "1=1";
        }
        $k = 1;
        for($i = 0; $i < 10; $i++){
            if(in_array($i,$exc)){
                continue;
            }
            if(is_array($where)){
                if(empty($where[$i])){
                    $tempWhere = '1=1';
                }else{
                    $tempWhere = $where[$i];
                }
            }else{
                $tempWhere = $where;
            }
            $sql .= (($k == 1?"":" union all ")." SELECT {$select} FROM {$tb}_{$i}  WHERE {$tempWhere} {$order} {$group} ");
            $k=0;
        }
        return $sql;
    }

    public function getTypes() {
         return $this->reason;
    }
    
    public function moneyAddType(){
        return [
        	1 =>"老虎机-摇奖",//获取money,spins.shield 消耗spins
        	2 =>"老虎机-打成功获得",//+money
		    3 =>"老虎机-打失败获得",//+money
		    4 =>"老虎机-偷取获得",//+money
		    9 =>"老虎机-机器人补发",//+money
		    10=>"老虎机-倍率系统补发",//+money
		    11=>"老虎机-宠物增益",//+money 
		    15 =>"签到-每日签到",//+money &&|| +spins
		    16 =>"签到-签到进度",//
		    20 =>"矿岛-收益",
		    22 =>"矿岛-矿工游戏",//+money,+spins,-money
		    30 =>"卡组-收集满",
		    31 =>"卡组-进度",
		    40 =>"转盘-夺宝转盘",
		    41 =>"转盘-大转盘",
		    50 =>"好友-好友赠送",
		    51 =>"好友-好友邀请",
		    52 =>"好友-好友招归",
		    60 =>"任务-每日任务",
		    61 =>"任务-每日任务进度",
		    80 =>"升级-通关奖励",
		    84 =>"升级-最大关奖",//+money  +spins
		    101 =>"新手引导",
		    102 =>"成就获得",
		    103 =>"用户回归",
		    104 =>"更新礼包",
		    105 =>"分享奖励",
		    106 =>"聊天礼物",
		    107 =>"通关奖励",
		    108 =>"广告获取",
		    110 =>"兑换码",
			202 =>"活动-节日收集",
    		203 =>"活动-建筑大师",
    		204 =>"活动-金蛋进度",
    		208 =>"活动-排行榜",
		    209 =>"活动-排行榜阶段奖励",
		    210 =>"活动-气球",
		    211 =>"活动-偷打活动",
		    212 =>"活动-JackPot活动",
		    213 =>"活动-宝藏活动",
		    300 =>"充值-礼包",
		    301 =>"充值-限时特惠",
		    302 =>"充值-优惠礼包",
		    303 =>"充值-常规礼包",
		    304 =>"充值-首充礼包",
		    305 =>"充值-节日礼包",
		    310 =>"充值-商城购买",//+spins||+money
		    350 =>"vip-开通奖励",
		    351 =>"vip-每日奖励",
		    352 =>"vip-每周奖励",
		    450 =>"礼包-连环礼包",
		    997 =>"系统补偿",
		    998 =>"系统补发",
		    999 =>"后台修改",
		    1002 => "宝藏活动-获得",
        ];
    }
    
    public function moneyLowType(){
        return [
            7 =>"老虎机-被偷消耗",//-money
            21 =>"矿岛-消耗",
            22 =>"矿岛-矿工游戏",//+money,+spins,-money
            81 =>"升级-新建建筑",//-money +star
    		82 =>"升级-修复建筑",//-money +star
    		86 =>"升级-打折活动",//-money +star
    		400 =>"购买-宝箱",
    		401 =>"购买-喇叭",
    		1003 =>"宝藏活动-消耗",
        ];
    }
    
    public function sipnAddType(){
        return [
        	1 =>"老虎机-摇奖",//获取money,spins.shield 消耗spins
        	5 =>"老虎机-盾牌转换获得",//+spins
        	15 =>"签到-每日签到",//+money &&|| +spins
    		16 =>"签到-签到进度",//
    		22 =>"矿岛-矿工游戏",//+money,+spins,-money
    		30 =>"卡组-收集满",
		    31 =>"卡组-进度",
		    42 =>"转盘-金体转盘",
		    50 =>"好友-好友赠送",
		    51 =>"好友-好友邀请",
		    52 =>"好友-好友招归",
		    60 =>"任务-每日任务",
		    61 =>"任务-每日任务进度",
		    80 =>"升级-通关奖励",
		    81 =>"升级-新建建筑",//-money +star
		    82 =>"升级-修复建筑",//-money +star
		    83 =>"升级-帮助修复",//+star
		    84 =>"升级-最大关奖",//+money  +spins
		    101 =>"新手引导",
		    102 =>"成就获得",
		    103 =>"用户回归",
		    104 =>"更新礼包",
		    105 =>"分享奖励",
		    106 =>"聊天礼物",
		    107 =>"通关奖励",
		    108 =>"广告获取",
		    109 =>"FB绑定",
		    110 =>"兑换码",
		    111 =>"自动恢复",//+spins
		    202 =>"活动-节日收集",
		    203 =>"活动-建筑大师",
		    204 =>"活动-金蛋进度",
		    208 =>"活动-排行榜",
		    209 =>"活动-排行榜阶段奖励",
		    210 =>"活动-气球",
		    211 =>"活动-偷打活动",
		    212 =>"活动-JackPot活动",
		    213 =>"活动-宝藏活动",
		    300 =>"充值-礼包",
		    301 =>"充值-限时特惠",
		    302 =>"充值-优惠礼包",
		    303 =>"充值-常规礼包",
		    304 =>"充值-首充礼包",
		    305 =>"充值-节日礼包",
		    310 =>"充值-商城购买",//+spins||+money
		    330 =>"月卡-体力月卡",
		    350 =>"vip-开通奖励",
		    351 =>"vip-每日奖励",
		    352 =>"vip-每周奖励",
		    450 =>"礼包-连环礼包",
		    997 =>"系统补偿",
		    998 =>"系统补发",
		    999 =>"后台修改",
        ];
    }
    public function sipnLowType(){
        return [
            1 =>"老虎机-摇奖",//获取money,spins.shield 消耗spins
        ];
    }

    public function diamondAddType(){
        return [
		    310 =>"充值-商城购买",//+spins||+money
        ];
    }

    public function diamondLowType(){
        return [
        	12 =>"钻石兑换-钻石消耗",//获取money,spins.shield 消耗spins
        ];
    }

    /**
     *	计算所有玩家
     *	type 1 新注册 其他登陆
     *  sid 1 安卓 2 ios
     *  lid 1 FB 2 游客
     */
    public function getAllPlayer($date, $type, $sidList = 0, $_lidEnd = 0)
    {
        //登陆和新增相关key
        $newPlayerKeyList = $this->newPlayerKeyList;

        $loginPlayerKeyList = $this->loginPlayerKeyList;

        $arr = ($type == 1) ? $newPlayerKeyList : $loginPlayerKeyList;
        $total = array();//人数0
        //如果sidList为空或者为999,则默认全部的sid
        if(empty($sidList) || is_array($sidList) && in_array(999, $sidList)) {
            //包列表
            $sidList = [1,2];
        }else {
            if(!is_array($sidList)) {
                $sidList = array($sidList);
            }
        }

        foreach ($sidList as $sid) {
            $tmpArr = $this->getAllPlayerOnce($arr, $date, $sid, $_lidEnd);
            $total = array_merge($tmpArr, $total);
        }
		
		$total = array_filter($total);//去掉空元素
        return array_unique($total);
    }

    /**
     * 获取一个sid的总人数
     * @param $arr
     * @param $date
     * @param $sid
     * @return array
     */
    private function getAllPlayerOnce($arr, $date, $sid, $_lidEnd = 0)
    {
    	$redisConfig = 'statistics';
    	if(strtotime($date) <= 1593647999){
    		$redisConfig = 'games';
    	}
        $total = [];
        if(empty($_lidEnd)){
        	$_lidEnd = 7;
        	for ($i=1; $i <= $_lidEnd; $i++) {
	            for ($j=1; $j <= 2; $j++) {
	                $key = $arr[$i][$j].':'.$sid.'_1:'.$date;
	                $members = oo::commonOprRedis($redisConfig)->sMembers($key);
	                $total = array_merge($total, $members);
	            }
	        }
        }else{
        	for ($j=1; $j <= 2; $j++) {
                $key = $arr[$_lidEnd][$j].':'.$sid.'_1:'.$date;
                $members = oo::commonOprRedis($redisConfig)->sMembers($key);
                $total = array_merge($total, $members);
            }
        }
        
        return $total;
    }

    /**
     * 统计邮件
     * Created by: Owen
     * Created on: 2020/11/21 16:26
     */
    public function sendMailSta(){
        $date = date("Ymd");
        $tb   = otable::SendMailSta();
        $num  = oo::commonOprRedis('Statistics')->incr(okeys::SendMailSta());
        oo::commonOprDb('statistics')->query("INSERT INTO {$tb} VALUES ('{$date}','{$num}')");
        oo::commonOprRedis('Statistics')->delete(okeys::SendMailSta());
    }

    /**
     * 参与率统计
     */
    public function saveParticipation($day = '') {
        if(empty($day)) {
            $day = date('Ymd', strtotime('-1 day'));
        }
        //dau玩家列表
    	$allUsers = oo::commonOprModel('statistics')->getAllPlayer($day, 2, [1, 2]);
        $allNum = count($allUsers);
        //宠物活动参与数据
        $this->savePetParticipation($day, $allNum);
        //黄金矿工小游戏活动参与数据
        $this->saveMiningParticipation($day, $allNum);
        //大转盘活动参与数
        $this->saveSlotParticipation($day, $allNum);
        //夺宝活动戏参与数据
        $this->saveLuckydrawpation($day, $allNum);
        //推金币小游戏活动参与数据
        $this->savecoinDozer($day, $allUsers);
        //金币老虎机活动参与数据
        $this->saveTreasure($day, $allNum);
    }

    /**
     * 宝藏活动参与数据
     * @param int $day
     * @param int $allNum
     */
    public function saveTreasure($day, $allNum = 0){
        if(empty($day)) {
            $day = date('Ymd', strtotime('-1 day'));
        }
        $key = okeys::participationLog($day);
        $type = 'treasure';
        $openNum = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 0)); //宝藏活动
        oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 0));

        $index         = oo::commonOprModel('participation')->getIndexByType($type);
        $totalDuration = oo::commonOprModel('participation')->playTotalDuration($day, $index);
        $totalTimes    = oo::commonOprModel('participation')->playTotalTimes($day, $index);

        $canNum = $allNum;
        $tb = otable::participation();
        $sql = "REPLACE INTO {$tb} VALUES({$day},{$allNum},'{$type}',{$canNum},{$openNum},1, {$totalDuration}, {$totalTimes})";
        oo::commonOprDb('statistics')->query($sql);
    }

    /**
     * 夺宝活动参与数据
     * @param int $day
     * @param int $allNum
     */
    public function saveLuckydrawpation($day, $allNum = 0){
        if(empty($day)) {
            $day = date('Ymd', strtotime('-1 day'));
        }
    	//$sql = "SELECT rid, count(*) as count FROM %s WHERE rid = 403 GROUP BY uid";
        //$ret = $this->getAssLogsWithAllTable($sql, $day);
        //$openNum = 0;
        //foreach($ret as $val){
        //    $openNum += 1;
        //}

        $key = okeys::participationLog($day);
        $type = 'luckydraw';
        $openNum = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 1)); //夺宝活动
        oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 1));

        $index         = oo::commonOprModel('participation')->getIndexByType($type);
        $totalDuration = oo::commonOprModel('participation')->playTotalDuration($day, $index);
        $totalTimes    = oo::commonOprModel('participation')->playTotalTimes($day, $index);

        $canNum = $allNum;
        $tb = otable::participation();
        $sql = "REPLACE INTO {$tb} VALUES({$day},{$allNum},'{$type}',{$canNum},{$openNum},1, {$totalDuration}, {$totalTimes})";
        oo::commonOprDb('statistics')->query($sql);
    }

    /**
     * 邀请领取进度奖励配置
     * @param string $day
     * @return bool
     */
    public function saveInviteStageReward($day = '') {
        if(empty($day)){
            $day = date('Ymd', strtotime('-1 day'));
        }
        $key = okeys::inviteStageSuccReward($day);
        $cacheArr = oo::commonOprRedis('Statistics')->hGetAll($key);
        if(empty($cacheArr)){
            return true;
        }
        $tb = otable::inviteStageSuccReward();
        $sql = '';
        foreach($cacheArr as $k => $v){
            $sql .= "({$day},{$k},{$v}),";
        }
        $sql = "REPLACE INTO {$tb} (day,stage,num) VALUES ". rtrim($sql, ',');
        $ret = oo::commonOprDb('statistics')->query($sql);
        if($ret){
            oo::commonOprRedis('Statistics')->delete($key);
        }
        return true;
    }

    /**
     * 大转盘活动参与数据
     * @param int $day
     * @param array $allNum
     */
    public function saveSlotParticipation($day, $allNum = 0){
        if(empty($day)) {
            $day = date('Ymd', strtotime('-1 day'));
        }
        /**
    	$sql = "SELECT rid, count(*) as count FROM %s WHERE rid in(41, 42, 43) GROUP BY rid, uid";
        $ret = $this->getAssLogsWithAllTable($sql, $day);
        $open0Num = $open1Num = 0;
        foreach($ret as $val){
            if($val['rid'] = 41){
                $open0Num += 1;
            }else{
                $open1Num += 1;
            }
        }
        */
        
        $key = okeys::participationLog($day);
        $type = 'turntable';
        $open0Num = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 0)); //免费大转盘
        $open1Num = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 1)); //付费大转盘
        oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 0));
        oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 1));

        $index         = oo::commonOprModel('participation')->getIndexByType($type);
        $totalDuration = oo::commonOprModel('participation')->playTotalDuration($day, $index);
        $totalTimes    = oo::commonOprModel('participation')->playTotalTimes($day, $index);

        $canNum = $allNum;
        $tb = otable::participation();
        $sql = "REPLACE INTO {$tb} VALUES({$day},{$allNum},'{$type}',{$canNum},{$open0Num},0,{$totalDuration},{$totalTimes}),({$day},{$allNum},'turntable',{$canNum},{$open1Num},1,{$totalDuration},{$totalTimes})";
        oo::commonOprDb('statistics')->query($sql);
    }

    /**
     * 黄金矿工小游戏参与数据
     */
    public function saveMiningParticipation($day, $allNum = 0){
        if(empty($day)) {
            $day = date('Ymd', strtotime('-1 day'));
        }
        //$tb = otable::MiningGameDateSta();
        //$sql = "SELECT * FROM {$tb} WHERE date='{$day}'";
        //$data = oo::commonOprDb('statistics')->getOne($sql, 1);
        //if(empty($data['data'])){
        //    return;
        //}
        //$data = json_decode($data['data'], true);
        //$openNum = isset($data[1], $data[1]['play']) ? $data[1]['play'] : 0; //统计第一关即可
        $canNum = $allNum;

        $key = okeys::participationLog($day);
        $type = 'mining';
        $openNum = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 0)); //黄金矿工
        oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 0));


        $index         = oo::commonOprModel('participation')->getIndexByType($type);
        $totalDuration = oo::commonOprModel('participation')->playTotalDuration($day, $index);
        $totalTimes    = oo::commonOprModel('participation')->playTotalTimes($day, $index);

        $tb = otable::participation();
        $sql = "REPLACE INTO {$tb} VALUES({$day},{$allNum},'{$type}',{$canNum},{$openNum},0,{$totalDuration},{$totalTimes})";
        oo::commonOprDb('log')->query($sql);
    }

    /**
     * 宠物参与数据
     */
    public function savePetParticipation($day, $allNum = 0) {
        if(empty($day)) {
            $day = date('Ymd', strtotime('-1 day'));
        }
        $types = ['attack', 'steal'];
        $key = okeys::participationLog($day);
        $tb = otable::participation();
        foreach($types as $type){
            //免费宠物参与偷/打
            $openTotal0 = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 0));
            //付费宠物参与偷/打
            $openTotal1 = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 1));
            oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 0));
            oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 1));

            $canNum = $allNum; //可玩数量
            //偷/打参与数据入库
            $sql = "INSERT IGNORE INTO {$tb} VALUES({$day},{$allNum},'{$type}',{$canNum},{$openTotal0},0, 0, 0),({$day},{$allNum},'{$type}',{$canNum},{$openTotal1},1, 0, 0)";
            oo::commonOprDb('Statistics')->query($sql);
        }
    }

    /**
     * 推金币游戏参与率统计
     */
    public function savecoinDozer($day = '', $allUsers = []) {
        if(empty($day)) {
            $day = date('Ymd', strtotime('-1 day'));
        }
        //$start = strtotime($day);
        //if(empty($start)){
        //    return; //日期错误
        //}
        //$end = $start + 24 * 3600;
        //$tb = otable::gamelog_coindozer();
        ////开启游戏的用户信息
        //$sql = "SELECT * FROM {$tb} where time >= {$start} AND time < {$end} AND type = 1 GROUP BY uid";
        //$tmp = oo::commonOprDb('log')->getAll($sql,1);
        //$openArr = !empty($tmp) ? array_column($tmp, 'time', 'uid') : []; //当日进入推金币游戏玩家列表
        //$openNum = count($openArr);
        $key = okeys::participationLog($day);
        $type = 'coindozer';
        $openNum = (int)oo::commonOprRedis('Statistics')->hGet($key, okeys::participationSubKey($type, 0)); //推金币
        oo::commonOprRedis('Statistics')->hDel($key, okeys::participationSubKey($type, 0));
        //日活玩家
        if(empty($allUsers)){
            $allUsers = oo::commonOprModel('statistics')->getAllPlayer($day, 2, [1, 2]);
        }
        $allNum = count($allUsers); 
        $canNum = 0; //可玩数量

        $config = oo::commonOprModel('config')->getSysCon('CoinDozer', "config");
        foreach($allUsers as $uid){
            if(isset($openArr[$uid]) || $this->checkIfCoinDozerOpen($uid, $config)){
                $canNum++;
                continue;
            }
        }

        $index         = oo::commonOprModel('participation')->getIndexByType($type);
        $totalDuration = oo::commonOprModel('participation')->playTotalDuration($day, $index);
        $totalTimes    = oo::commonOprModel('participation')->playTotalTimes($day, $index);

        $tb = otable::participation();
        $sql = "INSERT IGNORE INTO {$tb} VALUES({$day},{$allNum},'{$type}',{$canNum},{$openNum},0,{$totalDuration},{$totalTimes})";
        oo::commonOprDb('statistics')->query($sql);
        ////删除推金币数据当天数据
        //$tb = otable::gamelog_coindozer();
        ////开启游戏的用户信息
        //$sql = "DELETE FROM {$tb} where time >= {$start} AND time < {$end} AND type = 1";
        //oo::commonOprDb('log')->query($sql);
    }

    /**
     * 推金币游戏当前用户是否达到开启条件
     * @param int $uid
     */
    public function checkIfCoinDozerOpen($uid, $config){
        $config = is_string($config) ? (array)json_decode($config, true) : [];
        if(empty($config)){
            return false;
        }
        $gameCfg = $config['gameCfg'];
        $levelInfo = oo::commonOprModel('member')->getUserLevel($uid);
        $data['isSpecial'] = oo::commonOprModel('member')->isPushCoinsUser($uid)?1:0;
        if($data['isSpecial']){//广告渠道用户
            $thisCfg = $gameCfg['specialCfg'];
        }else{
            $thisCfg = $gameCfg['commonCfg'];
        }
        if($thisCfg['openExp']==1&&$levelInfo['levelId']==$thisCfg['expLevel']){//体验次数
            $allLimit = $thisCfg['freeExpLimit'];
            if($allLimit<=1){//次数不够
                return false;
            }
        }
        //当没有开放体验,或者开放体验等级不满足的情况下,等级不够
        if(($levelInfo['levelId']!=$thisCfg['expLevel']||$thisCfg['openExp']!=1)&&$levelInfo['levelId']<$thisCfg['openLevel']){
            return false;
        }
        return true;
    }

    /**
     * Notes:后台增加老虎机体力统计/老虎机体力关卡概率统计
     * User: Hss
     * Time: 2021/2/2 12:23
     */
    public function slotSpinsSta($date = ''){
        if(empty($date)){
            $date = date('Ymd',strtotime('-1 day'));
        }
        //查询数据库概率
        $tb = otable::slotConfig();
        $sql = "select * from {$tb} where levelId=1 limit 1";
        $conf = oo::commonOprDb('slavedb')->getOne($sql, MYSQLI_ASSOC);
        $ret = json_decode($conf['slotpro'],true);

        $out = [];
        foreach($ret as $row){
            $type = $row['id'];
            $temp = oo::commonOprRedis('statistics')->hgetall(okeys::slotSpinsSta($date,$type));
            $out[$type] = $temp;//不同类型的不同关卡的体力消耗情况
            //删除
            oo::commonOprRedis('statistics')->delete(okeys::slotSpinsSta($date,$type));
        }
        $data['list'] = $out;
        $data = json_encode($data,JSON_NUMERIC_CHECK);
        $tb = otable::staData();
        $type = 'slotSpinsSta';
        $sql = "INSERT INTO {$tb} VALUES('{$date}', '{$type}' ,'{$data}')";
        oo::commonOprDb('default')->query($sql);
    }

    /**
     * Notes:多天流水
     * User: Hss
     * Time: 2021/2/19 11:58
     */
    public function manyDaysLog($uid = 0,$sdate = '',$edate = '',$where = '1=1',$page = []){
        $sdate = date("Ymd",strtotime($sdate));
        $edate = date("Ymd",strtotime($edate));
        $tb = otable::Assetslog($sdate, $uid);
        $sql = "SELECT * FROM {$tb} WHERE {$where}";
        $dateTemp = date("Ymd",strtotime($sdate . " +1 days"));
        while ($dateTemp <= $edate){
            $tb = otable::Assetslog($dateTemp, $uid);
            $sql .= " union all  SELECT * FROM {$tb} WHERE {$where}";
            $dateTemp = date("Ymd",strtotime($dateTemp . " +1 days"));
        }
        //七天前
        $interval = date("Ymd",strtotime("-7 days 0:0:0"));
        $database = "log";
        if(!$this->config->item('oos_debug')){
            if($sdate < $interval && $edate < $interval){
                $database = "log2";
            }
        }

        $ret = oo::commonOprDb($database)->getAll(" SELECT * FROM ( ".$sql ." ) AS a ORDER BY time DESC limit {$page['page']},{$page['limit']}", MYSQLI_ASSOC);
        $ret2 = oo::commonOprDb($database)->getOne(" SELECT count(*) AS count FROM ( ".$sql ." ) AS a", MYSQLI_ASSOC);
        return ['list'=>$ret,'total'=>$ret2['count']];
    }

    /**
     * Notes:资源产销
     * User: Hss
     * Time: 2021/2/23 12:15
     */
    public function assetsRFMSta($date = '',$groupId = 0,$type = 'levelId'){
        if(empty($date)){
            $date = date("Ymd",strtotime("-1 days 0:0:0"));
        }
        if(empty($groupId)){
            $sql = $this->getAllLogSql($date,'type,crease,levelId,sum(num) AS total',"type in('money','spins','diamond')",'','GROUP BY type,crease,levelId');
            $sql = "SELECT type,crease,levelId,sum(total) AS total FROM ( ".$sql." ) AS a GROUP BY type,crease,levelId ";
            $ret = oo::commonOprDb("statistics")->getAll($sql,1);
            return $ret;
        }
        //取出这个分组的用户
        $tb = otable::UserGroupSta();
        $sql = "SELECT uid FROM {$tb} WHERE date = {$date} AND groupId like '%#{$groupId}#%'";
        $ret = oo::commonOprDb("statistics")->getAll($sql,1);
        $uids = [];
        if(!empty($ret)){
            foreach($ret as $row){
                $uids[$row['uid']%10][] = $row['uid'];
            }
            $where = $exc = [];
            for($i = 0; $i < 10; $i++){
                if(empty($uids[$i])){
                    $exc[] = $i;
                }else{
                    $usdStr = implode(",",$uids[$i]);
                    $where[$i] = " uid in ({$usdStr}) AND type in('money','spins','diamond')";
                }
            }
            if($type == "levelId"){
                $sql = $this->getAllLogSql($date,'type,crease,levelId,sum(num) AS total',$where,'','GROUP BY type,crease,levelId',$exc);
                $sql = "SELECT type,crease,levelId,sum(total) AS total FROM ( ".$sql." ) AS a GROUP BY type,crease,levelId ";
            }else{
                $sql = $this->getAllLogSql($date,'type,crease,sum(num) AS total',$where,'','GROUP BY type,crease',$exc);
                $sql = "SELECT type,crease,sum(total) AS total FROM ( ".$sql." ) AS a GROUP BY type,crease ";
            }
            $ret = oo::commonOprDb("statistics")->getAll($sql,1);
            return $ret;
        }
        return [];
    }

    /**
     * Notes:每日存量统计
     * 增加每日不同付费等级（根据RFM模型）玩家的金币/体力/钻石人均存量表格
     * User: Hss
     * Time: 2021/2/24 10:12
     */
    public function stockRFMSta($date = ''){
        if(empty($date)){
            $date = date("Ymd",strtotime("-1 days 0:0:0"));
        }
        $groupList = oo::commonOprModel('config')->getUserGroupConfig2();
        array_multisort(array_column($groupList,'sort'),SORT_ASC,$groupList);
        foreach ($groupList as $key=>$row){
            if(2 != $row['cid']){
                unset($groupList[$key]);
                continue;
            }
            //$groupList[$key]['count'] = max(intval(oo::commonOprRedis('games')->hGet(okeys::UserGroupTotal(),$row['id'])),0);
        }
        $tb = otable::UserGroupSta();
        $TodaySpinsLog = otable::TodaySpinsLog($date);
        $out = [];
        foreach($groupList as $key => $row){
            //取出这个分组的用户
            $sql = "SELECT uid FROM {$tb} WHERE date = {$date} AND groupId like '%#{$row['id']}#%'";
            $ret = oo::commonOprDb("statistics")->getAll($sql,1);
            $uids = [];
            foreach($ret as $vo){
                $uids[] = $vo['uid'];
            }
            if(!empty($uids)){
                $uidsStr = implode(",",$uids);
                $sql = "SELECT AVG(money) AS money,AVG(num) AS spins,AVG(diamond) AS diamond FROM {$TodaySpinsLog} WHERE uid in({$uidsStr})";
                $stockRet = oo::commonOprDb("log")->getOne($sql,1);
                $out[$row['id']] = $stockRet;
            }else{
                $out[$row['id']]['money']=$out[$row['groupId']]['spins']=$out[$row['groupId']]['diamond']=0;
            }
            $groupList[$key]['count'] = count($uids);
        }
        return ['groupList'=>$groupList,'list'=>$out];
    }

    /**
     * Notes:RFM连环礼包收入统计
     * 不同付费等级（根据RFM模型）玩家
     * 只记录超级连环礼包的、付费礼包销售额、购买人数
     * User: Hss
     * Time: 2021/2/24 16:30
     */
    public function serialPackRFMSta($date = ''){
        if(empty($date)){
            $date = date("Ymd",strtotime("-1 days 0:0:0"));
        }
        $stime = strtotime($date . " 0:0:1");
        $etime = strtotime($date . " 23:59:59");
        //获取超级连环礼包活动
        $tb = otable::activityConf();
        $sql = "SELECT * FROM {$tb} WHERE type = 'super_serial_pack' AND end_time >= {$stime} AND {$etime} >= start_time ORDER BY id DESC limit 1";
        $activityConf = oo::commonOprDb('slavedb')->getOne($sql,1);

        $groupList = oo::commonOprModel('config')->getUserGroupConfig2();
        array_multisort(array_column($groupList,'sort'),SORT_DESC,$groupList);
        foreach ($groupList as $key=>$row){
            if(2 != $row['cid']){
                unset($groupList[$key]);
                continue;
            }
        }
        $exc = $out = [];
        if($activityConf){
            $tb = otable::UserGroupSta();
            $summarylistTb = otable::summarylist();
            $payWhiteList = oo::commonOprModel("payment")->payWhiteList();

            //获取活动配置
            $confTb = otable::activityStageRewardConf();
            $sql = "SELECT * FROM {$confTb} WHERE aid = {$activityConf['id']}";
            $confRet = oo::commonOprDb('slavedb')->getOne($sql,1);
            $confRet['extra_reward'] = json_decode($confRet['extra_reward'],1);

            //配置分组
            $confGroup = [];
            $defaultGroup = 0;
            foreach($confRet['extra_reward'] as $k => $row){
                $gid = explode(",",$row['gid']);
                if(in_array(0,$gid)){
                    $defaultGroup = max($gid);
                }
                $confGroup[] = max($gid);
            }
            foreach($groupList as $row){
                //取出这个分组的用户
                $sql = "SELECT uid FROM {$tb} WHERE date = {$date} AND groupId like '%#{$row['id']}#%'";
                $ret = oo::commonOprDb("statistics")->getAll($sql,1);
                $uids = [];
                foreach($ret as $vo){
                    if(!in_array($vo['uid'],$exc) && !in_array($vo['uid'],$payWhiteList)){
                        $uids[] = $vo['uid'];
                    }
                }
                $exc = array_merge($exc,$uids);

                //如果活动配置没有这个分组 分配到默认分组
                if(!in_array($row['id'],$confGroup)){
                    $row['id'] = $defaultGroup;
                }
                if(!empty($uids)){
                    $uidsStr = implode(",",$uids);
                    $gidStr = implode(",",range(721,750));
                    if($this->config->item('oos_debug')){
                        $sql = "SELECT sl_gid,sum(sl_pusd) AS total FROM {$summarylistTb} WHERE sl_status = 2 AND sl_uid in({$uidsStr}) AND sl_pay_time >= {$stime} AND sl_pay_time <= {$etime} AND sl_gid in({$gidStr}) GROUP BY sl_gid";
                    }else{
                        $sql = "SELECT sl_gid,sum(sl_pusd) AS total FROM {$summarylistTb} WHERE sl_status = 2 AND sl_sid <> -1 AND sl_uid in({$uidsStr}) AND sl_pay_time >= {$stime} AND sl_pay_time <= {$etime} AND sl_gid in({$gidStr}) GROUP BY sl_gid";
                    }
                    $temp = oo::commonOprDb('slavedb')->getAll($sql,1);
                    foreach($temp as $tempVo){
                        $out[$row['id']]['total'][$tempVo['sl_gid']] += $tempVo['total'];
                    }
                    if($this->config->item('oos_debug')){
                        $sql = "SELECT sl_gid,count(*) AS count FROM {$summarylistTb} WHERE sl_status = 2 AND sl_uid in({$uidsStr}) AND sl_pay_time >= {$stime} AND sl_pay_time <= {$etime} AND sl_gid in({$gidStr}) GROUP BY sl_gid,sl_uid";
                    }else{
                        $sql = "SELECT sl_gid,count(*) AS count FROM {$summarylistTb} WHERE sl_status = 2 AND sl_sid <> -1 AND sl_uid in({$uidsStr}) AND sl_pay_time >= {$stime} AND sl_pay_time <= {$etime} AND sl_gid in({$gidStr}) GROUP BY sl_gid,sl_uid";
                    }
                    $temp = oo::commonOprDb('slavedb')->getAll($sql,1);
                    foreach($temp as $tempVo){
                        $out[$row['id']]['count'][$tempVo['sl_gid']]++;
                    }
                }else{
                    $out[$row['id']]['total'] = $out[$row['id']]['total'] ?? [];
                    $out[$row['id']]['count'] = $out[$row['id']]['count'] ?? [];
                }
            }
        }
        return ['groupList'=>$groupList,'list'=>$out];
    }

    /**
     * Notes:判断用户是否是买量用户
     * users array [uid,uid]
     * type buy买量 natural自然量
     * User: Hss
     * Time: 2021/2/25 16:35
     */
    public function isBuyUser($users = [],$type = 'buy'){
        if(empty($users)){
            return [];
        }
        $usersStr = implode(",",$users);
        $tb = otable::adjustAdsData();
        $sql = "SELECT uid FROM {$tb} WHERE uid in({$usersStr})";
        $ret = oo::commonOprDb('statistics')->getAll($sql,1);
        $uids = [];
        foreach($ret as $row){
            $uids[] = $row['uid'];
        }
        if($type == 'buy'){
            return $uids;
        }else if($type == 'natural'){
            return array_diff($users,$uids);
        }else{
            return [];
        }
    }

    /**
     * Notes:获取登陆用户
     * date 日期 20210225
     * address 国家 ZH、EN
     * sidList 设备 1安卓 2苹果
     * difference 后来加的区分平台的 0GOOGLE 1VIVO
     * lid 平台 0所有 1FB 2游客
     * userType 用户类型 buy买量 natural自然量
     * groupId 用户分组
     * type 1新增 2登陆
     * User: Hss
     * Time: 2021/2/25 16:35
     */
    function newloginplayer($date = '',$address = 'all',$sidList = [1,2],$difference = -1,$lid = 0,$userType = '',$groupId = 0,$type = 2){
        $date = date("Ymd",strtotime($date));
        $ret = oo::commonOprModel('statistics')->getAllPlayer($date, $type, $sidList, $lid);
        if($address == 'all'){
            $uids = $ret;
        }else{
            if(empty($ret)){
                return [];
            }
            $uidsStr = implode(",",$ret);
            $useraddress = otable::useraddress();
            $sql = "SELECT * FROM {$useraddress} WHERE uid in({$uidsStr}) AND country_code = '{$address}'";
            $ret = oo::commonOprDb('slavedb')->getAll($sql,1);
            $uids = [];
            foreach ($ret as $row){
                $uids[] = $row['uid'];
            }
        }
        if($difference !== -1){
            $uids = $this->getDifferenceUids($uids,$difference);
        }
        if($userType){
            $uids = $this->isBuyUser($uids,$userType);
        }

        if($groupId){
            $uids = $this->getGroupUser($date,$uids,$groupId);
        }

        return $uids;
    }

    //返回平台用户 0GOOGLE 1VIVO
    function getDifferenceUids($uids = [],$difference = 1){
        if(empty($uids)){
            return [];
        }
        $uidsStr = implode(",",$uids);
        $userinfoTb = otable::userinfo(1);
        $sql = "SELECT uid FROM {$userinfoTb} WHERE channel = {$difference} AND uid in({$uidsStr})";
        $ret = oo::commonOprDb('slavedb')->getAll($sql, 1);
        $player = [];
        foreach($ret as $temp){
            $player[] = $temp['uid'];
        }

        return $player;
    }

    //返回分组用户
    function getGroupUser($date,$users = [],$groupId = 0){
        if(empty($users)){
            return [];
        }
        if(empty($groupId)){
            return $users;
        }
        $tb = otable::UserGroupSta();
        //取出这个分组的用户
        $usersStr = implode(",",$users);
        $sql = "SELECT uid FROM {$tb} WHERE date = {$date} AND groupId like '%#{$groupId}#%' AND uid in({$usersStr})";
        $ret = oo::commonOprDb("statistics")->getAll($sql,1);
        $uids = [];
        foreach($ret as $vo){
            $uids[] = $vo['uid'];
        }
        return $uids;
    }

    //内购流水
    //date 日期
    //address 地区
    //type sum金额 || count人数 || orderCount订单数 || ['sum','count','orderCount']数组的话，则返回多个值
    //class all所有玩家 new新增玩家 login老活跃玩家(去除新增)
    //userType 用户类型 buy买量 natural自然量
    //groupId 用户分组
    public function gamesIncome($date = '',$address = 'all',$type = 'sum', $class = 'all', $sidList = [1,2],$userType = '',$groupId = 0){
        $time = strtotime($date .' 0:0:0');
        $date = date("Ymd",strtotime($date));
        $tb = otable::summarylist();

        $where = '';
        if(!empty($sidList)){
            $sidStr = implode(",",$sidList);
            $where .= " AND sl_sid in({$sidStr})";
        }

        if($class == "all"){
            $ret = $this->newloginplayer($date,$address,[1,2],-1,0,$userType,$groupId,2);
        }else if($class == "new"){
            $ret = $this->newloginplayer($date,$address,[1,2],-1,0,$userType,$groupId,1);
        }else if($class == "login"){
            $retLogin = $this->newloginplayer($date,$address,[1,2],-1,0,$userType,$groupId,2);
            $retNew = $this->newloginplayer($date,$address,[1,2],-1,0,$userType,$groupId,1);
            $ret = array_diff($retLogin,$retNew);
        }
        if(!$this->config->item('oos_debug')){
            $where .= " AND sl_sid <> -1 ";
        }
        if(empty($ret)){
            return 0;
        }
        $uidsStr = implode(",",$ret);

        if(!is_array($type)){
            $select = $group = '';
            if($type == 'sum'){
                $select = "sum(sl_pusd) as total";
            }else{
                $select = "sl_uid";
                $group = " GROUP BY sl_uid";
            }
            $sql = "SELECT {$select} FROM {$tb} WHERE sl_pay_time >= {$time} AND sl_pay_time <= {$time} + 86400 AND sl_status = 2 AND sl_sid <> -1 AND sl_uid in({$uidsStr}) {$where} {$group}";
            if($type == 'sum'){
                $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                return (empty($ret['total'])?0:(round($ret['total'],2)));
            }else{
                $ret = oo::commonOprDb('slavedb')->getAll($sql,1);
                return count($ret);
            }
        }else{
            $out = [];
            foreach($type as $typeTemp){
                switch ($typeTemp){
                    case 'sum':
                        $sql = "SELECT sum(sl_pusd) as total FROM {$tb} WHERE sl_pay_time >= {$time} AND sl_pay_time <= {$time} + 86400 AND sl_status = 2 AND sl_uid in({$uidsStr}) {$where}";
                        $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                        $out['sum'] = (empty($ret['total'])?0:(round($ret['total'],2)));
                        break;
                    case 'count':
                        $sql = "SELECT sl_uid FROM {$tb} WHERE sl_pay_time >= {$time} AND sl_pay_time <= {$time} + 86400 AND sl_status = 2 AND sl_uid in({$uidsStr}) {$where} GROUP BY sl_uid";
                        $ret = oo::commonOprDb('slavedb')->getAll($sql,1);
                        $out['count'] = count($ret);
                        break;
                    case 'orderCount':
                        $sql = "SELECT count(*) as orderCount FROM {$tb} WHERE sl_pay_time >= {$time} AND sl_pay_time <= {$time} + 86400 AND sl_status = 2 AND sl_uid in({$uidsStr}) {$where}";
                        $ret = oo::commonOprDb('slavedb')->getOne($sql,1);
                        $out['orderCount'] = (empty($ret['orderCount'])?0:(round($ret['orderCount'],2)));
                        break;
                }
            }
            return $out;
        }
    }

    /**
     * 锦标赛 + 超级收集活动 进度 统计
     * @return string
     * Created by: Hss
     * Created on: 2021/3/4 17:28
     */
    public function rankCollectSta($aid = 0,$set = false){
        if(empty($aid)){
            return [];
        }
        $data = [];
        //获取活动配置
        $tb = otable::activityConf();
        $sql = "SELECT * FROM {$tb} WHERE id = {$aid}";
        $config = oo::commonOprDb('slavedb')->getOne($sql,1);

        $tb = otable::activityStageRewardConf();
        $sql = "SELECT * FROM {$tb} WHERE aid={$aid}";
        $retStage = oo::commonOprDb('slavedb')->getOne($sql,1);
        if($retStage['type'] == 'rank'){
            $retStage['config'] = json_decode($retStage['reward'],1);
        }else{
            $retStage['config'] = json_decode($retStage['extra_reward'],1);
        }

        //先查库是否有数据
        $tb = otable::rankCollectSta();
        $sql = "SELECT * FROM {$tb} WHERE aid = {$aid}";
        $ret = oo::commonOprDb("statistics")->getOne($sql,1);
        if($ret){
            $data = json_decode($ret['data'],true);
            $data['config'] = $config;
            $data['retStage'] = $retStage;
            return $data;
        }

        $tb = otable::actStageLog($aid);
        $sql = "SELECT rid,stage,count(*) AS count FROM {$tb} WHERE type = 2 GROUP BY rid,stage";
        $actStageLogRet = oo::commonOprDb("statistics")->getAll($sql,1);
        $actStageLog = [];
        foreach($actStageLogRet as $row){
            $actStageLog[$row['rid']][$row['stage']] = $row['count'];
        }

        //每层总数
        $stageSum = [];
        //付费金额 //付费人数
        $payTotal = $payNum = [];
        //付费前平均体力
        $paySpins = [];
        //付费时平均进度百分比
        $paySpeed = [];
        //当前层平均消耗体力
        $lowSpins = [];
        //用户付费总金额
        $uidPayTotalData = [];
        //用户活动体力总消耗
        $uidSpinsLowData = [];
        foreach($retStage['config'] as $rid => $actConfig){
            //获取该区间配置
            foreach($actConfig['list'] as $vo){
                $stage = $vo['stage'];
                $stepnum = $vo['stepnum'];
                $stageSum[$rid][$stage] = $actStageLog[$rid][$stage];
                for($i = 1; $i < $stage; $i++){
                    $stageSum[$rid][$i] += $stageSum[$rid][$stage];
                }

                $temp = oo::commonOprRedis('Statistics')->hGetAll(okeys::rankCollectPaySta($aid,$config['type'], $rid, $stage));
                if(is_array($temp)) {
                    foreach ($temp as $uid => $gprice) {
                        $uidPayTotalData[$uid] += ($gprice / 100);
                    }
                }
                $payTotal[$rid][$stage] = empty($temp) ? 0 :number_format(array_sum($temp) / 100,1,'.','');
                $payNum[$rid][$stage] = empty($temp) ? 0 : count($temp);

                $temp = oo::commonOprRedis('Statistics')->hGetAll(okeys::rankCollectSpinsSta($aid,$config['type'], $rid, $stage));
                $paySpins[$rid][$stage] = empty($temp) ? 0 : number_format(array_sum($temp) / count($temp),1,'.','');

                $temp = oo::commonOprRedis('Statistics')->hGetAll(okeys::rankCollectNumSta($aid,$config['type'], $rid, $stage));
                $totalPercent = 0;
                if(is_array($temp)) {
                    foreach ($temp as $uid => $num) {
                        $totalPercent += ($num / $stepnum);
                    }
                }
                $paySpeed[$rid][$stage] = empty($totalPercent) ? 0 : number_format($totalPercent / count($temp) * 100,1,'.','');

                $type = $config['type'] == "rank" ? "rank-up" : "super_collect-up";
                $temp = oo::commonOprRedis('Statistics')->hGetAll(okeys::rankConsumeSta($aid,$type, $rid, $stage));
                if(is_array($temp)){
                    foreach($temp as $uid => $spins){
                        $uidSpinsLowData[$uid] += $spins;
                    }
                }
                $lowSpins[$rid][$stage] = empty($temp) ? 0 :number_format(array_sum($temp) / count($temp),1,'.','');
            }
        }
        //计算通过率
        $passRate = [];
        foreach($retStage['config'] as $rid => $actConfig){
            //获取该区间配置
            foreach($actConfig['list'] as $vo){
                $stage = $vo['stage'];
                $passRate[$rid][$stage] = (empty($stageSum[$rid][$stage]) || empty($stageSum[$rid][$stage+1])) ? 0 : number_format($stageSum[$rid][$stage+1] / $stageSum[$rid][$stage] * 100,1,'.','');
            }
        }

        $data['config'] = $config;
        $data['retStage'] = $retStage;
        $data['actStageLog'] = $actStageLog;
        $data['stageSum'] = $stageSum;
        $data['passRate'] = $passRate;
        $data['payTotal'] = $payTotal;//付费金额
        $data['payNum'] = $payNum;//付费人数
        //arppu 付费金额/付费人数
        //arpu 付费金额/DAU
        //付费率 付费人数/该配置该进度人数
        $data['paySpins'] = $paySpins;
        $data['paySpeed'] = $paySpeed;
        $data['lowSpins'] = $lowSpins;

        if($config['type'] == "rank"){
            $extraData = json_decode($config['extraData'],true);
            $spinsSet = $extraData['spinsSet'];
            rsort($spinsSet);
            $arrId  = [];
            foreach($spinsSet as $key=>$row){
                $arrId[] = $key + 1;
            }
            $data['rankData']['arrId'] = $arrId;
            $data['rankData']['spinsSet'] = $spinsSet;
            //排行榜多加排行奖励统计
            $tb = otable::rankActLog($aid);
            $sql = "SELECT uid,roomId,ranking FROM {$tb} WHERE ranking <= 10";
            $rankActLog = oo::commonOprDb('slavedb')->getAll($sql,1);

            $tb  = otable::Robot();
            $sql = "SELECT * FROM {$tb} WHERE 1";
            $ret = oo::commonOprDb('slavedb')->getAll($sql,1);
            $robot = [];
            foreach ($ret as $row){
                $robot[] = $row['uid'];
            }

            //分块
            $blockData = [];
            //房间列表
            $roomArr = [];
            foreach($rankActLog as $row){
                $block = substr($row['roomId'] , 0 , 1);
                if(!in_array($row['roomId'],$roomArr[$block])){
                    $roomArr[$block][] = $row['roomId'];
                }
                $uid = $row['uid'];
                if(in_array($uid,$robot)){
                    //机器人
                    $blockData[$block]['rankingRobot'][$row['ranking']]++;//名次人数
                }else{
                    //真实玩家
                    $blockData[$block]['ranking'][$row['ranking']]++;//名次人数
                    if(isset($uidPayTotalData[$uid])){
                        //付费人数
                        $blockData[$block]['payNum'][$row['ranking']]++;
                        //付费金额
                        $blockData[$block]['payTotal'][$row['ranking']] += $uidPayTotalData[$uid];
                    }
                    if(isset($uidSpinsLowData[$uid])){
                        //体力消耗
                        $blockData[$block]['spinsTotalLow'][$row['ranking']] += $uidSpinsLowData[$uid];
                    }
                }
            }
            foreach($arrId as $block){
                $blockData[$block]['roomNumber'] = count($roomArr[$block]) ?? 0;
            }
            $data['rankData']['blockData'] = $blockData;
        }
        if($set){
            unset($data['config']);
            unset($data['retStage']);
            $content = json_encode($data);
            //写入数据库
            $tb = otable::rankCollectSta();
            $sql = "INSERT INTO {$tb} values ('{$aid}','{$content}')";
            $status = oo::commonOprDb('statistics')->query($sql);
            if($status){
                //清空缓存
                foreach($retStage['config'] as $rid => $actConfig){
                    //获取该区间配置
                    foreach($actConfig['list'] as $vo){
                        $stage = $vo['stage'];
                        oo::commonOprRedis('Statistics')->delete(okeys::rankCollectPaySta($aid,$config['type'], $rid, $stage));
                        oo::commonOprRedis('Statistics')->delete(okeys::rankCollectSpinsSta($aid,$config['type'], $rid, $stage));
                        oo::commonOprRedis('Statistics')->delete(okeys::rankCollectNumSta($aid,$config['type'], $rid, $stage));
                        $type = $config['type'] == "rank" ? "rank-up" : "super_collect-up";
                        oo::commonOprRedis('Statistics')->delete(okeys::rankConsumeSta($aid,$type, $rid, $stage));
                    }
                }
            }
            return $status;
        }else{
            return $data;
        }
    }

    /**
     * 锦标赛 + 超级收集活动 统计 统计保存到数据库
     * @return string
     * Created by: Hss
     * Created on: 2021/3/4 17:28
     */
    public function rankCollectSaveSta(){
        $time = time();
        //取出统计表中最大的活动ID
        $rankCollectSta = otable::rankCollectSta();
        $sql = "SELECT max(aid) as maxAid FROM {$rankCollectSta}";
        $ret = oo::commonOprDb('statistics')->getOne($sql,1);
        if(empty($ret)){
            $maxAid = $ret['maxAid']-10;
        }else{
            $maxAid = 2021;
        }
        $tb = otable::activityConf();
        $sql = "SELECT * FROM {$tb} WHERE id > {$maxAid} AND id <> {$ret['maxAid']} AND type in('rank','super_collect') AND end_time <= {$time}-3600";
        $activityConf = oo::commonOprDb('slavedb')->getAll($sql,1);
        foreach($activityConf as $row){
            $aid = $row['id'];
            $sql = "SELECT * FROM {$rankCollectSta} WHERE aid = {$aid}";
            $temp = oo::commonOprDb('statistics')->getOne($sql,1);
            if(empty($temp)){
                self::rankCollectSta($aid,true);
            }
        }
    }

    public function avgLoginTime(){
//        $robot = oo::commonOprModel('robot')->getAllRobot();
//        $NotUid = implode(',',$robot);
//        $sum = 0;
//        $total = 0;
//        for($i=0;$i<100;$i++){
//            $tb = otable::statistics($i);
//            $dbsum = oo::commonOprDb('statistics')->getOne("SELECT SUM(loginTime) as sum FROM {$tb} WHERE uid NOT IN ($NotUid)", MYSQLI_ASSOC);
//            $dbtotal = oo::commonOprDb('statistics')->getOne(" SELECT count(1) as total FROM {$tb} WHERE uid NOT IN ($NotUid)", MYSQLI_ASSOC);
//            $sum += $dbsum['sum'];
//            $total += $dbtotal['total'];
//        }

        $data = $this->getAllLoginTime();
        $sum = array_sum(array_values($data));
        $total = count(array_keys($data));
        if(empty($data)){
            return 0;
        }
        return $sum/$total;
    }

    /**
     * 获取登录时长所有数据(分散在多个环形hash key内)
     * @return array
     */
    public function getAllLoginTime() {
        $keys = okeys::LoginTimes();
        $data = [];
        foreach($keys as $k){
            $data = $data + oo::commonOprRedis('games')->hGetAll($k);
        }
        return $data;
    }

    /**
     * 查询是否是首次充值
     * @param $uid
     * @param $time
     * @return bool
     */
    public function checkPayFirst($uid, $time)
    {
        empty($time) && $time = strtotime('0:0:0') ;
        $table = otable::payment($uid);
        $sql = "SELECT pid FROM {$table} WHERE uid = {$uid} AND status = 2 AND pay_time < {$time} LIMIT 1 ";
        $ret = oo::commonOprDb('gameslave')->getOne($sql, MYSQLI_ASSOC);

        if( !empty($ret) ) return false;


        $minYear = 2022;
        $maxYear = max(date('Y'), $minYear);
        $minYear = max($minYear, date('Y', $time));
        $maxYear = min($maxYear, date('Y', $time));
        $time = date('Y-m-d H:i:s', $time);
        for($tempYear = $minYear; $tempYear<=$maxYear; $tempYear++){
            $table = otable::order($tempYear);
            $sql = "SELECT uid FROM {$table} WHERE uid = {$uid} AND status = 4 AND pay_time < {$time} LIMIT 1 ";
            $ret = oo::commonOprDb('gameslave')->getOne($sql, MYSQLI_ASSOC);
            if( !empty($ret) ) return false;
        }

        return true;
    }
}
