where(['parent_id' => 0])->select(); foreach ($promotes as $promote) { $promote['chain'] = '/'; $promote['level'] = 1; M('promote', 'tab_')->where(['id' => $promote['id']])->save(['chain' => '/', 'level' => 1]); $subPromote = $promote; unset($subPromote['id']); $subPromote['parent_id'] = $promote['id']; $subPromote['parent_name'] = $promote['account']; $subPromote['chain'] = $promote['chain'] . $promote['id'] . '/'; $subPromote['level'] = $promote['level'] + 1; $subPromote['account'] = 'second_' . $promote['account']; $subPromote['nickname'] = '二级_' . $promote['nickname']; $subPromote['mobile_phone'] = ''; $subPromote['email'] = ''; $subPromote['real_name'] = ''; $subPromote['money'] = 0; $subPromote['total_money'] = 0; $subPromote['balance_coin'] = 0; $subPromote['create_time'] = time(); $subPromote['last_login_time'] = 0; $subPromote['idcard'] = ''; M('promote', 'tab_')->add($subPromote); $subId = M()->getLastInsID(); $subChain = $subPromote['chain'] . $subId . '/'; M('promote', 'tab_')->where(['parent_id' => $promote['id'], 'id' => ['neq', $subId]])->save([ 'parent_id' => $subId, 'parent_name' => $subPromote['account'], 'chain' => $subChain, 'level' => 3, ]); // echo M()->getLastSql() . "\n"; M('promote', 'tab_')->where(['grand_id' => $promote['id']])->save([ 'chain' => ['exp', 'concat("' . $subChain. '",parent_id,"/")'], 'level' => 4, ]); // echo M()->getLastSql() . "\n"; } } public function runShiftTask() { $promoteService = new PromoteService(); $tasks = M('shift_task', 'sys_')->where(['status' => 0, 'order_time' => ['elt', time()]])->select(); if (count($tasks) == 0) { Printer::export('无可执行任务', true); } foreach ($tasks as $task) { if ($task['type'] == 1) { $message = '推广员迁移[' . $task['id'] . ']'; $result = $promoteService->shiftPromote($task); if ($result['status']) { $message = 'SUCCESS ----- ' . $message . $result['msg']; } else { $message = 'ERROR ----- ' . $message . $result['msg']; } Printer::export($message); } elseif ($task['type'] == 2) { $message = '玩家迁移[' . $task['id'] . ']'; $result = $promoteService->shiftPlayer($task); if ($result['status']) { $message = 'SUCCESS ----- ' . $message . $result['msg']; } else { $message = 'ERROR ----- ' . $message . $result['msg']; } Printer::export($message); } } } public function runTask($queue = 'common', $count = 10) { Printer::export($queue); Printer::export($count); try { $task = new Task($queue); $task->run($count); Printer::export('运行完成'); } catch (\Exception $e) { Printer::export($e->getMessage()); } } public function addTask() { /* $id = M('market_shift', 'tab_')->add([ 'from_id' => 1, 'to_id' => 2, 'split_time' => 0, 'created_time' => time() ]); $params = [ 'market_shift_id' => $id ]; */ for ($i=0; $i<50; $i++) { Task::add('test', ['value' => $i]); } } public function testAggregate() { /* $client = new AggregateClient(); $result = $client->api('game-data', ['unique_codes' => ['w123'], 'started_at' => '2019-06-27', 'ended_at' => '2020-07-27']); var_dump($result); */ echo M('game', 'tab_')->where('id>2')->field(['id', 'game_name'])->where('sdk_version=1')->select(false); } public function initMarketAdmin() { $marketService = new MarketService(); $promoteService = new PromoteService(); $promotes = M('promote', 'tab_')->field(['id', 'admin_id', 'account', 'chain', 'level']) ->where(['level' => 1, 'admin_id' => ['gt', 0], 'company_belong' => ['in', [1, 2]]]) ->select(); foreach ($promotes as $promote) { Printer::export('处理会长: ' . $promote['account']); $subPromotes = $promoteService->getAllChildren($promote, 0, ['id']); $promoteIds = [$promote['id']]; $promoteIds = array_merge(array_column($subPromotes, 'id'), $promoteIds); $marketService->shiftSpend($promoteIds, 0, $promote['admin_id']); $marketService->shiftDeposit($promoteIds, 0, $promote['admin_id']); } } public function initPromoteAdmin() { $promotes = M('promote', 'tab_')->field(['id', 'chain', 'level', 'admin_id'])->where(['level' => 1, 'admin_id' => ['gt', 0]])->select(); foreach ($promotes as $promote) { M('promote', 'tab_')->where(['chain' => ['like', $promote['chain'] . $promote['id'] . '/%']])->save(['admin_id' => $promote['admin_id']]); } } public function modifyLoginRepair() { $this->modifyLogin(1569686400); } public function modifyLoginGenerate($start_time=0) { $start_time = $start_time ? $start_time : date('Y-m-d', strtotime('-1 day')); $this->modifyLogin(strtotime($start_time)); } public function modifyLoginCheck($start_time=0, $end_time=0) { $start_time = $start_time ? strtotime($start_time) : strtotime(date("Y-m-d")); $end_time = $end_time ? strtotime($end_time) : $start_time; $this->modifyLogin($start_time, $end_time); } /** * 登录校验 */ private function modifyLogin($start_time=0, $end_time=0) { $current_time = $end_time?: strtotime(date("Y-m-d"))-86400; for ($i=$start_time; $i<=$current_time; $i+=86400) { $end_time = $i+86400; $result = M()->query("SELECT game_id, UNIX_TIMESTAMP(FROM_UNIXTIME(login_time, '%Y-%m-%d')) create_time, user_id, promote_id FROM tab_user_login_record ulr WHERE login_time >= {$i} and login_time < {$end_time} AND NOT EXISTS ( SELECT id FROM tab_login_daily_record ldr where ldr.create_time >= {$i} and ldr.create_time < {$end_time} and ldr.game_id = ulr.game_id and ldr.user_id = ulr.user_id and ldr.promote_id = ulr.promote_id ) GROUP BY create_time, game_id, user_id, promote_id"); if ($result) { foreach ($result as $index => $item) { if (is_null($result[$index]['promote_id'])) { unset($result[$index]); } } $step = 500; for ($j=0;;$j+=$step) { $insData = array_slice($result, $j, $step); if ($insData) { $res = M("login_daily_record", 'tab_')->addAll($insData); echo "写入 $res \n"; } else { break; } } } else { echo "写入{$item['create_time']} 无 \n"; } } } public function deleteRepeatUserPlayInfo() { $gameIds = [157, 155, 153, 150, 151, 148, 175, 142, 143, 172, 173, 155, 154, 180]; foreach($gameIds as $gameId) { $this->doDeleteRepeatUserPlayInfo($gameId); } } public function doDeleteRepeatUserPlayInfo($gameId) { $sql = 'select id from tab_user_play_info a left join ( select role_id, server_id, game_id, count(1) from tab_user_play_info where server_id="' . $serverId . '" and game_id = ' . $gameId . ' GROUP BY role_id, server_id, game_id, server_name having count(1) > 1 ) b on a.role_id=b.role_id where a.server_id=b.server_id and a.game_id=b.game_id and a.server_id="' . $serverId . '" and a.game_id = ' . $gameId . ' order by a.role_id, a.server_id, a.game_id'; $model = new \Think\Model(); $servers = M('server', 'tab_')->field('server_id')->where(['game_id' => $gameId])->group('server_id')->select(); foreach ($servers as $server) { $serverId = $server['server_id']; $sql = 'select a.id, a.role_id, a.server_id, a.game_id, a.role_level from tab_user_play_info a left join ( select role_id, server_id, game_id, count(1) from tab_user_play_info where server_id="' . $serverId . '" and game_id = ' . $gameId . ' GROUP BY role_id, server_id, game_id, server_name having count(1) > 1 ) b on a.role_id=b.role_id where a.server_id=b.server_id and a.game_id=b.game_id and a.server_id="' . $serverId . '" and a.game_id = ' . $gameId . ' order by a.role_id, a.server_id, a.game_id'; // var_dump($sql); $result = $model->query($sql); $uniqueRole = null; $items = []; foreach ($result as $item) { $items[$item['role_id']][] = $item; } $maxRoleIds = []; $repeatIds = []; foreach ($items as $roles) { $maxRole = null; foreach ($roles as $role) { if ($maxRole == null) { $maxRole = $role; } elseif ($role['role_level'] > $maxRole['role_level']) { $repeatIds[] = $maxRole['id']; $maxRole = $role; } else { $repeatIds[] = $role['id']; } } $maxRoleIds[] = $maxRole['id']; } if (count($repeatIds) > 0) { M('user_play_info', 'tab_')->where(['id' => ['in', $repeatIds], 'game_id' => $gameId, 'server_id' => $serverId])->delete(); echo M()->getLastSql(); echo PHP_EOL; } } } public function deleteRepeatUserPlayInfo2() { $gameIds = [157, 148, 150, 151, 158, 175, 142, 143, 172, 173, 154, 155, 176, 165, 164, 179, 156, 153, 180]; foreach ($gameIds as $gameId) { $this->doDeleteRepeatUserPlayInfo2($gameId); } } public function doDeleteRepeatUserPlayInfo2($gameId) { $sql = 'select id from tab_user_play_info a left join ( select role_id, server_id, game_id, count(1) from tab_user_play_info where server_id="' . $serverId . '" and game_id = ' . $gameId . ' GROUP BY role_id, server_id, game_id, server_name having count(1) > 1 ) b on a.role_id=b.role_id where a.server_id=b.server_id and a.game_id=b.game_id and a.server_id="' . $serverId . '" and a.game_id = ' . $gameId . ' order by a.role_id, a.server_id, a.game_id'; $model = new \Think\Model(); $servers = M('server', 'tab_')->field('server_id')->where(['game_id' => $gameId])->group('server_id')->select(); foreach ($servers as $server) { $serverId = $server['server_id']; $sql = 'select a.id, a.role_id, a.server_id, a.game_id, a.role_level from tab_user_play_info a left join ( select role_id, server_id, game_id, count(1) from tab_user_play_info where server_id="' . $serverId . '" and game_id = ' . $gameId . ' GROUP BY role_id, server_id, game_id having count(1) > 1 ) b on a.role_id=b.role_id where a.server_id=b.server_id and a.game_id=b.game_id and a.server_id="' . $serverId . '" and a.game_id = ' . $gameId . ' order by a.role_id, a.server_id, a.game_id'; // var_dump($sql); $result = $model->query($sql); $uniqueRole = null; $items = []; foreach ($result as $item) { $items[$item['role_id']][] = $item; } $maxRoleIds = []; $repeatIds = []; foreach ($items as $roles) { $maxRole = null; foreach ($roles as $role) { if ($maxRole == null) { $maxRole = $role; } elseif ($role['role_level'] >= $maxRole['role_level']) { $repeatIds[] = $maxRole['id']; $maxRole = $role; } else { $repeatIds[] = $role['id']; } } $maxRoleIds[] = $maxRole['id']; } if (count($repeatIds) > 0) { M('user_play_info', 'tab_')->where(['id' => ['in', $repeatIds], 'game_id' => $gameId, 'server_id' => $serverId])->delete(); echo M()->getLastSql(); echo PHP_EOL; } } } public function resetIndexChart() { for ($i=1; $i<100; $i++) { $item = M('index_chart', 'tab_')->where(['id' => $i])->find(); if ($item) { $item['new_user_hours'] = json_encode(unserialize($item['new_user_hours'])); $item['active_user_hours'] = json_encode(unserialize($item['active_user_hours'])); $item['active_user_list'] = json_encode(unserialize($item['active_user_list'])); $item['pay_user_hours'] = json_encode(unserialize($item['pay_user_hours'])); $item['pay_user_list'] = json_encode(unserialize($item['pay_user_list'])); $item['pay_money_hours'] = json_encode(unserialize($item['pay_money_hours'])); $item['promote_new_hours'] = json_encode(unserialize($item['promote_new_hours'])); $item['all_count'] = json_encode(unserialize($item['all_count'])); M("index_chart_1", "tab_")->add($item); } } } public function testLogin() { /* $client = new Client([ 'base_uri' => 'http://47.111.118.107:9501', 'timeout' => 10.0, ]); $response = $client->post('/game-event/login', [ 'form_params' => [ 'user_id' => 28747, 'game_id' => 153, 'login_time' => 1577361998 ] ]); $result = (string)$response->getBody(); echo $result; */ $data = [ 'user_id' => 28747, 'game_id' => 153, 'login_time' => 1577361998 ]; $client = new Client([ 'base_uri' => 'http://47.111.118.107:9501', 'timeout' => 5.0, ]); $promise = $client->requestAsync('POST', '/game-event/login', [ 'form_params' => $data ]); $promise->then( function (ResponseInterface $res) { echo $res->getStatusCode() . PHP_EOL; }, function (RequestException $e) { echo $e->getMessage() . PHP_EOL; echo $e->getRequest()->getMethod(); } ); } public function divideWarnCheck() { $redis = new \Org\RedisSDK\Redis(['host'=>'127.0.0.1','port'=>6379],[]); $warns = M('partner_divide_warn', 'tab_')->alias('pdw') ->field('pdw.*, cgr.ratio, sum(s.pay_amount) as total_amount, p.partner') ->join('tab_partner p on pdw.partner_id = p.id') ->join('tab_game g on pdw.partner_id = g.partner_id') ->join('tab_cp_game_ratio cgr on cgr.game_id = g.id and begin_total_amount = 0 and is_del = 0') ->join('tab_game_data s on s.game_id = g.id') ->where(['pdw.status'=>1]) ->group('pdw.id') ->select(); if (!$warns) return; $taskClient = new TaskClient(); $current_time = date('Y-m-d H:i:s'); foreach ($warns as $info) { if (!$info['ratio']) return; $total_amount = ceil(($info['ratio'] / 100) * $info['total_amount']); $cacheKey = "divide:warn:check:{$info['partner_id']}"; if (!($lastStep = $redis->get($cacheKey))) { $lastStep = 0; } if ((intval($info['advance_amount']) - intval($total_amount)) <= $info['warming_amount']) { if ($total_amount - $lastStep >= $info['warn_frequency']) { // 达到预警 // 发送预警短信 $content = "{$info['partner']}的预付分成款已于{$current_time}余额不足{$info['warming_amount']}元,请尽快进行充值。"; $sendRes = $taskClient->sendSmsBatch(json_decode($info['phones'], true), $content); if ($sendRes['code'] != TaskClient::SUCCESS) { continue; } // 变换缓存值,如果为0,需要设置过期时间 if ($lastStep) { $redis->set($cacheKey, $total_amount); } else { $redis->setex($cacheKey, 86400 * 30, $total_amount); } } } } } public function coinRecords() { $deposit = M('deposit', 'tab_')->field('pay_order_number,user_id,user_account,pay_status,pay_way,pay_amount,create_time as pay_time,2 as record_type')->where(['pay_status'=>1])->select(false); // $agent = M('agent', 'tab_')->field('pay_order_number,user_id,user_account,pay_status,pay_way,real_amount as pay_amount,create_time as pay_time,3 as record_type')->where(['pay_status'=>1])->select(false); // $spend = M('spend', 'tab_')->field('pay_order_number,user_id,user_account,pay_status,pay_way,pay_amount,pay_time,1 as record_type')->where(['pay_status' => 1,'pay_way'=>0])->select(false); $query = M('spend', 'tab_')->field('pay_order_number,user_id,user_account,pay_status,pay_way,pay_amount,pay_time,1 as record_type')->where(['pay_status' => 1,'pay_way'=>0])->union($deposit,'pay_time')->select(false); $model = new \Think\Model(); $datas = $model->table('(' . $query . ') a ')->order('pay_time asc')->select(); foreach ($datas as $key => $data) { if(empty($data['pay_order_number'])) { $order = 0; }else { $order = $data['pay_order_number']; } $data['order_number'] = $order; $data['user_id'] = $data['user_id']; $data['value'] = $data['pay_amount']; $data['before_value'] = 0; $data['after_value'] = 0; $data['create_time'] = $data['pay_time']; if ($data['record_type'] == 1) { $data['type'] = 'spend'; $data['remark'] ='历史消费spend'; $data['pay_type'] = 1; $data['value'] = -$data['pay_amount']; } if ($data['record_type'] == 2) { $data['type'] = 'deposit'; $data['remark'] ='历史充值deposit'; $data['pay_type'] = 2; $data['value'] = $data['pay_amount']; } M('value_detail_log', 'tab_')->add($data); } echo "success"; } public function updateValue() { //$map['type'] = ['neq', '2']; $valueDetails = M('value_detail_log', 'tab_')->field('user_id')->where($map)->group('user_id')->select(); foreach ($valueDetails as $key => $valueDetail) { $user_id = $valueDetail['user_id']; $map['user_id'] = $user_id; $userValues = M('value_detail_log', 'tab_')->where($map)->select(); $currentValue = 0; foreach ($userValues as $userValue) { $id = $userValue['id']; $userValue['before_value'] = $currentValue; $userValue['after_value'] = $currentValue + $userValue['value']; M('value_detail_log', 'tab_')->where(['id' => $id])->save($userValue); $after_update = M('value_detail_log', 'tab_')->where(['id'=>$id])->find(); $currentValue = $after_update['after_value']; } } } public function arpu() { $start = I('start', date('Y-m-d')); $end = I('end', date('Y-m-d')); $gameIds = I('game_ids', ''); $startTime = strtotime($start . ' 00:00:00'); $endTime = strtotime($end . ' 23:59:59'); $gameIdRows = explode(',', $gameIds); // 新增用户 /* M('user', 'tab_') ->field('count(*) count, FROM_UNIXTIME(register_time, "%Y-%m-%d") date') ->where([ 'game_id' => ['in', $gameIdRows], 'register_time' => ['between', [$startTime, $endTime]] ]) ->group('date') ->select(); */ $newUsers = M('user_play', 'tab_') ->field('count(DISTINCT user_id) count, FROM_UNIXTIME(create_time, "%Y-%m-%d") date') ->where([ 'game_id' => ['in', $gameIdRows], 'create_time' => ['between', [$startTime, $endTime]] ]) ->group('date') ->select(); $newUsers = index_by_column('date', $newUsers); // 活跃用户 $loginUsers = M('login_daily_record', 'tab_') ->field('count(DISTINCT user_id) count, FROM_UNIXTIME(create_time, "%Y-%m-%d") date') ->where([ 'game_id' => ['in', $gameIdRows], 'create_time' => ['between', [$startTime, $endTime]] ]) ->group('date') ->select(); $loginUsers = index_by_column('date', $loginUsers); // 付费玩家,付费金额 $payLogs = M('spend', 'tab_') ->field('count(DISTINCT user_id) count, sum(pay_amount) amount, FROM_UNIXTIME(pay_time, "%Y-%m-%d") date') ->where([ 'game_id' => ['in', $gameIdRows], 'pay_time' => ['between', [$startTime, $endTime]], 'pay_status' => 1, ]) ->group('date') ->select(); $payLogs = index_by_column('date', $payLogs); // 起始时间前的总充值金额 /* $beforePayAmount =M('spend', 'tab_') ->where([ 'game_id' => ['in', $gameIdRows], 'pay_time' => ['lt', $startTime], 'pay_status' => 1, ]) ->sum('pay_amount'); */ $rows = []; for ($time = $startTime; $time < $endTime; $time = $time + 24*3600) { $date = date('Y-m-d', $time); $newUser = isset($newUsers[$date]) ? $newUsers[$date]['count'] : 0; $loginUser = isset($loginUsers[$date]) ? $loginUsers[$date]['count'] : 0; $payAmount = isset($payLogs[$date]) ? $payLogs[$date]['amount'] : 0; $payUser = isset($payLogs[$date]) ? $payLogs[$date]['count'] : 0; $rows[] = [ 'date' => $date, 'new_user' => $newUser, 'login_user' => $loginUser, 'pay_amount' => $payAmount, 'pay_user' => $payUser, 'pay_rate' => $loginUser > 0 ? (round($payUser / $loginUser * 100, 2) . '%') : '--', 'arpu' => $loginUser > 0 ? (round($payAmount / $loginUser, 2)) : '0.00', 'arppu' => $payUser > 0 ? (round($payAmount / $payUser, 2)) : '0.00', ]; } $thml = ''; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; foreach ($rows as $row) { $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; $html .= '' . PHP_EOL; } $html .= '
日期新增用户活跃玩家充值金额付费玩家付费率ARPUARPPU
' . $row['date'] . '' . $row['new_user'] . '' . $row['login_user'] . '' . $row['pay_amount'] . '' . $row['pay_user'] . '' . $row['pay_rate'] . '' . $row['arpu'] . '' . $row['arppu'] . '
' . PHP_EOL; echo $html; // 付费率 (当日充值用户数/当日活跃用户数) // ARPU (当日充值金额/当日活跃用户数) // ARRPU (当日充值金额/当日充值用户数) } public function checkAndfreezeTestingUser() { $pageCount = 100; $hasNext = true; $lastId = 0; do { $testingUsers = M('testing_user', 'tab_') ->where(['status' => ['in', [1, 2]], 'id' => ['gt', $lastId]]) ->order('id asc') ->limit($pageCount) ->select(); if (count($testingUser) < $pageCount) { $hasNext = false; } $userIds = array_column($testingUsers, 'user_id'); $users = M('user', 'tab_')->field(['id', 'account', 'login_time'])->where(['id' => ['in', $userIds]])->select(); $users = index_by_column('id', $users); $unloginLimitTime = 7 * 24 * 3600; $unloginUserIds = []; foreach ($testingUsers as $testingUser) { $user = $users[$testingUser['user_id']] ?? null; if ($user && (time() - $user['login_time']) > $unloginLimitTime) { $unloginUserIds[] = $user['id']; } $lastId = $testingUser['id']; } if (count($unloginUserIds) > 0) { M('testing_user', 'tab_')->where(['user_id' => ['in', $unloginUserIds]])->save([ 'status' => 3 ]); } } while($hasNext); } public function statUserRetention() { $begin = I('begin', date('Y-m-d')); $end = I('end', date('Y-m-d')); $baseGameId = I('base_game_id', 0); $repository = new GameRepository(); $baseGame = M('base_game', 'tab_')->where(['id' => $baseGameId])->find(); $beginDate = strtotime($begin); $endDate = strtotime($end); $dayTime = 24 * 3600; $trs = ''; for ($date = $beginDate; $date <= $endDate; $date = $date + $dayTime) { $dateStr = date('Y-m-d', $date); $userRegisterCount = $repository->getUserRegisterCount($baseGame, $dateStr); $userRetentionCount60 = $repository->getUserRetentionCount($baseGame, $dateStr, 60); $userRetentionCount90 = $repository->getUserRetentionCount($baseGame, $dateStr, 90); $trs .= '' . PHP_EOL; $trs .= '' . PHP_EOL; $trs .= '' . PHP_EOL; $trs .= '' . PHP_EOL; $trs .= '' . PHP_EOL; $trs .= '' . PHP_EOL; $trs .= '' . PHP_EOL; $trs .= ''. PHP_EOL; } echo '
' . $dateStr . '' . $userRegisterCount . '' . $userRetentionCount60 . '' . $userRetentionCount90 . '' . round($userRetentionCount60 / $userRegisterCount * 100, 2) . '%' . '' . round($userRetentionCount90 / $userRegisterCount * 100, 2) . '%' . '
' . PHP_EOL . $trs . '
'; } }