using BlueLaminate.Core.Tradeups; using Xunit; namespace BlueLaminate.Tests.Tradeups; public class TradeupMathTests { [Fact] public void NormalizedFraction_maps_value_into_its_own_range() { // Mid-point of a 0.06–0.80 range. var frac = TradeupMath.NormalizedFraction(0.43m, 0.06m, 0.80m); Assert.Equal(0.5m, frac, precision: 6); } [Theory] [InlineData(-0.5)] // below min [InlineData(2.0)] // above max public void NormalizedFraction_clamps_out_of_range_values(double value) { var frac = TradeupMath.NormalizedFraction((decimal)value, 0.0m, 1.0m); Assert.InRange(frac, 0m, 1m); } [Fact] public void NormalizedFraction_returns_zero_for_zero_width_range() { Assert.Equal(0m, TradeupMath.NormalizedFraction(0.3m, 0.3m, 0.3m)); } [Fact] public void OutputFloat_maps_average_fraction_onto_output_range() { // avg 0.10 onto a 0.00–0.70 output range → 0.07 (the FN/MW boundary). var outFloat = TradeupMath.OutputFloat(0.10m, 0.00m, 0.70m); Assert.Equal(0.07m, outFloat, precision: 6); } [Fact] public void Full_contract_float_math_matches_hand_calculation() { // Ten inputs, each normalised to its own range, then averaged and mapped onto the // output's 0.00–0.80 range. Five inputs at fraction 0.2 and five at 0.4 → avg 0.3. var fractions = new[] { 0.2m, 0.2m, 0.2m, 0.2m, 0.2m, 0.4m, 0.4m, 0.4m, 0.4m, 0.4m }; var avg = fractions.Sum() / fractions.Length; Assert.Equal(0.3m, avg, precision: 6); var outFloat = TradeupMath.OutputFloat(avg, 0.00m, 0.80m); Assert.Equal(0.24m, outFloat, precision: 6); Assert.Equal(WearBand.FieldTested, WearBands.FromFloat(outFloat)); } }