重构猜谜活动并统一聊天室答题通知

This commit is contained in:
pllx
2026-04-29 13:35:20 +08:00
parent 192259f0a4
commit fe3e74b5f8
34 changed files with 3369 additions and 1833 deletions
+4 -76
View File
@@ -176,88 +176,16 @@ Schedule::call(function () {
}
})->everyMinute()->name('lottery:check')->withoutOverlapping();
// ──────────── 猜成语自动出题 ────────────────────────────────────
// ──────────── 猜谜活动自动出题 ──────────────────────────────────
//
// 每分钟:检查是否到时间自动出题(仅 auto_start_interval > 0 时生效)
// 每分钟:按房间范围 + 题型维度独立检查是否自动出题
Schedule::call(function () {
if (! \App\Models\GameConfig::isEnabled('idiom')) {
return;
}
// 先统一结算超时回合,避免旧题长期占用进行中状态
$roomId = 1;
app(\App\Services\IdiomGameService::class)->expireActiveRoundsForRoom($roomId);
$config = \App\Models\GameConfig::forGame('idiom')?->params ?? [];
$interval = (int) ($config['auto_start_interval'] ?? 0);
if ($interval <= 0) {
return; // 仅手动模式
}
// 检查每个房间是否有进行中的回合(先只处理 1 号房间)
$activeRound = \App\Models\IdiomGameRound::where('room_id', $roomId)
->whereIn('status', ['pending', 'active'])
->first();
if ($activeRound) {
return; // 当前有未答完的题,跳过
}
// 检查距上一题结束/创建时间是否已达到间隔
$lastRound = \App\Models\IdiomGameRound::where('room_id', $roomId)
->latest()
->first();
if ($lastRound) {
$lastTime = $lastRound->ended_at ?? $lastRound->started_at ?? $lastRound->created_at;
if ($lastTime && $lastTime->diffInMinutes(now()) < $interval) {
return; // 还没到时间
}
}
// 随机选一道启用的题目
$idiom = \App\Models\Idiom::where('is_active', true)->inRandomOrder()->first();
if (! $idiom) {
return; // 题库为空
}
$rewardGold = (int) ($config['reward_gold'] ?? 50);
$rewardExp = (int) ($config['reward_exp'] ?? 30);
// 创建新回合,并以 started_at 作为后续过期判断起点。
$round = \App\Models\IdiomGameRound::create([
'room_id' => $roomId,
'idiom_id' => $idiom->id,
'status' => 'active',
'reward_gold' => $rewardGold,
'reward_exp' => $rewardExp,
'started_at' => now(),
]);
// 广播到聊天室
broadcast(new \App\Events\IdiomGameStarted(
roomId: $roomId,
hint: $idiom->hint,
roundId: $round->id,
rewardGold: $rewardGold,
rewardExp: $rewardExp,
));
// 同时推一条 MessageSent 消息显示在聊天窗口
$msg = [
'id' => app(\App\Services\ChatStateService::class)->nextMessageId($roomId),
'room_id' => $roomId,
'from_user' => '星海小博士',
'to_user' => '大家',
'content' => "🧩 猜成语时间!{$idiom->hint}",
'is_secret' => false,
'font_color' => '#7c3aed',
'action' => '',
'idiom_game_round_id' => $round->id,
'idiom_reward_gold' => $rewardGold,
'idiom_reward_exp' => $rewardExp,
'sent_at' => now()->toDateTimeString(),
];
app(\App\Services\ChatStateService::class)->pushMessage($roomId, $msg);
broadcast(new \App\Events\MessageSent($roomId, $msg));
// 出题、过期结算、房间范围与题型独立判定统一交给服务层处理
app(\App\Services\RiddleGameService::class)->autoStartEligibleRounds();
})->everyMinute()->name('idiom:auto-start')->withoutOverlapping();
// 每日 18:00:超级期预热广播(若当前期次为超级期,提醒用户购票)