namespace ChromeboxFanControl;
///
/// Fan curve: 14 control points at 0 °C and 40–100 °C every 5 °C, linear interpolation.
///
public static class FanCurve
{
private const int PointCount = 14;
/// Temperature breakpoints (°C): 0, 40, 45, 50, …, 100.
public static readonly int[] TempBreakpoints = [0, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100];
/// CPU temperature in °C.
/// Exactly 14 values 0–100 (fan duty).
public static byte CalculateFanPercent(double tempC, ReadOnlySpan curve)
{
if (curve.Length != PointCount)
throw new ArgumentException($"Curve must contain exactly {PointCount} points.", nameof(curve));
var t = Math.Clamp(tempC, 0, 100);
if (t <= TempBreakpoints[0])
return (byte)Math.Clamp(curve[0], 0, 100);
if (t >= TempBreakpoints[PointCount - 1])
return (byte)Math.Clamp(curve[PointCount - 1], 0, 100);
for (var i = 0; i < PointCount - 1; i++)
{
var t0 = TempBreakpoints[i];
var t1 = TempBreakpoints[i + 1];
if (t >= t0 && t <= t1)
{
var d0 = Math.Clamp(curve[i], 0, 100);
var d1 = Math.Clamp(curve[i + 1], 0, 100);
var frac = (t - t0) / (t1 - t0);
return (byte)Math.Round(d0 + (d1 - d0) * frac);
}
}
return (byte)Math.Clamp(curve[PointCount - 1], 0, 100);
}
}