Welche Sprachen eine Serie durchgehend führt
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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2c51f639be
commit
22be288fc3
@@ -0,0 +1,125 @@
|
||||
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));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user