Files
chatroom/app/Models/FishingEvent.php

90 lines
1.9 KiB
PHP
Raw Normal View History

<?php
/**
* 文件功能:钓鱼事件模型
*
* 对应 fishing_events 表,每条记录是一个钓鱼随机奖惩事件。
* 概率由 weight权重字段决定权重越大被选中概率越高。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class FishingEvent extends Model
{
/**
* 可批量赋值字段
*
* @var array<int, string>
*/
protected $fillable = [
'emoji',
'name',
'message',
'exp',
'jjb',
'weight',
'is_active',
'sort',
];
/**
* 字段类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'exp' => 'integer',
'jjb' => 'integer',
'weight' => 'integer',
'is_active' => 'boolean',
'sort' => 'integer',
];
}
/**
* 作用域:只查询已启用的事件
*/
public function scopeActive(Builder $query): Builder
{
return $query->where('is_active', true);
}
/**
* 根据权重随机抽取一个激活的钓鱼事件
*
* 实现加权随机:权重越大,被选中概率越高。
* 若无任何激活事件,返回 null
*/
public static function rollOne(): ?static
{
$events = static::active()->orderBy('sort')->get();
if ($events->isEmpty()) {
return null;
}
// 计算总权重后加权随机
$totalWeight = $events->sum('weight');
$roll = random_int(1, max($totalWeight, 1));
$cumulative = 0;
foreach ($events as $event) {
$cumulative += $event->weight;
if ($roll <= $cumulative) {
return $event;
}
}
// 兜底:返回最后一个
return $events->last();
}
}