Skip to content

Commit

Permalink
Merge pull request #203 from shangfengh/dev
Browse files Browse the repository at this point in the history
refactor(SafeValue): ♻️ move the InRangeTimeBased
  • Loading branch information
shangfengh authored Apr 11, 2024
2 parents d5ab5e4 + d78c934 commit cfe0a00
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 283 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
using Preparation.Utility;
using System;
using System.Numerics;
using System.Threading;

namespace Preparation.Utility
{
//其对应属性不应当有set访问器,避免不安全的=赋值

public class LongInVariableRangeWithStartTime : InVariableRange<long>
{
public StartTime startTime = new();
public LongInVariableRangeWithStartTime(long value, long maxValue) : base(value, maxValue) { }
/// <summary>
/// 默认使Value=maxValue
/// </summary>
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

/// <summary>
/// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue
/// 如果无法加到maxValue则不加
/// </summary>
/// <returns>返回试图加到的值与最大值</returns>
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());
});
}

/// <summary>
/// 增加量为时间差*速度,并将startTime变为long.MaxValue
/// </summary>
/// <returns>返回实际改变量</returns>
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;
});
}

/// <summary>
/// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上
/// 如果无法加到maxValue则清零
/// 无论如何startTime变为long.MaxValue
/// </summary>
/// <returns>返回是否清零</returns>
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;
}
/// <summary>
/// 使进度条强制终止清零
/// </summary>
public void Set0()
{
progress.SetAndStop();
}
/// <summary>
/// 如果进度条加上时间差不能为满,使进度条强制终止清零
/// </summary>
public void TryStop()
{
progress.Set0IfNotAddStartTimeToMaxV(speed);
}
/// <summary>
/// 使进度条暂停
/// </summary>
public bool Pause()
{
return progress.AddStartTime((double)speed) != 0;
}
/// <summary>
/// 使进度条进度为满
/// </summary>
public void Finish()
{
progress.SetVToMaxV();
progress.startTime.Stop();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,6 @@ public class InVariableRange<T> : LockedValue, IIntAddable, IAddable<T>, IDouble
protected T v;
protected T maxV;

#region NeedToDo
public virtual TResult ReadNeed<TResult>(Func<TResult> func)
{
lock (vLock)
{
return func();
}
}
public virtual void ReadNeed(Action func)
{
lock (vLock)
{
func();
}
}

public virtual TResult WriteNeed<TResult>(Func<TResult> func)
{
lock (vLock)
{
return func();
}
}
public virtual void WriteNeed(Action func)
{
lock (vLock)
{
func();
}
}
#endregion

#region 构造与读取
public InVariableRange(T value, T maxValue) : base()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@ public abstract class LockedValue
{
protected readonly object vLock = new();
protected object VLock => vLock;

#region NeedToDo
public virtual TResult ReadNeed<TResult>(Func<TResult> func)
{
lock (vLock)
{
return func();
}
}
public virtual void ReadNeed(Action func)
{
lock (vLock)
{
func();
}
}

public virtual TResult WriteNeed<TResult>(Func<TResult> 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;
Expand Down
Loading

0 comments on commit cfe0a00

Please sign in to comment.