GEN-3c: unknown allele displays as '-' (storage stays '?'); parser accepts '-' and skips fully-unknown tokens; de.ts hints

This commit is contained in:
2026-06-06 10:45:15 +02:00
parent a57b481a7e
commit 2e20df624f
2 changed files with 674 additions and 667 deletions

View File

@@ -79,12 +79,14 @@ export function wildType(): Genotype {
* The Sls locus is OMITTED when wild-type (sl/sl) so legacy 8-locus strings and
* the colour catalog stay byte-identical; it only appears for WP/Sls carriers
* (e.g. "… spsp rere Slsl"). Round-trips: a missing Sls re-parses to sl/sl.
* GEN-3c: unknown alleles are STORED as '?' but DISPLAYED as '-' (breeder
* convention) — e.g. ['C','?'] renders "C-".
*/
export function toDisplayString(g: Genotype): string {
return LOCUS_ORDER.filter(
(locus) => locus !== 'Sls' || !(g.Sls[0] === 'sl' && g.Sls[1] === 'sl'),
)
.map((locus) => g[locus][0] + g[locus][1])
.map((locus) => (g[locus][0] + g[locus][1]).replace(/\?/g, '-'))
.join(' ')
}
@@ -144,6 +146,9 @@ function normalizeToken(tok: string): string | null {
if (t === 'WP') t = 'Slsl'
t = t.replace(/S\(l\)/g, 'Sl').replace(/s\(l\)/g, 'sl')
t = t.replace(/Uw/g, 'G').replace(/uw/g, 'g')
// GEN-3c: '-' is the breeder's UNKNOWN marker on input; store internally as '?'
// (the frozen storage contract keeps '?'; only DISPLAY renders '-').
t = t.replace(/-/g, '?')
return t
}
@@ -193,7 +198,9 @@ export function fromDisplayString(input: string): Genotype {
const [a, b] = splitToken(token)
const refAllele = a === WILDCARD ? b : a
if (refAllele === WILDCARD) {
throw new Error(`Token "${token}" is fully unknown; cannot infer its locus`)
// Fully-unknown token ("--"/"??", e.g. a positional placeholder): the locus
// can't be inferred — skip it (defaults to wild-type), don't throw.
continue
}
const locus = ALLELE_TO_LOCUS[refAllele]
if (!locus) throw new Error(`Unknown allele "${refAllele}" in token "${token}"`)

File diff suppressed because it is too large Load Diff