Das Menü auf der Serienseite bot zwanzig Sprachen an, von denen die Serie
zwei hatte. Um das zu ändern, muss jemand wissen, welche es wirklich
gibt — und zwar in einer Abfrage: zwanzig Folgen einzeln zu holen wären
zwanzig Rundreisen, und am Ende müsste der Client dieselbe Rechnung
anstellen.
`GET /api/v1/series/{id}/languages` nennt Ton- und Textsprachen als
**Schnittmenge** über alle Folgen. Eine Sprache anzubieten, die es nur in
Staffel 1 gibt, hiesse: eine Einstellung für die Serie, die ab Staffel 2
stillschweigend etwas anderes tut. Was dabei wegfällt, wird gezählt —
damit die Oberfläche es sagen kann, statt es zu verschweigen.
Zwei Dinge, die sonst falsche Ergebnisse gäben:
Gruppiert wird nach dem **Namen**, nicht nach dem Kürzel. Eine gewachsene
Sammlung trägt „ger" und „deu" nebeneinander; nach dem Kürzel gezählt
fiele Deutsch aus der Schnittmenge, obwohl es überall liegt.
Gezählt werden nur Folgen, die eine **Datei** haben. Eine angekündigte
Folge kann keine Sprache beisteuern; sie als fehlend zu zählen liesse das
Menü bei jeder laufenden Serie leer.
Die Rechnung steht in `Flaro.Core`, nicht im Endpunkt: sie hängt an keiner
Datenbank und lässt sich so prüfen, ohne eine Serie anzulegen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
126 lines
4.3 KiB
C#
126 lines
4.3 KiB
C#
using Flaro.Core.Media;
|
|
|
|
namespace Flaro.Core.Tests;
|
|
|
|
/// <summary>Welche Sprachen eine Serie durchgehend führt.</summary>
|
|
///
|
|
/// <remarks>
|
|
/// <b>Der Anlass.</b> Auf der Serienseite stand ein Menü mit zwanzig
|
|
/// Sprachen, von denen die Serie zwei hatte. Die Frage dahinter — welche
|
|
/// gilt für die ganze Serie — beantwortet die Schnittmenge: eine Sprache,
|
|
/// die es nur in Staffel 1 gibt, taugt nicht als Einstellung für die Serie.
|
|
/// </remarks>
|
|
public class SprachschnittTests
|
|
{
|
|
private static readonly Guid Eins = Guid.NewGuid();
|
|
private static readonly Guid Zwei = Guid.NewGuid();
|
|
private static readonly Guid Drei = Guid.NewGuid();
|
|
|
|
[Test]
|
|
public void Was_in_jeder_Folge_liegt_kommt_durch()
|
|
{
|
|
var (durch, fehlt) = Sprachschnitt.Von(
|
|
[(Eins, "deu"), (Eins, "eng"), (Zwei, "deu"), (Zwei, "eng")], folgen: 2);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(durch.Select(x => x.Code), Is.EquivalentTo(new[] { "deu", "eng" }));
|
|
Assert.That(fehlt, Is.Zero);
|
|
});
|
|
}
|
|
|
|
/// <summary>Eine Sprache aus nur einer Staffel fällt weg — und wird gezählt.</summary>
|
|
///
|
|
/// <remarks>
|
|
/// <b>Gezählt, nicht verschwiegen.</b> Wer Japanisch in Staffel 1 gesehen
|
|
/// hat und es im Menü vermisst, hielte das sonst für einen Fehler.
|
|
/// </remarks>
|
|
[Test]
|
|
public void Was_nur_in_einer_Folge_liegt_faellt_weg()
|
|
{
|
|
var (durch, fehlt) = Sprachschnitt.Von(
|
|
[(Eins, "deu"), (Eins, "jpn"), (Zwei, "deu")], folgen: 2);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(durch.Select(x => x.Code), Is.EquivalentTo(new[] { "deu" }));
|
|
Assert.That(fehlt, Is.EqualTo(1), "Japanisch gibt es, aber nicht überall.");
|
|
});
|
|
}
|
|
|
|
/// <summary>„ger" und „deu" sind dieselbe Sprache.</summary>
|
|
///
|
|
/// <remarks>
|
|
/// <b>Sonst fiele Deutsch aus der Schnittmenge</b>, obwohl es in jeder
|
|
/// Folge liegt — nur mit zwei Kürzeln, je nachdem, womit die Datei
|
|
/// erstellt wurde. Genau so sieht eine gewachsene Sammlung aus.
|
|
/// </remarks>
|
|
[Test]
|
|
public void Zwei_Kuerzel_fuer_dieselbe_Sprache_zaehlen_als_eine()
|
|
{
|
|
var (durch, fehlt) = Sprachschnitt.Von(
|
|
[(Eins, "ger"), (Zwei, "deu"), (Drei, "de-DE")], folgen: 3);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(durch, Has.Count.EqualTo(1));
|
|
Assert.That(durch[0].Name, Is.EqualTo("Deutsch"));
|
|
Assert.That(fehlt, Is.Zero);
|
|
});
|
|
}
|
|
|
|
/// <summary>„und" ist keine Sprache, sondern das Fehlen einer Angabe.</summary>
|
|
[Test]
|
|
public void Eine_unbekannte_Angabe_zaehlt_nicht_mit()
|
|
{
|
|
var (durch, fehlt) = Sprachschnitt.Von(
|
|
[(Eins, "und"), (Eins, "deu"), (Zwei, "deu"), (Zwei, null)], folgen: 2);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(durch.Select(x => x.Code), Is.EquivalentTo(new[] { "deu" }));
|
|
Assert.That(fehlt, Is.Zero);
|
|
});
|
|
}
|
|
|
|
/// <summary>Ohne Folgen mit Datei gibt es nichts zu schneiden.</summary>
|
|
///
|
|
/// <remarks>
|
|
/// <b>Und keine Division durch die Erwartung.</b> Eine angekündigte
|
|
/// Serie ohne eine einzige Datei darf kein leeres Menü mit einem Hinweis
|
|
/// ergeben, sondern gar keines.
|
|
/// </remarks>
|
|
[Test]
|
|
public void Ohne_Folgen_kommt_nichts()
|
|
{
|
|
var (durch, fehlt) = Sprachschnitt.Von([(Eins, "deu")], folgen: 0);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(durch, Is.Empty);
|
|
Assert.That(fehlt, Is.Zero);
|
|
});
|
|
}
|
|
|
|
/// <summary>Dieselbe Sprache zweimal in einer Folge zählt einmal.</summary>
|
|
///
|
|
/// <remarks>
|
|
/// Zwei deutsche Tonspuren — Original und Audiodeskription — kommen vor.
|
|
/// Gezählt wird die Folge, nicht die Spur; sonst käme eine Serie mit
|
|
/// zwei Spuren in Folge 1 und keiner in Folge 2 auf dieselbe Zahl wie
|
|
/// eine durchgehende.
|
|
/// </remarks>
|
|
[Test]
|
|
public void Zwei_Spuren_derselben_Sprache_in_einer_Folge_zaehlen_einmal()
|
|
{
|
|
var (durch, fehlt) = Sprachschnitt.Von(
|
|
[(Eins, "deu"), (Eins, "deu")], folgen: 2);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(durch, Is.Empty, "Folge 2 hat keine deutsche Spur.");
|
|
Assert.That(fehlt, Is.EqualTo(1));
|
|
});
|
|
}
|
|
}
|