*/ private array $drawNoById = []; public function __construct( private readonly LotteryHallRealtimeBroadcaster $hallRealtime, ) {} public function publishAfterLock( int $drawId, string $normalizedNumber, int $soldOutStatusBefore, int $lockedAmountBefore, int $totalCapBefore, RiskPool $poolAfter, ): void { $drawNo = $this->resolveDrawNo($drawId); $normalizedNumber = strtoupper(trim($normalizedNumber)); $totalCap = (int) $poolAfter->total_cap_amount; if ($totalCap < 1) { $totalCap = max(1, $totalCapBefore); } $soldOutAfter = (int) $poolAfter->sold_out_status; if ($soldOutAfter === 1 && $soldOutStatusBefore !== 1) { $this->hallRealtime->notifyRiskSoldOut($drawId, $drawNo, $normalizedNumber); } $lockedAfter = (int) $poolAfter->locked_amount; $usageBefore = $totalCapBefore > 0 ? $lockedAmountBefore / $totalCapBefore : 0.0; $usageAfter = $totalCap > 0 ? $lockedAfter / $totalCap : 1.0; if ($usageAfter >= self::WARNING_RATIO && $usageBefore < self::WARNING_RATIO) { $this->hallRealtime->notifyRiskWarning( $drawId, $drawNo, $normalizedNumber, $usageAfter, ); } } public function publishManualSoldOut(Draw $draw, string $normalizedNumber): void { $this->hallRealtime->notifyRiskSoldOut( (int) $draw->id, (string) $draw->draw_no, strtoupper(trim($normalizedNumber)), ); } private function resolveDrawNo(int $drawId): string { if (isset($this->drawNoById[$drawId])) { return $this->drawNoById[$drawId]; } $drawNo = Draw::query()->whereKey($drawId)->value('draw_no'); $resolved = is_string($drawNo) && $drawNo !== '' ? $drawNo : (string) $drawId; $this->drawNoById[$drawId] = $resolved; return $resolved; } }