using System;
namespace Models;
///
/// 属性值类型(通用数值封装)
/// 设计说明:
/// 1) 过去固定使用 0-100 的范围,导致“精力/算力”等大数值被强行截断。
/// 2) 现在改为“每个实例自带范围”,默认仍然是 0-100,兼顾直觉和可扩展性。
/// 3) 这个类仅承担“数值与范围”的职责,不负责业务含义,便于在 MVC 中被复用。
/// 注意事项:
/// - 运算符会保留左操作数的范围(或右操作数的范围),避免范围丢失。
/// - 如果需要无上限/无下限,请显式传入更大的 Max/更小的 Min。
/// 未来扩展:
/// - 可加入“软上限/软下限”和“可见范围”等 UI 表现字段。
/// - 可增加数值变化事件,以便 View 层更高效地刷新。
///
public sealed class PropertyValue
{
public const float DefaultMin = 0f;
public const float DefaultMax = 100f;
///
/// 最小值
///
public float Min { get; }
///
/// 最大值
///
public float Max { get; }
private float _value;
///
/// 当前值(自动限制在 Min/Max 范围内)
///
public float Value
{
get => _value;
set => _value = Clamp(value, Min, Max);
}
///
/// 构造函数
///
/// 初始值
/// 最小值
/// 最大值
public PropertyValue(float value = 0, float min = DefaultMin, float max = DefaultMax)
{
if (max < min)
{
// 兜底修正,避免传参错误导致全局异常
(min, max) = (max, min);
}
Min = min;
Max = max;
Value = value;
}
///
/// 构造函数(整数)
///
/// 初始值
/// 最小值
/// 最大值
public PropertyValue(int value, float min = DefaultMin, float max = DefaultMax)
: this((float)value, min, max)
{
}
///
/// 获取显示的整数值
///
/// 整数值
public int DisplayInt() => (int)_value;
///
/// 获取归一化值 (0.0 - 1.0)
///
public float Normalized
{
get
{
if (Max <= Min) return 0f;
return (Value - Min) / (Max - Min);
}
}
///
/// 克隆
///
/// 新实例
public PropertyValue Clone() => new(Value, Min, Max);
///
/// 增加值
///
/// 增量
public void Add(float delta) => Value += delta;
///
/// 减少值
///
/// 减量
public void Subtract(float delta) => Value -= delta;
public override string ToString() => DisplayInt().ToString();
// --- 隐式转换(用于简化调用,但不改变范围语义) ---
public static implicit operator PropertyValue(int value)
{
return new PropertyValue(value);
}
public static implicit operator PropertyValue(float value)
{
return new PropertyValue(value);
}
public static implicit operator int(PropertyValue p)
{
return (int)p._value;
}
public static implicit operator float(PropertyValue p)
{
return p._value;
}
// --- 运算符重载(保留范围) ---
public static PropertyValue operator +(PropertyValue a, int b) => new(a._value + b, a.Min, a.Max);
public static PropertyValue operator +(int a, PropertyValue b) => new(a + b._value, b.Min, b.Max);
public static PropertyValue operator -(PropertyValue a, int b) => new(a._value - b, a.Min, a.Max);
public static PropertyValue operator -(int a, PropertyValue b) => new(a - b._value, b.Min, b.Max);
public static PropertyValue operator *(PropertyValue a, int b) => new(a._value * b, a.Min, a.Max);
public static PropertyValue operator *(int a, PropertyValue b) => new(a * b._value, b.Min, b.Max);
public static PropertyValue operator /(PropertyValue a, int b)
{
return b == 0 ? throw new DivideByZeroException() : new PropertyValue(a._value / b, a.Min, a.Max);
}
public static PropertyValue operator /(int a, PropertyValue b)
{
return b._value == 0 ? throw new DivideByZeroException() : new PropertyValue(a / b._value, b.Min, b.Max);
}
public static PropertyValue operator +(PropertyValue a, float b) => new(a._value + b, a.Min, a.Max);
public static PropertyValue operator +(float a, PropertyValue b) => new(a + b._value, b.Min, b.Max);
public static PropertyValue operator -(PropertyValue a, float b) => new(a._value - b, a.Min, a.Max);
public static PropertyValue operator -(float a, PropertyValue b) => new(a - b._value, b.Min, b.Max);
public static PropertyValue operator *(PropertyValue a, float b) => new(a._value * b, a.Min, a.Max);
public static PropertyValue operator *(float a, PropertyValue b) => new(a * b._value, b.Min, b.Max);
public static PropertyValue operator /(PropertyValue a, float b) => new(a._value / b, a.Min, a.Max);
public static PropertyValue operator /(float a, PropertyValue b) => new(a / b._value, b.Min, b.Max);
public static PropertyValue operator +(PropertyValue a, PropertyValue b) => new(a._value + b._value, a.Min, a.Max);
public static PropertyValue operator -(PropertyValue a, PropertyValue b) => new(a._value - b._value, a.Min, a.Max);
public static PropertyValue operator *(PropertyValue a, PropertyValue b) => new(a._value * b._value, a.Min, a.Max);
public static PropertyValue operator /(PropertyValue a, PropertyValue b)
{
return b._value == 0 ? throw new DivideByZeroException() : new PropertyValue(a._value / b._value, a.Min, a.Max);
}
private static float Clamp(float value, float min, float max)
{
if (value < min) return min;
if (value > max) return max;
return value;
}
}