优化ai小班长
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* 在每局百家乐开启时延迟调度执行:
|
||||
* 1. 检查是否存在连输休息惩罚(1小时)
|
||||
* 2. 检查可用金币,确保留存底金
|
||||
* 2. 检查可用金币与活动时间窗,确定本局下注额度
|
||||
* 3. 调用 AI 接口预测路单走势决定下注方向(AI 不可用时回退本地决策)
|
||||
* 4. 提交下注
|
||||
*
|
||||
@@ -87,10 +87,10 @@ class AiBaccaratBetJob implements ShouldQueue
|
||||
// 5. 查询当前是否命中“你玩游戏我买单”活动窗口。
|
||||
$lossCoverService = app(BaccaratLossCoverService::class);
|
||||
$lossCoverEvent = $lossCoverService->findEventForBetTime(now());
|
||||
$hasActiveLossCover = $lossCoverEvent?->status === 'active';
|
||||
$isInLossCoverWindow = $lossCoverEvent !== null;
|
||||
|
||||
// 买单活动进行中时允许 AI 全仓下注;平时只动用当前手上的 jjb,不再强制保留 100 万。
|
||||
$bettableGold = $hasActiveLossCover
|
||||
// 买单活动进行中时允许 AI 统筹“手上 + 银行”总资产;平时只动用当前手上的 jjb。
|
||||
$bettableGold = $isInLossCoverWindow
|
||||
? $aiFinance->getTotalGoldAssets($user)
|
||||
: $aiFinance->getSpendableGold($user);
|
||||
if ($bettableGold < $minBet) {
|
||||
@@ -129,7 +129,7 @@ class AiBaccaratBetJob implements ShouldQueue
|
||||
'recent_results' => $recentResults,
|
||||
'available_gold' => $bettableGold,
|
||||
'historical_bets' => $historicalBets,
|
||||
'loss_cover_active' => $hasActiveLossCover,
|
||||
'loss_cover_active' => $isInLossCoverWindow,
|
||||
];
|
||||
|
||||
$aiPrediction = $predictionService->predict($context);
|
||||
@@ -145,10 +145,10 @@ class AiBaccaratBetJob implements ShouldQueue
|
||||
$reason = $aiPrediction['reason'];
|
||||
|
||||
if ($betType !== 'pass') {
|
||||
if ($hasActiveLossCover) {
|
||||
// 买单活动进行中时,AI 可放心动用全部总资产,因为本局若输可返还。
|
||||
$amount = $bettableGold;
|
||||
$reason = trim($reason.' 买单活动进行中,本局采用总资产全额下注策略。');
|
||||
if ($isInLossCoverWindow) {
|
||||
// 买单活动进行中且金币足够时,直接按百家乐单局最高限额下注。
|
||||
$amount = min($bettableGold, $maxBet);
|
||||
$reason = trim($reason.' 买单活动进行中,本局按百家乐最高限额下注。');
|
||||
} else {
|
||||
// 非买单活动期间,限定单局最高下注不超过手头金币的 5% 以防止 AI 破产。
|
||||
$percent = min(5, max(0, $percent));
|
||||
@@ -177,10 +177,10 @@ class AiBaccaratBetJob implements ShouldQueue
|
||||
}
|
||||
|
||||
if ($betType !== 'pass') {
|
||||
if ($hasActiveLossCover) {
|
||||
// 本地兜底策略命中买单活动时,同样执行总资产全额下注。
|
||||
$amount = $bettableGold;
|
||||
$reason = '买单活动进行中,采用本地总资产全额下注兜底策略。';
|
||||
if ($isInLossCoverWindow) {
|
||||
// 本地兜底策略命中买单活动时,同样优先按百家乐最高限额下注。
|
||||
$amount = min($bettableGold, $maxBet);
|
||||
$reason = '买单活动进行中,采用本地最高限额下注兜底策略。';
|
||||
} else {
|
||||
$percent = rand(2, 5) / 100.0;
|
||||
$amount = (int) round($bettableGold * $percent);
|
||||
@@ -207,8 +207,8 @@ class AiBaccaratBetJob implements ShouldQueue
|
||||
return;
|
||||
}
|
||||
|
||||
// 买单活动期间允许全仓下注;非活动期间只检查当前手上金币是否够本次下注。
|
||||
$isReadyToSpend = $hasActiveLossCover
|
||||
// 买单活动期间允许为本次高额下注从银行调拨;非活动期间只检查当前手上金币是否够本次下注。
|
||||
$isReadyToSpend = $isInLossCoverWindow
|
||||
? $aiFinance->prepareAllInSpend($user, $amount)
|
||||
: $aiFinance->prepareSpend($user, $amount);
|
||||
if (! $isReadyToSpend) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* 统一维护 AI小班长的银行存取与阶段性理财里程碑公告,
|
||||
* 常规场景下仅在手上金币超过 100 万时自动存银行,
|
||||
* 特殊场景(如买单活动全仓下注)才会动用银行资产。
|
||||
* 特殊场景(如买单活动的大额下注)才会动用银行资产。
|
||||
*/
|
||||
|
||||
namespace App\Services;
|
||||
@@ -17,7 +17,7 @@ use App\Models\User;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 负责 AI小班长的常规存款、全仓取款与里程碑播报。
|
||||
* 负责 AI小班长的常规存款、大额调款与里程碑播报。
|
||||
*/
|
||||
class AiFinanceService
|
||||
{
|
||||
@@ -74,9 +74,9 @@ class AiFinanceService
|
||||
}
|
||||
|
||||
/**
|
||||
* 为全仓支出准备手头金币。
|
||||
* 为大额支出准备手头金币。
|
||||
*
|
||||
* 该模式不会保留手上余额阈值,适用于买单活动等可接受全额下注的场景。
|
||||
* 该模式不会保留手上余额阈值,适用于买单活动等需要临时调拨银行金币的场景。
|
||||
*/
|
||||
public function prepareAllInSpend(User $user, int $spendAmount): bool
|
||||
{
|
||||
|
||||
@@ -105,13 +105,17 @@ class BaccaratLossCoverService
|
||||
|
||||
/**
|
||||
* 获取某个下注时间点命中的活动。
|
||||
*
|
||||
* 这里按管理员设定的开始/结束时间窗口判断,
|
||||
* 不强依赖后台状态已经及时切到 active,
|
||||
* 这样刚到开始时间的活动也能立即参与买单判定。
|
||||
*/
|
||||
public function findEventForBetTime(?Carbon $betTime = null): ?BaccaratLossCoverEvent
|
||||
{
|
||||
$betTime = $betTime ?? now();
|
||||
|
||||
return BaccaratLossCoverEvent::query()
|
||||
->whereIn('status', ['active', 'settlement_pending', 'claimable'])
|
||||
->whereNotIn('status', ['cancelled', 'completed'])
|
||||
->where('starts_at', '<=', $betTime)
|
||||
->where('ends_at', '>=', $betTime)
|
||||
->orderByDesc('id')
|
||||
|
||||
@@ -106,10 +106,6 @@
|
||||
class="text-purple-300 hover:text-purple-100 font-bold flex items-center transition hidden sm:flex {{ request()->routeIs('duty-hall.*') ? 'text-purple-100 underline underline-offset-4' : '' }}">
|
||||
勤务台
|
||||
</a>
|
||||
<a href="{{ route('vip.center') }}"
|
||||
class="text-rose-400 hover:text-rose-300 font-bold flex items-center transition hidden sm:flex {{ request()->routeIs('vip.center') ? 'text-rose-200 underline underline-offset-4' : '' }}">
|
||||
会员中心
|
||||
</a>
|
||||
<a href="{{ route('guestbook.index') }}"
|
||||
class="text-indigo-200 hover:text-white font-bold flex items-center transition hidden sm:flex">
|
||||
留言板
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* 文件功能:AI小班长百家乐下注任务测试
|
||||
*
|
||||
* 覆盖 AI 在“你玩游戏我买单”活动进行中时的全额下注策略,
|
||||
* 覆盖 AI 在“你玩游戏我买单”活动时间窗口内的最高限额下注策略,
|
||||
* 并验证下注会正确挂到买单活动记录上。
|
||||
*/
|
||||
|
||||
@@ -57,9 +57,9 @@ class AiBaccaratBetJobTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* 买单活动进行中时,AI 会动用全部总资产下注,并把下注挂到活动名下。
|
||||
* 买单活动时间窗口命中时,AI 会按百家乐最大下注额下注,并把下注挂到活动名下。
|
||||
*/
|
||||
public function test_ai_bets_all_spendable_gold_when_loss_cover_event_is_active(): void
|
||||
public function test_ai_bets_baccarat_max_bet_when_loss_cover_time_window_is_active(): void
|
||||
{
|
||||
Event::fake();
|
||||
Queue::fake([SaveMessageJob::class]);
|
||||
@@ -87,7 +87,7 @@ class AiBaccaratBetJobTest extends TestCase
|
||||
]);
|
||||
|
||||
$event = BaccaratLossCoverEvent::factory()->create([
|
||||
'status' => 'active',
|
||||
'status' => 'scheduled',
|
||||
'starts_at' => now()->subMinutes(2),
|
||||
'ends_at' => now()->addMinutes(10),
|
||||
]);
|
||||
@@ -114,14 +114,14 @@ class AiBaccaratBetJobTest extends TestCase
|
||||
'user_id' => $aiUser->id,
|
||||
'loss_cover_event_id' => $event->id,
|
||||
'bet_type' => 'big',
|
||||
'amount' => 1200000,
|
||||
'amount' => 50000,
|
||||
'status' => 'pending',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('baccarat_loss_cover_records', [
|
||||
'event_id' => $event->id,
|
||||
'user_id' => $aiUser->id,
|
||||
'total_bet_amount' => 1200000,
|
||||
'total_bet_amount' => 50000,
|
||||
'claim_status' => 'not_eligible',
|
||||
]);
|
||||
|
||||
@@ -132,8 +132,8 @@ class AiBaccaratBetJobTest extends TestCase
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'id' => $aiUser->id,
|
||||
'jjb' => 0,
|
||||
'bank_jjb' => 0,
|
||||
'jjb' => 950000,
|
||||
'bank_jjb' => 200000,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
/**
|
||||
* 文件功能:AI小班长资金调度服务测试
|
||||
*
|
||||
* 覆盖 AI小班长的常规存款、全仓取款与阶段性目标公告逻辑,
|
||||
* 防止后续调整后再次出现“超过 100 万未存款”或全仓提取异常。
|
||||
* 覆盖 AI小班长的常规存款、大额调款与阶段性目标公告逻辑,
|
||||
* 防止后续调整后再次出现“超过 100 万未存款”或银行调款异常。
|
||||
*/
|
||||
|
||||
namespace Tests\Feature;
|
||||
@@ -19,7 +19,7 @@ use Illuminate\Support\Facades\Queue;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* 验证 AI小班长的常规存款与全仓调仓规则。
|
||||
* 验证 AI小班长的常规存款与大额调仓规则。
|
||||
*/
|
||||
class AiFinanceServiceTest extends TestCase
|
||||
{
|
||||
@@ -50,7 +50,7 @@ class AiFinanceServiceTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* 全仓支出场景允许从银行提取差额,把总资产集中到手上。
|
||||
* 大额支出场景允许从银行提取差额,把目标下注额调到手上。
|
||||
*/
|
||||
public function test_prepare_all_in_spend_withdraws_needed_gold_from_bank(): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user