129 lines
3.5 KiB
PHP
129 lines
3.5 KiB
PHP
<?php
|
||
|
||
namespace App\Services\Settlement;
|
||
|
||
use App\Models\DrawResultItem;
|
||
use Illuminate\Support\Collection;
|
||
|
||
/**
|
||
* 已发布开奖批次的号码视图,供结算匹配(产品文档 §5 奖项分区 ↔ {@see DrawPrizeLayout})。
|
||
*/
|
||
final class PublishedDrawResultBoard
|
||
{
|
||
/** @var array<string, int> prize_type => 越小越优 */
|
||
private const TIER_RANK = [
|
||
'first' => 0,
|
||
'second' => 1,
|
||
'third' => 2,
|
||
'starter' => 3,
|
||
'consolation' => 4,
|
||
];
|
||
|
||
/** @var Collection<int, DrawResultItem> */
|
||
private readonly Collection $items;
|
||
|
||
private string $firstPrizeNumber = '';
|
||
|
||
/** @var array<string, array{tier: string, rank: int}> */
|
||
private array $numberToBestTier = [];
|
||
|
||
/**
|
||
* @param Collection<int, DrawResultItem> $items
|
||
*/
|
||
public function __construct(Collection $items)
|
||
{
|
||
$this->items = $items;
|
||
|
||
$first = $items->firstWhere(fn (DrawResultItem $r) => $r->prize_type === 'first' && (int) $r->prize_index === 0);
|
||
$this->firstPrizeNumber = $first !== null ? (string) $first->number_4d : '';
|
||
|
||
foreach ($items as $row) {
|
||
$num = (string) $row->number_4d;
|
||
if ($num === '') {
|
||
continue;
|
||
}
|
||
$tier = (string) $row->prize_type;
|
||
$rank = self::TIER_RANK[$tier] ?? 99;
|
||
if (! isset($this->numberToBestTier[$num]) || $rank < $this->numberToBestTier[$num]['rank']) {
|
||
$this->numberToBestTier[$num] = ['tier' => $tier, 'rank' => $rank];
|
||
}
|
||
}
|
||
}
|
||
|
||
/** @return Collection<int, DrawResultItem> */
|
||
public function allRows(): Collection
|
||
{
|
||
return $this->items;
|
||
}
|
||
|
||
public function row(string $prizeType, int $prizeIndex = 0): ?DrawResultItem
|
||
{
|
||
return $this->items->firstWhere(
|
||
fn (DrawResultItem $r) => (string) $r->prize_type === $prizeType && (int) $r->prize_index === $prizeIndex,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* @return list<string>
|
||
*/
|
||
public function numbersForPrizeType(string $prizeType): array
|
||
{
|
||
$out = [];
|
||
foreach ($this->items as $row) {
|
||
if ((string) $row->prize_type !== $prizeType) {
|
||
continue;
|
||
}
|
||
$n = (string) $row->number_4d;
|
||
if ($n !== '') {
|
||
$out[] = $n;
|
||
}
|
||
}
|
||
|
||
return $out;
|
||
}
|
||
|
||
public function firstPrizeNumber4d(): string
|
||
{
|
||
return $this->firstPrizeNumber;
|
||
}
|
||
|
||
public function suffix3ForTier(string $prizeType, int $prizeIndex = 0): string
|
||
{
|
||
$r = $this->row($prizeType, $prizeIndex);
|
||
|
||
return $r !== null ? (string) $r->suffix_3d : '';
|
||
}
|
||
|
||
public function suffix2ForTier(string $prizeType, int $prizeIndex = 0): string
|
||
{
|
||
$r = $this->row($prizeType, $prizeIndex);
|
||
|
||
return $r !== null ? (string) $r->suffix_2d : '';
|
||
}
|
||
|
||
/**
|
||
* Big:任意 23 档中最佳命中档。
|
||
*
|
||
* @return array{tier: string, rank: int}|null
|
||
*/
|
||
public function bestTierForNumber(string $number4d): ?array
|
||
{
|
||
return $this->numberToBestTier[$number4d] ?? null;
|
||
}
|
||
|
||
/**
|
||
* Small:仅头 / 二 / 三奖(rank 0–2)。
|
||
*
|
||
* @return array{tier: string, rank: int}|null
|
||
*/
|
||
public function bestSmallTierForNumber(string $number4d): ?array
|
||
{
|
||
$hit = $this->bestTierForNumber($number4d);
|
||
if ($hit === null) {
|
||
return null;
|
||
}
|
||
|
||
return $hit['rank'] <= 2 ? $hit : null;
|
||
}
|
||
}
|