39 lines
1.6 KiB
C#
39 lines
1.6 KiB
C#
namespace BlueLaminate.Core.Tradeups;
|
||
|
||
/// <summary>
|
||
/// The exact float arithmetic of a CS2 tradeup. Kept pure and dependency-free so it
|
||
/// can be unit-tested in isolation and reused verbatim by any frontend.
|
||
/// <para>
|
||
/// The contract: each input float is normalised to its own skin's range FIRST, those
|
||
/// fractions are averaged, and the average is mapped onto the OUTPUT skin's range. The
|
||
/// output float depends only on the average input fraction — a single scalar — which
|
||
/// is what makes the search tractable (see the engine design notes).
|
||
/// </para>
|
||
/// </summary>
|
||
public static class TradeupMath
|
||
{
|
||
/// <summary>
|
||
/// Normalises an input float to the fraction of its own skin's wear range:
|
||
/// <c>(value − min) / (max − min)</c>, clamped to [0,1]. A zero-width range
|
||
/// (min == max) has no meaningful fraction and yields 0.
|
||
/// </summary>
|
||
public static decimal NormalizedFraction(decimal floatValue, decimal skinFloatMin, decimal skinFloatMax)
|
||
{
|
||
var span = skinFloatMax - skinFloatMin;
|
||
if (span <= 0m)
|
||
{
|
||
return 0m;
|
||
}
|
||
|
||
var fraction = (floatValue - skinFloatMin) / span;
|
||
return Math.Clamp(fraction, 0m, 1m);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Maps an average input fraction onto an output skin's wear range to get the exact
|
||
/// float the tradeup would produce: <c>avgFraction × (max − min) + min</c>.
|
||
/// </summary>
|
||
public static decimal OutputFloat(decimal averageFraction, decimal outputFloatMin, decimal outputFloatMax)
|
||
=> averageFraction * (outputFloatMax - outputFloatMin) + outputFloatMin;
|
||
}
|