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 .= '日期 | 新增用户 | 活跃玩家 | 充值金额 | 付费玩家 | 付费率 | ARPU | ARPPU | ' . PHP_EOL;
$html .= '
' . PHP_EOL;
foreach ($rows as $row) {
$html .= '' . PHP_EOL;
$html .= '' . $row['date'] . ' | ' . PHP_EOL;
$html .= '' . $row['new_user'] . ' | ' . PHP_EOL;
$html .= '' . $row['login_user'] . ' | ' . PHP_EOL;
$html .= '' . $row['pay_amount'] . ' | ' . PHP_EOL;
$html .= '' . $row['pay_user'] . ' | ' . PHP_EOL;
$html .= '' . $row['pay_rate'] . ' | ' . PHP_EOL;
$html .= '' . $row['arpu'] . ' | ' . PHP_EOL;
$html .= '' . $row['arppu'] . ' | ' . PHP_EOL;
$html .= '
' . PHP_EOL;
}
$html .= '' . 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 .= '' . $dateStr . ' | ' . PHP_EOL;
$trs .= '' . $userRegisterCount . ' | ' . PHP_EOL;
$trs .= '' . $userRetentionCount60 . ' | ' . PHP_EOL;
$trs .= '' . $userRetentionCount90 . ' | ' . PHP_EOL;
$trs .= '' . round($userRetentionCount60 / $userRegisterCount * 100, 2) . '%' . ' | ' . PHP_EOL;
$trs .= '' . round($userRetentionCount90 / $userRegisterCount * 100, 2) . '%' . ' | ' . PHP_EOL;
$trs .= '
'. PHP_EOL;
}
echo '';
}
}