Files
chatroom/app/Models/FishingEvent.php

90 lines
1.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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();
}
}