Die sechs Punkte des Commanders vom 02.09.2026 abends und seine Entscheide:
* Restzeit der Kompression aus HandBrakes eigener ETA-Klammer (Formatstring
aus dem Binary 1.11.2 gelesen), KompressionStand.restS.
* Kachel zeigt nach dem Rip nur noch eine Zeile — Balken, Prozent, Ziel in
der Kompressions-Karte und im Verlauf ("nur in der Kompressions-Karte").
* Kopfzeile bleibt beim Scrollen stehen (sticky), Sektionswahl darunter.
* Untertitel-Vorwahl je Extra ("NUR für Extras, IMMER OPTIONAL"): welche
Untertitel-Spur beim Abspielen an ist — weiche Spur, nie eingebrannt;
RipAuftragTitel/RohDatei.untertitelVorwahl, sprachwahl.
* Mehrere Filme je Disc: "anderer Film …" je Titel mit TMDb-Suche;
filme.ts filmGruppen trennt am Rip-Ende in eigene Roh-Ordner, Vorgänge
und Kompressions-Aufträge mit voller Zuordnung (erkennung.zuordnungAus).
* Roh-Ordner und Dateien tragen den Filmnamen (filme.ts rohOrdnerName,
ablage/dateinamen.ts: Akira (1988).mkv, - Fassung n, - Extra nn).
* Hell-Modus: Einstellung design (dunkel/hell/system), data-design auf
<html>, Token --color-tinte statt white/-Alpha-Klassen.
* Vorgangs-Leiste (Commander: "Phase 1–4 plus Komprimierung — zu einem
machen"): gemeinsam/vorgangsleiste.ts + uebersicht/VorgangsLeiste.tsx,
vier Stationen (Rettung als Zwischenstation), Segment-Balken in der
aktiven Station; Kachel, Kompressions-Karte, Verlauf. PHASE-x/4-Texte weg.
* Automatik-Kasten leert sich, sobald ein Rip startet.
Beweise: 446 Tests (neu: filme, dateinamen, vorgangsleiste; erweitert:
auftrag, handbrake, automatik, ablegen), drei Typprüfungen, Klick-Beweis
33 Schritte inkl. Vorwahl, anderer Film, Vorgangs-Leiste, Restzeit,
Hell-Modus (Bilder beweise/klick/01…11).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
74 lines
3.8 KiB
TypeScript
74 lines
3.8 KiB
TypeScript
// Tests zu mehreren Filmen je Disc und Ordnern mit Filmnamen
|
|
// (kern/ablauf/filme.ts, 5.6.0).
|
|
import { describe, expect, it } from 'vitest'
|
|
import type { MetaVorschlag } from '../src/gemeinsam/nachrichten'
|
|
import type { RohDatei } from '../src/kern/ablauf/auftrag'
|
|
import { filmGruppen, rohOrdnerName, zuordnungAusVorschlag } from '../src/kern/ablauf/filme'
|
|
import { LEERER_TREFFER, type Zuordnung } from '../src/kern/metadaten/zuordnung'
|
|
|
|
function zuordnung(titel: string, jahr: number | null, typ: 'movie' | 'tv' = 'movie', id = 1): Zuordnung {
|
|
return { titel, jahr, confidence: 0.95, meta: { ...LEERER_TREFFER, typ, id, titel, jahr, quelle: 'tmdb' } }
|
|
}
|
|
|
|
function datei(pfad: string, film?: MetaVorschlag): RohDatei {
|
|
return { pfad, titelNr: 0, rolle: 'hauptfilm', dauerS: 6000, groesseBytes: 1e9, audioSprachen: [], untertitelSprachen: [], ...(film !== undefined ? { film } : {}) }
|
|
}
|
|
|
|
const akira: MetaVorschlag = { typ: 'movie', tmdbId: 149, titel: 'Akira', jahr: 1988, posterPfad: '/a.jpg' }
|
|
const ghost: MetaVorschlag = { typ: 'movie', tmdbId: 9323, titel: 'Ghost in the Shell', jahr: 1995, posterPfad: '' }
|
|
|
|
describe('rohOrdnerName', () => {
|
|
it('Film: „Titel (Jahr)"', () => {
|
|
expect(rohOrdnerName(zuordnung('Akira', 1988), null, 'bluray-2026', () => false)).toBe('Akira (1988)')
|
|
})
|
|
it('Serie: Titel, Staffel und Disc', () => {
|
|
expect(rohOrdnerName(zuordnung('Spartacus', 2010, 'tv'), { staffel: 1, discNr: 2 }, 'bluray-2026', () => false)).toBe('Spartacus - Staffel 1 Disc 2')
|
|
expect(rohOrdnerName(zuordnung('Spartacus', 2010, 'tv'), { staffel: null, discNr: null }, 'bluray-2026', () => false)).toBe('Spartacus')
|
|
})
|
|
it('bei Wiederholung mit Zusatz (2), (3) …', () => {
|
|
const da = new Set(['Akira (1988)', 'Akira (1988) (2)'])
|
|
expect(rohOrdnerName(zuordnung('Akira', 1988), null, 'bluray-2026', (n) => da.has(n))).toBe('Akira (1988) (3)')
|
|
})
|
|
it('ohne Zuordnung oder ohne brauchbaren Namen bleibt der Vorgangsname', () => {
|
|
expect(rohOrdnerName(null, null, 'bluray-2026', () => false)).toBe('bluray-2026')
|
|
expect(rohOrdnerName(zuordnung(' ', null), null, 'bluray-2026', () => false)).toBe('bluray-2026')
|
|
expect(rohOrdnerName(zuordnung('???', null), null, 'bluray-2026', () => false)).toBe('bluray-2026')
|
|
})
|
|
it('Sonderzeichen werden entschärft', () => {
|
|
expect(rohOrdnerName(zuordnung('Alien: Covenant', 2017), null, 'x', () => false)).not.toContain(':')
|
|
})
|
|
})
|
|
|
|
describe('filmGruppen', () => {
|
|
it('ohne Film-Zuordnung je Titel bleibt alles beim Hauptvorgang', () => {
|
|
const g = filmGruppen([datei('a'), datei('b')], 149)
|
|
expect(g.primaer).toHaveLength(2)
|
|
expect(g.primaerFilm).toBeNull()
|
|
expect(g.weitere).toHaveLength(0)
|
|
})
|
|
it('ein Titel, der zur Disc-Zuordnung passt, zählt als Hauptvorgang; ein anderer Film wird eigene Gruppe', () => {
|
|
const g = filmGruppen([datei('a', akira), datei('b', ghost), datei('c', ghost)], 149)
|
|
expect(g.primaer.map((d) => d.pfad)).toEqual(['a'])
|
|
expect(g.weitere).toHaveLength(1)
|
|
expect(g.weitere[0].film.titel).toBe('Ghost in the Shell')
|
|
expect(g.weitere[0].dateien.map((d) => d.pfad)).toEqual(['b', 'c'])
|
|
})
|
|
it('hat kein Titel die Disc-Zuordnung behalten, wird die erste Gruppe zum Hauptvorgang', () => {
|
|
const g = filmGruppen([datei('a', ghost), datei('b', akira)], 42)
|
|
expect(g.primaerFilm?.titel).toBe('Ghost in the Shell')
|
|
expect(g.primaer.map((d) => d.pfad)).toEqual(['a'])
|
|
expect(g.weitere.map((w) => w.film.titel)).toEqual(['Akira'])
|
|
})
|
|
})
|
|
|
|
describe('zuordnungAusVorschlag', () => {
|
|
it('ist sicher (vom Nutzer) und trägt Titel, Jahr, Poster', () => {
|
|
const z = zuordnungAusVorschlag(akira)
|
|
expect(z.confidence).toBe(1)
|
|
expect(z.titel).toBe('Akira')
|
|
expect(z.meta.id).toBe(149)
|
|
expect(z.meta.posterPfad).toBe('/a.jpg')
|
|
expect(z.meta.typ).toBe('movie')
|
|
})
|
|
})
|