1.优化抽奖券的抽奖逻辑
This commit is contained in:
@@ -118,7 +118,8 @@ class PlayStartLogic
|
||||
}
|
||||
|
||||
$configType0 = DiceLotteryPoolConfig::where('name', 'default')->where('dept_id', $configDeptId)->find();
|
||||
$configType1 = DiceLotteryPoolConfig::where('name', 'killScore')->where('dept_id', $configDeptId)->find();
|
||||
$configKill = DiceLotteryPoolConfig::where('name', 'killScore')->where('dept_id', $configDeptId)->find();
|
||||
$configFree = DiceLotteryPoolConfig::where('name', 'free')->where('dept_id', $configDeptId)->find();
|
||||
if (!$configType0) {
|
||||
throw new ApiException('Lottery pool config not found (name=default required)');
|
||||
}
|
||||
@@ -132,17 +133,28 @@ class PlayStartLogic
|
||||
}
|
||||
|
||||
// 彩金池累计盈利:用于判断是否触发杀分(不再依赖单个玩家累计盈利)
|
||||
// 该值来自 dice_lottery_pool_config.profit_amount
|
||||
// 该值来自 dice_lottery_pool_config.profit_amount(default 奖池)
|
||||
$poolProfitTotal = $configType0->profit_amount ?? 0;
|
||||
$safetyLine = (int) ($configType0->safety_line ?? 0);
|
||||
$killEnabled = ((int) ($configType0->kill_enabled ?? 1)) === 1;
|
||||
// 盈利>=安全线且开启杀分:付费/免费都用 killScore;盈利<安全线:付费用玩家权重,免费用 killScore(无则用 default)
|
||||
// 记录 lottery_config_id:用池权重时记对应池,付费用玩家权重时记 default
|
||||
$usePoolWeights = ($ticketType === self::LOTTERY_TYPE_PAID && $killEnabled && $poolProfitTotal >= $safetyLine && $configType1 !== null)
|
||||
|| ($ticketType === self::LOTTERY_TYPE_FREE);
|
||||
$config = $usePoolWeights
|
||||
? (($ticketType === self::LOTTERY_TYPE_FREE && $configType1 === null) ? $configType0 : $configType1)
|
||||
: $configType0;
|
||||
|
||||
$usePaidKill = $ticketType === self::LOTTERY_TYPE_PAID
|
||||
&& $killEnabled
|
||||
&& $poolProfitTotal >= $safetyLine
|
||||
&& $configKill !== null;
|
||||
|
||||
if ($ticketType === self::LOTTERY_TYPE_FREE) {
|
||||
// 免费抽奖券:使用本渠道 name=free 奖池档位权重;无 free 时回退 default
|
||||
$config = $configFree ?? $configType0;
|
||||
$usePoolWeights = true;
|
||||
} elseif ($usePaidKill) {
|
||||
$config = $configKill;
|
||||
$usePoolWeights = true;
|
||||
} else {
|
||||
// 付费未触发杀分:按玩家 T*_weight 抽档,lottery_config_id 记 default
|
||||
$config = $configType0;
|
||||
$usePoolWeights = false;
|
||||
}
|
||||
|
||||
// 按档位 T1-T5 抽取后,从 DiceReward 表按当前方向取该档位数据,再按 weight 抽取一条得到 grid_number
|
||||
$rewardInstance = DiceReward::getCachedInstance($configDeptId);
|
||||
|
||||
@@ -96,7 +96,7 @@ class DiceRewardController extends BaseController
|
||||
* 参数:lottery_config_id 可选;paid_tier_weights / free_tier_weights 自定义档位;
|
||||
* paid_s_count, paid_n_count
|
||||
* chain_free_mode=1:仅按付费次数模拟;付费抽到再来一次/T5 则在队列中插入免费局(同底注、lottery_type=免费、paid_amount=0)
|
||||
* kill_mode_enabled=1:测试内启用杀分;当模拟玩家累计盈利达到 test_safety_line 后,付费抽奖切到 killScore
|
||||
* kill_mode_enabled=1:测试内启用杀分;规则与线上一致(default.profit_amount + safety_line + kill_enabled)
|
||||
*/
|
||||
#[Permission('一键测试权重', 'dice:reward:index:startWeightTest')]
|
||||
public function startWeightTest(Request $request): Response
|
||||
|
||||
@@ -15,7 +15,10 @@ use support\think\Db;
|
||||
|
||||
/**
|
||||
* 一键测试权重:单进程后台执行模拟摇色子,写入 dice_play_record_test 并更新 dice_reward_config_record 进度
|
||||
* 支持测试内杀分:当模拟玩家累计盈利达到安全线后,付费抽奖切换到 killScore
|
||||
* 抽奖规则与 PlayStartLogic 一致:
|
||||
* - 付费未杀分:按模拟玩家档位权重抽档,lottery_config_id 记 default
|
||||
* - 付费杀分:default.profit_amount + safety_line + kill_enabled 满足后切 killScore
|
||||
* - 免费券:name=free 奖池(无则 default),排除 5/30 豹子
|
||||
*/
|
||||
class WeightTestRunner
|
||||
{
|
||||
@@ -72,7 +75,8 @@ class WeightTestRunner
|
||||
DiceRewardConfig::clearRequestInstance();
|
||||
|
||||
$configType0 = DiceLotteryPoolConfig::findByNameForDept('default', $deptId);
|
||||
$configType1 = DiceLotteryPoolConfig::findByNameForDept('killScore', $deptId);
|
||||
$configKill = DiceLotteryPoolConfig::findByNameForDept('killScore', $deptId);
|
||||
$configFree = DiceLotteryPoolConfig::findByNameForDept('free', $deptId);
|
||||
if (!$configType0) {
|
||||
$this->markFailed($recordId, '彩金池配置 name=default 不存在(当前渠道)');
|
||||
return;
|
||||
@@ -92,9 +96,9 @@ class WeightTestRunner
|
||||
if (!$paidPoolConfig || AdminScopeHelper::normalizeRecordDeptId($paidPoolConfig->dept_id ?? null) !== $deptId) {
|
||||
$paidPoolConfig = $configType0;
|
||||
}
|
||||
$freePoolConfig = $freePoolConfigId > 0 ? DiceLotteryPoolConfig::find($freePoolConfigId) : $configType1;
|
||||
$freePoolConfig = $freePoolConfigId > 0 ? DiceLotteryPoolConfig::find($freePoolConfigId) : $configFree;
|
||||
if (!$freePoolConfig || AdminScopeHelper::normalizeRecordDeptId($freePoolConfig->dept_id ?? null) !== $deptId) {
|
||||
$freePoolConfig = $configType1 ?: $configType0;
|
||||
$freePoolConfig = $configFree ?: $configType0;
|
||||
}
|
||||
|
||||
if ($paidTierWeightsCustom !== null && array_sum($paidTierWeightsCustom) <= 0) {
|
||||
@@ -111,13 +115,14 @@ class WeightTestRunner
|
||||
DiceReward::clearRequestInstance();
|
||||
|
||||
$killModeEnabled = (int) ($record->kill_mode_enabled ?? 0) === 1;
|
||||
$testSafetyLine = (int) ($record->test_safety_line ?? 5000);
|
||||
if ($testSafetyLine < 0) {
|
||||
$testSafetyLine = 0;
|
||||
}
|
||||
$safetyLine = (int) ($configType0->safety_line ?? 0);
|
||||
$dbKillEnabled = ((int) ($configType0->kill_enabled ?? 1)) === 1;
|
||||
|
||||
// 测试内“玩家累计盈利”:用于控制付费局是否切换杀分
|
||||
$playerProfitTotal = 0.0;
|
||||
// 彩金池累计盈利:与线上一致,从 default.profit_amount 起步并在测试内逐局累加
|
||||
$poolProfitTotal = (float) ($configType0->profit_amount ?? 0);
|
||||
|
||||
// 付费未杀分时的模拟玩家档位权重(自定义 > 快照 > 兜底奖池)
|
||||
$paidPlayerWeights = $paidTierWeightsCustom ?? $this->resolveTierWeightsSnapshot($record, 'paid');
|
||||
|
||||
$playLogic = new PlayStartLogic();
|
||||
$resultCounts = [];
|
||||
@@ -133,14 +138,16 @@ class WeightTestRunner
|
||||
$paidS,
|
||||
$paidN,
|
||||
$ante,
|
||||
$configType0,
|
||||
$paidPoolConfig,
|
||||
$freePoolConfig,
|
||||
$configType1,
|
||||
$paidTierWeightsCustom,
|
||||
$configKill,
|
||||
$paidPlayerWeights,
|
||||
$freeTierWeightsCustom,
|
||||
$killModeEnabled,
|
||||
$testSafetyLine,
|
||||
$playerProfitTotal,
|
||||
$safetyLine,
|
||||
$dbKillEnabled,
|
||||
$poolProfitTotal,
|
||||
$resultCounts,
|
||||
$tierCounts,
|
||||
$buffer,
|
||||
@@ -172,14 +179,16 @@ class WeightTestRunner
|
||||
int $paidS,
|
||||
int $paidN,
|
||||
int $ante,
|
||||
$defaultPoolConfig,
|
||||
$paidPoolConfig,
|
||||
$freePoolConfig,
|
||||
$killPoolConfig,
|
||||
?array $paidTierWeightsCustom,
|
||||
?array $paidPlayerWeights,
|
||||
?array $freeTierWeightsCustom,
|
||||
bool $killModeEnabled,
|
||||
int $testSafetyLine,
|
||||
float &$playerProfitTotal,
|
||||
int $safetyLine,
|
||||
bool $dbKillEnabled,
|
||||
float &$poolProfitTotal,
|
||||
array &$resultCounts,
|
||||
array &$tierCounts,
|
||||
array &$buffer,
|
||||
@@ -201,13 +210,21 @@ class WeightTestRunner
|
||||
$lotteryType = $isPaid ? 0 : 1;
|
||||
|
||||
if ($isPaid) {
|
||||
$useKillForPaid = $killModeEnabled && $playerProfitTotal >= $testSafetyLine && $killPoolConfig !== null;
|
||||
$useKillForPaid = $killModeEnabled
|
||||
&& $dbKillEnabled
|
||||
&& $poolProfitTotal >= $safetyLine
|
||||
&& $killPoolConfig !== null;
|
||||
if ($useKillForPaid) {
|
||||
$cfg = $killPoolConfig;
|
||||
$customWeights = null;
|
||||
} else {
|
||||
$cfg = $paidPoolConfig;
|
||||
$customWeights = $paidTierWeightsCustom;
|
||||
// 付费未杀分:模拟玩家档位权重,lottery_config_id 记 default(与 PlayStartLogic 一致)
|
||||
$cfg = $defaultPoolConfig;
|
||||
$customWeights = $paidPlayerWeights;
|
||||
if ($customWeights === null) {
|
||||
$cfg = $paidPoolConfig;
|
||||
$customWeights = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$cfg = $freePoolConfig;
|
||||
@@ -217,7 +234,8 @@ class WeightTestRunner
|
||||
$row = $playLogic->simulateOnePlay($cfg, $dir, $lotteryType, $playAnte, $customWeights, $deptId);
|
||||
$winCoin = (float) ($row['win_coin'] ?? 0);
|
||||
$paidAmount = (float) ($row['paid_amount'] ?? 0);
|
||||
$playerProfitTotal += $winCoin - $paidAmount;
|
||||
$perPlayProfit = $isPaid ? ($winCoin - $paidAmount) : $winCoin;
|
||||
$poolProfitTotal += round($perPlayProfit, 2);
|
||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||
$buffer[] = $this->rowForInsert($row, $recordId, $deptId);
|
||||
$done++;
|
||||
@@ -232,6 +250,23 @@ class WeightTestRunner
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 tier_weights_snapshot 读取付费/免费档位权重快照
|
||||
*/
|
||||
private function resolveTierWeightsSnapshot(DiceRewardConfigRecord $record, string $side): ?array
|
||||
{
|
||||
$snap = $record->tier_weights_snapshot ?? null;
|
||||
if (! is_array($snap)) {
|
||||
return null;
|
||||
}
|
||||
$weights = $snap[$side] ?? null;
|
||||
if (! is_array($weights) || $weights === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $weights;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析本次测试渠道:优先读库字段,避免 ORM 字段缓存未含 dept_id 时读不到
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user