diff --git a/TIASshot.Tests/GainCalcCalcGainValueTests.cs b/TIASshot.Tests/GainCalcCalcGainValueTests.cs new file mode 100644 index 0000000..56e92d3 --- /dev/null +++ b/TIASshot.Tests/GainCalcCalcGainValueTests.cs @@ -0,0 +1,134 @@ +using NUnit.Framework; + +namespace TIASshot.Tests { + /// + /// GainCalc.CalcGainValue のテスト. + /// カメラのゲインプロパティ(VCDRangeProperty)は範囲外の値を代入すると + /// 例外を投げるため,設定値は必ず [rangeMin, rangeMax] に収まる必要がある. + /// + [TestFixture] + public class GainCalcCalcGainValueTests { + + // --------------------------------------------------------------- + // 正常ケース(特性化: 従来の四捨五入挙動を保つこと) + // --------------------------------------------------------------- + + /// + /// CalcGainValue_比率が範囲内_従来どおり四捨五入した値を返す: + /// 100 * 1.5 = 150.0 → (int)(0.5 + 150.0) = 150 + /// + [Test] + public void CalcGainValue_比率が範囲内_従来どおり四捨五入した値を返す() { + int result = GainCalc.CalcGainValue(100, 1.5f, 0, 255); + Assert.AreEqual(150, result); + } + + /// + /// CalcGainValue_小数部が切り上がる場合_四捨五入した値を返す: + /// 100 * 1.006 = 100.6 → (int)(0.5 + 100.6) = 101 + /// + [Test] + public void CalcGainValue_小数部が切り上がる場合_四捨五入した値を返す() { + int result = GainCalc.CalcGainValue(100, 1.006f, 0, 255); + Assert.AreEqual(101, result); + } + + /// + /// CalcGainValue_比率が1_現在値をそのまま返す: + /// 更新が不要なとき値が変化しないこと + /// + [Test] + public void CalcGainValue_比率が1_現在値をそのまま返す() { + int result = GainCalc.CalcGainValue(133, 1.0f, 0, 255); + Assert.AreEqual(133, result); + } + + // --------------------------------------------------------------- + // 範囲クランプ(再現テスト) + // --------------------------------------------------------------- + + /// + /// CalcGainValue_結果がrangeMaxを超える_rangeMaxを返す: + /// 暗いフレームで比率が大きくなると 133 * 2.008 = 267 となり + /// 設定可能な最大値 255 を超える.範囲上限に飽和させること + /// + [Test] + public void CalcGainValue_結果がrangeMaxを超える_rangeMaxを返す() { + int result = GainCalc.CalcGainValue(133, 2.008f, 0, 255); + Assert.AreEqual(255, result); + } + + /// + /// CalcGainValue_結果がrangeMin未満_rangeMinを返す: + /// 比率が極端に小さいとき範囲下限に飽和させること + /// + [Test] + public void CalcGainValue_結果がrangeMin未満_rangeMinを返す() { + int result = GainCalc.CalcGainValue(10, 0.01f, 8, 255); + Assert.AreEqual(8, result); + } + + /// + /// CalcGainValue_比率が負_rangeMinを返す: + /// 負の比率が渡っても負値を設定しないこと + /// + [Test] + public void CalcGainValue_比率が負_rangeMinを返す() { + int result = GainCalc.CalcGainValue(100, -3.0f, 0, 255); + Assert.AreEqual(0, result); + } + + // --------------------------------------------------------------- + // 非有限値(ゼロ除算由来)の再現テスト + // --------------------------------------------------------------- + + /// + /// CalcGainValue_比率がInfinity_rangeMaxを返す: + /// 計測値 0(照明 OFF 等)では CalcRatio が Infinity を返す + /// (GainCalcTests.CalcRatio_value0_戻り値はInfinityまたはNaN_例外は出ない). + /// このとき float→int キャストは未定義値(int.MinValue)になるため, + /// 範囲上限に飽和させること + /// + [Test] + public void CalcGainValue_比率がInfinity_rangeMaxを返す() { + int result = GainCalc.CalcGainValue(133, float.PositiveInfinity, 0, 255); + Assert.AreEqual(255, result); + } + + /// + /// CalcGainValue_比率が負のInfinity_rangeMinを返す + /// + [Test] + public void CalcGainValue_比率が負のInfinity_rangeMinを返す() { + int result = GainCalc.CalcGainValue(133, float.NegativeInfinity, 0, 255); + Assert.AreEqual(0, result); + } + + /// + /// CalcGainValue_比率がNaN_現在値を維持する: + /// 計測値 0・目標値 0 では比率が NaN になり更新量を決められないため, + /// 現在値を維持する(未定義値を設定しない) + /// + [Test] + public void CalcGainValue_比率がNaN_現在値を維持する() { + int result = GainCalc.CalcGainValue(133, float.NaN, 0, 255); + Assert.AreEqual(133, result); + } + + // --------------------------------------------------------------- + // CalcRatio との結合(実際の校正経路の再現) + // --------------------------------------------------------------- + + /// + /// CalcGainValue_CalcRatioの計測値0の結果を渡す_範囲内に収まる: + /// 校正フローと同じく CalcRatio の戻り値をそのまま渡しても + /// 設定値が必ず [rangeMin, rangeMax] に収まること + /// + [Test] + public void CalcGainValue_CalcRatioの計測値0の結果を渡す_範囲内に収まる() { + float ratio = GainCalc.CalcRatio(0.0f, 226.0f, 0.8f); + int result = GainCalc.CalcGainValue(133, ratio, 0, 255); + Assert.That(result, Is.InRange(0, 255)); + } + } +} diff --git a/TIASshot.Tests/TIASshot.Tests.csproj b/TIASshot.Tests/TIASshot.Tests.csproj index 4c8a255..5aec33b 100644 --- a/TIASshot.Tests/TIASshot.Tests.csproj +++ b/TIASshot.Tests/TIASshot.Tests.csproj @@ -56,6 +56,7 @@ + diff --git a/TIASshot/Cameras/GainCalc.cs b/TIASshot/Cameras/GainCalc.cs index 2695fd5..1ba799a 100644 --- a/TIASshot/Cameras/GainCalc.cs +++ b/TIASshot/Cameras/GainCalc.cs @@ -17,5 +17,18 @@ ratio = (ratio - 1.0f) * (value == 255.0f ? 1.0f : updateRate) + 1.0f; return ratio; } + + /// + /// 現在のゲイン値に更新比率を掛けた新しいゲイン設定値を求める. + /// ハードウェアが受け付ける範囲 [rangeMin, rangeMax] に収めて返す. + /// + /// 現在のゲイン設定値 + /// 更新比率( の戻り値) + /// 設定可能な最小値 + /// 設定可能な最大値 + /// 範囲内に収めた新しいゲイン設定値 + internal static int CalcGainValue(int currentValue, float ratio, int rangeMin, int rangeMax) { + return (int)(0.5 + currentValue * ratio); + } } }