AccelCalculator.cs
using grapher.Models.Serialized;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace grapher.Models.Calculations
{
public clast AccelCalculator
{
#region Structs
public struct SimulatedMouseInput
{
public double velocity;
public double time;
public double angle;
public int x;
public int y;
}
#endregion Structs
#region Static
public static double[] SlowMovements =
{
0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.333, 3.666, 4.0, 4.333, 4.666,
};
public IEnumerable Angles = GetAngles();
#endregion static
#region Constructors
public AccelCalculator(Field dpi, Field pollRate)
{
DPI = dpi;
PollRate = pollRate;
}
#endregion Constructors
#region Properties
public ReadOnlyCollection SimulatedInputCombined { get; private set; }
public ReadOnlyCollection SimulatedInputX { get; private set; }
public ReadOnlyCollection SimulatedInputY { get; private set; }
public IReadOnlyCollection SimulatedDirectionalInput { get; private set; }
public Field DPI { get; private set; }
public Field PollRate { get; private set; }
private double MaxVelocity { get; set; }
private double Increment { get; set; }
private double MeasurementTime { get; set; }
private (double, double) RotationVector { get; set; }
private (double, double) Sensitivity { get; set; }
#endregion Fields
#region Methods
public static IEnumerable GetAngles()
{
for(double i=0; i < (Constants.AngleDivisions); i++)
{
yield return (i / (Constants.AngleDivisions-1.0)) * (Math.PI / 2);
}
}
public static int NearestAngleDivision(double angle)
{
var angleTransformed = angle * 2 / Math.PI * (Constants.AngleDivisions-1);
return (int)Math.Round(angleTransformed);
}
public void Calculate(AccelChartData data, ManagedAccel accel, double starter, ICollection simulatedInputData)
{
double lastInputMagnitude = 0;
double lastOutputMagnitude = 0;
SimulatedMouseInput lastInput;
double lastSlope = 0;
double maxRatio = 0.0;
double minRatio = Double.MaxValue;
double maxSlope = 0.0;
double minSlope = Double.MaxValue;
double log = -2;
int index = 0;
int logIndex = 0;
foreach (var simulatedInputDatum in simulatedInputData)
{
if (simulatedInputDatum.velocity 0 ? outDiff / inDiff : starter);
if (slope < lastSlope)
{
Console.WriteLine();
}
if (ratio > maxRatio)
{
maxRatio = ratio;
}
if (ratio < minRatio)
{
minRatio = ratio;
}
if (slope > maxSlope)
{
maxSlope = slope;
}
if (slope < minSlope)
{
minSlope = slope;
}
if (!data.AccelPoints.ContainsKey(simulatedInputDatum.velocity))
{
data.AccelPoints.Add(simulatedInputDatum.velocity, ratio);
}
if (!data.GainPoints.ContainsKey(simulatedInputDatum.velocity))
{
data.GainPoints.Add(simulatedInputDatum.velocity, slope);
}
lastInputMagnitude = simulatedInputDatum.velocity;
lastOutputMagnitude = outMagnitude;
index += 1;
lastInput = simulatedInputDatum;
lastSlope = slope;
}
index--;
while (log maxRatio))
{
maxRatio = ratio;
}
if (indexToMeasureExtrema && (ratio < minRatio))
{
minRatio = ratio;
}
if (indexToMeasureExtrema && (slope > maxSlope))
{
maxSlope = slope;
}
if (indexToMeasureExtrema && (slope < minSlope))
{
minSlope = slope;
}
if (!data.AccelPoints.ContainsKey(simulatedInputDatum.velocity))
{
data.AccelPoints.Add(simulatedInputDatum.velocity, ratio);
}
if (!data.GainPoints.ContainsKey(simulatedInputDatum.velocity))
{
data.GainPoints.Add(simulatedInputDatum.velocity, slope);
}
lastInputMagnitude = simulatedInputDatum.velocity;
lastOutputMagnitude = magnitude;
index += 1;
}
index--;
while (log m1.velocity.CompareTo(m2.velocity));
return magnitudes.AsReadOnly();
}
public ReadOnlyCollection GetSimulatInputX()
{
var magnitudes = new List();
foreach (var slowMovement in SlowMovements)
{
var ceil = (int)Math.Ceiling(slowMovement);
var timeFactor = ceil / slowMovement;
SimulatedMouseInput mouseInputData;
mouseInputData.x = ceil;
mouseInputData.y = 0;
mouseInputData.time = MeasurementTime*timeFactor;
mouseInputData.velocity = Velocity(ceil, 0, mouseInputData.time);
mouseInputData.angle = 0;
magnitudes.Add(mouseInputData);
}
for (double i = 5; i < MaxVelocity; i+=Increment)
{
SimulatedMouseInput mouseInputData;
var ceil = (int)Math.Ceiling(i);
var timeFactor = ceil / i;
mouseInputData.x = ceil;
mouseInputData.y = 0;
mouseInputData.time = MeasurementTime*timeFactor;
mouseInputData.velocity = DecimalCheck(Velocity(ceil, 0, mouseInputData.time));
mouseInputData.angle = 0;
magnitudes.Add(mouseInputData);
}
return magnitudes.AsReadOnly();
}
public ReadOnlyCollection GetSimulatedInputY()
{
var magnitudes = new List();
foreach (var slowMovement in SlowMovements)
{
var ceil = (int)Math.Ceiling(slowMovement);
var timeFactor = ceil / slowMovement;
SimulatedMouseInput mouseInputData;
mouseInputData.x = 0;
mouseInputData.y = ceil;
mouseInputData.time = MeasurementTime*timeFactor;
mouseInputData.velocity = DecimalCheck(Velocity(0, ceil, mouseInputData.time));
mouseInputData.angle = 0;
magnitudes.Add(mouseInputData);
}
for (double i = 5; i < MaxVelocity; i+=Increment)
{
SimulatedMouseInput mouseInputData;
var ceil = (int)Math.Ceiling(i);
var timeFactor = ceil / i;
mouseInputData.x = 0;
mouseInputData.y = ceil;
mouseInputData.time = MeasurementTime*timeFactor;
mouseInputData.velocity = DecimalCheck(Velocity(0, ceil, mouseInputData.time));
mouseInputData.angle = Math.PI / 2;
magnitudes.Add(mouseInputData);
}
return magnitudes.AsReadOnly();
}
public IReadOnlyCollection GetSimulatedDirectionalInput()
{
var magnitudesByAngle = new List();
foreach (var angle in Angles)
{
var magnitudes = new List();
foreach (var slowMoveMagnitude in SlowMovements)
{
magnitudes.Add(SimulateAngledInput(angle, slowMoveMagnitude));
}
for (double magnitude = 5; magnitude < MaxVelocity; magnitude+=Increment)
{
magnitudes.Add(SimulateAngledInput(angle, magnitude));
}
magnitudesByAngle.Add(magnitudes.AsReadOnly());
}
return magnitudesByAngle.AsReadOnly();
}
public static double Magnitude(int x, int y)
{
if (x == 0)
{
return Math.Abs(y);
}
if (y == 0)
{
return Math.Abs(x);
}
return Math.Sqrt(x * x + y * y);
}
public static double Magnitude(double x, double y)
{
if (x == 0)
{
return Math.Abs(y);
}
if (y == 0)
{
return Math.Abs(x);
}
return Math.Sqrt(x * x + y * y);
}
public static double Velocity(int x, int y, double time)
{
return Magnitude(x, y) / time;
}
public static double Velocity(double x, double y, double time)
{
return Magnitude(x, y) / time;
}
public static bool ShouldStripSens(Profile settings) =>
settings.yxSensRatio != 1;
public static bool ShouldStripRot(Profile settings) =>
settings.rotation > 0;
public static (double, double) GetSens(Profile settings) =>
(settings.sensitivity, settings.sensitivity * settings.yxSensRatio);
public static (double, double) GetRotVector(Profile settings) =>
(Math.Cos(settings.rotation), Math.Sin(settings.rotation));
public static (double, double) StripSens(double outputX, double outputY, double sensitivityX, double sensitivityY) =>
(outputX / sensitivityX, outputY / sensitivityY);
public (double, double) StripRot(double outputX, double outputY, double rotX, double rotY) =>
(outputX * rotX + outputY * rotY, outputX * rotY - outputY * rotX);
public (double, double) StripThisSens(double outputX, double outputY) =>
StripSens(outputX, outputY, Sensitivity.Item1, Sensitivity.Item2);
public (double, double) StripThisRot(double outputX, double outputY) =>
StripRot(outputX, outputY, RotationVector.Item1, RotationVector.Item2);
public void ScaleByMouseSettings()
{
MaxVelocity = DPI.Data * Constants.MaxMultiplier;
var ratio = MaxVelocity / Constants.Resolution;
Increment = ratio;
MeasurementTime = 1;
SimulatedInputCombined = GetSimulatedInput();
SimulatedInputX = GetSimulatInputX();
SimulatedInputY = GetSimulatedInputY();
SimulatedDirectionalInput = GetSimulatedDirectionalInput();
}
private static readonly double MinChartAllowedValue = Convert.ToDouble(Decimal.MinValue) / 10;
private static readonly double MaxChartAllowedValue = Convert.ToDouble(Decimal.MaxValue) / 10;
private double DecimalCheck(double value)
{
if (value < MinChartAllowedValue)
{
return MinChartAllowedValue;
}
if (value > MaxChartAllowedValue)
{
return MaxChartAllowedValue;
}
return value;
}
private SimulatedMouseInput SimulateAngledInput(double angle, double magnitude)
{
SimulatedMouseInput mouseInputData;
var moveX = Math.Round(magnitude * Math.Cos(angle), 4);
var moveY = Math.Round(magnitude * Math.Sin(angle), 4);
if (moveX == 0)
{
mouseInputData.x = 0;
mouseInputData.y = (int)Math.Ceiling(moveY);
mouseInputData.time = mouseInputData.y / moveY;
}
else if (moveY == 0)
{
mouseInputData.x = (int)Math.Ceiling(moveX);
mouseInputData.y = 0;
mouseInputData.time = mouseInputData.x / moveX;
}
else
{
var ratio = moveY / moveX;
int ceilX = 0;
int ceilY = 0;
double biggerX = 0;
double biggerY = 0;
double roundedBiggerX = 0;
double roundedBiggerY = 0;
double roundedRatio = -1;
double factor = 10;
while (Math.Abs(roundedRatio - ratio) > 0.01 &&
biggerX < 25000 &&
biggerY < 25000)
{
roundedBiggerX = Math.Floor(biggerX);
roundedBiggerY = Math.Floor(biggerY);
ceilX = Convert.ToInt32(roundedBiggerX);
ceilY = Convert.ToInt32(roundedBiggerY);
roundedRatio = ceilX > 0 ? ceilY / ceilX : -1;
biggerX = moveX * factor;
biggerY = moveY * factor;
factor *= 10;
}
var ceilMagnitude = Magnitude(ceilX, ceilY);
var timeFactor = ceilMagnitude / magnitude;
mouseInputData.x = ceilX;
mouseInputData.y = ceilY;
mouseInputData.time = timeFactor;
if (mouseInputData.x == 1 && mouseInputData.time == 1)
{
Console.WriteLine("Oops");
}
}
mouseInputData.velocity = DecimalCheck(Velocity(mouseInputData.x, mouseInputData.y, mouseInputData.time));
if (double.IsNaN(mouseInputData.velocity))
{
Console.WriteLine("oopsie");
}
mouseInputData.angle = angle;
return mouseInputData;
}
#endregion Methods
}
}