Files
dafuweng-saiadmin6.x/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php

247 lines
9.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: your name
// +----------------------------------------------------------------------
namespace app\dice\logic\lottery_pool_config;
use app\api\cache\UserCache;
use app\api\service\LotteryService;
use app\dice\helper\AdminScopeHelper;
use app\dice\helper\ConfigScopeEditHelper;
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
use app\dice\model\player\DicePlayer;
use app\dice\basic\DiceBaseLogic;
use plugin\saiadmin\exception\ApiException;
use plugin\saiadmin\utils\Helper;
use support\think\Cache;
use support\think\Db;
/**
* 色子奖池配置逻辑层
*/
class DiceLotteryPoolConfigLogic extends DiceBaseLogic
{
/** Redis 当前彩金池type=0 实例key无则按 type=0 创建 */
private const REDIS_KEY_CURRENT_POOL = 'api:game:lottery_pool:default';
private const EXPIRE = 86400 * 7;
/**
* 构造函数
*/
public function __construct()
{
$this->model = new DiceLotteryPoolConfig();
}
/**
* 按渠道隔离更新(主键 id 全局唯一,仍校验 dept_id 防止越权)
*/
public function edit($id, array $data, ?array $adminInfo = null, $requestDeptId = null): mixed
{
$pickedDeptId = AdminScopeHelper::pickRequestDeptId($requestDeptId, $data);
$deptId = AdminScopeHelper::resolveConfigDeptId($adminInfo, $pickedDeptId);
$result = ConfigScopeEditHelper::updateByPkAndDept(
$this->model,
$id,
$deptId,
$data,
['id', 'dept_id', 'create_time', 'update_time', 'delete_time', 'row_id'],
$adminInfo,
$pickedDeptId
);
if ($result) {
$pool = DiceLotteryPoolConfig::where('id', $id)->find();
if ($pool && $pool->isPlayerDefaultTemplate()) {
$this->syncPlayersBoundToPlayerDefaultPool($pool);
}
}
return $result;
}
/**
* 修改 playerDefault 后:同步同渠道所有绑定该池(及应跟随 playerDefault 的玩家T1T5 权重,并刷新 Redis
*
* @return int 已同步玩家数量
*/
public function syncPlayersBoundToPlayerDefaultPool(DiceLotteryPoolConfig $pool): int
{
$poolId = (int) ($pool->id ?? 0);
if ($poolId <= 0) {
return 0;
}
$fresh = DiceLotteryPoolConfig::where('id', $poolId)->find();
if (!$fresh || !$fresh->isPlayerDefaultTemplate()) {
return 0;
}
$pool = $fresh;
$weights = $this->extractPoolTierWeights($pool);
$poolDeptId = AdminScopeHelper::normalizeRecordDeptId($pool->dept_id ?? null);
$legacyDefaultPoolId = $this->findDefaultPoolIdForDept($poolDeptId);
$idsMap = [];
$boundPlayers = DicePlayer::where('lottery_config_id', $poolId)->select();
foreach ($boundPlayers as $player) {
$idsMap[(int) $player->id] = true;
}
if ($legacyDefaultPoolId > 0 && $legacyDefaultPoolId !== $poolId) {
$legacyPlayers = DicePlayer::where('lottery_config_id', $legacyDefaultPoolId)->select();
foreach ($legacyPlayers as $player) {
if (AdminScopeHelper::resolvePlayerConfigDeptId($player) === $poolDeptId) {
$idsMap[(int) $player->id] = true;
}
}
}
$unboundPlayers = DicePlayer::where(function ($q) {
$q->where('lottery_config_id', 0)->whereOr('lottery_config_id', null);
})->select();
foreach ($unboundPlayers as $player) {
if (AdminScopeHelper::resolvePlayerConfigDeptId($player) === $poolDeptId) {
$idsMap[(int) $player->id] = true;
}
}
if ($idsMap === []) {
return 0;
}
$ids = array_keys($idsMap);
$update = array_merge($weights, ['lottery_config_id' => $poolId]);
Db::table('dice_player')->whereIn('id', $ids)->update($update);
foreach ($ids as $playerId) {
LotteryService::patchPlayerWeightsCache($playerId, $weights);
LotteryService::invalidatePlayerLotteryCache($playerId);
UserCache::deleteUser($playerId);
}
return count($ids);
}
/**
* @return array{t1_weight:float,t2_weight:float,t3_weight:float,t4_weight:float,t5_weight:float}
*/
private function extractPoolTierWeights(DiceLotteryPoolConfig $pool): array
{
$data = $pool->getData();
return [
't1_weight' => (float) ($data['t1_weight'] ?? 0),
't2_weight' => (float) ($data['t2_weight'] ?? 0),
't3_weight' => (float) ($data['t3_weight'] ?? 0),
't4_weight' => (float) ($data['t4_weight'] ?? 0),
't5_weight' => (float) ($data['t5_weight'] ?? 0),
];
}
private function findDefaultPoolIdForDept(int $deptId): int
{
$query = DiceLotteryPoolConfig::where('name', 'default');
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
$query->where(function ($q) {
$q->where('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT)
->whereOr('dept_id', null);
});
} else {
$query->where('dept_id', $deptId);
}
$row = $query->find();
return $row ? (int) $row->id : 0;
}
/**
* 获取当前彩金池type=0+ 杀分权重为 type=1 的只读展示
* profit_amount 每次从 DB 实时读取t1_weightt5_weight 来自 type=1杀分权重不可在弹窗内修改
*
* @return array{id:int,name:string,safety_line:int,kill_enabled:int,t1_weight:int,...,t5_weight:int,profit_amount:float}
*/
public function getCurrentPool(int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): array
{
$query0 = DiceLotteryPoolConfig::where('name', 'default');
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
$query0->where(function ($q) {
$q->where('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT)
->whereOr('dept_id', null);
});
} else {
$query0->where('dept_id', $deptId);
}
$configType0 = $query0->find();
if (!$configType0) {
throw new ApiException('No name=default pool config found, please create one first');
}
$query1 = DiceLotteryPoolConfig::where('name', 'killScore');
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
$query1->where(function ($q) {
$q->where('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT)
->whereOr('dept_id', null);
});
} else {
$query1->where('dept_id', $deptId);
}
$configType1 = $query1->find();
$row0 = $configType0->toArray();
$profitAmount = isset($row0['profit_amount']) ? (float) $row0['profit_amount'] : (isset($row0['ev']) ? (float) $row0['ev'] : 0.0);
$pool = [
'id' => (int) $row0['id'],
'name' => (string) ($row0['name'] ?? ''),
'safety_line' => (int) ($row0['safety_line'] ?? 0),
'kill_enabled' => (int) ($row0['kill_enabled'] ?? 1),
'profit_amount' => $profitAmount,
];
$row1 = $configType1 ? $configType1->toArray() : [];
$pool['t1_weight'] = (int) ($row1['t1_weight'] ?? 0);
$pool['t2_weight'] = (int) ($row1['t2_weight'] ?? 0);
$pool['t3_weight'] = (int) ($row1['t3_weight'] ?? 0);
$pool['t4_weight'] = (int) ($row1['t4_weight'] ?? 0);
$pool['t5_weight'] = (int) ($row1['t5_weight'] ?? 0);
return $pool;
}
/**
* 更新当前彩金池:仅允许修改 type=0 的 safety_line、kill_enabled杀分权重来自 type=1不可在此接口修改
*
* @param array{safety_line?:int,kill_enabled?:int} $data
*/
public function updateCurrentPool(array $data, int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): void
{
$pool = $this->getCurrentPool($deptId);
$id = (int) $pool['id'];
if (!array_key_exists('safety_line', $data) && !array_key_exists('kill_enabled', $data)) {
return;
}
$update = [];
if (array_key_exists('safety_line', $data)) {
$update['safety_line'] = (int) $data['safety_line'];
}
if (array_key_exists('kill_enabled', $data)) {
$update['kill_enabled'] = ((int) $data['kill_enabled']) === 1 ? 1 : 0;
}
if ($update === []) {
return;
}
$query = DiceLotteryPoolConfig::where('id', $id);
ConfigScopeEditHelper::applyDeptIdWhere($query, $deptId);
$query->update($update);
}
/**
* 重置当前彩金池的玩家累计盈利:将 profit_amount 置为 0并刷新 Redis 缓存
*/
public function resetProfitAmount(int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): void
{
$pool = $this->getCurrentPool($deptId);
$id = (int) $pool['id'];
$query = DiceLotteryPoolConfig::where('id', $id);
ConfigScopeEditHelper::applyDeptIdWhere($query, $deptId);
$query->update(['profit_amount' => 0]);
$pool['profit_amount'] = 0.0;
Cache::set(self::REDIS_KEY_CURRENT_POOL, json_encode($pool), self::EXPIRE);
}
}