Files
chatroom/app/Models/HorseRace.php
lkddi f45483bcba 功能更新与UI优化:游戏图标移除、用户名片修复、婚礼红包界面重设计
- 移除聊天室右下角浮动游戏图标(占卜、百家乐、赛马、老虎机)
- 用户名片按钮区:修复已婚/已好友时按钮换行问题,统一单行显示
- 婚礼红包弹窗:重设计为喜庆鲜红背景,领取按钮改为圆形米黄样式
- 新增婚礼红包恢复接口(/wedding/pending-envelopes),刷新后自动恢复领取按钮
- 修复 Alpine :style 字符串覆盖静态 style 导致圆形按钮失效的问题
- 撤职后用户等级改为根据经验值重新计算,不再无条件重置为1
- 管理员修改用户经验值后自动重算等级,有职务用户等级锁定
- 娱乐大厅钓鱼游戏按钮直接调用 startFishing() 简化操作流程
- 新增赛马、占卜、百家乐游戏及相关后端逻辑
2026-03-03 23:19:59 +08:00

150 lines
4.1 KiB
PHP

<?php
/**
* 文件功能:赛马竞猜局次模型
*
* 代表一场赛马比赛,包含参赛马匹信息、场次状态、
* 注池统计以及赛果信息。提供当前场次查询和赔率计算方法。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class HorseRace extends Model
{
protected $fillable = [
'status',
'bet_opens_at',
'bet_closes_at',
'race_starts_at',
'race_ends_at',
'horses',
'winner_horse_id',
'total_bets',
'total_pool',
'settled_at',
];
/**
* 属性类型转换。
*/
protected function casts(): array
{
return [
'bet_opens_at' => 'datetime',
'bet_closes_at' => 'datetime',
'race_starts_at' => 'datetime',
'race_ends_at' => 'datetime',
'settled_at' => 'datetime',
'horses' => 'array',
'winner_horse_id' => 'integer',
'total_bets' => 'integer',
'total_pool' => 'integer',
];
}
/**
* 本场所有下注记录。
*/
public function bets(): HasMany
{
return $this->hasMany(HorseBet::class, 'race_id');
}
/**
* 判断当前是否在押注时间窗口内。
*/
public function isBettingOpen(): bool
{
return $this->status === 'betting'
&& now()->between($this->bet_opens_at, $this->bet_closes_at);
}
/**
* 查询当前正在进行的场次(状态为 betting 且押注未截止)。
*/
public static function currentRace(): ?static
{
return static::query()
->whereIn('status', ['betting', 'running'])
->latest()
->first();
}
/**
* 生成参赛马匹列表(根据马匹数量随机选名)。
*
* @param int $count 马匹数量
* @return array<int, array{id: int, name: string, emoji: string}>
*/
public static function generateHorses(int $count): array
{
// 可用马匹名池(原版竞技风格)
$namePool = [
['name' => '赤兔', 'emoji' => '🐎'],
['name' => '乌骓', 'emoji' => '🐴'],
['name' => '的卢', 'emoji' => '🎠'],
['name' => '绝影', 'emoji' => '🦄'],
['name' => '紫骍', 'emoji' => '🐎'],
['name' => '爪黄', 'emoji' => '🐴'],
['name' => '汗血', 'emoji' => '🎠'],
['name' => '飞电', 'emoji' => '⚡'],
];
// 随机打乱并取前 N 个
shuffle($namePool);
$selected = array_slice($namePool, 0, $count);
$horses = [];
foreach ($selected as $i => $horse) {
$horses[] = [
'id' => $i + 1,
'name' => $horse['name'],
'emoji' => $horse['emoji'],
];
}
return $horses;
}
/**
* 根据注池计算各马匹实时赔率(彩池制,扣除庄家抽水后按比例分配)。
*
* @param int $horseBetAmounts 各马匹的注额数组 [horse_id => amount]
* @param int $housePercent 庄家抽水百分比
* @return array<int, float> horse_id => 赔率(含本金)
*/
public static function calcOdds(array $horseBetAmounts, int $housePercent): array
{
$totalPool = array_sum($horseBetAmounts);
if ($totalPool <= 0) {
// 尚无下注,返回等额赔率
$count = count($horseBetAmounts);
return array_map(fn () => 1.0, $horseBetAmounts);
}
$netPool = $totalPool * (1 - $housePercent / 100);
$odds = [];
foreach ($horseBetAmounts as $horseId => $amount) {
if ($amount <= 0) {
// 无人押注的马,赔率设为理论最大值
$odds[$horseId] = round($netPool, 2);
} else {
// 赔率 = 净注池 / 该马注额(含本金返还)
$odds[$horseId] = round($netPool / $amount, 2);
}
}
return $odds;
}
}