Files
2024-10-16 00:03:41 +08:00

227 lines
6.7 KiB
C#

using System;
using System.Collections.Generic;
using System.RandomPool;
namespace Game.Data
{
/// <summary>
/// 通用随机池单元组,用于最终产生随机节点
/// </summary>
public class CommonRandomGroup<T> where T : class
{
private int _poolId;
private int _weightMax;
private readonly List<RandomNode<T>> _item;
private int _curWeightSum; //当前的总权重
private int _curConditionMask; //当前条件阈值 ,必须大于此值
public int ValidRofCount { get; private set; }
public CommonRandomGroup(int poolId)
{
this._poolId = poolId;
this._item = new List<RandomNode<T>>();
this._weightMax = 0;
this._curWeightSum = 0;
this._curConditionMask = -1;
this.ValidRofCount = -2;
}
public bool SetMask(int exploreCount, IList<int> disableKeys = null , object customMask = null)
{
this.ValidRofCount = 0;
this._curWeightSum = 0;
var isSet = false;
for (int i = 0; i < this._item.Count; i++)
{
var node = this._item[i];
if (disableKeys != null && disableKeys.Contains(node.key))
{
node.curWeight = -1;
continue;
}
var isBound = this.IsBound(node, exploreCount);
if (!isBound)
{
node.curWeight = -1;
continue;
}
if (!this.OnCustomMask(node , customMask))
{
node.curWeight = -1;
continue;
}
isSet = true;
this._curWeightSum += node.weight;
node.curWeight = this._curWeightSum;
this.ValidRofCount += 1;
}
this._curConditionMask = exploreCount;
return isSet;
}
protected virtual bool OnCustomMask(RandomNode<T> node, object customMask)
{
return true;
}
private bool IsBound(RandomNode<T> node, int maskCount)
{
if (!node.IsValid(RandomLogController.GetPoolLog(this._poolId, node.key)))
{
return false;
}
if (maskCount == -1)
return true;
if (node.weight <= 0)
return false;
if (node.maxRange == -1 && node.minRange == -1)
return true;
if (node.minRange == -1)
{
return maskCount <= node.maxRange;
}
if (node.maxRange == -1)
{
return maskCount >= node.minRange;
}
return maskCount >= node.minRange && maskCount <= node.maxRange;
}
public void PutItem(RandomNode<T> node)
{
//此处后续可增加数量限制判断
this._weightMax += node.weight;
this._item.Add(node);
}
public void PullItem(int node)
{
for (int i = 0; i < _item.Count; i++)
{
var randomNode = _item[i];
if (randomNode.key == node)
{
RandomLogController.PoolPullLog (this._poolId , node);
return;
}
}
}
public void RemoveItem(int node)
{
for (int i = 0; i < _item.Count; i++)
{
var randomNode = _item[i];
if (randomNode.key == node)
{
_item.RemoveAt(i);
_weightMax -= randomNode.weight;
return;
}
}
}
internal RandomNode<T> GetItem(int id)
{
for (int i = 0; i < this._item.Count; i++)
{
var node = this._item[i];
if (id == node.key)
{
return node;
}
}
return null;
}
public float GetItemRate(int id)
{
var f = 0f;
var item = this.GetItem(id);
if (item != null)
{
if (item.curWeight != -1)
{
f = item.weight / (this._weightMax * 1.0f);
}
}
return f;
}
public T RandomItem(int poolId, int seedId)
{
if (this._item.Count == 0 || ValidRofCount == 0)
{
return null;
}
RandomNode<T> item = null;
var p = RandomUtils.RandomFloat () * this._curWeightSum;
for (int i = 0; i < this._item.Count; i++)
{
var randomNode = this._item[i];
if (p <= randomNode.curWeight)
{
item = randomNode;
RandomLogController.PoolPushLog(poolId, item.key);
break;
}
}
return item?.value;
}
public RandomNode<T> RandomNode(int poolId, int seedId)
{
if (this._item.Count == 0 || ValidRofCount == 0)
{
return null;
}
RandomNode<T> item = null;
var p = RandomUtils.RandomFloat () * this._curWeightSum;
for (int i = 0; i < this._item.Count; i++)
{
var randomNode = this._item[i];
if (p <= randomNode.curWeight)
{
item = randomNode;
RandomLogController.PoolPushLog(poolId, item.key);
break;
}
}
return item;
}
public static bool IsPush(int poolId, int id, int maskCount)
{
return RandomLogController.IsPush(poolId, id, maskCount);
}
public void ResetItemWeight(int id, int weight)
{
for (int i = 0; i < this._item.Count; i++)
{
var randomNode = this._item[i];
if (randomNode.key == id)
{
this._weightMax -= randomNode.weight;
randomNode.weight = weight;
this._weightMax += randomNode.weight;
return;
}
}
}
}
}