You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
8.4 KiB
PHP

<?php
namespace Base\Service;
use Base\Facade\Request;
use Base\Tool\GameCatClient;
class PromoteGradeService
{
const FOREVER_TIME = 300001;
public static $symbols = [
1 => '>=',
2 => '>',
];
/**
* @config
* reach_level
* grades
* - name
* - value
*/
public function saveSetting($params, $promote)
{
$id = $params['id'] ?? 0;
if (empty($params['base_game_id'])) {
throw new \Exception('请选择游戏');
}
$monthBegin = isset($params['month_begin']) && $params['month_begin'] ?
date('Ym', strtotime($params['month_begin'])) : 0;
$monthEnd = isset($params['month_end']) && $params['month_end'] ?
date('Ym', strtotime($params['month_end'])) : self::FOREVER_TIME;
$setting = null;
if ($id > 0) {
$setting = M('promote_grade_setting', 'tab_')->where(['id' => $id])->find();
if (is_null($setting)) {
throw new \Exception('记录不存在');
}
if ($setting['company_id'] != $promote['company_id']) {
throw new \Exception('不允许修改其他公司的配置');
}
} else {
$count = $this->getRepeatRuleCount($promote['company_id'], $params['base_game_id'], $monthBegin, $monthEnd);
if ($count > 0) {
throw new \Exception('该游戏在相同时间段内已经设置规则');
}
}
if ($monthBegin > 0 && $monthEnd > 0 && $monthBegin > $monthEnd) {
throw new \Exception('规则截止时间不能大于规则开始时间');
}
$config = [];
$config['reach_level'] = $params['level'];
$config['grades'] = $this->sortGrades($params['grades']);
$config['default_grade_name'] = $params['default_grade_name'];
$data = [];
$data['status'] = 1;
$data['base_game_id'] = $params['base_game_id'];
$data['month_begin'] = $monthBegin;
$data['month_end'] = $monthEnd;
$data['name'] = $params['name'];
$data['config'] = json_encode($config);
if ($setting) {
$data['create_time'] = time();
M('promote_grade_setting', 'tab_')->where(['id' => $id])->save($data);
} else {
$data['company_id'] = $promote['company_id'];
$data['create_time'] = time();
$data['update_time'] = time();
M('promote_grade_setting', 'tab_')->add($data);
}
}
private function sortGrades($grades)
{
if (count($grades) == 0) {
return $grades;
}
$values = [];
$symbols = [];
foreach ($grades as $key => $row) {
$values[$key] = $row['value'];
$symbols[$key] = $row['symbol'];
}
array_multisort($values, SORT_ASC, $symbols, SORT_ASC, $grades);
return $grades;
}
public function getTimeRepeatCondition($monthBegin, $monthEnd)
{
return ' ((month_begin >= ' . $monthBegin . ' AND month_begin <= ' . $monthEnd . ') OR (month_begin <= ' . $monthBegin . ' AND month_end >= ' . $monthEnd
. ') OR (month_end >= ' . $monthBegin . ' AND month_end <= ' . $monthEnd . '))';
}
public function getRepeatRuleCount($companyId, $baseGameId, $monthBegin, $monthEnd)
{
$conditions = [
'compnay_id' => $companyId,
'base_game_id' => $baseGameId,
];
$conditions['_string'] = $this->getTimeRepeatCondition($monthBegin, $monthEnd);
$count = M('promote_grade_setting', 'tab_')->where($conditions)->count();
return intval($count);
}
public function getCurrentSetting($promote, $baseGameId, $month)
{
$timeCondition = 'month_end >= ' . $month . ' and month_begin <= ' . $month;
return M('promote_grade_setting', 'tab_')
->where([
'status' => 1,
'company_id' => $promote['company_id'],
'base_game_id' => $baseGameId,
'_string' => $timeCondition
])
->find();
}
public function searchGradeByPromotes($promotes, $params, $setting)
{
$config = json_decode($setting['config'], true);
$settingLevel = $config['reach_level'];
$month = $params['month'] ?? date('Y-m');
$baseGameId = $params['base_game_id'] ?? 0;
$promoteIds = array_column($promotes, 'id');
$beginTime = strtotime($month . '-01 00:00:00');
$endDate = date('Y-m-01 00:00:00', strtotime($month . '-01' . ' +1 month'));
$endTime = strtotime($endDate) - 1;
$betweenTime = [$beginTime, $endTime];
$userSubSql = M('user', 'tab_')
->field(['id'])
->where(['register_time' => ['between', $betweenTime], 'promote_id' => ['in', $promoteIds]])
->group('promote_id')
->select(false);
$baseGame = null;
if ($baseGameId > 0) {
$baseGame = M('base_game', 'tab_')->where(['id' => $baseGameId])->find();
}
$roleMap = [
'role_level' => ['egt', $settingLevel],
'create_time' => ['between', $betweenTime],
'promote_id' => ['in', $promoteIds],
'_string' => 'user_id in (' . $userSubSql . ')'
];
$spendMap = [
'pay_time' => ['between', $betweenTime],
'pay_status' => 1,
'promote_id' => ['in', $promoteIds],
'_string' => 'user_id in (' . $userSubSql . ')'
];
if ($baseGame) {
$roleMap['game_id'] = ['in', [$baseGame['android_game_id'], $baseGame['ios_game_id']]];
$spendMap['game_id'] = ['in', [$baseGame['android_game_id'], $baseGame['ios_game_id']]];
} else {
$roleMap['_string'] .= ' and 1=0';
$spendMap['_string'] .= ' and 1=0';
}
$accountItems = M('user_play_info', 'tab_')
->field(['promote_id', 'count(DISTINCT user_id) num'])
->where($roleMap)
->group('promote_id')
->select();
$accountItems = index_by_column('promote_id', $accountItems);
$amountItems = M('spend', 'tab_')
->field(['promote_id', 'sum(pay_amount) amount'])
->where($spendMap)
->group('promote_id')
->select();
$amountItems = index_by_column('promote_id', $amountItems);
$promoteService = new PromoteService();
$records = [];
foreach ($promotes as $promote) {
$amountItem = $amountItems[$promote['id']] ?? null;
$accountItem = $accountItems[$promote['id']] ?? null;
$amount = $amountItem ? $amountItem['amount'] : 0;
$num = $accountItem ? $accountItem['num'] : 0;
$value = $num == 0 ? 0 : round($amount / $num, 2);
$records[] = [
'id' => $promote['id'],
'level' => $promote['level'],
'amount' => $amount,
'num' => $num,
'real_name' => hideRealName($promote['real_name']),
'account' => $promote['account'],
'promote_group' => $promoteService->getGroupNameByChain($promote['chain'], $promote['id']),
'value' => $value,
'grade_name' => $this->getGradeByValue($value, $setting),
'current_display' => ''
];
}
return $records;
}
public function getGradeByValue($value, $setting)
{
$config = json_decode($setting['config'], true);
$grades = $config['grades'];
$gradeName = $config['default_grade_name'];
foreach ($grades as $key => $grade) {
if ($key == 0 && !$this->isBigger($value, $grade)) {
$gradeName = $config['default_grade_name'];
break;
}
$nextGrade = $grades[$key + 1] ?? null;
if ($this->isBigger($value, $grade) && !$this->isBigger($value, $nextGrade)) {
$gradeName = $grade['name'];
break;
}
}
return $gradeName;
}
private function isBigger($value, $grade)
{
if (is_null($grade)) {
return false;
}
if ($grade['symbol'] == 1 && $value >= $grade['value']) {
return true;
} elseif ($grade['symbol'] == 2 && $value > $grade['value']) {
return true;
}
return false;
}
}