Files
chatroom/routes/console.php
T

223 lines
8.9 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
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
// 每天凌晨 3 点清理超过 30 天的聊天记录
Schedule::command('messages:purge')->dailyAt('03:00');
// 每 5 分钟为所有在线用户自动存点(经验/金币/等级)
Schedule::command('chatroom:auto-save-exp')->everyFiveMinutes();
// 每 1 分钟为 AI小班长 独立模拟一次挂机心跳,触发随机事件
Schedule::command('chatroom:ai-heartbeat')->everyMinute();
// 每 15 分钟:关闭掉线用户的开放职务日志(久无心跳 = 掉线,自动写入 logout_at
Schedule::command('duty:close-stale-logs')->everyFifteenMinutes();
// ──────────── 婚姻系统定时任务 ────────────────────────────────────
// 每 5 分钟:扫描超时求婚(48h后失效 + 戒指消失 + 广播通知)
Schedule::job(new \App\Jobs\ExpireMarriageProposals)->everyFiveMinutes();
// 每 5 分钟:触发到时的定时婚礼(红包分发 + 广播庆典)
Schedule::job(new \App\Jobs\TriggerScheduledWeddings)->everyFiveMinutes();
// 每小时:协议离婚超时自动升级为强制(72h无响应)
Schedule::job(new \App\Jobs\AutoExpireDivorces)->hourly();
// 每小时:清理过期婚礼红包(expired_at 过后标记 completed
Schedule::job(new \App\Jobs\ExpireWeddingEnvelopes)->hourly();
// 每天 00:05:全量处理婚姻亲密度时间奖励(每日加分)
Schedule::job(new \App\Jobs\ProcessMarriageIntimacy)->dailyAt('00:05');
// ──────────── 节日福利定时任务 ────────────────────────────────────
// 每分钟:扫描并触发到期的节日福利活动
Schedule::call(function () {
\App\Models\HolidayEvent::pendingToTrigger()
->each(fn ($e) => \App\Jobs\TriggerHolidayEventJob::dispatch($e));
})->everyMinute()->name('holiday-events:trigger')->withoutOverlapping();
// 每分钟:收尾已过期但尚未结算的节日福利批次
Schedule::call(function () {
\App\Models\HolidayEventRun::pendingToExpire()
->each(function (\App\Models\HolidayEventRun $run): void {
$run->update(['status' => 'expired']);
});
})->everyMinute()->name('holiday-event-runs:expire')->withoutOverlapping();
// 每分钟:推进百家乐买单活动状态(开始 / 等待结算 / 开放领取 / 过期收尾)
Schedule::call(function () {
app(\App\Services\BaccaratLossCoverService::class)->tick();
})->everyMinute()->name('baccarat-loss-cover:tick')->withoutOverlapping();
// ──────────── 百家乐定时任务 ─────────────────────────────────────
// 每分钟:检查是否应开新一局(游戏开启 + 无正在进行的局)
Schedule::call(function () {
if (! \App\Models\GameConfig::isEnabled('baccarat')) {
return;
}
$config = \App\Models\GameConfig::forGame('baccarat')?->params ?? [];
$interval = (int) ($config['interval_minutes'] ?? 2);
$roomScopeService = app(\App\Services\GameRoomScopeService::class);
foreach ($roomScopeService->getScopedRoomIdsForGame('baccarat') as $roomId) {
$lastRound = \App\Models\BaccaratRound::query()
->where('room_id', $roomId)
->latest()
->first();
if ($lastRound && $lastRound->created_at->diffInMinutes(now()) < $interval) {
continue;
}
if (! \App\Models\BaccaratRound::currentRound($roomId)) {
\App\Jobs\OpenBaccaratRoundJob::dispatch($roomId);
}
}
})->everyMinute()->name('baccarat:open-round')->withoutOverlapping();
// ──────────── 神秘箱子定时投放 ─────────────────────────────────
// 每分钟:检查是否应自动投放一个新箱子
Schedule::call(function () {
if (! \App\Models\GameConfig::isEnabled('mystery_box')) {
return;
}
$config = \App\Models\GameConfig::forGame('mystery_box')?->params ?? [];
// 自动投放开关
if (! ($config['auto_drop_enabled'] ?? false)) {
return;
}
$intervalHours = (float) ($config['auto_interval_hours'] ?? 2);
$roomScopeService = app(\App\Services\GameRoomScopeService::class);
foreach ($roomScopeService->getScopedRoomIdsForGame('mystery_box') as $roomId) {
if (\App\Models\MysteryBox::currentOpenBox($roomId)) {
continue;
}
$lastBox = \App\Models\MysteryBox::query()
->where('room_id', $roomId)
->latest()
->first();
if ($lastBox && $lastBox->created_at->diffInHours(now()) < $intervalHours) {
continue;
}
$trapChance = (int) ($config['trap_chance_percent'] ?? 10);
$rand = random_int(1, 100);
$boxType = match (true) {
$rand <= $trapChance => 'trap',
$rand <= $trapChance + 15 => 'rare',
default => 'normal',
};
\App\Jobs\DropMysteryBoxJob::dispatch($boxType, $roomId);
}
})->everyMinute()->name('mystery-box:auto-drop')->withoutOverlapping();
// ──────────── 赛马竞猜定时任务 ─────────────────────────────────
// 每分钟:检查是否应开启新一场赛马
Schedule::call(function () {
if (! \App\Models\GameConfig::isEnabled('horse_racing')) {
return;
}
$config = \App\Models\GameConfig::forGame('horse_racing')?->params ?? [];
$interval = (int) ($config['interval_minutes'] ?? 30);
$roomScopeService = app(\App\Services\GameRoomScopeService::class);
foreach ($roomScopeService->getScopedRoomIdsForGame('horse_racing') as $roomId) {
if (\App\Models\HorseRace::currentRace($roomId)) {
continue;
}
$lastRace = \App\Models\HorseRace::query()
->where('room_id', $roomId)
->latest()
->first();
if ($lastRace && $lastRace->created_at->diffInMinutes(now()) < $interval) {
continue;
}
\App\Jobs\OpenHorseRaceJob::dispatch($roomId)->delay(now()->addSeconds(30));
}
})->everyMinute()->name('horse-race:open-race')->withoutOverlapping();
// ──────────── 双色球彩票定时任务 ─────────────────────────────────
// 每分钟:检查是否到开奖时间,到期触发开奖;同时确保有进行中的期次
Schedule::call(function () {
if (! \App\Models\GameConfig::isEnabled('lottery')) {
return;
}
$roomScopeService = app(\App\Services\GameRoomScopeService::class);
foreach ($roomScopeService->getScopedRoomIdsForGame('lottery') as $roomId) {
$issue = \App\Models\LotteryIssue::query()
->where('room_id', $roomId)
->whereIn('status', ['open', 'closed'])
->latest()
->first();
if (! $issue) {
\App\Jobs\OpenLotteryIssueJob::dispatch($roomId);
continue;
}
if ($issue->status === 'open' && $issue->sell_closes_at && now()->gte($issue->sell_closes_at)) {
$issue->update(['status' => 'closed']);
$issue->refresh();
}
if ($issue->status === 'closed' && $issue->draw_at && now()->gte($issue->draw_at)) {
\App\Jobs\DrawLotteryJob::dispatch($issue);
}
}
})->everyMinute()->name('lottery:check')->withoutOverlapping();
// ──────────── 猜谜活动自动出题 ──────────────────────────────────
//
// 每分钟:按房间范围 + 题型维度独立检查是否应自动出题
Schedule::call(function () {
if (! \App\Models\GameConfig::isEnabled('idiom')) {
return;
}
// 出题、过期结算、房间范围与题型独立判定统一交给服务层处理。
app(\App\Services\RiddleGameService::class)->autoStartEligibleRounds();
})->everyMinute()->name('idiom:auto-start')->withoutOverlapping();
// 每日 18:00:超级期预热广播(若当前期次为超级期,提醒用户购票)
Schedule::call(function () {
if (! \App\Models\GameConfig::isEnabled('lottery')) {
return;
}
$roomScopeService = app(\App\Services\GameRoomScopeService::class);
foreach ($roomScopeService->getScopedRoomIdsForGame('lottery') as $roomId) {
$issue = \App\Models\LotteryIssue::currentIssue($roomId);
if ($issue && $issue->is_super_issue) {
\App\Jobs\OpenLotteryIssueJob::dispatch($roomId); // 触发广播
}
}
})->dailyAt('18:00')->name('lottery:super-reminder');