Files
chatroom/app/Jobs/OpenHorseRaceJob.php
T

116 lines
3.5 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
/**
* 文件功能:赛马开赛队列任务
*
* 由调度器按配置间隔触发,游戏开启时创建新场次,
* 生成参赛马匹,广播开赛事件并安排跑马任务。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Jobs;
use App\Events\HorseRaceOpened;
use App\Events\MessageSent;
use App\Models\GameConfig;
use App\Models\HorseRace;
use App\Services\ChatStateService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
/**
* 类功能:按房间开启一场新的赛马竞猜回合。
*/
class OpenHorseRaceJob implements ShouldQueue
{
use Queueable;
/**
* 构造开赛任务。
*
* @param int $roomId 目标房间
*/
public function __construct(
public readonly int $roomId = 1,
) {}
/**
* 最大重试次数。
*/
public int $tries = 1;
/**
* 执行开赛逻辑。
*/
public function handle(ChatStateService $chatState): void
{
// 检查游戏是否开启
if (! GameConfig::isEnabled('horse_racing')) {
return;
}
// 防止重复开赛(上一场还在进行中)
if (HorseRace::currentRace($this->roomId)) {
return;
}
$config = GameConfig::forGame('horse_racing')?->params ?? [];
$betSeconds = (int) ($config['bet_window_seconds'] ?? 90);
$horseCount = (int) ($config['horse_count'] ?? 4);
$minBet = (int) ($config['min_bet'] ?? 100);
$maxBet = (int) ($config['max_bet'] ?? 100000);
$seedPool = (int) ($config['seed_pool'] ?? 0);
$now = now();
$closesAt = $now->copy()->addSeconds($betSeconds);
// 生成参赛马匹
$horses = HorseRace::generateHorses($horseCount);
// 创建新场次
$race = HorseRace::create([
'room_id' => $this->roomId,
'status' => 'betting',
'bet_opens_at' => $now,
'bet_closes_at' => $closesAt,
'horses' => $horses,
'total_pool' => $seedPool,
]);
// 广播开赛事件
broadcast(new HorseRaceOpened($race));
// 公屏系统公告
$horseList = implode(' ', array_map(
fn ($h) => "{$h['emoji']}{$h['name']}",
$horses
));
$quickOpenButton = '<button type="button" '
.'onclick="event.preventDefault(); Alpine.$data(document.getElementById(\'horse-race-panel\')).openFromHall();" '
.'style="margin-left:8px; padding:2px 8px; border:1px solid #d97706; border-radius:999px; background:#fff7ed; color:#b45309; font-size:12px; font-weight:bold; cursor:pointer;">'
.'快速参与赌马</button>';
$content = "🐎 开赛:{$horseList}{$betSeconds} 秒下注,".number_format($minBet).'~'.number_format($maxBet).' 金币。'.$quickOpenButton;
$msg = [
'id' => $chatState->nextMessageId($this->roomId),
'room_id' => $this->roomId,
'from_user' => '系统传音',
'to_user' => '大家',
'content' => $content,
'is_secret' => false,
'font_color' => '#16a34a',
'action' => '大声宣告',
'sent_at' => $now->toDateTimeString(),
];
$chatState->pushMessage($this->roomId, $msg);
broadcast(new MessageSent($this->roomId, $msg));
SaveMessageJob::dispatch($msg);
// 押注截止后触发跑马 & 结算任务
RunHorseRaceJob::dispatch($race)->delay($closesAt);
}
}