Files
chatroom/app/Models/LotteryIssue.php

165 lines
4.6 KiB
PHP
Raw Normal View History

<?php
/**
* 文件功能:双色球期次 Model
*
* 管理每期彩票的生命周期open购票中 closed停售 settled已开奖
* 提供静态查询方法、奖级判定辅助及号码排序工具。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class LotteryIssue extends Model
{
protected $fillable = [
'issue_no',
'status',
'red1', 'red2', 'red3', 'blue',
'pool_amount',
'carry_amount',
'is_super_issue',
'no_winner_streak',
'total_tickets',
'payout_amount',
'sell_closes_at',
'draw_at',
];
/**
* 字段类型转换。
*/
protected function casts(): array
{
return [
'is_super_issue' => 'boolean',
'pool_amount' => 'integer',
'carry_amount' => 'integer',
'payout_amount' => 'integer',
'total_tickets' => 'integer',
'sell_closes_at' => 'datetime',
'draw_at' => 'datetime',
];
}
// ─── 关联 ──────────────────────────────────────────────────────────
/**
* 本期所有购票记录。
*/
public function tickets(): HasMany
{
return $this->hasMany(LotteryTicket::class, 'issue_id');
}
/**
* 本期奖池流水。
*/
public function poolLogs(): HasMany
{
return $this->hasMany(LotteryPoolLog::class, 'issue_id');
}
// ─── 静态查询 ──────────────────────────────────────────────────────
/**
* 获取当前正在购票的期次status=open
*/
public static function currentIssue(): ?static
{
return static::query()->where('status', 'open')->latest()->first();
}
/**
* 获取最新一期(不论状态)。
*/
public static function latestIssue(): ?static
{
return static::query()->latest()->first();
}
/**
* 生成下一期的期号(格式:年份 + 三位序号,如 2026001)。
*/
public static function nextIssueNo(): string
{
$year = now()->year;
$last = static::query()
->whereYear('created_at', $year)
->latest()
->first();
$seq = $last ? ((int) substr($last->issue_no, -3)) + 1 : 1;
return $year.str_pad($seq, 3, '0', STR_PAD_LEFT);
}
// ─── 业务方法 ──────────────────────────────────────────────────────
/**
* 判断当前期次是否仍在售票中。
*/
public function isOpen(): bool
{
return $this->status === 'open' && now()->lt($this->sell_closes_at);
}
/**
* 距离开奖剩余秒数。
*/
public function secondsUntilDraw(): int
{
if (! $this->draw_at) {
return 0;
}
return max(0, (int) now()->diffInSeconds($this->draw_at, false));
}
/**
* 判断给定号码是否与开奖号码匹配并返回奖级0=未中)。
*
* @param int $r1 用户红球1已排序
* @param int $r2 用户红球2
* @param int $r3 用户红球3
* @param int $b 用户蓝球
*/
public function calcPrizeLevel(int $r1, int $r2, int $r3, int $b): int
{
$userReds = [$r1, $r2, $r3];
$drawReds = [$this->red1, $this->red2, $this->red3];
$redMatches = count(array_intersect($userReds, $drawReds));
$blueMatch = ($b === $this->blue);
return match (true) {
$redMatches === 3 && $blueMatch => 1, // 一等奖
$redMatches === 3 && ! $blueMatch => 2, // 二等奖
$redMatches === 2 && $blueMatch => 3, // 三等奖
$redMatches === 2 && ! $blueMatch => 4, // 四等奖
$redMatches === 1 && $blueMatch => 5, // 五等奖
default => 0, // 未中奖
};
}
/**
* 返回奖级的中文标签。
*/
public static function prizeLevelLabel(int $level): string
{
return match ($level) {
1 => '一等奖',
2 => '二等奖',
3 => '三等奖',
4 => '四等奖',
5 => '五等奖',
default => '未中奖',
};
}
}