using Flaro.Core.Media; namespace Flaro.Core.Tests; /// Wo der Abspann eines Films anfängt. /// /// /// Mit erfundenen Messreihen statt mit Filmen. Geprüft wird das /// Beurteilen, nicht ob ffmpeg rechnen kann. Die Zahlen stammen aus einer /// Messung an einem erzeugten Film: Handlung 125, Abspann 18. /// public class AbspannkanteTests { private static readonly Abspannregeln Regeln = Abspannregeln.Vorgabe; /// Eine Reihe von Messpunkten im Abstand von zehn Sekunden. /// /// Ab wann dunkel. null heisst: nie. private static List Reihe(double von, double bis, double? abspannAb) { var proben = new List(); for (var t = von; t <= bis; t += 10) proben.Add(new Bildprobe(t, abspannAb is { } ab && t >= ab ? 18 : 125)); return proben; } [Test] public void Eine_dunkle_Strecke_bis_zum_Ende_ist_der_Abspann() { var proben = Reihe(0, 600, abspannAb: 420); Assert.That(Abspannkante.Suchen(proben, Regeln), Is.EqualTo(420)); } /// Ein Film, der hell endet, hat keinen erkennbaren Abspann. /// /// /// Namen über laufendem Bild — Marvel, Pixar, jede zweite Komödie. Kein /// Fund ist hier die richtige Antwort: ein geratener Knopf schnitte /// Handlung weg. /// [Test] public void Ohne_dunkles_Ende_kein_Fund() { Assert.That(Abspannkante.Suchen(Reihe(0, 600, abspannAb: null), Regeln), Is.Null); } /// Eine Schwarzblende mitten im Film zählt nicht. [Test] public void Eine_Schwarzblende_in_der_Mitte_zaehlt_nicht() { var proben = Reihe(0, 600, abspannAb: null); for (var i = 20; i < 30; i++) proben[i] = proben[i] with { Helligkeit = 10 }; Assert.That(Abspannkante.Suchen(proben, Regeln), Is.Null, "sie hält nicht bis zum Ende durch"); } /// Eine Szene nach dem Abspann nimmt den Fund weg. /// /// /// Lieber keine Marke als eine, die über die Szene hinwegspringt. /// [Test] public void Eine_Szene_nach_dem_Abspann_nimmt_den_Fund_weg() { var proben = Reihe(0, 600, abspannAb: 420); for (var i = proben.Count - 5; i < proben.Count; i++) proben[i] = proben[i] with { Helligkeit = 120 }; Assert.That(Abspannkante.Suchen(proben, Regeln), Is.Null); } /// Eine helle Schrifttafel mittendrin bricht die Strecke nicht. [Test] public void Eine_kurze_helle_Tafel_bricht_nichts() { var proben = Reihe(0, 600, abspannAb: 420); // Zwei Proben, also zwanzig Sekunden, sind hell. proben[50] = proben[50] with { Helligkeit = 140 }; proben[51] = proben[51] with { Helligkeit = 140 }; Assert.That(Abspannkante.Suchen(proben, Regeln), Is.EqualTo(420)); } /// Zwanzig Sekunden Dunkelheit sind kein Abspann. [Test] public void Zu_kurz_zaehlt_nicht() { Assert.That(Abspannkante.Suchen(Reihe(0, 600, abspannAb: 580), Regeln), Is.Null); } /// Ein halber Film im Dunkeln ist ein Fehlfund. [Test] public void Zu_lang_zaehlt_auch_nicht() { Assert.That(Abspannkante.Suchen(Reihe(0, 3600, abspannAb: 600), Regeln), Is.Null); } [Test] public void Die_letzte_helle_Probe_begrenzt_die_Suche() { var proben = Reihe(0, 600, abspannAb: 420); Assert.That(Abspannkante.HellDavor(proben, 420, Regeln), Is.EqualTo(410)); } // ---------- Nachmessen ---------- /// Die binäre Suche findet die Kante auf vier Sekunden genau. [Test] public async Task Die_Kante_wird_eingegrenzt() { const double echteKante = 417.3; var sonden = 0; var kante = await Abspannkante.VerfeinernAsync(410, 420, Regeln, stelle => { sonden++; return Task.FromResult(stelle >= echteKante ? 18 : 125); }); Assert.Multiple(() => { Assert.That(kante, Is.EqualTo(echteKante).Within(4)); Assert.That(kante, Is.GreaterThanOrEqualTo(echteKante), "lieber ein paar Sekunden Abspann zu viel als eine Sekunde Handlung"); Assert.That(sonden, Is.LessThanOrEqualTo(4), "zehn Sekunden auf vier: zwei Halbierungen"); }); } /// Antwortet eine Sonde nicht, gilt der grobe Fund. [Test] public async Task Ohne_Antwort_bleibt_es_beim_groben_Fund() { var kante = await Abspannkante.VerfeinernAsync( 410, 420, Regeln, _ => Task.FromResult(null)); Assert.That(kante, Is.EqualTo(420)); } /// Ein schon enger Bereich braucht keine Sonde. [Test] public async Task Ein_enger_Bereich_wird_nicht_angefasst() { var sonden = 0; var kante = await Abspannkante.VerfeinernAsync(418, 420, Regeln, _ => { sonden++; return Task.FromResult(18); }); Assert.Multiple(() => { Assert.That(kante, Is.EqualTo(420)); Assert.That(sonden, Is.Zero); }); } }