Hanni und Nanni ist nicht Hanni und Nanni 3
Deine drei Fälle haben eines gemeinsam, und es ist nicht das, was ich zuerst vermutet hatte: keiner der Dateinamen nennt ein Jahr. Der Riegel von gestern greift deshalb nicht. Gemessen, woran es wirklich liegt. Bei TMDB heisst der Film „Hanni & Nanni", auf der Platte „Hanni und Nanni". Das Kaufmanns-Und fällt im Vergleichs- schlüssel als Sonderzeichen heraus, das Wort „und" bleibt stehen — die Namensgleichheit griff also nie. Gewählt wurde stattdessen der erstbeste Treffer, und das war „Hanni & Nanni 3". Der richtige stand auf Platz zwei, und alle vier Treffer hatten dieselbe Beliebtheit: die Reihenfolge war Zufall. Bindewörter zwischen zwei Namen zählen jetzt nicht mehr mit — gestrichen, nicht übersetzt, sonst bliebe „Batman and Robin" aussen vor. Am Wortanfang bleiben sie stehen: „Und dann kam Polly" ist kein „dann kam Polly". Und die Suche vergleicht über den Schlüssel statt Zeichen für Zeichen. Das verhindert aber nur Neues. Was schon zusammengelegt ist, bleibt es — deshalb gibt es jetzt „Eigener Film": eine Datei löst sich aus ihrem Titel und wird ein eigener Eintrag, mit dem Titel aus dem Dateinamen und ohne Kennung. Eine zu raten hiesse, denselben Fehler zu wiederholen; so steht sie unter „Ohne Zuordnung" und ist in zwei Klicks richtig. Der Super-Mario-Fall liegt anders: beide Titel treffen heute richtig. Der steckt noch aus einem früheren Lauf fest und braucht das Trennen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c3124ba27c
commit
58e06d0539
@@ -41,9 +41,12 @@ public sealed record OhneZuordnung(
|
||||
public sealed record Mehrfachbericht(
|
||||
int Gesamt, IReadOnlyList<Mehrfachtitel> Titel);
|
||||
|
||||
/// <param name="Dateien">Die Namen der Dateien, die an diesem einen Titel hängen.</param>
|
||||
/// <param name="Dateien">Die Dateien, die an diesem einen Titel hängen.</param>
|
||||
public sealed record Mehrfachtitel(
|
||||
Guid Id, string Art, string Titel, int? Jahr, IReadOnlyList<string> Dateien);
|
||||
Guid Id, string Art, string Titel, int? Jahr, IReadOnlyList<Fassungsdatei> Dateien);
|
||||
|
||||
/// <summary>Eine Datei an einem Titel — mit Kennung, damit sie sich herauslösen lässt.</summary>
|
||||
public sealed record Fassungsdatei(Guid Id, string Name);
|
||||
|
||||
public sealed record UnzugeordneteDatei(Guid Id, string Pfad, string Grund);
|
||||
|
||||
|
||||
@@ -299,15 +299,15 @@ public static class ManagementEndpoints
|
||||
.Select(m => new
|
||||
{
|
||||
m.Id, m.Title, Jahr = m.ParsedYear ?? m.Year,
|
||||
Pfade = db.MediaFiles.Where(f => f.MovieId == m.Id)
|
||||
.Select(f => f.Path).ToList(),
|
||||
Dateien = db.MediaFiles.Where(f => f.MovieId == m.Id)
|
||||
.Select(f => new { f.Id, f.Path }).ToList(),
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
var liste = mehrfach
|
||||
.Select(m => new Mehrfachtitel(
|
||||
m.Id, "movie", m.Title, m.Jahr,
|
||||
m.Pfade.Select(p => Dateiname(p) ?? p).ToList()))
|
||||
m.Dateien.Select(f => new Fassungsdatei(f.Id, Dateiname(f.Path) ?? f.Path)).ToList()))
|
||||
.ToList();
|
||||
|
||||
return Results.Ok(new Mehrfachbericht(liste.Count, liste));
|
||||
|
||||
@@ -151,6 +151,63 @@ public static class MatchEndpoints
|
||||
return betroffen > 0 ? Results.NoContent() : Results.NotFound();
|
||||
}).RequireAuthorization(FlaroPolicies.Administrator);
|
||||
|
||||
// **Eine Datei aus ihrem Titel herauslösen.**
|
||||
//
|
||||
// Zwei Dateien hängen an einem Eintrag, gehören aber zu zwei Filmen:
|
||||
// „Hanni und Nanni" und „Hanni und Nanni 3" liefen bei der
|
||||
// Metadatenquelle auf denselben Treffer, und der zweite Film war
|
||||
// damit nicht mehr zu sehen. Die Riegel dagegen greifen erst beim
|
||||
// nächsten Lauf — was schon zusammengelegt ist, bleibt es.
|
||||
//
|
||||
// Der neue Eintrag bekommt den Titel aus dem Dateinamen und keine
|
||||
// Kennung: er steht danach unter „Ohne Zuordnung" und lässt sich dort
|
||||
// in zwei Klicks richtigstellen. Eine Kennung zu raten hiesse, denselben
|
||||
// Fehler noch einmal zu machen.
|
||||
app.MapPost("/api/v1/files/{id:guid}/split", async (
|
||||
Guid id, FlaroContext db, TimeProvider clock) =>
|
||||
{
|
||||
var datei = await db.MediaFiles.FirstOrDefaultAsync(f => f.Id == id);
|
||||
if (datei is null) return Results.NotFound();
|
||||
|
||||
if (datei.MovieId is not { } alt)
|
||||
{
|
||||
return Results.Problem(
|
||||
"Nur eine Filmdatei lässt sich herauslösen. Bei Serien entscheidet "
|
||||
+ "die Folgennummer, zu welcher Folge eine Datei gehört.",
|
||||
statusCode: StatusCodes.Status400BadRequest);
|
||||
}
|
||||
|
||||
var geschwister = await db.MediaFiles.CountAsync(f => f.MovieId == alt);
|
||||
if (geschwister < 2)
|
||||
{
|
||||
return Results.Problem(
|
||||
"An diesem Titel hängt nur diese eine Datei — da gibt es nichts zu trennen.",
|
||||
statusCode: StatusCodes.Status409Conflict);
|
||||
}
|
||||
|
||||
var name = FileNames.ParseMovie(datei.Path);
|
||||
var bisher = await db.Movies.AsNoTracking().FirstAsync(m => m.Id == alt);
|
||||
|
||||
var neu = new Movie
|
||||
{
|
||||
LibraryId = datei.LibraryId,
|
||||
ParsedTitle = name.Title,
|
||||
ParsedYear = name.Year,
|
||||
Title = name.Title,
|
||||
SortTitleValue = SortTitle.For(name.Title),
|
||||
Year = name.Year,
|
||||
// **Sofort sichtbar.** Wer etwas herauslöst, will es sehen —
|
||||
// nicht erst freigeben müssen.
|
||||
PublishAt = bisher.PublishAt ?? clock.GetUtcNow(),
|
||||
};
|
||||
db.Movies.Add(neu);
|
||||
|
||||
datei.MovieId = neu.Id;
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
return Results.Ok(new MatchState(null, null, false, neu.Title, neu.Year, Id: neu.Id));
|
||||
}).RequireAuthorization(FlaroPolicies.Administrator);
|
||||
|
||||
// **Woher dieser Titel kommt.**
|
||||
//
|
||||
// Steht im Dialog über der Suche. Wenn eine Zuordnung völlig daneben
|
||||
|
||||
Reference in New Issue
Block a user