diff --git a/logic/Preparation/Utility/Value/SafeValue/LockedValue/InRangeTimeBased.cs b/logic/Preparation/Utility/Value/SafeValue/LockedValue/InRangeTimeBased.cs new file mode 100644 index 00000000..5c4eb018 --- /dev/null +++ b/logic/Preparation/Utility/Value/SafeValue/LockedValue/InRangeTimeBased.cs @@ -0,0 +1,193 @@ +using Preparation.Utility; +using System; +using System.Numerics; +using System.Threading; + +namespace Preparation.Utility +{ + //其对应属性不应当有set访问器,避免不安全的=赋值 + + public class LongInVariableRangeWithStartTime : InVariableRange + { + public StartTime startTime = new(); + public LongInVariableRangeWithStartTime(long value, long maxValue) : base(value, maxValue) { } + /// + /// 默认使Value=maxValue + /// + public LongInVariableRangeWithStartTime(long maxValue) : base(maxValue) { } + + #region 读取 + public (long, long) GetValueWithStartTime() + { + return ReadNeed(() => (v, startTime.Get())); + } + public (long, long, long) GetValueAndMaxVWithStartTime() + { + return ReadNeed(() => (v, maxV, startTime.Get())); + } + #endregion + + /// + /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue + /// 如果无法加到maxValue则不加 + /// + /// 返回试图加到的值与最大值 + public (long, long, long) AddStartTimeToMaxV(double speed = 1.0) + { + return WriteNeed(() => + { + long addV = (long)(startTime.StopIfPassing(maxV - v) * speed); + if (addV < 0) return (v, maxV, startTime.Get()); + if (maxV - v < addV) return (v = maxV, maxV, startTime.Get()); + return (v + addV, maxV, startTime.Get()); + }); + } + + /// + /// 增加量为时间差*速度,并将startTime变为long.MaxValue + /// + /// 返回实际改变量 + public long AddStartTime(double speed = 1.0) + { + return WriteNeed(() => + { + long previousV = v; + long addV = (Environment.TickCount64 - startTime.Stop()); + if (addV < 0) v += (long)(addV * speed); + else return 0; + if (v > maxV) v = maxV; + return v - previousV; + }); + } + + /// + /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上 + /// 如果无法加到maxValue则清零 + /// 无论如何startTime变为long.MaxValue + /// + /// 返回是否清零 + public bool Set0IfNotAddStartTimeToMaxV(double speed = 1.0) + { + return WriteNeed(() => + { + if (v == maxV) return false; + long addV = (long)(startTime.Stop() * speed); + if (addV < 0) + { + v = 0; + return true; + } + if (maxV - v < addV) + { + v = maxV; + return false; + } + v = 0; + return false; + }); + } + + public void SetAndStop(long value = 0) + { + WriteNeed(() => + { + this.v = value; + startTime.Stop(); + }); + } + } + + public class TimeBasedProgressAtVariableSpeed + { + private readonly LongInVariableRangeWithStartTime progress; + public AtomicDouble speed; + + #region 构造 + public TimeBasedProgressAtVariableSpeed(long needProgress, double speed = 1.0) + { + progress = new LongInVariableRangeWithStartTime(0, needProgress); + if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0."); + this.speed = new(speed); + } + public TimeBasedProgressAtVariableSpeed() + { + progress = new LongInVariableRangeWithStartTime(0, 0); + this.speed = new(1.0); + } + #endregion + + #region 读取 + public override string ToString() + { + long progressStored, lastStartTime; + (progressStored, lastStartTime) = progress.GetValueWithStartTime(); + return "ProgressStored: " + progressStored.ToString() + + " ; LastStartTime: " + lastStartTime.ToString() + "ms" + + " ; Speed: " + speed.ToString(); + } + public long GetProgressNow() => progress.AddStartTimeToMaxV((double)speed).Item1; + public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.AddStartTimeToMaxV((double)speed); + public long GetProgressStored() => progress.GetValue(); + public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV(); + public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxVWithStartTime(); + + public bool IsFinished() + { + long progressNow, needTime; + (progressNow, needTime, _) = progress.AddStartTimeToMaxV((double)speed); + return progressNow == needTime; + } + public bool IsProgressing() + { + long progressNow, needTime, startT; + (progressNow, needTime, startT) = progress.AddStartTimeToMaxV((double)speed); + return (startT != long.MaxValue && progressNow != needTime); + } + #endregion + + public bool Start(long needTime) + { + if (needTime <= 2) + { + Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0."); + return false; + } + if (progress.startTime.Start() != long.MaxValue) return false; + progress.SetMaxV(needTime); + return true; + } + public bool Start() + { + return progress.startTime.Start() == long.MaxValue; + } + /// + /// 使进度条强制终止清零 + /// + public void Set0() + { + progress.SetAndStop(); + } + /// + /// 如果进度条加上时间差不能为满,使进度条强制终止清零 + /// + public void TryStop() + { + progress.Set0IfNotAddStartTimeToMaxV(speed); + } + /// + /// 使进度条暂停 + /// + public bool Pause() + { + return progress.AddStartTime((double)speed) != 0; + } + /// + /// 使进度条进度为满 + /// + public void Finish() + { + progress.SetVToMaxV(); + progress.startTime.Stop(); + } + } +} diff --git a/logic/Preparation/Utility/Value/SafeValue/LockedValue/InTheRange.cs b/logic/Preparation/Utility/Value/SafeValue/LockedValue/InTheRange.cs index e38a616f..05ed64ff 100644 --- a/logic/Preparation/Utility/Value/SafeValue/LockedValue/InTheRange.cs +++ b/logic/Preparation/Utility/Value/SafeValue/LockedValue/InTheRange.cs @@ -16,38 +16,6 @@ public class InVariableRange : LockedValue, IIntAddable, IAddable, IDouble protected T v; protected T maxV; - #region NeedToDo - public virtual TResult ReadNeed(Func func) - { - lock (vLock) - { - return func(); - } - } - public virtual void ReadNeed(Action func) - { - lock (vLock) - { - func(); - } - } - - public virtual TResult WriteNeed(Func func) - { - lock (vLock) - { - return func(); - } - } - public virtual void WriteNeed(Action func) - { - lock (vLock) - { - func(); - } - } - #endregion - #region 构造与读取 public InVariableRange(T value, T maxValue) : base() { diff --git a/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedDouble.cs b/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedDouble.cs index bdf1d00d..97b4e8a9 100644 --- a/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedDouble.cs +++ b/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedDouble.cs @@ -9,31 +9,26 @@ public class LockedDouble(double x) : LockedValue, IDouble public override string ToString() { - lock (vLock) - return v.ToString(); + return ReadNeed(() => v.ToString()); } public double Get() { - lock (vLock) - return v; + return ReadNeed(() => v); } public double ToDouble() => Get(); public static implicit operator double(LockedDouble adouble) => adouble.Get(); public void Set(double value) { - lock (vLock) - v = value; + WriteNeed(() => v = value); } public double AddRNow(double value) { - lock (vLock) - return v += value; + return WriteNeed(() => v += value); } public double MulRNow(double value) { - lock (vLock) - return v *= value; + return WriteNeed(() => v *= value); } } } diff --git a/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedValue.cs b/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedValue.cs index d63d760a..b5267700 100644 --- a/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedValue.cs +++ b/logic/Preparation/Utility/Value/SafeValue/LockedValue/LockedValue.cs @@ -7,6 +7,39 @@ public abstract class LockedValue { protected readonly object vLock = new(); protected object VLock => vLock; + + #region NeedToDo + public virtual TResult ReadNeed(Func func) + { + lock (vLock) + { + return func(); + } + } + public virtual void ReadNeed(Action func) + { + lock (vLock) + { + func(); + } + } + + public virtual TResult WriteNeed(Func func) + { + lock (vLock) + { + return func(); + } + } + public virtual void WriteNeed(Action func) + { + lock (vLock) + { + func(); + } + } + #endregion + private static int numOfClass = 0; public static int NumOfClass => numOfClass; private readonly int idInClass; diff --git a/logic/Preparation/Utility/Value/SafeValue/LockedValue/PositiveV.cs b/logic/Preparation/Utility/Value/SafeValue/LockedValue/PositiveV.cs index c0bf13ab..849bb680 100644 --- a/logic/Preparation/Utility/Value/SafeValue/LockedValue/PositiveV.cs +++ b/logic/Preparation/Utility/Value/SafeValue/LockedValue/PositiveV.cs @@ -30,23 +30,17 @@ public PositiveValue() : base() public override string ToString() { - lock (vLock) - { - return "value:" + v.ToString(); - } + return ReadNeed(() => "value:" + v.ToString()); } - public T Get() { lock (vLock) return v; } + public T Get() { return ReadNeed(() => v); } public static implicit operator T(PositiveValue aint) => aint.Get(); - public bool IsZero() { lock (vLock) return v == T.Zero; } + public bool IsZero() { return ReadNeed(() => v == T.Zero); } #endregion #region 内嵌读取(在锁的情况下读取内容同时读取其他更基本的外部数据) public (T, long) GetValue(StartTime startTime) { - lock (vLock) - { - return (v, startTime.Get()); - } + return ReadNeed(() => (v, startTime.Get())); } #endregion @@ -55,64 +49,55 @@ public T SetRNow(T value) { if (value < T.Zero) { - lock (vLock) - { - return v = T.Zero; - } - } - lock (vLock) - { - return v = value; + return WriteNeed(() => v = T.Zero); } + return WriteNeed(() => v = value); } /// /// 应当保证该value>=0 /// public T SetPositiveVRNow(T value) { - lock (vLock) - { - return v = value; - } + return WriteNeed(() => v = value); } public void Add(T addV) { - lock (vLock) + WriteNeed(() => { v += addV; if (v < T.Zero) v = T.Zero; - } + }); } public void Add(int addV) { - lock (vLock) + WriteNeed(() => { v += T.CreateChecked(addV); if (v < T.Zero) v = T.Zero; - } + }); } public void Add(TA addV) where TA : IConvertible, INumber { - lock (vLock) + WriteNeed(() => { v += T.CreateChecked(addV); if (v < T.Zero) v = T.Zero; - } + }); } /// 返回实际改变量 public T AddRChange(T addV) { - lock (vLock) + return WriteNeed(() => { T previousV = v; v += addV; if (v < T.Zero) v = T.Zero; return v - previousV; - } + }); } /// /// 应当保证增加值大于0 @@ -120,55 +105,55 @@ public T AddRChange(T addV) /// 返回实际改变量 public T AddPositiveVRChange(T addPositiveV) { - lock (vLock) + WriteNeed(() => { v += addPositiveV; - } + }); return addPositiveV; } public void Mul(T mulV) { if (mulV.CompareTo(0) <= 0) { - lock (vLock) v = T.Zero; + WriteNeed(() => v = T.Zero); return; } - lock (vLock) + WriteNeed(() => { v *= mulV; - } + }); } public void Mul(TA mulV) where TA : IConvertible, INumber { if (mulV < TA.Zero) { - lock (vLock) v = T.Zero; + WriteNeed(() => v = T.Zero); ; return; } - lock (vLock) + WriteNeed(() => { v = T.CreateChecked(v.ToDouble(null) * mulV.ToDouble(null)); - } + }); } /// /// 应当保证乘数大于0 /// public void MulPositiveV(T mulPositiveV) { - lock (vLock) + WriteNeed(() => { v *= mulPositiveV; - } + }); } /// 返回实际改变量 public T SubRChange(T subV) { - lock (vLock) + WriteNeed(() => { subV = (subV.CompareTo(v) > 0) ? v : subV; v -= subV; - } + }); return subV; } #endregion @@ -176,39 +161,39 @@ public T SubRChange(T subV) #region 特殊条件的设置和运算 public bool Set0IfNot0() { - lock (vLock) + return WriteNeed(() => { if (v.CompareTo(0) > 0) { v = T.Zero; return true; } - } - return false; + return false; + }); } #endregion #region 与LockedValue类的运算,运算会影响该对象的值 public T AddRChange(InVariableRange a) where TA : IConvertible, IComparable, INumber { - return EnterOtherLock(a, () => + return EnterOtherLock(a, () => WriteNeed(() => { T previousV = v; v += T.CreateChecked(a.GetValue()); a.SubPositiveVRChange(TA.CreateChecked(v - previousV)); return v - previousV; - })!; + }))!; } public T SubRChange(InVariableRange a) where TA : IConvertible, IComparable, INumber { - return EnterOtherLock(a, () => + return EnterOtherLock(a, () => WriteNeed(() => { T previousV = v; v -= T.CreateChecked(a.GetValue()); if (v < T.Zero) v = T.Zero; a.SubPositiveVRChange(TA.CreateChecked(previousV - v)); return v - previousV; - })!; + }))!; } #endregion @@ -219,14 +204,14 @@ public T SubRChange(InVariableRange a) where TA : IConvertible, ICompara /// 返回实际改变量 public T AddV(StartTime startTime, double speed = 1.0) { - lock (vLock) + return WriteNeed(() => { T previousV = v; T addV = T.CreateChecked((Environment.TickCount64 - startTime.Stop()) * speed); if (addV.CompareTo(T.Zero) <= 0) return T.Zero; else v += addV; return v - previousV; - } + }); } #endregion } diff --git a/logic/Preparation/Utility/Value/SafeValue/TimeBased.cs b/logic/Preparation/Utility/Value/SafeValue/TimeBased.cs index ea274d90..fd05f889 100644 --- a/logic/Preparation/Utility/Value/SafeValue/TimeBased.cs +++ b/logic/Preparation/Utility/Value/SafeValue/TimeBased.cs @@ -35,196 +35,6 @@ public long StopIfPassing(long passedTime) } } - public class LongInTheVariableRangeWithStartTime : InVariableRange - { - public StartTime startTime = new(); - public LongInTheVariableRangeWithStartTime(long value, long maxValue) : base(value, maxValue) { } - /// - /// 默认使Value=maxValue - /// - public LongInTheVariableRangeWithStartTime(long maxValue) : base(maxValue) { } - - #region 读取 - public (long, long) GetValueWithStartTime() - { - lock (vLock) - { - return (v, startTime.Get()); - } - } - public (long, long, long) GetValueAndMaxVWithStartTime() - { - lock (vLock) - { - return (v, maxV, startTime.Get()); - } - } - #endregion - - /// - /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue - /// 如果无法加到maxValue则不加 - /// - /// 返回试图加到的值与最大值 - public (long, long, long) AddStartTimeToMaxV(double speed = 1.0) - { - lock (vLock) - { - long addV = (long)(startTime.StopIfPassing(maxV - v) * speed); - if (addV < 0) return (v, maxV, startTime.Get()); - if (maxV - v < addV) return (v = maxV, maxV, startTime.Get()); - return (v + addV, maxV, startTime.Get()); - } - } - - /// - /// 增加量为时间差*速度,并将startTime变为long.MaxValue - /// - /// 返回实际改变量 - public long AddStartTime(double speed = 1.0) - { - lock (vLock) - { - long previousV = v; - long addV = (Environment.TickCount64 - startTime.Stop()); - if (addV < 0) v += (long)(addV * speed); - else return 0; - if (v > maxV) v = maxV; - return v - previousV; - } - } - - /// - /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上 - /// 如果无法加到maxValue则清零 - /// 无论如何startTime变为long.MaxValue - /// - /// 返回是否清零 - public bool Set0IfNotAddStartTimeToMaxV(double speed = 1.0) - { - lock (vLock) - { - if (v == maxV) return false; - long addV = (long)(startTime.Stop() * speed); - if (addV < 0) - { - v = 0; - return true; - } - if (maxV - v < addV) - { - v = maxV; - return false; - } - v = 0; - return false; - } - } - - public void SetAndStop(long value = 0) - { - lock (vLock) - { - this.v = value; - startTime.Stop(); - } - } - } - - public class TimeBasedProgressAtVariableSpeed - { - private readonly LongInTheVariableRangeWithStartTime progress; - public AtomicDouble speed; - - #region 构造 - public TimeBasedProgressAtVariableSpeed(long needProgress, double speed = 1.0) - { - progress = new LongInTheVariableRangeWithStartTime(0, needProgress); - if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0."); - this.speed = new(speed); - } - public TimeBasedProgressAtVariableSpeed() - { - progress = new LongInTheVariableRangeWithStartTime(0, 0); - this.speed = new(1.0); - } - #endregion - - #region 读取 - public override string ToString() - { - long progressStored, lastStartTime; - (progressStored, lastStartTime) = progress.GetValueWithStartTime(); - return "ProgressStored: " + progressStored.ToString() - + " ; LastStartTime: " + lastStartTime.ToString() + "ms" - + " ; Speed: " + speed.ToString(); - } - public long GetProgressNow() => progress.AddStartTimeToMaxV((double)speed).Item1; - public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.AddStartTimeToMaxV((double)speed); - public long GetProgressStored() => progress.GetValue(); - public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV(); - public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxVWithStartTime(); - - public bool IsFinished() - { - long progressNow, needTime; - (progressNow, needTime, _) = progress.AddStartTimeToMaxV((double)speed); - return progressNow == needTime; - } - public bool IsProgressing() - { - long progressNow, needTime, startT; - (progressNow, needTime, startT) = progress.AddStartTimeToMaxV((double)speed); - return (startT != long.MaxValue && progressNow != needTime); - } - #endregion - - public bool Start(long needTime) - { - if (needTime <= 2) - { - Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0."); - return false; - } - if (progress.startTime.Start() != long.MaxValue) return false; - progress.SetMaxV(needTime); - return true; - } - public bool Start() - { - return progress.startTime.Start() == long.MaxValue; - } - /// - /// 使进度条强制终止清零 - /// - public void Set0() - { - progress.SetAndStop(); - } - /// - /// 如果进度条加上时间差不能为满,使进度条强制终止清零 - /// - public void TryStop() - { - progress.Set0IfNotAddStartTimeToMaxV(speed); - } - /// - /// 使进度条暂停 - /// - public bool Pause() - { - return progress.AddStartTime((double)speed) != 0; - } - /// - /// 使进度条进度为满 - /// - public void Finish() - { - progress.SetVToMaxV(); - progress.startTime.Stop(); - } - } - /// /// 根据时间推算Start后完成多少进度的进度条(long)。 /// 只允许Start(清零状态的进度条才可以Start)时修改needTime(请确保大于0);