117 lines
3.8 KiB
C#
117 lines
3.8 KiB
C#
using WebmrAPI.Utils.Sequences;
|
|
|
|
namespace WebmrAPI.Utils
|
|
{
|
|
public sealed class ScrollAmountGenerator : BaseGenerator<int>
|
|
{
|
|
public enum Direction
|
|
{
|
|
Up,
|
|
Down
|
|
}
|
|
|
|
public class CorrectionData
|
|
{
|
|
public Direction Dir { get; set; }
|
|
public int Order { get; set; }
|
|
}
|
|
|
|
private double _fJitter = 0.12;
|
|
private double _fAccuracy = 0.83;
|
|
private int _nCorrections = 0;
|
|
private int _bAmount = 120;
|
|
public int TotalAmount { get; private set; }
|
|
public int CurrentAmount { get; private set; }
|
|
public int BaseAmount { get => _bAmount; private set => UpdateSpread(value, FJitter); }
|
|
public double FJitter { get => _fJitter; private set => UpdateSpread(BaseAmount, Math.Clamp(Math.Abs(value), 0.0, 1.0)); }
|
|
public int CorrectionLimit { get; private set; } = 1;
|
|
public override double Progress { get => (double)CurrentAmount / TotalAmount; protected set => base.Progress = value; }
|
|
public double FAccuracy { get => _fAccuracy; private set => _fAccuracy = Math.Clamp(Math.Abs(value), 0.0, 1.0); }
|
|
public Direction Dir { get; private set; }
|
|
public override double Step { get; protected set; }
|
|
|
|
public delegate void CorrectionHandler(object sender, CorrectionData data);
|
|
|
|
public event CorrectionHandler? Correction;
|
|
|
|
public ScrollAmountGenerator SetBaseAmount(int baseAmount) { BaseAmount = baseAmount; return this; }
|
|
public ScrollAmountGenerator SetJitterFactor(double jitterFactor) { FJitter = jitterFactor; return this; }
|
|
public ScrollAmountGenerator SetCorrectionLimit(int limit) { CorrectionLimit = limit; return this; }
|
|
public ScrollAmountGenerator SetAccuracyFactor(double accuracyFactor) { FAccuracy = accuracyFactor; return this; }
|
|
|
|
private void ToggleDirection()
|
|
{
|
|
Dir = Dir == Direction.Up ? Direction.Down : Direction.Up;
|
|
}
|
|
|
|
private void UpdateSpread(int baseAmount, double jitterFactor)
|
|
{
|
|
var offset = baseAmount * jitterFactor;
|
|
var amount = Math.Abs(Double.CreateChecked(baseAmount));
|
|
|
|
_bAmount = baseAmount;
|
|
_fJitter = jitterFactor;
|
|
Min = (int)(amount - offset);
|
|
Max = (int)(amount + offset);
|
|
}
|
|
|
|
protected override int Calc()
|
|
{
|
|
int value;
|
|
if (Generate(0, 100000) > (int)(FAccuracy * 100000))
|
|
value = Generate(Min, Max);
|
|
else value = BaseAmount;
|
|
|
|
if (Dir == Direction.Down)
|
|
{
|
|
value = -value;
|
|
}
|
|
|
|
CurrentAmount += value;
|
|
return value;
|
|
}
|
|
|
|
public override int Next()
|
|
{
|
|
if (Progress < 0)
|
|
{
|
|
Progress = 0;
|
|
return First();
|
|
}
|
|
|
|
if (!HasValues || IsZero(1.0 - Progress))
|
|
{
|
|
HasValues = false;
|
|
Progress = 1.0;
|
|
return Last();
|
|
}
|
|
else if (Progress > 1.0 && _nCorrections < CorrectionLimit)
|
|
{
|
|
ToggleDirection();
|
|
Correction?.Invoke(this, new CorrectionData { Dir = Dir, Order = ++_nCorrections });
|
|
}
|
|
|
|
return Calc();
|
|
}
|
|
|
|
public override ISequenceGenerator<int> Reset()
|
|
{
|
|
HasValues = true;
|
|
if ((_nCorrections & 1) != 0)
|
|
{
|
|
ToggleDirection();
|
|
}
|
|
_nCorrections = 0;
|
|
return this;
|
|
}
|
|
|
|
public ScrollAmountGenerator(int totalAmount, Direction dir)
|
|
: base(default, default)
|
|
{
|
|
TotalAmount = (dir == Direction.Up) ? totalAmount : -totalAmount;
|
|
Dir = dir;
|
|
UpdateSpread(BaseAmount, FJitter);
|
|
}
|
|
}
|
|
}
|