优化彩金池安全线触发方式
This commit is contained in:
@@ -97,7 +97,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前彩金池(Redis 实例化,无则按 type=0 创建),含 profit_amount 实时值
|
* 获取当前彩金池(Redis 实例化,无则按 type=0 创建),含玩家累计盈利 profit_amount 实时值
|
||||||
*/
|
*/
|
||||||
getCurrentPool() {
|
getCurrentPool() {
|
||||||
return request.get<{
|
return request.get<{
|
||||||
@@ -130,5 +130,14 @@ export default {
|
|||||||
url: '/core/dice/lottery_pool_config/DiceLotteryPoolConfig/updateCurrentPool',
|
url: '/core/dice/lottery_pool_config/DiceLotteryPoolConfig/updateCurrentPool',
|
||||||
data: params
|
data: params
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置当前彩金池的玩家累计盈利(profit_amount 置为 0)
|
||||||
|
*/
|
||||||
|
resetProfitAmount() {
|
||||||
|
return request.post<any>({
|
||||||
|
url: '/core/dice/lottery_pool_config/DiceLotteryPoolConfig/resetProfitAmount'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,19 +16,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="profit-row mb-3">
|
<div class="profit-row mb-3">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="text-gray-500">彩金池盈利(profit_amount):</span>
|
<span class="text-gray-500">玩家累计盈利(profit_amount):</span>
|
||||||
<span class="font-mono text-lg" :class="profitAmountClass">{{ displayProfitAmount }}</span>
|
<span class="font-mono text-lg" :class="profitAmountClass">{{
|
||||||
|
displayProfitAmount
|
||||||
|
}}</span>
|
||||||
<span class="realtime-badge">实时</span>
|
<span class="realtime-badge">实时</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="profit-calc-hint">
|
<div class="profit-calc-hint">
|
||||||
计算方式:每局抽奖扣除本局发放成本(普通档位 real_ev + 中大奖时 BIGWIN.real_ev),弹窗打开期间每 2 秒自动刷新
|
计算方式:每局按“当前中奖金额(含超级大奖 BIGWIN)减去抽奖券费用 100”累加,弹窗打开期间每 2 秒自动刷新
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tip-block">
|
<div class="tip-block">
|
||||||
<div class="tip-title">抽奖档位规则</div>
|
<div class="tip-title">抽奖档位规则</div>
|
||||||
<div class="tip-content">
|
<div class="tip-content">
|
||||||
当彩金池盈利 <strong>低于安全线</strong> 时,按<strong>玩家</strong>的 T*_weight 权重抽取抽奖档位;
|
当玩家在当前彩金池的累计盈利 <strong>低于安全线</strong> 时,按<strong>玩家</strong>的 T*_weight 权重抽取档位;
|
||||||
当彩金池盈利 <strong>高于或等于安全线</strong> 时,按<strong>当前彩金池</strong>的 T*_weight 权重抽取档位。
|
当累计盈利 <strong>高于或等于安全线</strong> 时,按<strong>当前彩金池</strong>的 T*_weight 权重抽取档位(杀分)。
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,6 +70,9 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="handleClose">关闭</el-button>
|
<el-button @click="handleClose">关闭</el-button>
|
||||||
|
<el-button :loading="resetting" :disabled="!pool" @click="handleResetProfit">
|
||||||
|
重置玩家累计盈利
|
||||||
|
</el-button>
|
||||||
<el-button type="primary" :loading="saving" :disabled="!pool" @click="handleSubmit">
|
<el-button type="primary" :loading="saving" :disabled="!pool" @click="handleSubmit">
|
||||||
保存权重与安全线
|
保存权重与安全线
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -102,6 +107,7 @@
|
|||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const saving = ref(false)
|
const saving = ref(false)
|
||||||
|
const resetting = ref(false)
|
||||||
const pool = ref<PoolData | null>(null)
|
const pool = ref<PoolData | null>(null)
|
||||||
const formRef = ref<FormInstance>()
|
const formRef = ref<FormInstance>()
|
||||||
|
|
||||||
@@ -221,6 +227,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleResetProfit() {
|
||||||
|
if (!pool.value) return
|
||||||
|
try {
|
||||||
|
resetting.value = true
|
||||||
|
await api.resetProfitAmount()
|
||||||
|
ElMessage.success('玩家累计盈利已重置为 0')
|
||||||
|
await loadPool()
|
||||||
|
emit('success')
|
||||||
|
} catch (e: any) {
|
||||||
|
ElMessage.error(e?.message ?? '重置失败')
|
||||||
|
} finally {
|
||||||
|
resetting.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
stopPolling()
|
stopPolling()
|
||||||
visible.value = false
|
visible.value = false
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class PlayStartLogic
|
|||||||
$config = $ticketType === self::LOTTERY_TYPE_PAID
|
$config = $ticketType === self::LOTTERY_TYPE_PAID
|
||||||
? ($lotteryService->getConfigType0Id() ? DiceLotteryPoolConfig::find($lotteryService->getConfigType0Id()) : null)
|
? ($lotteryService->getConfigType0Id() ? DiceLotteryPoolConfig::find($lotteryService->getConfigType0Id()) : null)
|
||||||
: ($lotteryService->getConfigType1Id() ? DiceLotteryPoolConfig::find($lotteryService->getConfigType1Id()) : null);
|
: ($lotteryService->getConfigType1Id() ? DiceLotteryPoolConfig::find($lotteryService->getConfigType1Id()) : null);
|
||||||
// 未找到付费/免费对应配置时,统一回退到 type=0 的彩金池,保证所有玩家累加同一彩金池
|
// 未找到付费/免费对应配置时,统一回退到 type=0 的彩金池
|
||||||
if (!$config) {
|
if (!$config) {
|
||||||
$config = DiceLotteryPoolConfig::where('type', 0)->find();
|
$config = DiceLotteryPoolConfig::where('type', 0)->find();
|
||||||
}
|
}
|
||||||
@@ -81,10 +81,16 @@ class PlayStartLogic
|
|||||||
throw new ApiException('奖池配置不存在');
|
throw new ApiException('奖池配置不存在');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 彩金池盈利低于安全线时按玩家权重抽档,高于或等于安全线时按奖池权重抽档
|
// 计算当前玩家在该彩金池中的累计盈利金额:当前中奖金额(含 BIGWIN)减去抽奖券费用 100
|
||||||
$poolProfit = (float) ($config->profit_amount ?? $config->ev ?? 0);
|
$playerQuery = DicePlayRecord::where('player_id', $playerId)
|
||||||
|
->where('lottery_config_id', $config->id)
|
||||||
|
->where('status', self::RECORD_STATUS_SUCCESS);
|
||||||
|
$playerWinSum = (float) $playerQuery->sum('win_coin');
|
||||||
|
$playerPlayCount = (int) $playerQuery->count();
|
||||||
|
$playerProfitTotal = $playerWinSum - 100.0 * $playerPlayCount;
|
||||||
$safetyLine = (int) ($config->safety_line ?? 0);
|
$safetyLine = (int) ($config->safety_line ?? 0);
|
||||||
$usePoolWeights = $poolProfit >= $safetyLine;
|
// 玩家累计盈利金额达到或超过安全线时,按奖池 T*_weight 杀分;否则按玩家 T*_weight 抽档位
|
||||||
|
$usePoolWeights = $playerProfitTotal >= $safetyLine;
|
||||||
|
|
||||||
// 按档位 T1-T5 抽取后,从 DiceReward 表按当前方向取该档位数据,再按 weight 抽取一条得到 grid_number
|
// 按档位 T1-T5 抽取后,从 DiceReward 表按当前方向取该档位数据,再按 weight 抽取一条得到 grid_number
|
||||||
$rewardInstance = DiceReward::getCachedInstance();
|
$rewardInstance = DiceReward::getCachedInstance();
|
||||||
@@ -244,10 +250,10 @@ class PlayStartLogic
|
|||||||
|
|
||||||
$p->save();
|
$p->save();
|
||||||
|
|
||||||
// 彩金池盈利:每局扣除本局发放的真实成本(普通档位 real_ev + BIGWIN.real_ev 如触发),不额外加 100
|
// 玩家累计盈利底层仍使用 profit_amount 字段存储:每局按“当前中奖金额(含 BIGWIN) - 抽奖券费用 100”累加
|
||||||
// 需确保表有 profit_amount 字段(见 db/dice_lottery_config_add_profit_amount.sql)
|
// 需确保表有 profit_amount 字段(见 db/dice_lottery_config_add_profit_amount.sql)
|
||||||
$totalRealEv = $realEv + $bigWinRealEv;
|
$perPlayProfit = $winCoin - 100.0;
|
||||||
$addProfit = -$totalRealEv;
|
$addProfit = $perPlayProfit;
|
||||||
try {
|
try {
|
||||||
DiceLotteryPoolConfig::where('id', $configId)->update([
|
DiceLotteryPoolConfig::where('id', $configId)->update([
|
||||||
'profit_amount' => Db::raw('IFNULL(profit_amount,0) + ' . (float) $addProfit),
|
'profit_amount' => Db::raw('IFNULL(profit_amount,0) + ' . (float) $addProfit),
|
||||||
@@ -479,6 +485,7 @@ class PlayStartLogic
|
|||||||
|
|
||||||
$superWinCoin = 0;
|
$superWinCoin = 0;
|
||||||
$isWin = 0;
|
$isWin = 0;
|
||||||
|
$bigWinRealEv = 0.0;
|
||||||
if (in_array($rollNumber, self::SUPER_WIN_GRID_NUMBERS, true)) {
|
if (in_array($rollNumber, self::SUPER_WIN_GRID_NUMBERS, true)) {
|
||||||
$bigWinConfig = DiceRewardConfig::getCachedByTierAndGridNumber('BIGWIN', $rollNumber);
|
$bigWinConfig = DiceRewardConfig::getCachedByTierAndGridNumber('BIGWIN', $rollNumber);
|
||||||
$alwaysSuperWin = in_array($rollNumber, self::SUPER_WIN_ALWAYS_GRID_NUMBERS, true);
|
$alwaysSuperWin = in_array($rollNumber, self::SUPER_WIN_ALWAYS_GRID_NUMBERS, true);
|
||||||
@@ -491,10 +498,13 @@ class PlayStartLogic
|
|||||||
$roll = (random_int(0, PHP_INT_MAX - 1) / (float) PHP_INT_MAX);
|
$roll = (random_int(0, PHP_INT_MAX - 1) / (float) PHP_INT_MAX);
|
||||||
$doSuperWin = $bigWinWeight > 0 && $roll < ($bigWinWeight / 10000.0);
|
$doSuperWin = $bigWinWeight > 0 && $roll < ($bigWinWeight / 10000.0);
|
||||||
}
|
}
|
||||||
|
if ($bigWinConfig !== null && isset($bigWinConfig['real_ev'])) {
|
||||||
|
$bigWinRealEv = (float) $bigWinConfig['real_ev'];
|
||||||
|
}
|
||||||
if ($doSuperWin) {
|
if ($doSuperWin) {
|
||||||
$rollArray = $this->getSuperWinRollArray($rollNumber);
|
$rollArray = $this->getSuperWinRollArray($rollNumber);
|
||||||
$isWin = 1;
|
$isWin = 1;
|
||||||
$superWinCoin = ($bigWinConfig['real_ev'] ?? 0) > 0 ? (float) ($bigWinConfig['real_ev'] ?? 0) : self::SUPER_WIN_BONUS;
|
$superWinCoin = $bigWinRealEv > 0 ? $bigWinRealEv : self::SUPER_WIN_BONUS;
|
||||||
$rewardWinCoin = 0;
|
$rewardWinCoin = 0;
|
||||||
} else {
|
} else {
|
||||||
$rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber);
|
$rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber);
|
||||||
@@ -507,6 +517,7 @@ class PlayStartLogic
|
|||||||
$configId = $config !== null ? (int) $config->id : 0;
|
$configId = $config !== null ? (int) $config->id : 0;
|
||||||
$rewardId = ($isWin === 1 && $superWinCoin > 0) ? 0 : $targetIndex;
|
$rewardId = ($isWin === 1 && $superWinCoin > 0) ? 0 : $targetIndex;
|
||||||
$configName = $config !== null ? (string) ($config->name ?? '') : '自定义';
|
$configName = $config !== null ? (string) ($config->name ?? '') : '自定义';
|
||||||
|
$costRealEv = $realEv + ($isWin === 1 ? $bigWinRealEv : 0.0);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'player_id' => 0,
|
'player_id' => 0,
|
||||||
@@ -528,6 +539,9 @@ class PlayStartLogic
|
|||||||
'status' => self::RECORD_STATUS_SUCCESS,
|
'status' => self::RECORD_STATUS_SUCCESS,
|
||||||
'tier' => $tier,
|
'tier' => $tier,
|
||||||
'roll_number_for_count' => $rollNumber,
|
'roll_number_for_count' => $rollNumber,
|
||||||
|
'real_ev' => $realEv,
|
||||||
|
'bigwin_real_ev' => $isWin === 1 ? $bigWinRealEv : 0.0,
|
||||||
|
'cost_ev' => $costRealEv,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class DiceLotteryPoolConfigController extends BaseController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前彩金池(Redis 实例化,无则按 type=0 创建)
|
* 获取当前彩金池(Redis 实例化,无则按 type=0 创建)
|
||||||
* 返回含 profit_amount 实时值,供前端轮询展示
|
* 返回含玩家累计盈利 profit_amount 实时值,供前端轮询展示
|
||||||
*/
|
*/
|
||||||
#[Permission('色子奖池配置列表', 'dice:lottery_pool_config:index:index')]
|
#[Permission('色子奖池配置列表', 'dice:lottery_pool_config:index:index')]
|
||||||
public function getCurrentPool(Request $request): Response
|
public function getCurrentPool(Request $request): Response
|
||||||
@@ -168,4 +168,14 @@ class DiceLotteryPoolConfigController extends BaseController
|
|||||||
$this->logic->updateCurrentPool($data);
|
$this->logic->updateCurrentPool($data);
|
||||||
return $this->success('保存成功');
|
return $this->success('保存成功');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置当前彩金池的玩家累计盈利:将 profit_amount 置为 0
|
||||||
|
*/
|
||||||
|
#[Permission('色子奖池配置修改', 'dice:lottery_pool_config:index:update')]
|
||||||
|
public function resetProfitAmount(Request $request): Response
|
||||||
|
{
|
||||||
|
$this->logic->resetProfitAmount();
|
||||||
|
return $this->success('重置成功');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class DiceLotteryPoolConfigLogic extends BaseLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前彩金池:从 Redis 读取实例,profit_amount 每次从 DB 实时读取以保证与抽奖累加一致
|
* 获取当前彩金池:从 Redis 读取实例,profit_amount 每次从 DB 实时读取(表示玩家在该池子的累计盈利)
|
||||||
*
|
*
|
||||||
* @return array{id:int,name:string,safety_line:int,t1_weight:int,t2_weight:int,t3_weight:int,t4_weight:int,t5_weight:int,profit_amount:float}
|
* @return array{id:int,name:string,safety_line:int,t1_weight:int,t2_weight:int,t3_weight:int,t4_weight:int,t5_weight:int,profit_amount:float}
|
||||||
*/
|
*/
|
||||||
@@ -109,4 +109,16 @@ class DiceLotteryPoolConfigLogic extends BaseLogic
|
|||||||
: (float) ($pool['profit_amount'] ?? 0);
|
: (float) ($pool['profit_amount'] ?? 0);
|
||||||
Cache::set(self::REDIS_KEY_CURRENT_POOL, json_encode($pool), self::EXPIRE);
|
Cache::set(self::REDIS_KEY_CURRENT_POOL, json_encode($pool), self::EXPIRE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置当前彩金池的玩家累计盈利:将 profit_amount 置为 0,并刷新 Redis 缓存
|
||||||
|
*/
|
||||||
|
public function resetProfitAmount(): void
|
||||||
|
{
|
||||||
|
$pool = $this->getCurrentPool();
|
||||||
|
$id = (int) $pool['id'];
|
||||||
|
DiceLotteryPoolConfig::where('id', $id)->update(['profit_amount' => 0]);
|
||||||
|
$pool['profit_amount'] = 0.0;
|
||||||
|
Cache::set(self::REDIS_KEY_CURRENT_POOL, json_encode($pool), self::EXPIRE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
|||||||
use app\dice\model\reward\DiceReward;
|
use app\dice\model\reward\DiceReward;
|
||||||
use app\dice\model\reward_config\DiceRewardConfig;
|
use app\dice\model\reward_config\DiceRewardConfig;
|
||||||
use support\Log;
|
use support\Log;
|
||||||
|
use support\think\Db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一键测试权重:单进程后台执行模拟摇色子,写入 dice_play_record_test 并更新 dice_reward_config_record 进度
|
* 一键测试权重:单进程后台执行模拟摇色子,写入 dice_play_record_test 并更新 dice_reward_config_record 进度
|
||||||
@@ -67,27 +68,31 @@ class WeightTestRunner
|
|||||||
$this->markFailed($recordId, '免费奖池配置不存在');
|
$this->markFailed($recordId, '免费奖池配置不存在');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$paidTierWeights = null;
|
$paidTierWeights = (is_array($record->paid_tier_weights ?? null) && $record->paid_tier_weights !== [])
|
||||||
$freeTierWeights = null;
|
? $record->paid_tier_weights
|
||||||
if ($paidConfig === null) {
|
: null;
|
||||||
$paidTierWeights = $record->paid_tier_weights;
|
$freeTierWeights = (is_array($record->free_tier_weights ?? null) && $record->free_tier_weights !== [])
|
||||||
if (!is_array($paidTierWeights) || $paidTierWeights === []) {
|
? $record->free_tier_weights
|
||||||
$this->markFailed($recordId, '付费未选奖池时需提供 paid_tier_weights');
|
: null;
|
||||||
return;
|
if ($paidConfig === null && $paidTierWeights === null) {
|
||||||
}
|
$this->markFailed($recordId, '付费未选奖池时需提供 paid_tier_weights');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if ($freeConfig === null) {
|
if ($freeConfig === null && $freeTierWeights === null) {
|
||||||
$freeTierWeights = $record->free_tier_weights;
|
$this->markFailed($recordId, '免费未选奖池时需提供 free_tier_weights');
|
||||||
if (!is_array($freeTierWeights) || $freeTierWeights === []) {
|
return;
|
||||||
$this->markFailed($recordId, '免费未选奖池时需提供 free_tier_weights');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 每次测试开始前清空进程内静态缓存,强制从共享缓存读取最新 BIGWIN/奖励配置,与数据库一致
|
// 每次测试开始前清空进程内静态缓存,强制从共享缓存读取最新 BIGWIN/奖励配置,与数据库一致
|
||||||
DiceRewardConfig::clearRequestInstance();
|
DiceRewardConfig::clearRequestInstance();
|
||||||
DiceReward::clearRequestInstance();
|
DiceReward::clearRequestInstance();
|
||||||
|
|
||||||
|
// 测试时按“单个虚拟玩家”累计中奖金额来判断是否触发杀分:达到 safety_line 前用自定义档位(玩家权重),达到后用奖池权重
|
||||||
|
$paidSafetyLine = $paidConfig !== null ? (int) ($paidConfig->safety_line ?? 0) : 0;
|
||||||
|
$freeSafetyLine = $freeConfig !== null ? (int) ($freeConfig->safety_line ?? 0) : 0;
|
||||||
|
$paidPlayerWinTotal = 0.0;
|
||||||
|
$freePlayerWinTotal = 0.0;
|
||||||
|
|
||||||
$playLogic = new PlayStartLogic();
|
$playLogic = new PlayStartLogic();
|
||||||
$resultCounts = [];
|
$resultCounts = [];
|
||||||
$tierCounts = [];
|
$tierCounts = [];
|
||||||
@@ -96,28 +101,40 @@ class WeightTestRunner
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
for ($i = 0; $i < $paidS; $i++) {
|
for ($i = 0; $i < $paidS; $i++) {
|
||||||
$row = $playLogic->simulateOnePlay($paidConfig, 0, 0, $paidTierWeights);
|
$usePoolWeights = $paidConfig !== null && $paidPlayerWinTotal >= $paidSafetyLine && $paidSafetyLine > 0;
|
||||||
|
$customWeights = $usePoolWeights ? null : $paidTierWeights;
|
||||||
|
$row = $playLogic->simulateOnePlay($paidConfig, 0, 0, $customWeights);
|
||||||
|
$this->accumulatePlayerWin($row, $paidPlayerWinTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
$done++;
|
$done++;
|
||||||
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
||||||
}
|
}
|
||||||
for ($i = 0; $i < $paidN; $i++) {
|
for ($i = 0; $i < $paidN; $i++) {
|
||||||
$row = $playLogic->simulateOnePlay($paidConfig, 1, 0, $paidTierWeights);
|
$usePoolWeights = $paidConfig !== null && $paidPlayerWinTotal >= $paidSafetyLine && $paidSafetyLine > 0;
|
||||||
|
$customWeights = $usePoolWeights ? null : $paidTierWeights;
|
||||||
|
$row = $playLogic->simulateOnePlay($paidConfig, 1, 0, $customWeights);
|
||||||
|
$this->accumulatePlayerWin($row, $paidPlayerWinTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
$done++;
|
$done++;
|
||||||
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
||||||
}
|
}
|
||||||
for ($i = 0; $i < $freeS; $i++) {
|
for ($i = 0; $i < $freeS; $i++) {
|
||||||
$row = $playLogic->simulateOnePlay($freeConfig, 0, 1, $freeTierWeights);
|
$usePoolWeights = $freeConfig !== null && $freePlayerWinTotal >= $freeSafetyLine && $freeSafetyLine > 0;
|
||||||
|
$customWeights = $usePoolWeights ? null : $freeTierWeights;
|
||||||
|
$row = $playLogic->simulateOnePlay($freeConfig, 0, 1, $customWeights);
|
||||||
|
$this->accumulatePlayerWin($row, $freePlayerWinTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
$done++;
|
$done++;
|
||||||
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
$this->flushIfNeeded($buffer, $recordId, $done, $total, $resultCounts, $tierCounts);
|
||||||
}
|
}
|
||||||
for ($i = 0; $i < $freeN; $i++) {
|
for ($i = 0; $i < $freeN; $i++) {
|
||||||
$row = $playLogic->simulateOnePlay($freeConfig, 1, 1, $freeTierWeights);
|
$usePoolWeights = $freeConfig !== null && $freePlayerWinTotal >= $freeSafetyLine && $freeSafetyLine > 0;
|
||||||
|
$customWeights = $usePoolWeights ? null : $freeTierWeights;
|
||||||
|
$row = $playLogic->simulateOnePlay($freeConfig, 1, 1, $customWeights);
|
||||||
|
$this->accumulatePlayerWin($row, $freePlayerWinTotal);
|
||||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||||
$done++;
|
$done++;
|
||||||
@@ -135,6 +152,15 @@ class WeightTestRunner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 累加单个虚拟玩家在测试过程中的中奖金额(win_coin) */
|
||||||
|
private function accumulatePlayerWin(array $row, float &$runningWinTotal): void
|
||||||
|
{
|
||||||
|
if (!isset($row['win_coin'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$runningWinTotal += (float) $row['win_coin'];
|
||||||
|
}
|
||||||
|
|
||||||
private function aggregate(array $row, array &$resultCounts, array &$tierCounts): void
|
private function aggregate(array $row, array &$resultCounts, array &$tierCounts): void
|
||||||
{
|
{
|
||||||
$grid = (int) ($row['roll_number_for_count'] ?? $row['roll_number'] ?? 0);
|
$grid = (int) ($row['roll_number_for_count'] ?? $row['roll_number'] ?? 0);
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ Route::group('/core', function () {
|
|||||||
Route::get('/dice/lottery_pool_config/DiceLotteryPoolConfig/getOptions', [\app\dice\controller\lottery_pool_config\DiceLotteryPoolConfigController::class, 'getOptions']);
|
Route::get('/dice/lottery_pool_config/DiceLotteryPoolConfig/getOptions', [\app\dice\controller\lottery_pool_config\DiceLotteryPoolConfigController::class, 'getOptions']);
|
||||||
Route::get('/dice/lottery_pool_config/DiceLotteryPoolConfig/getCurrentPool', [\app\dice\controller\lottery_pool_config\DiceLotteryPoolConfigController::class, 'getCurrentPool']);
|
Route::get('/dice/lottery_pool_config/DiceLotteryPoolConfig/getCurrentPool', [\app\dice\controller\lottery_pool_config\DiceLotteryPoolConfigController::class, 'getCurrentPool']);
|
||||||
Route::post('/dice/lottery_pool_config/DiceLotteryPoolConfig/updateCurrentPool', [\app\dice\controller\lottery_pool_config\DiceLotteryPoolConfigController::class, 'updateCurrentPool']);
|
Route::post('/dice/lottery_pool_config/DiceLotteryPoolConfig/updateCurrentPool', [\app\dice\controller\lottery_pool_config\DiceLotteryPoolConfigController::class, 'updateCurrentPool']);
|
||||||
|
Route::post('/dice/lottery_pool_config/DiceLotteryPoolConfig/resetProfitAmount', [\app\dice\controller\lottery_pool_config\DiceLotteryPoolConfigController::class, 'resetProfitAmount']);
|
||||||
fastRoute('dice/reward_config_record/DiceRewardConfigRecord', \app\dice\controller\reward_config_record\DiceRewardConfigRecordController::class);
|
fastRoute('dice/reward_config_record/DiceRewardConfigRecord', \app\dice\controller\reward_config_record\DiceRewardConfigRecordController::class);
|
||||||
Route::post('/dice/reward_config_record/DiceRewardConfigRecord/importFromRecord', [\app\dice\controller\reward_config_record\DiceRewardConfigRecordController::class, 'importFromRecord']);
|
Route::post('/dice/reward_config_record/DiceRewardConfigRecord/importFromRecord', [\app\dice\controller\reward_config_record\DiceRewardConfigRecordController::class, 'importFromRecord']);
|
||||||
fastRoute('dice/play_record_test/DicePlayRecordTest', \app\dice\controller\play_record_test\DicePlayRecordTestController::class);
|
fastRoute('dice/play_record_test/DicePlayRecordTest', \app\dice\controller\play_record_test\DicePlayRecordTestController::class);
|
||||||
|
|||||||
Reference in New Issue
Block a user