fix(tickets): 16 Tickets der Züchterin — Genetik, Importer, Daten, Akte
Genetik-Engine (bde4ec70, f89e95ad, 2322c2a8):
- Saphir/Platin/Platin-Hell unterscheiden sich NUR in der C-Zygotie und waren im
Katalog identisch (locusToken reduziert auf das dominante Allel) → Saphir war
unerreichbar. Token darf jetzt ein exaktes, ungeordnetes Allelpaar "x/y"
verlangen: Platin C/C, Saphir C/cchm, Platin-Hell C/ch. TS- und Python-Mirror
identisch, Seeds regeneriert, Migration ReseedColorVarietiesGen6Saphir.
- c[hm] wird als Alias auf c[chm] normalisiert (Tippfehler in zwei Charts) —
vorher war Jays Gencode unparsebar und ergab "Zobel-Hell".
- 6 Tiere wechseln den errechneten Farbschlag (5x Platin→Saphir, Jay→Zobel).
Importer-Logik:
- renameTo-Notiz-Sweep: der alte Name blieb in Wurf-Notizen stehen ("Blacky +
Kruke") — jetzt wortgenau ersetzt, mit vier Guards gegen Kollateralschaden.
- Neuer Resolution-Schlüssel goHomeDate (autoritativ, zieht GivenAway nach) und
spottingType; Gencode-Overrides gewinnen jetzt bei präzisem Match (vorher
wurden Entscheidungen stumm verschluckt, z. B. Eliza und Chris).
- parse_date verwirft implausible Jahre (JackJack hatte 1310-05-13).
- extract.py erkennt Stammbaum-Blöcke auch ohne Stern vor dem Geburtsdatum
(Bijou bekam dadurch den Nachbar-Ast als Mutter).
- Backend-Ingest überträgt SpottingType (nur bei Payload-Wert).
Daten (conflict-decisions.json, re-ingest-stabil): Kuke-Merge + Zuchtname,
Jamie- und Sakura-Dubletten, Phantom-Tier "Unbekannt", Eltern von Kathlin,
Fast Boy/Ziwa und dem Q4-/TS-Wurf, Eliza-Gencode, Merle-Abgabe, JackJack.
Frontend (24522f5f): Abgabedatum steht in der Tier-Akte jetzt direkt unter dem
Abnehmer und hängt nicht mehr am Status.
Tests: +25 Checks test_merge_resolve, +7 test_genotype, +8 genetics.test.ts,
neuer Extract- und Ingest-Test, e2e GOHOME-ROW. Alles grün.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -913,3 +913,68 @@ describe('GEN-5: parent inference fills unknown alleles (cc9ea3fe / 1a508c04)',
|
||||
expect(res.inferred).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('GEN-6: C-Locus-Zygotie Platin / Saphir / Platin-Hell (bde4ec70 / f89e95ad)', () => {
|
||||
const name = (s: string) => genotypeToFarbschlag(fromDisplayString(s))
|
||||
|
||||
// Züchterin autoritativ (Ticket f89e95ad): „Saphir ist aa Cc[chm] D- E- G- pp und
|
||||
// Platin ist aa CC D- E- G- pp. Es ist nicht dasselbe!" Vorher trugen Platin,
|
||||
// Saphir und Platin-Hell identische Katalog-Tokens (C:'C') → first-match-wins
|
||||
// lieferte immer Platin.
|
||||
it('aa CC DD EE GG pp -> Platin (zwei volle C)', () => {
|
||||
expect(name('aa CC DD EE GG pp spsp rere')).toBe('Platin')
|
||||
expect(name('aa CC DD EE GG pp Spsp')).toBe('Platin Schecke')
|
||||
})
|
||||
|
||||
it('aa Cc[chm] DD EE GG pp -> Saphir (ein c[chm] daneben)', () => {
|
||||
expect(name('aa Cc[chm] DD EE GG pp spsp rere')).toBe('Saphir')
|
||||
})
|
||||
|
||||
it('JackJack (b6d8b3ef): aa Cc[chm] DD E- G- pp Spsp -> Saphir Schecke, NICHT Platin Schecke', () => {
|
||||
expect(name('aa Cc[chm] DD E- G- pp Spsp')).toBe('Saphir Schecke')
|
||||
})
|
||||
|
||||
it('aa Cc[h] DD EE GG pp -> Platin-Hell (GEN-3g: „-Hell" == c[h]-Allel)', () => {
|
||||
expect(name('aa Cc[h] DD EE GG pp spsp rere')).toBe('Platin-Hell')
|
||||
})
|
||||
|
||||
it('die drei Katalog-Einträge bilden ihren eigenen Namen zurück (kein Synonym-Kollaps)', () => {
|
||||
for (const varietyName of ['Platin', 'Saphir', 'Platin-Hell']) {
|
||||
const entry = BASE_COLORS.find((e) => e.name === varietyName)!
|
||||
expect(genotypeToFarbschlag(representativeGenotype(entry))).toBe(varietyName)
|
||||
}
|
||||
})
|
||||
|
||||
it('Seed-Kompaktnotation „aa Ccchm …" (so schreibt der Import JackSack) -> Saphir Schecke', () => {
|
||||
// merge_and_resolve übernimmt bei Farb-LABEL „Saphir-Sp" ohne Gencode den
|
||||
// CanonicalGenotype aus colorVarietySeed.backend.json (frozen symbols).
|
||||
// Seit GEN-6 ist das die HET-Form — vorher „aa CC …" (= Platin-Gencode).
|
||||
expect(name('aa Ccchm DD EE GG pp Spsp rere')).toBe('Saphir Schecke')
|
||||
expect(name('aa Cch DD EE GG pp spsp rere')).toBe('Platin-Hell')
|
||||
})
|
||||
|
||||
it('A-Wurf 18.02.2010 (Blacky × Kuke) erwartet Saphir UND Saphir Schecke', () => {
|
||||
const blacky = fromDisplayString('aa Cc[chm] DD EE GG Pp spsp') // Vater
|
||||
const kuke = fromDisplayString('aa CC DD Ee gg Pp Spsp') // Mutter (rpro3: Anthrazit-Schecke)
|
||||
const names = breed(blacky, kuke).byFarbschlag.map((f) => f.farbschlag)
|
||||
expect(names).toContain('Saphir')
|
||||
expect(names).toContain('Saphir Schecke')
|
||||
expect(names).not.toContain('Unbekannter Farbschlag')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Schreibfehler-Alias c[hm] == c[chm] (Ticket 2322c2a8, Jay *24.10.2021)', () => {
|
||||
it('c[hm] parst als c[chm] und ergibt Zobel, nicht Zobel-Hell', () => {
|
||||
// Die Quell-Charts (Alberto Kids / Pukas Kids) schreiben „aa c[chm]c[hm] …" —
|
||||
// dem zweiten Allel fehlt das c. Ohne Alias war der Genotyp unparsebar bzw.
|
||||
// (im Python-Mirror) ein fremdes Allel → „Zobel-Hell".
|
||||
const g = fromDisplayString('aa c[chm]c[hm] Dd Ee gg P- spsp')
|
||||
expect(g.C).toEqual(['cchm', 'cchm'])
|
||||
expect(genotypeToFarbschlag(g)).toBe('Zobel')
|
||||
})
|
||||
|
||||
it('Cc[hm] bleibt ein c[chm]-Träger (relevant für die Probeverpaarung)', () => {
|
||||
expect(fromDisplayString('aa Cc[hm] DD EE GG pp spsp').C).toEqual(['C', 'cchm'])
|
||||
expect(genotypeToFarbschlag(fromDisplayString('aa Cc[hm] DD EE GG pp spsp'))).toBe('Saphir')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user