Compare commits
25 Commits
461d7feb2d
...
feature/we
| Author | SHA1 | Date | |
|---|---|---|---|
| d93e8d1586 | |||
| 114bbd92c8 | |||
| a8d8ae0dfc | |||
| 522f2eec51 | |||
| 3f71d8e28e | |||
| 0e7ec5ab61 | |||
| 12604fba7c | |||
| 311c5461fd | |||
| 3634d6ef9a | |||
| aa345aa796 | |||
| 0317c5d454 | |||
| ea8c3e9966 | |||
| 4d3383a4f1 | |||
| 19a0a6c79b | |||
| b9033238c9 | |||
| 594923e10f | |||
| aa20d6f809 | |||
| afd321ec9f | |||
| ae825ae80a | |||
| e055061d85 | |||
| df13136955 | |||
| 4aca1d528b | |||
| 4e02133d95 | |||
| f3efd4aa2b | |||
| 972570b142 |
@@ -104,7 +104,7 @@ namespace GerbilManager.Tests
|
|||||||
Assert.Equal(1, root.GetProperty("gerbils").GetArrayLength());
|
Assert.Equal(1, root.GetProperty("gerbils").GetArrayLength());
|
||||||
Assert.Equal(1, root.GetProperty("litters").GetArrayLength());
|
Assert.Equal(1, root.GetProperty("litters").GetArrayLength());
|
||||||
Assert.Equal(1, root.GetProperty("contacts").GetArrayLength());
|
Assert.Equal(1, root.GetProperty("contacts").GetArrayLength());
|
||||||
Assert.True(root.GetProperty("colorVarieties").GetArrayLength() >= 70); // HasData-Seed
|
Assert.True(root.GetProperty("colorVarieties").GetArrayLength() >= 60); // HasData-Seed (61 nach GEN-3f)
|
||||||
var g = root.GetProperty("gerbils")[0];
|
var g = root.GetProperty("gerbils")[0];
|
||||||
Assert.Equal("Aa CC Dd EE GG Pp Spsp rere", g.GetProperty("genotype").GetString());
|
Assert.Equal("Aa CC Dd EE GG Pp Spsp rere", g.GetProperty("genotype").GetString());
|
||||||
Assert.Equal("Stammbaum von Akio Kids.xlsx", g.GetProperty("importSource").GetString());
|
Assert.Equal("Stammbaum von Akio Kids.xlsx", g.GetProperty("importSource").GetString());
|
||||||
|
|||||||
@@ -278,6 +278,33 @@ namespace GerbilManager.Tests
|
|||||||
finally { try { Directory.Delete(dir, recursive: true); } catch { } }
|
finally { try { Directory.Delete(dir, recursive: true); } catch { } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Decision_resolved_animal_loads_and_is_counted()
|
||||||
|
{
|
||||||
|
// extract.py clears the conflict + sets resolvedByDecision when a human conflict-decision
|
||||||
|
// un-quarantines an animal; the loader must then LOAD it and surface the count.
|
||||||
|
var dir = Path.Combine(Path.GetTempPath(), "dec-" + Guid.NewGuid().ToString("N"));
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.WriteAllText(Path.Combine(dir, "litters.json"), "[]");
|
||||||
|
File.WriteAllText(Path.Combine(dir, "animals.json"), """
|
||||||
|
[
|
||||||
|
{"id":"firefly","name":"Firefly","dob":"18.12.2019","death":"","farbschlag":"Agouti",
|
||||||
|
"genotype":{"mapped8locus":{"A":["A","a"],"D":["D","?"]},"rawGenotype":"Aa D-","unmappedTokens":[]},
|
||||||
|
"conflict":false,"resolvedByDecision":true}
|
||||||
|
]
|
||||||
|
""");
|
||||||
|
using var db = NewDb();
|
||||||
|
var report = await new ImportService(db, dir, dir).RunAsync(execute: true);
|
||||||
|
|
||||||
|
Assert.Equal(1, report.Animals.ConflictsResolvedByDecision);
|
||||||
|
Assert.True(await db.Gerbils.AnyAsync(g => g.ExternalRef == "firefly")); // loaded, not quarantined
|
||||||
|
Assert.Equal(0, report.Animals.Quarantined.Conflicts);
|
||||||
|
}
|
||||||
|
finally { try { Directory.Delete(dir, recursive: true); } catch { } }
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ComposeGenotype_strips_carets_and_fills_missing_loci()
|
public void ComposeGenotype_strips_carets_and_fills_missing_loci()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -256,8 +256,6 @@ public class ApplicationContext : DbContext
|
|||||||
("C-Separator", "aa CC DD ee gg pp spsp rere"),
|
("C-Separator", "aa CC DD ee gg pp spsp rere"),
|
||||||
("Elfenbein", "AA CC DD EE gg pp spsp rere"),
|
("Elfenbein", "AA CC DD EE gg pp spsp rere"),
|
||||||
("Kohlfuchs", "aa CC DD ee GG PP spsp rere"),
|
("Kohlfuchs", "aa CC DD ee GG PP spsp rere"),
|
||||||
("Marder", "aa cchmcchm DD EE GG PP spsp rere"),
|
|
||||||
("Siam (Marder-Hell)", "aa cchmcchm DD EE GG PP spsp rere"),
|
|
||||||
("Polarfuchs", "AA CC DD ee gg PP spsp rere"),
|
("Polarfuchs", "AA CC DD ee gg PP spsp rere"),
|
||||||
("Saphir", "aa CC DD EE GG pp spsp rere"),
|
("Saphir", "aa CC DD EE GG pp spsp rere"),
|
||||||
("Orangeschimmel", "AA CC DD efef GG PP spsp rere"),
|
("Orangeschimmel", "AA CC DD efef GG PP spsp rere"),
|
||||||
@@ -267,44 +265,34 @@ public class ApplicationContext : DbContext
|
|||||||
("Silberagouti dd", "AA CC dd EE gg PP spsp rere"),
|
("Silberagouti dd", "AA CC dd EE gg PP spsp rere"),
|
||||||
("Kohlfuchs dd", "aa CC dd ee GG PP spsp rere"),
|
("Kohlfuchs dd", "aa CC dd ee GG PP spsp rere"),
|
||||||
("Anthrazit dd", "aa CC dd EE gg PP spsp rere"),
|
("Anthrazit dd", "aa CC dd EE gg PP spsp rere"),
|
||||||
("Agouti CP-Hell", "AA cchmcchm DD EE GG PP spsp rere"),
|
|
||||||
("Blaufuchs CP", "aa cchmcchm DD ee gg PP spsp rere"),
|
|
||||||
("Silberschimmel", "AA CC DD efef gg PP spsp rere"),
|
("Silberschimmel", "AA CC DD efef gg PP spsp rere"),
|
||||||
("Polarfuchsschimmel", "AA CC DD efef gg PP spsp rere"),
|
("Polarfuchsschimmel", "AA CC DD efef gg PP spsp rere"),
|
||||||
("Algierfuchsschimmel", "AA CC DD efef GG PP spsp rere"),
|
("Algierfuchsschimmel", "AA CC DD efef GG PP spsp rere"),
|
||||||
("Polarfuchs-Hell CP", "AA cchmcchm DD ee gg PP spsp rere"),
|
|
||||||
("Kohlfuchsschimmel", "aa CC DD efef GG PP spsp rere"),
|
("Kohlfuchsschimmel", "aa CC DD efef GG PP spsp rere"),
|
||||||
("Blaufuchsschimmel", "aa CC DD efef gg PP spsp rere"),
|
("Blaufuchsschimmel", "aa CC DD efef gg PP spsp rere"),
|
||||||
("Kohlfuchs, hell", "aa CC DD ee GG PP spsp rere"),
|
("Kohlfuchs, hell", "aa CC DD ee GG PP spsp rere"),
|
||||||
("Goldfuchs, hell", "AA CC DD ee GG pp spsp rere"),
|
("Goldfuchs, hell", "AA CC DD ee GG pp spsp rere"),
|
||||||
("Goldfuchsschimmel", "AA CC DD efef GG pp spsp rere"),
|
("Goldfuchsschimmel", "AA CC DD efef GG pp spsp rere"),
|
||||||
("Gold-Hell", "AA CC DD EE GG pp spsp rere"),
|
("Gold-Hell", "AA CC DD EE GG pp spsp rere"),
|
||||||
("Siam (Marder-Hell) dd", "aa cchmcchm dd EE GG PP spsp rere"),
|
|
||||||
("Marder dd", "aa cchmcchm dd EE GG PP spsp rere"),
|
|
||||||
("Zobel-Hell", "aa cchmcchm DD EE gg PP spsp rere"),
|
|
||||||
("Silberagouti dd CP", "AA cchmcchm dd EE gg PP spsp rere"),
|
|
||||||
("Silberagouti-Hell dd CP", "AA cchmcchm dd EE gg PP spsp rere"),
|
|
||||||
("Agouti dd CP", "AA cchmcchm dd EE GG PP spsp rere"),
|
|
||||||
("Agouti-Hell dd CP", "AA cchmcchm dd EE GG PP spsp rere"),
|
|
||||||
("Blaufuchs, hell", "aa CC DD ee gg PP spsp rere"),
|
("Blaufuchs, hell", "aa CC DD ee gg PP spsp rere"),
|
||||||
("Rotfuchsschimmel", "aa CC DD efef GG pp spsp rere"),
|
("Rotfuchsschimmel", "aa CC DD efef GG pp spsp rere"),
|
||||||
("Polarfuchs, hell", "AA CC DD ee gg PP spsp rere"),
|
("Polarfuchs, hell", "AA CC DD ee gg PP spsp rere"),
|
||||||
("Kohlfuchsschimmel, hell", "aa CC DD efef GG PP spsp rere"),
|
("Kohlfuchsschimmel, hell", "aa CC DD efef GG PP spsp rere"),
|
||||||
("Rotfuchs, hell", "aa CC DD ee GG pp spsp rere"),
|
("Rotfuchs, hell", "aa CC DD ee GG pp spsp rere"),
|
||||||
("Zobel dd", "aa cchmcchm dd EE gg PP spsp rere"),
|
|
||||||
("Kohlfuchs-Hell", "aa CC DD ee GG PP spsp rere"),
|
("Kohlfuchs-Hell", "aa CC DD ee GG PP spsp rere"),
|
||||||
("Kohlfuchs CP", "aa cchmcchm DD ee GG PP spsp rere"),
|
|
||||||
("Algierfuchs CP", "AA cchmcchm DD ee GG PP spsp rere"),
|
|
||||||
("Silberagouti CP", "AA cchmcchm DD EE gg PP spsp rere"),
|
|
||||||
("Agouti CP", "AA cchmcchm DD EE GG PP spsp rere"),
|
|
||||||
("Algierfuchs-Hell CP", "AA cchmcchm DD ee GG PP spsp rere"),
|
|
||||||
("Kohlfuchs,hell CP", "aa cchmcchm DD ee GG PP spsp rere"),
|
|
||||||
("Polarfuchs CP", "AA cchmcchm DD ee gg PP spsp rere"),
|
|
||||||
("Algierfuchs, hell", "AA CC DD ee GG PP spsp rere"),
|
("Algierfuchs, hell", "AA CC DD ee GG PP spsp rere"),
|
||||||
("Topas dd", "AA CC dd EE GG pp spsp rere"),
|
("Topas dd", "AA CC dd EE GG pp spsp rere"),
|
||||||
("Zobel-Hell dd", "aa cchmcchm dd EE gg PP spsp rere"),
|
|
||||||
("Kohlfuchsschimmel CP", "aa cchmcchm DD efef GG PP spsp rere"),
|
|
||||||
("Blaufuchs dd", "aa CC dd ee gg pp spsp rere"),
|
("Blaufuchs dd", "aa CC dd ee gg pp spsp rere"),
|
||||||
|
("Marder", "aa cchmcchm DD EE GG PP spsp rere"),
|
||||||
|
("Siam", "aa cchmch DD EE GG PP spsp rere"),
|
||||||
|
("Zobel-Hell", "aa cchmch DD EE gg PP spsp rere"),
|
||||||
|
("CP-Agouti", "AA cchmcchm DD EE GG PP spsp rere"),
|
||||||
|
("CP-Silberagouti", "AA cchmcchm DD EE gg PP spsp rere"),
|
||||||
|
("CP-Algierfuchs", "AA cchmcchm DD ee GG PP spsp rere"),
|
||||||
|
("CP-Polarfuchs", "AA cchmcchm DD ee gg PP spsp rere"),
|
||||||
|
("CP-Fuchs", "AA cchmcchm dd ee GG PP spsp rere"),
|
||||||
|
("CP-Fuchs-Hell", "AA cchmch dd ee GG PP spsp rere"),
|
||||||
|
("CP-Blaufuchs", "AA cchmcchm dd ee gg PP spsp rere"),
|
||||||
("CP-Orangeschimmel", "AA cchmcchm DD efef GG PP spsp rere"),
|
("CP-Orangeschimmel", "AA cchmcchm DD efef GG PP spsp rere"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ namespace GerbilManagerWebAPI.Import
|
|||||||
// provenance/breeding tags (WFNZ/RV/GV/DP) — neither is genotype.
|
// provenance/breeding tags (WFNZ/RV/GV/DP) — neither is genotype.
|
||||||
public bool? Deaf { get; set; }
|
public bool? Deaf { get; set; }
|
||||||
public List<string> Tags { get; set; } = new();
|
public List<string> Tags { get; set; } = new();
|
||||||
|
|
||||||
|
// Set by extract.py when a human conflict-decision (conflict-decisions.json) un-quarantined
|
||||||
|
// this animal (its genotype/farbschlag are then authoritative). For reporting.
|
||||||
|
public bool ResolvedByDecision { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SourceGenotype
|
public sealed class SourceGenotype
|
||||||
@@ -92,7 +96,8 @@ namespace GerbilManagerWebAPI.Import
|
|||||||
int FarbschlagUnmatched,
|
int FarbschlagUnmatched,
|
||||||
int AlreadyImported,
|
int AlreadyImported,
|
||||||
QuarantineSummary Quarantined,
|
QuarantineSummary Quarantined,
|
||||||
int ParentLinksFromChart = 0);
|
int ParentLinksFromChart = 0,
|
||||||
|
int ConflictsResolvedByDecision = 0);
|
||||||
|
|
||||||
public sealed record QuarantineSummary(
|
public sealed record QuarantineSummary(
|
||||||
int Conflicts,
|
int Conflicts,
|
||||||
|
|||||||
@@ -404,6 +404,9 @@ namespace GerbilManagerWebAPI.Import
|
|||||||
notes.Add($"Stammbaum-Diagramm: {parentLinksAdded} Tiere über Eltern-Verknüpfung einem (abgeleiteten) Wurf zugeordnet ({derivedLitters} abgeleitete Würfe).");
|
notes.Add($"Stammbaum-Diagramm: {parentLinksAdded} Tiere über Eltern-Verknüpfung einem (abgeleiteten) Wurf zugeordnet ({derivedLitters} abgeleitete Würfe).");
|
||||||
notes.Add($"FK-Integrität: {litterParentFksDropped} Eltern-Verknüpfung(en) verworfen (Elternteil nicht ladbar), {derivedLittersSkipped} abgeleitete Würfe übersprungen (kein ladbares Elternteil). Bei 0/0 ist /import/execute FK-sicher.");
|
notes.Add($"FK-Integrität: {litterParentFksDropped} Eltern-Verknüpfung(en) verworfen (Elternteil nicht ladbar), {derivedLittersSkipped} abgeleitete Würfe übersprungen (kein ladbares Elternteil). Bei 0/0 ist /import/execute FK-sicher.");
|
||||||
notes.Add($"Bestand/Herkunft: {residentTotal} im Bestand (Clan Kleine Chaoten), {externalTotal} externe Ahnen ({flippedByParentRule} davon über die Eltern-Regel als Bestand erkannt).");
|
notes.Add($"Bestand/Herkunft: {residentTotal} im Bestand (Clan Kleine Chaoten), {externalTotal} externe Ahnen ({flippedByParentRule} davon über die Eltern-Regel als Bestand erkannt).");
|
||||||
|
int conflictsResolvedByDecision = loadable.Count(a => a.ResolvedByDecision);
|
||||||
|
if (conflictsResolvedByDecision > 0)
|
||||||
|
notes.Add($"Konfliktauflösungen: {conflictsResolvedByDecision} Tier(e) anhand von conflict-decisions.json un-quarantänet (Genotyp/Farbschlag der Züchterin ist maßgeblich).");
|
||||||
if (!execute) notes.Add("DRY-RUN: nichts gespeichert. /import/execute lädt die konfliktfreien Daten.");
|
if (!execute) notes.Add("DRY-RUN: nichts gespeichert. /import/execute lädt die konfliktfreien Daten.");
|
||||||
|
|
||||||
return new ImportReport(
|
return new ImportReport(
|
||||||
@@ -412,7 +415,7 @@ namespace GerbilManagerWebAPI.Import
|
|||||||
Animals: new AnimalSummary(
|
Animals: new AnimalSummary(
|
||||||
animals.Count, animalsCreated, linked, fbMatched, fbUnmatched, animalsExisting,
|
animals.Count, animalsCreated, linked, fbMatched, fbUnmatched, animalsExisting,
|
||||||
new QuarantineSummary(conflicts, stubs, dateOnly, ambiguous, conflicts + stubs),
|
new QuarantineSummary(conflicts, stubs, dateOnly, ambiguous, conflicts + stubs),
|
||||||
parentLinksAdded),
|
parentLinksAdded, conflictsResolvedByDecision),
|
||||||
Photos: new PhotoSummary(photosAttached, photosMissing),
|
Photos: new PhotoSummary(photosAttached, photosMissing),
|
||||||
Samples: samples,
|
Samples: samples,
|
||||||
Notes: notes,
|
Notes: notes,
|
||||||
|
|||||||
1302
GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.Designer.cs
generated
Normal file
1302
GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,632 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace GerbilManagerWebAPI.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class ReseedColorVarietiesGen3f : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000062"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000063"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000064"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000065"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000066"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000067"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000068"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000069"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000070"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000071"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000072"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000073"));
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000024"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD ee gg PP spsp rere", "Polarfuchs" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000025"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD EE GG pp spsp rere", "Saphir" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000026"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef GG PP spsp rere", "Orangeschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000027"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD EE GG pp spsp rere", "Topas" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000028"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD EE GG pp spsp rere", "Platin-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000029"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC dd EE GG PP spsp rere", "Agouti dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000030"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC dd EE gg PP spsp rere", "Silberagouti dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000031"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC dd ee GG PP spsp rere", "Kohlfuchs dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000032"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC dd EE gg PP spsp rere", "Anthrazit dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000033"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef gg PP spsp rere", "Silberschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000034"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef gg PP spsp rere", "Polarfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000035"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef GG PP spsp rere", "Algierfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000036"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef GG PP spsp rere", "Kohlfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000037"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef gg PP spsp rere", "Blaufuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000038"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee GG PP spsp rere", "Kohlfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000039"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD ee GG pp spsp rere", "Goldfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000040"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef GG pp spsp rere", "Goldfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000041"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD EE GG pp spsp rere", "Gold-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000042"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee gg PP spsp rere", "Blaufuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000043"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef GG pp spsp rere", "Rotfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000044"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD ee gg PP spsp rere", "Polarfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000045"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef GG PP spsp rere", "Kohlfuchsschimmel, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000046"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee GG pp spsp rere", "Rotfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000047"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee GG PP spsp rere", "Kohlfuchs-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000048"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD ee GG PP spsp rere", "Algierfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000049"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC dd EE GG pp spsp rere", "Topas dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000050"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC dd ee gg pp spsp rere", "Blaufuchs dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000051"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm DD EE GG PP spsp rere", "Marder" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000052"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmch DD EE GG PP spsp rere", "Siam" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000053"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmch DD EE gg PP spsp rere", "Zobel-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000054"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm DD EE GG PP spsp rere", "CP-Agouti" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000055"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm DD EE gg PP spsp rere", "CP-Silberagouti" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000056"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm DD ee GG PP spsp rere", "CP-Algierfuchs" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000057"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm DD ee gg PP spsp rere", "CP-Polarfuchs" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000058"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm dd ee GG PP spsp rere", "CP-Fuchs" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000059"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmch dd ee GG PP spsp rere", "CP-Fuchs-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000060"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm dd ee gg PP spsp rere", "CP-Blaufuchs" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000061"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm DD efef GG PP spsp rere", "CP-Orangeschimmel" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000024"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm DD EE GG PP spsp rere", "Marder" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000025"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm DD EE GG PP spsp rere", "Siam (Marder-Hell)" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000026"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD ee gg PP spsp rere", "Polarfuchs" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000027"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD EE GG pp spsp rere", "Saphir" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000028"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef GG PP spsp rere", "Orangeschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000029"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD EE GG pp spsp rere", "Topas" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000030"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD EE GG pp spsp rere", "Platin-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000031"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC dd EE GG PP spsp rere", "Agouti dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000032"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC dd EE gg PP spsp rere", "Silberagouti dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000033"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC dd ee GG PP spsp rere", "Kohlfuchs dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000034"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC dd EE gg PP spsp rere", "Anthrazit dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000035"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm DD EE GG PP spsp rere", "Agouti CP-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000036"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm DD ee gg PP spsp rere", "Blaufuchs CP" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000037"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef gg PP spsp rere", "Silberschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000038"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef gg PP spsp rere", "Polarfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000039"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef GG PP spsp rere", "Algierfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000040"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm DD ee gg PP spsp rere", "Polarfuchs-Hell CP" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000041"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef GG PP spsp rere", "Kohlfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000042"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef gg PP spsp rere", "Blaufuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000043"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee GG PP spsp rere", "Kohlfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000044"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD ee GG pp spsp rere", "Goldfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000045"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD efef GG pp spsp rere", "Goldfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000046"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD EE GG pp spsp rere", "Gold-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000047"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm dd EE GG PP spsp rere", "Siam (Marder-Hell) dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000048"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm dd EE GG PP spsp rere", "Marder dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000049"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm DD EE gg PP spsp rere", "Zobel-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000050"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm dd EE gg PP spsp rere", "Silberagouti dd CP" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000051"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm dd EE gg PP spsp rere", "Silberagouti-Hell dd CP" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000052"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm dd EE GG PP spsp rere", "Agouti dd CP" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000053"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA cchmcchm dd EE GG PP spsp rere", "Agouti-Hell dd CP" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000054"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee gg PP spsp rere", "Blaufuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000055"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef GG pp spsp rere", "Rotfuchsschimmel" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000056"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "AA CC DD ee gg PP spsp rere", "Polarfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000057"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD efef GG PP spsp rere", "Kohlfuchsschimmel, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000058"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee GG pp spsp rere", "Rotfuchs, hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000059"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm dd EE gg PP spsp rere", "Zobel dd" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000060"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa CC DD ee GG PP spsp rere", "Kohlfuchs-Hell" });
|
||||||
|
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("00000000-0000-0000-0000-000000000061"),
|
||||||
|
columns: new[] { "CanonicalGenotype", "Name" },
|
||||||
|
values: new object[] { "aa cchmcchm DD ee GG PP spsp rere", "Kohlfuchs CP" });
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "ColorVarieties",
|
||||||
|
columns: new[] { "Id", "CanonicalGenotype", "Name", "SortOrder" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000062"), "AA cchmcchm DD ee GG PP spsp rere", "Algierfuchs CP", 61 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000063"), "AA cchmcchm DD EE gg PP spsp rere", "Silberagouti CP", 62 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000064"), "AA cchmcchm DD EE GG PP spsp rere", "Agouti CP", 63 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000065"), "AA cchmcchm DD ee GG PP spsp rere", "Algierfuchs-Hell CP", 64 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000066"), "aa cchmcchm DD ee GG PP spsp rere", "Kohlfuchs,hell CP", 65 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000067"), "AA cchmcchm DD ee gg PP spsp rere", "Polarfuchs CP", 66 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000068"), "AA CC DD ee GG PP spsp rere", "Algierfuchs, hell", 67 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000069"), "AA CC dd EE GG pp spsp rere", "Topas dd", 68 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000070"), "aa cchmcchm dd EE gg PP spsp rere", "Zobel-Hell dd", 69 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000071"), "aa cchmcchm DD efef GG PP spsp rere", "Kohlfuchsschimmel CP", 70 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000072"), "aa CC dd ee gg pp spsp rere", "Blaufuchs dd", 71 },
|
||||||
|
{ new Guid("00000000-0000-0000-0000-000000000073"), "AA cchmcchm DD efef GG PP spsp rere", "CP-Orangeschimmel", 72 }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -343,352 +343,268 @@ namespace GerbilManagerWebAPI.Migrations
|
|||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000024"),
|
Id = new Guid("00000000-0000-0000-0000-000000000024"),
|
||||||
CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere",
|
CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
|
||||||
Name = "Marder",
|
Name = "Polarfuchs",
|
||||||
SortOrder = 23
|
SortOrder = 23
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000025"),
|
Id = new Guid("00000000-0000-0000-0000-000000000025"),
|
||||||
CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere",
|
CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
|
||||||
Name = "Siam (Marder-Hell)",
|
Name = "Saphir",
|
||||||
SortOrder = 24
|
SortOrder = 24
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000026"),
|
Id = new Guid("00000000-0000-0000-0000-000000000026"),
|
||||||
CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
|
CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
|
||||||
Name = "Polarfuchs",
|
Name = "Orangeschimmel",
|
||||||
SortOrder = 25
|
SortOrder = 25
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000027"),
|
Id = new Guid("00000000-0000-0000-0000-000000000027"),
|
||||||
CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
|
CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
|
||||||
Name = "Saphir",
|
Name = "Topas",
|
||||||
SortOrder = 26
|
SortOrder = 26
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000028"),
|
Id = new Guid("00000000-0000-0000-0000-000000000028"),
|
||||||
CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
|
CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
|
||||||
Name = "Orangeschimmel",
|
Name = "Platin-Hell",
|
||||||
SortOrder = 27
|
SortOrder = 27
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000029"),
|
Id = new Guid("00000000-0000-0000-0000-000000000029"),
|
||||||
CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
|
CanonicalGenotype = "AA CC dd EE GG PP spsp rere",
|
||||||
Name = "Topas",
|
Name = "Agouti dd",
|
||||||
SortOrder = 28
|
SortOrder = 28
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000030"),
|
Id = new Guid("00000000-0000-0000-0000-000000000030"),
|
||||||
CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
|
CanonicalGenotype = "AA CC dd EE gg PP spsp rere",
|
||||||
Name = "Platin-Hell",
|
Name = "Silberagouti dd",
|
||||||
SortOrder = 29
|
SortOrder = 29
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000031"),
|
Id = new Guid("00000000-0000-0000-0000-000000000031"),
|
||||||
CanonicalGenotype = "AA CC dd EE GG PP spsp rere",
|
CanonicalGenotype = "aa CC dd ee GG PP spsp rere",
|
||||||
Name = "Agouti dd",
|
Name = "Kohlfuchs dd",
|
||||||
SortOrder = 30
|
SortOrder = 30
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000032"),
|
Id = new Guid("00000000-0000-0000-0000-000000000032"),
|
||||||
CanonicalGenotype = "AA CC dd EE gg PP spsp rere",
|
CanonicalGenotype = "aa CC dd EE gg PP spsp rere",
|
||||||
Name = "Silberagouti dd",
|
Name = "Anthrazit dd",
|
||||||
SortOrder = 31
|
SortOrder = 31
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000033"),
|
Id = new Guid("00000000-0000-0000-0000-000000000033"),
|
||||||
CanonicalGenotype = "aa CC dd ee GG PP spsp rere",
|
CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
|
||||||
Name = "Kohlfuchs dd",
|
Name = "Silberschimmel",
|
||||||
SortOrder = 32
|
SortOrder = 32
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000034"),
|
Id = new Guid("00000000-0000-0000-0000-000000000034"),
|
||||||
CanonicalGenotype = "aa CC dd EE gg PP spsp rere",
|
CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
|
||||||
Name = "Anthrazit dd",
|
Name = "Polarfuchsschimmel",
|
||||||
SortOrder = 33
|
SortOrder = 33
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000035"),
|
Id = new Guid("00000000-0000-0000-0000-000000000035"),
|
||||||
CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere",
|
CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
|
||||||
Name = "Agouti CP-Hell",
|
Name = "Algierfuchsschimmel",
|
||||||
SortOrder = 34
|
SortOrder = 34
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000036"),
|
Id = new Guid("00000000-0000-0000-0000-000000000036"),
|
||||||
CanonicalGenotype = "aa cchmcchm DD ee gg PP spsp rere",
|
CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
|
||||||
Name = "Blaufuchs CP",
|
Name = "Kohlfuchsschimmel",
|
||||||
SortOrder = 35
|
SortOrder = 35
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000037"),
|
Id = new Guid("00000000-0000-0000-0000-000000000037"),
|
||||||
CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
|
CanonicalGenotype = "aa CC DD efef gg PP spsp rere",
|
||||||
Name = "Silberschimmel",
|
Name = "Blaufuchsschimmel",
|
||||||
SortOrder = 36
|
SortOrder = 36
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000038"),
|
Id = new Guid("00000000-0000-0000-0000-000000000038"),
|
||||||
CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
|
CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
|
||||||
Name = "Polarfuchsschimmel",
|
Name = "Kohlfuchs, hell",
|
||||||
SortOrder = 37
|
SortOrder = 37
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000039"),
|
Id = new Guid("00000000-0000-0000-0000-000000000039"),
|
||||||
CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
|
CanonicalGenotype = "AA CC DD ee GG pp spsp rere",
|
||||||
Name = "Algierfuchsschimmel",
|
Name = "Goldfuchs, hell",
|
||||||
SortOrder = 38
|
SortOrder = 38
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000040"),
|
Id = new Guid("00000000-0000-0000-0000-000000000040"),
|
||||||
CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere",
|
CanonicalGenotype = "AA CC DD efef GG pp spsp rere",
|
||||||
Name = "Polarfuchs-Hell CP",
|
Name = "Goldfuchsschimmel",
|
||||||
SortOrder = 39
|
SortOrder = 39
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000041"),
|
Id = new Guid("00000000-0000-0000-0000-000000000041"),
|
||||||
CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
|
CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
|
||||||
Name = "Kohlfuchsschimmel",
|
Name = "Gold-Hell",
|
||||||
SortOrder = 40
|
SortOrder = 40
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000042"),
|
Id = new Guid("00000000-0000-0000-0000-000000000042"),
|
||||||
CanonicalGenotype = "aa CC DD efef gg PP spsp rere",
|
CanonicalGenotype = "aa CC DD ee gg PP spsp rere",
|
||||||
Name = "Blaufuchsschimmel",
|
Name = "Blaufuchs, hell",
|
||||||
SortOrder = 41
|
SortOrder = 41
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000043"),
|
Id = new Guid("00000000-0000-0000-0000-000000000043"),
|
||||||
CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
|
CanonicalGenotype = "aa CC DD efef GG pp spsp rere",
|
||||||
Name = "Kohlfuchs, hell",
|
Name = "Rotfuchsschimmel",
|
||||||
SortOrder = 42
|
SortOrder = 42
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000044"),
|
Id = new Guid("00000000-0000-0000-0000-000000000044"),
|
||||||
CanonicalGenotype = "AA CC DD ee GG pp spsp rere",
|
CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
|
||||||
Name = "Goldfuchs, hell",
|
Name = "Polarfuchs, hell",
|
||||||
SortOrder = 43
|
SortOrder = 43
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000045"),
|
Id = new Guid("00000000-0000-0000-0000-000000000045"),
|
||||||
CanonicalGenotype = "AA CC DD efef GG pp spsp rere",
|
CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
|
||||||
Name = "Goldfuchsschimmel",
|
Name = "Kohlfuchsschimmel, hell",
|
||||||
SortOrder = 44
|
SortOrder = 44
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000046"),
|
Id = new Guid("00000000-0000-0000-0000-000000000046"),
|
||||||
CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
|
CanonicalGenotype = "aa CC DD ee GG pp spsp rere",
|
||||||
Name = "Gold-Hell",
|
Name = "Rotfuchs, hell",
|
||||||
SortOrder = 45
|
SortOrder = 45
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000047"),
|
Id = new Guid("00000000-0000-0000-0000-000000000047"),
|
||||||
CanonicalGenotype = "aa cchmcchm dd EE GG PP spsp rere",
|
CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
|
||||||
Name = "Siam (Marder-Hell) dd",
|
Name = "Kohlfuchs-Hell",
|
||||||
SortOrder = 46
|
SortOrder = 46
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000048"),
|
Id = new Guid("00000000-0000-0000-0000-000000000048"),
|
||||||
CanonicalGenotype = "aa cchmcchm dd EE GG PP spsp rere",
|
CanonicalGenotype = "AA CC DD ee GG PP spsp rere",
|
||||||
Name = "Marder dd",
|
Name = "Algierfuchs, hell",
|
||||||
SortOrder = 47
|
SortOrder = 47
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000049"),
|
Id = new Guid("00000000-0000-0000-0000-000000000049"),
|
||||||
CanonicalGenotype = "aa cchmcchm DD EE gg PP spsp rere",
|
CanonicalGenotype = "AA CC dd EE GG pp spsp rere",
|
||||||
Name = "Zobel-Hell",
|
Name = "Topas dd",
|
||||||
SortOrder = 48
|
SortOrder = 48
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000050"),
|
Id = new Guid("00000000-0000-0000-0000-000000000050"),
|
||||||
CanonicalGenotype = "AA cchmcchm dd EE gg PP spsp rere",
|
CanonicalGenotype = "aa CC dd ee gg pp spsp rere",
|
||||||
Name = "Silberagouti dd CP",
|
Name = "Blaufuchs dd",
|
||||||
SortOrder = 49
|
SortOrder = 49
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000051"),
|
Id = new Guid("00000000-0000-0000-0000-000000000051"),
|
||||||
CanonicalGenotype = "AA cchmcchm dd EE gg PP spsp rere",
|
CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere",
|
||||||
Name = "Silberagouti-Hell dd CP",
|
Name = "Marder",
|
||||||
SortOrder = 50
|
SortOrder = 50
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000052"),
|
Id = new Guid("00000000-0000-0000-0000-000000000052"),
|
||||||
CanonicalGenotype = "AA cchmcchm dd EE GG PP spsp rere",
|
CanonicalGenotype = "aa cchmch DD EE GG PP spsp rere",
|
||||||
Name = "Agouti dd CP",
|
Name = "Siam",
|
||||||
SortOrder = 51
|
SortOrder = 51
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000053"),
|
Id = new Guid("00000000-0000-0000-0000-000000000053"),
|
||||||
CanonicalGenotype = "AA cchmcchm dd EE GG PP spsp rere",
|
CanonicalGenotype = "aa cchmch DD EE gg PP spsp rere",
|
||||||
Name = "Agouti-Hell dd CP",
|
Name = "Zobel-Hell",
|
||||||
SortOrder = 52
|
SortOrder = 52
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000054"),
|
Id = new Guid("00000000-0000-0000-0000-000000000054"),
|
||||||
CanonicalGenotype = "aa CC DD ee gg PP spsp rere",
|
CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere",
|
||||||
Name = "Blaufuchs, hell",
|
Name = "CP-Agouti",
|
||||||
SortOrder = 53
|
SortOrder = 53
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000055"),
|
Id = new Guid("00000000-0000-0000-0000-000000000055"),
|
||||||
CanonicalGenotype = "aa CC DD efef GG pp spsp rere",
|
CanonicalGenotype = "AA cchmcchm DD EE gg PP spsp rere",
|
||||||
Name = "Rotfuchsschimmel",
|
Name = "CP-Silberagouti",
|
||||||
SortOrder = 54
|
SortOrder = 54
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000056"),
|
Id = new Guid("00000000-0000-0000-0000-000000000056"),
|
||||||
CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
|
CanonicalGenotype = "AA cchmcchm DD ee GG PP spsp rere",
|
||||||
Name = "Polarfuchs, hell",
|
Name = "CP-Algierfuchs",
|
||||||
SortOrder = 55
|
SortOrder = 55
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000057"),
|
Id = new Guid("00000000-0000-0000-0000-000000000057"),
|
||||||
CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
|
CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere",
|
||||||
Name = "Kohlfuchsschimmel, hell",
|
Name = "CP-Polarfuchs",
|
||||||
SortOrder = 56
|
SortOrder = 56
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000058"),
|
Id = new Guid("00000000-0000-0000-0000-000000000058"),
|
||||||
CanonicalGenotype = "aa CC DD ee GG pp spsp rere",
|
CanonicalGenotype = "AA cchmcchm dd ee GG PP spsp rere",
|
||||||
Name = "Rotfuchs, hell",
|
Name = "CP-Fuchs",
|
||||||
SortOrder = 57
|
SortOrder = 57
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000059"),
|
Id = new Guid("00000000-0000-0000-0000-000000000059"),
|
||||||
CanonicalGenotype = "aa cchmcchm dd EE gg PP spsp rere",
|
CanonicalGenotype = "AA cchmch dd ee GG PP spsp rere",
|
||||||
Name = "Zobel dd",
|
Name = "CP-Fuchs-Hell",
|
||||||
SortOrder = 58
|
SortOrder = 58
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000060"),
|
Id = new Guid("00000000-0000-0000-0000-000000000060"),
|
||||||
CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
|
CanonicalGenotype = "AA cchmcchm dd ee gg PP spsp rere",
|
||||||
Name = "Kohlfuchs-Hell",
|
Name = "CP-Blaufuchs",
|
||||||
SortOrder = 59
|
SortOrder = 59
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000061"),
|
Id = new Guid("00000000-0000-0000-0000-000000000061"),
|
||||||
CanonicalGenotype = "aa cchmcchm DD ee GG PP spsp rere",
|
|
||||||
Name = "Kohlfuchs CP",
|
|
||||||
SortOrder = 60
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000062"),
|
|
||||||
CanonicalGenotype = "AA cchmcchm DD ee GG PP spsp rere",
|
|
||||||
Name = "Algierfuchs CP",
|
|
||||||
SortOrder = 61
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000063"),
|
|
||||||
CanonicalGenotype = "AA cchmcchm DD EE gg PP spsp rere",
|
|
||||||
Name = "Silberagouti CP",
|
|
||||||
SortOrder = 62
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000064"),
|
|
||||||
CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere",
|
|
||||||
Name = "Agouti CP",
|
|
||||||
SortOrder = 63
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000065"),
|
|
||||||
CanonicalGenotype = "AA cchmcchm DD ee GG PP spsp rere",
|
|
||||||
Name = "Algierfuchs-Hell CP",
|
|
||||||
SortOrder = 64
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000066"),
|
|
||||||
CanonicalGenotype = "aa cchmcchm DD ee GG PP spsp rere",
|
|
||||||
Name = "Kohlfuchs,hell CP",
|
|
||||||
SortOrder = 65
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000067"),
|
|
||||||
CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere",
|
|
||||||
Name = "Polarfuchs CP",
|
|
||||||
SortOrder = 66
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000068"),
|
|
||||||
CanonicalGenotype = "AA CC DD ee GG PP spsp rere",
|
|
||||||
Name = "Algierfuchs, hell",
|
|
||||||
SortOrder = 67
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000069"),
|
|
||||||
CanonicalGenotype = "AA CC dd EE GG pp spsp rere",
|
|
||||||
Name = "Topas dd",
|
|
||||||
SortOrder = 68
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000070"),
|
|
||||||
CanonicalGenotype = "aa cchmcchm dd EE gg PP spsp rere",
|
|
||||||
Name = "Zobel-Hell dd",
|
|
||||||
SortOrder = 69
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000071"),
|
|
||||||
CanonicalGenotype = "aa cchmcchm DD efef GG PP spsp rere",
|
|
||||||
Name = "Kohlfuchsschimmel CP",
|
|
||||||
SortOrder = 70
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000072"),
|
|
||||||
CanonicalGenotype = "aa CC dd ee gg pp spsp rere",
|
|
||||||
Name = "Blaufuchs dd",
|
|
||||||
SortOrder = 71
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000073"),
|
|
||||||
CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere",
|
CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere",
|
||||||
Name = "CP-Orangeschimmel",
|
Name = "CP-Orangeschimmel",
|
||||||
SortOrder = 72
|
SortOrder = 60
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ gelisteten Konflikt-Tiere + Tiere mit Sonder-Kürzeln warten in Quarantäne —
|
|||||||
| ~~C5~~ | ✅ **BEANTWORTET** (2026-06-06): **Es gibt KEIN „Schwarzschimmel"** — das war ein Fehler in unserem Katalog. Die korrekten Schimmelarten: `efef` → **Orangeschimmel** · `efef pp` → **Rotaugenschimmel** · `efef gg` → **Silberschimmel** · Kombis z. B. `c[chm]c[chm] efef` → **CP-Orangeschimmel**. Michael korrigiert den Katalog (Schwarzschimmel raus, efef = Orangeschimmel). | — erledigt |
|
| ~~C5~~ | ✅ **BEANTWORTET** (2026-06-06): **Es gibt KEIN „Schwarzschimmel"** — das war ein Fehler in unserem Katalog. Die korrekten Schimmelarten: `efef` → **Orangeschimmel** · `efef pp` → **Rotaugenschimmel** · `efef gg` → **Silberschimmel** · Kombis z. B. `c[chm]c[chm] efef` → **CP-Orangeschimmel**. Michael korrigiert den Katalog (Schwarzschimmel raus, efef = Orangeschimmel). | — erledigt |
|
||||||
| C6 | **Die 32 Konflikt-Tiere prüfen** → siehe Abschnitt **D**. | diese 32 Tiere werden erst danach geladen |
|
| C6 | **Die 32 Konflikt-Tiere prüfen** → siehe Abschnitt **D**. | diese 32 Tiere werden erst danach geladen |
|
||||||
| C7 | *(optional)* Was hat dir bei **Renner Pro** gefehlt? Lieblings-Auswertungen? | mögliche neue Funktionen |
|
| C7 | *(optional)* Was hat dir bei **Renner Pro** gefehlt? Lieblings-Auswertungen? | mögliche neue Funktionen |
|
||||||
| C8 | **„Himalaya" vs. „Hermelin":** Du hast gesagt `c[h]c[h]` = **Hermelin**. In unserem Katalog gibt es aktuell ZWEI Farben mit `c[h]c[h]`: **Hermelin** (`aa c[h]c[h]`, nicht-agouti) und **Himalaya** (`A- c[h]c[h]`, agouti). Gibt es bei dir „Himalaya" überhaupt, oder ist **alles** mit `c[h]c[h]` einfach **Hermelin** (dann nehmen wir „Himalaya" raus, wie bei Schwarzschimmel)? | Farbschlag-Katalog (Himalaya behalten oder entfernen) |
|
| ~~C8~~ | ✅ **BEANTWORTET** (2026-06-06): **Himalaya gibt es** — Himalaya = **`A- c[h]c[h]`** (agouti), Hermelin = **`aa c[h]c[h]`** (nicht-agouti). Beide bleiben im Katalog; die Engine unterscheidet bereits korrekt nach A-/aa. — erledigt |
|
||||||
|
| C9 | *(optional, technisch)* Bei den **CP-Fuchs-Farben**: Wodurch unterscheiden sich genetisch **CP-Fuchs** ↔ **CP-Blaufuchs** ↔ **CP-Fuchs-Hell**? (Vermutung: Blaufuchs = `dd`-Verdünnung, „-Hell" = `c[chm]c[h]` statt `c[chm]c[chm]` — stimmt das?) Aktuell rechnet das Programm alle drei als „CP-Fuchs"; mit deiner Regel können wir sie genau unterscheiden. Per Hand auswählbar sind sie schon. | Farb-Engine Feinschliff (niedrige Priorität) |
|
||||||
|
|
||||||
### Hinweis zu C5 — woher kam das falsche „Schwarzschimmel"? (wie gewünscht notiert)
|
### Hinweis zu C5 — woher kam das falsche „Schwarzschimmel"? (wie gewünscht notiert)
|
||||||
„Schwarzschimmel" stammt aus **unserem ursprünglichen Farbkatalog** `gerbil-manager-web/src/genetics/catalog.ts` (Genotyp `efef`), den wir ganz am Anfang aus den deutschen Genetik-Quellen (de.wikibooks „Schwarze Augen", rennmauswelten, clan-of-topolino) aufgebaut hatten. Von dort kam es in die DB-Seed-Liste + Stammbaum-Farbchips. → Wird in GEN-3 korrigiert: Schwarzschimmel entfernt, `efef` = Orangeschimmel. *(Falls du der Quelle Bescheid geben willst: es ist die de.wikibooks-Farbgenetik-Seite.)*
|
„Schwarzschimmel" stammt aus **unserem ursprünglichen Farbkatalog** `gerbil-manager-web/src/genetics/catalog.ts` (Genotyp `efef`), den wir ganz am Anfang aus den deutschen Genetik-Quellen (de.wikibooks „Schwarze Augen", rennmauswelten, clan-of-topolino) aufgebaut hatten. Von dort kam es in die DB-Seed-Liste + Stammbaum-Farbchips. → Wird in GEN-3 korrigiert: Schwarzschimmel entfernt, `efef` = Orangeschimmel. *(Falls du der Quelle Bescheid geben willst: es ist die de.wikibooks-Farbgenetik-Seite.)*
|
||||||
@@ -84,17 +85,38 @@ Alle Details (sämtliche Genotyp-Varianten + Quelldateien): `tools/import/output
|
|||||||
~~Ella · Roswitha · Silenos gen. Adonis · Brandon Stark · Enya~~ (erledigt)
|
~~Ella · Roswitha · Silenos gen. Adonis · Brandon Stark · Enya~~ (erledigt)
|
||||||
|
|
||||||
### D3 · Genotyp: **kleine Abweichung** (eine Quelle genauer als die andere — `DD`↔`D-`, `PP`↔`P-`, `Ee`↔`E`, mit/ohne `spsp`) — welche stimmt?
|
### D3 · Genotyp: **kleine Abweichung** (eine Quelle genauer als die andere — `DD`↔`D-`, `PP`↔`P-`, `Ee`↔`E`, mit/ohne `spsp`) — welche stimmt?
|
||||||
~~Firefly v.d. K.C. (*18.12.2019, DD↔D-)~~ ✅ **D- ist richtig** (DD war ein Tippfehler) — Julian 2026-06-06 · Zuleika v.d. K.C. (*24.10.2015) · ~~WildFire v.d. K.C. (*05.10.2017, PP↔P-)~~ ✅ **PP ist richtig** (Julian 2026-06-06) · Milka of LennyLengo (*09.12.2018) · Silvain v.d. K.C. (*27.03.2022) · Daja of Little Rose (*16.05.2021, spsp) · Ichika v.d. K.C. (*19.04.2020) · Chelsea v.d. K.C. (*02.04.2021)
|
Bitte je Tier sagen, **welcher Wert stimmt** (die Quellen widersprechen sich beim genannten Locus). Alle Varianten: `review-report.md`.
|
||||||
|
|
||||||
|
| Tier | Konkreter Konflikt — was stimmt? | Status |
|
||||||
|
|---|---|---|
|
||||||
|
| Firefly v.d. K.C. (*18.12.2019) | D-Locus: **D-** ↔ **DD** | ✅ **D-** (DD war Tippfehler) — Julian |
|
||||||
|
| WildFire v.d. K.C. (*05.10.2017) | P-Locus: **P-** ↔ **PP** | ✅ **PP** — Julian |
|
||||||
|
| Zuleika v.d. K.C. (*24.10.2015) | D-Locus: **D-** ↔ **DD** | ✅ **DD, Ee, Gg, PP** (`aa c[chm]c[h] DD Ee Gg PP spsp`) — Julian |
|
||||||
|
| Milka of LennyLengo (*09.12.2018) | C-Locus: **C-** ↔ **Cc[h]** · E-Locus: **E-** ↔ **EE** | ✅ **Cc[h], EE** (`aa Cc[h] dd EE Gg P- Spsp`) — Julian |
|
||||||
|
| Silvain v.d. K.C. (*27.03.2022) | E-Locus: **Ee** ↔ **ee** · P-Locus: **P-** ↔ **Pp** | ✅ **ee, Pp** (`aa c[chm]c[chm] Dd ee[-] Gg Pp Spsp`) — Julian |
|
||||||
|
| Ichika v.d. K.C. (*19.04.2020) | E-Locus: **ee** ↔ **ee[f]** | ✅ **ee[f]** (Beibehalten-Regel: `[f]` war vorhanden) — Julian |
|
||||||
|
| Daja of Little Rose (*16.05.2021) | Scheckung: **mit `spsp`** ↔ **ohne** | ✅ **mit `spsp`** (Beibehalten-Regel) — Julian |
|
||||||
|
| Chelsea v.d. K.C. | ⚠️ **Kein Genotyp-Konflikt** — zwei „Chelsea" mit verschiedenem Datum (\*02.04.2021 / \*15.10.2021) | ✅ **ein Tier, Geburtsdatum 02.04.2021** (15.10.2021 war falsch → zusammengeführt) — Julian |
|
||||||
|
|
||||||
### D4 · **Marker** unterschiedlich (`WP` / `DP` / `WFNZ` / „hörend" mal vorhanden, mal nicht) — welcher gilt?
|
### D4 · **Marker** unterschiedlich (`WP` / `DP` / `WFNZ` / „hörend" mal vorhanden, mal nicht) — welcher gilt?
|
||||||
Vestra von den Schlossmäusen (*08.02.2019, WP) · Hedwig of BGB (*30.10.2019, DP + hörend) · Pitari gen. Piti v.d. K.C. (*16.05.2021, DP) · Little Hero of Black Forest (*22.02.2018, WFNZ ± spsp) · Victoria Welby gen. Welby v.d. K.C. (*16.01.2023, DP + Genotyp Ee[f]↔ee[f])
|
> ✅ **REGEL (Julian 2026-06-06):** „Wenn irgendwo etwas vorhanden war, das anderswo fehlte → **immer beibehalten**." Gilt generell für Marker/Flags und Angaben wie `spsp` oder `[f]` (Vorhandensein gewinnt über Fehlen). Wird zur Standard-Regel im Importer → löst alle „mit/ohne"-Fälle automatisch (z. B. Daja `spsp`, Ichika `[f]`). Greift NICHT bei echten Wert-Widersprüchen (z. B. `DD`↔`D-`, `Ee`↔`ee`) — die brauchen weiter deine Entscheidung.
|
||||||
|
>
|
||||||
|
> ℹ️ Bei D4 waren die Marker `WP`/`DP`/`WFNZ`/`hörend` in BEIDEN Quellen gleich — also **gar nicht** der Konflikt (und jetzt sowieso Flags). Der echte Konflikt ist beim Genotyp. **3 von 5 dadurch automatisch gelöst:**
|
||||||
|
|
||||||
|
| Tier | Konkreter Konflikt — was stimmt? | Status |
|
||||||
|
|---|---|---|
|
||||||
|
| Vestra von den Schlossmäusen (*08.02.2019) | D-Locus: **D-** ↔ **DD** (WP gleich in beiden) | ✅ **DD** — Julian |
|
||||||
|
| Victoria Welby gen. Welby v.d. K.C. (*16.01.2023) | E-Locus: **Ee[f]** ↔ **ee[f]** — **Mutter von „C"!** | ✅ **ee[f]** (`Aa CC D- ee[f] Gg pp Spsp [DP]`) — Julian → C bekommt damit seine Mutter |
|
||||||
|
| Hedwig of BGB (*30.10.2019) | (WP/DP/hörend) | ✅ auto-gelöst — sind jetzt Flags, kein Konflikt mehr |
|
||||||
|
| Pitari gen. Piti v.d. K.C. (*16.05.2021) | (DP) | ✅ auto-gelöst — DP ist jetzt ein Flag |
|
||||||
|
| Little Hero of Black Forest (*22.02.2018) | (WFNZ ± spsp) | ✅ kein Genotyp-Konflikt mehr (WFNZ = Flag) |
|
||||||
|
|
||||||
### D5 · **Sterbedatum** widersprüchlich
|
### D5 · **Sterbedatum** widersprüchlich
|
||||||
| Tier | Problem |
|
| Tier | Problem |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Flint v.d. Kleinen Chaoten (*23.12.2017) | Tod 10.05.**2021** vs. 10.05.**2022** (Jahr-Tippfehler?) |
|
| ~~Flint v.d. Kleinen Chaoten (*23.12.2017)~~ | ✅ **Tod 10.05.2021** (2022 war Tippfehler) — Julian 2026-06-06 |
|
||||||
| Hanami v.d. Kleinen Chaoten (*10.09.2015) | Tod 12.12.2019 vs. 14.01.2020 |
|
| Hanami v.d. Kleinen Chaoten (*10.09.2015) | Tod 12.12.2019 vs. 14.01.2020 |
|
||||||
| Molly of Black Forest (*13.09.2021) | Tod **03.05.2021 — VOR der Geburt** → klarer Datenfehler, bitte korrigieren |
|
| ~~Molly of Black Forest (*13.09.2021)~~ | ✅ **Tod 03.05.2022** (03.05.2021 war Jahr-Tippfehler → lag vor der Geburt) — Julian 2026-06-06 |
|
||||||
|
|
||||||
*(Das sind 32 Tiere: 11 + 5 + 8 + 5 + 3.)*
|
*(Das sind 32 Tiere: 11 + 5 + 8 + 5 + 3.)*
|
||||||
|
|
||||||
|
|||||||
43
gerbil-manager-web/e2e/bestand.spec.ts
Normal file
43
gerbil-manager-web/e2e/bestand.spec.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/** BESTAND-FILTER: die Tiere-Liste zeigt standardmäßig nur den eigenen Bestand. */
|
||||||
|
import { de, expect, gotoSection, skipUnlessMock, test } from './fixtures'
|
||||||
|
|
||||||
|
const t = de.pages.gerbils
|
||||||
|
|
||||||
|
test('Tiere-Liste blendet externe Ahnen standardmäßig aus', async ({ page }) => {
|
||||||
|
skipUnlessMock()
|
||||||
|
await gotoSection(page, de.nav.gerbils)
|
||||||
|
await expect(page.getByRole('heading', { name: t.title, exact: true })).toBeVisible()
|
||||||
|
|
||||||
|
// Bestand ist sichtbar …
|
||||||
|
await expect(page.locator('.gerbil-row', { hasText: 'Krümel' })).toBeVisible()
|
||||||
|
// … aber die externe Ahne „Max“ (isResident=false) nicht.
|
||||||
|
await expect(page.locator('.gerbil-row', { hasText: 'Max' })).toHaveCount(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Toggle „Externe Ahnen einblenden“ zeigt externe Tiere mit Extern-Markierung', async ({ page }) => {
|
||||||
|
skipUnlessMock()
|
||||||
|
await gotoSection(page, de.nav.gerbils)
|
||||||
|
await expect(page.locator('.gerbil-row', { hasText: 'Krümel' })).toBeVisible()
|
||||||
|
|
||||||
|
await page.getByRole('checkbox', { name: t.filters.showExternal }).check()
|
||||||
|
|
||||||
|
const maxRow = page.locator('.gerbil-row', { hasText: 'Max' })
|
||||||
|
await expect(maxRow).toBeVisible()
|
||||||
|
await expect(maxRow.getByText(t.externalBadge, { exact: true })).toBeVisible()
|
||||||
|
// Der Bestand bleibt weiterhin sichtbar.
|
||||||
|
await expect(page.locator('.gerbil-row', { hasText: 'Krümel' })).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Bearbeiten-Formular kann ein Tier als extern markieren (Bestand-Häkchen)', async ({ page }) => {
|
||||||
|
skipUnlessMock()
|
||||||
|
// Krümel gehört zum Bestand -> Häkchen entfernen und speichern.
|
||||||
|
await page.goto('/rennmaeuse/kruemel/bearbeiten')
|
||||||
|
const check = page.getByRole('checkbox', { name: t.form.isResidentLabel })
|
||||||
|
await expect(check).toBeChecked()
|
||||||
|
await check.uncheck()
|
||||||
|
await page.getByRole('button', { name: t.form.save }).click()
|
||||||
|
|
||||||
|
// Auf der Detailseite ist Krümel jetzt als „Extern“ markiert.
|
||||||
|
await expect(page.getByRole('heading', { name: 'Krümel' })).toBeVisible()
|
||||||
|
await expect(page.getByText(t.externalBadge, { exact: true })).toBeVisible()
|
||||||
|
})
|
||||||
@@ -88,6 +88,8 @@ function gerbil(
|
|||||||
nameSearch: name.toLowerCase().replace(/[\s._-]/g, ''),
|
nameSearch: name.toLowerCase().replace(/[\s._-]/g, ''),
|
||||||
genotype,
|
genotype,
|
||||||
notes: null,
|
notes: null,
|
||||||
|
// BESTAND-FILTER: default = eigener Bestand; einzelne externe Ahnen unten gesetzt.
|
||||||
|
isResident: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,8 +112,9 @@ export function seedDb(): MockDb {
|
|||||||
gerbil('greta', 'Greta', 'female', '2019-05-23', null, 'cv-schwarz'),
|
gerbil('greta', 'Greta', 'female', '2019-05-23', null, 'cv-schwarz'),
|
||||||
gerbil('frieda', 'Frieda', 'female', '2020-01-18', null, 'cv-gold'),
|
gerbil('frieda', 'Frieda', 'female', '2020-01-18', null, 'cv-gold'),
|
||||||
gerbil('emil', 'Emil', 'male', '2017-03-03', 'w-emil', 'cv-agouti'),
|
gerbil('emil', 'Emil', 'male', '2017-03-03', 'w-emil', 'cv-agouti'),
|
||||||
gerbil('hilde', 'Hilde', 'female', '2017-11-11', null, 'cv-schwarz'),
|
// BESTAND-FILTER: externe Ahnen (Gründertiere fremder Zuchten, nur für den Stammbaum).
|
||||||
gerbil('max', 'Max', 'male', '2015-08-08', null, 'cv-agouti'),
|
{ ...gerbil('hilde', 'Hilde', 'female', '2017-11-11', null, 'cv-schwarz'), isResident: false, originBreeder: 'Zoohandlung Meier' },
|
||||||
|
{ ...gerbil('max', 'Max', 'male', '2015-08-08', null, 'cv-agouti'), isResident: false, originBreeder: 'Zoohandlung Meier' },
|
||||||
// Statistik: Verstorbene + Abgegebene für Verluste/Bestandskurve
|
// Statistik: Verstorbene + Abgegebene für Verluste/Bestandskurve
|
||||||
{ ...gerbil('willi', 'Willi', 'male', '2019-09-09', null, 'cv-schwarz'), status: 'Deceased', dateOfDeath: '2022-04-04' },
|
{ ...gerbil('willi', 'Willi', 'male', '2019-09-09', null, 'cv-schwarz'), status: 'Deceased', dateOfDeath: '2022-04-04' },
|
||||||
{ ...gerbil('rosa', 'Rosa', 'female', '2020-02-02', null, 'cv-gold'), status: 'Deceased', dateOfDeath: '2023-08-15' },
|
{ ...gerbil('rosa', 'Rosa', 'female', '2020-02-02', null, 'cv-gold'), status: 'Deceased', dateOfDeath: '2023-08-15' },
|
||||||
|
|||||||
@@ -47,6 +47,13 @@ export interface Gerbil {
|
|||||||
*/
|
*/
|
||||||
characterTraits?: string[] | null
|
characterTraits?: string[] | null
|
||||||
characterNote?: string | null
|
characterNote?: string | null
|
||||||
|
/**
|
||||||
|
* Residency (Bestand): true = part of the own clan (Kleine Chaoten), false =
|
||||||
|
* external/pedigree-only ancestor imported for the Stammbaum. Gridify-filterable
|
||||||
|
* (`isResident==true`); the Tiere list defaults to resident-only. Absent = treat
|
||||||
|
* as resident (backend default true).
|
||||||
|
*/
|
||||||
|
isResident?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Payload for POST /gerbils. */
|
/** Payload for POST /gerbils. */
|
||||||
@@ -68,6 +75,7 @@ export interface CreateGerbil {
|
|||||||
notes?: string | null
|
notes?: string | null
|
||||||
characterTraits?: string[] | null
|
characterTraits?: string[] | null
|
||||||
characterNote?: string | null
|
characterNote?: string | null
|
||||||
|
isResident?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Payload for PUT /gerbils/{id} (all optional / partial update). */
|
/** Payload for PUT /gerbils/{id} (all optional / partial update). */
|
||||||
|
|||||||
@@ -179,8 +179,10 @@ describe('Farbschlag catalog', () => {
|
|||||||
expect(match.name).toBe('Unbekannter Farbschlag')
|
expect(match.name).toBe('Unbekannter Farbschlag')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has the expected catalogue coverage (GEN-2: frozen 18 + 55 portal varieties)', () => {
|
it('has the expected catalogue coverage (GEN-3f: 61 after cchm CP reconciliation)', () => {
|
||||||
expect(CATALOG_SIZE).toBe(73)
|
// GEN-3f collapsed the 24 portal cchm colourpoint rows to 12 breeder-named
|
||||||
|
// varieties (Marder/Siam/Zobel/Zobel-Hell + CP-<base>), so 73 -> 61.
|
||||||
|
expect(CATALOG_SIZE).toBe(61)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('frozen contract names round-trip to themselves (DB-key guard)', () => {
|
it('frozen contract names round-trip to themselves (DB-key guard)', () => {
|
||||||
@@ -206,7 +208,11 @@ describe('Farbschlag catalog', () => {
|
|||||||
expect(new Set(names).size).toBe(names.length)
|
expect(new Set(names).size).toBe(names.length)
|
||||||
for (const entry of BASE_COLORS) {
|
for (const entry of BASE_COLORS) {
|
||||||
for (const [locus, value] of Object.entries(entry.tokens)) {
|
for (const [locus, value] of Object.entries(entry.tokens)) {
|
||||||
expect(LOCI[locus as LocusKey].alleles).toContain(value)
|
// GEN-3f: a token may be a heterozygous pair "x/y" (e.g. C: 'cchm/ch'
|
||||||
|
// for the het colourpoints Siam/Zobel-Hell) — validate each allele.
|
||||||
|
for (const allele of value.split('/')) {
|
||||||
|
expect(LOCI[locus as LocusKey].alleles).toContain(allele)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -429,3 +435,46 @@ describe('GEN-3e: C-locus colourpoint naming', () => {
|
|||||||
expect(name('aa cchmcchm DD EE GG PP Spsp rere')).toBe('Marder Schecke')
|
expect(name('aa cchmcchm DD EE GG PP Spsp rere')).toBe('Marder Schecke')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('GEN-3f: CP catalog reconciled to the breeder CP- naming (matches her live data)', () => {
|
||||||
|
const name = (s: string) => genotypeToFarbschlag(fromDisplayString(s))
|
||||||
|
const has = (n: string) => BASE_COLORS.some((e) => e.name === n)
|
||||||
|
|
||||||
|
it('every CP- name her data uses exists as a catalog row (import name-match)', () => {
|
||||||
|
for (const n of [
|
||||||
|
'CP-Agouti', 'CP-Silberagouti', 'CP-Algierfuchs', 'CP-Polarfuchs',
|
||||||
|
'CP-Fuchs', 'CP-Fuchs-Hell', 'CP-Blaufuchs', 'CP-Orangeschimmel',
|
||||||
|
'Marder', 'Siam', 'Zobel', 'Zobel-Hell',
|
||||||
|
]) {
|
||||||
|
expect(has(n)).toBe(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('the removed portal suffix-names are gone (collapsed)', () => {
|
||||||
|
for (const n of [
|
||||||
|
'Agouti CP', 'Agouti CP-Hell', 'Silberagouti CP', 'Algierfuchs CP',
|
||||||
|
'Polarfuchs CP', 'Blaufuchs CP', 'Kohlfuchs CP', 'Kohlfuchsschimmel CP',
|
||||||
|
'Marder dd', 'Zobel dd', 'Siam (Marder-Hell)', 'Agouti dd CP',
|
||||||
|
]) {
|
||||||
|
expect(has(n)).toBe(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('the engine computes the agouti CP- names her data uses (E-family fallback covers fox/dilute)', () => {
|
||||||
|
expect(name('AA cchmcchm DD EE GG PP spsp rere')).toBe('CP-Agouti')
|
||||||
|
expect(name('AA cchmcchm DD EE gg PP spsp rere')).toBe('CP-Silberagouti')
|
||||||
|
expect(name('AA cchmcchm DD ee GG PP spsp rere')).toBe('CP-Algierfuchs')
|
||||||
|
expect(name('AA cchmcchm DD ee gg PP spsp rere')).toBe('CP-Polarfuchs')
|
||||||
|
// dd agouti fox has no dedicated base -> the eFamily fallback yields 'CP-Fuchs'.
|
||||||
|
expect(name('AA cchmcchm dd ee GG PP spsp rere')).toBe('CP-Fuchs')
|
||||||
|
// A- cchm efef -> CP-Orangeschimmel (Schimmel base under full C).
|
||||||
|
expect(name('AA cchmcchm DD efef GG PP spsp rere')).toBe('CP-Orangeschimmel')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('het cchm/ch colourpoints (Siam, Zobel-Hell) resolve to their own names', () => {
|
||||||
|
const siam = BASE_COLORS.find((e) => e.name === 'Siam')!
|
||||||
|
const zh = BASE_COLORS.find((e) => e.name === 'Zobel-Hell')!
|
||||||
|
expect(genotypeToFarbschlag(representativeGenotype(siam))).toBe('Siam')
|
||||||
|
expect(genotypeToFarbschlag(representativeGenotype(zh))).toBe('Zobel-Hell')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ export const BASE_COLORS: readonly FarbschlagEntry[] = [
|
|||||||
{ name: 'C-Separator', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'g', P: 'p' }, image: 'c-separator.jpg' },
|
{ name: 'C-Separator', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'g', P: 'p' }, image: 'c-separator.jpg' },
|
||||||
{ name: 'Elfenbein', tokens: { A: 'A', C: 'C', D: 'D', E: 'E', G: 'g', P: 'p' }, image: 'elfenbein.jpg' },
|
{ name: 'Elfenbein', tokens: { A: 'A', C: 'C', D: 'D', E: 'E', G: 'g', P: 'p' }, image: 'elfenbein.jpg' },
|
||||||
{ name: 'Kohlfuchs', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs.jpg' },
|
{ name: 'Kohlfuchs', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs.jpg' },
|
||||||
{ name: 'Marder', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'E', G: 'G', P: 'P' }, image: 'marder.JPG' },
|
|
||||||
{ name: 'Siam (Marder-Hell)', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'E', G: 'G', P: 'P' }, image: 'siam-marder-hell.JPG' },
|
|
||||||
{ name: 'Polarfuchs', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'polarfuchs.jpg' },
|
{ name: 'Polarfuchs', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'polarfuchs.jpg' },
|
||||||
{ name: 'Saphir', tokens: { A: 'a', C: 'C', D: 'D', E: 'E', G: 'G', P: 'p' }, image: 'saphir.jpg' },
|
{ name: 'Saphir', tokens: { A: 'a', C: 'C', D: 'D', E: 'E', G: 'G', P: 'p' }, image: 'saphir.jpg' },
|
||||||
// GEN-3a: efef base (otherwise wild C/D/G/P) = Orangeschimmel (breeder C5).
|
// GEN-3a: efef base (otherwise wild C/D/G/P) = Orangeschimmel (breeder C5).
|
||||||
@@ -88,48 +86,47 @@ export const BASE_COLORS: readonly FarbschlagEntry[] = [
|
|||||||
{ name: 'Silberagouti dd', tokens: { A: 'A', C: 'C', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'silberagouti-dd.jpg' },
|
{ name: 'Silberagouti dd', tokens: { A: 'A', C: 'C', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'silberagouti-dd.jpg' },
|
||||||
{ name: 'Kohlfuchs dd', tokens: { A: 'a', C: 'C', D: 'd', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-dd.jpg' },
|
{ name: 'Kohlfuchs dd', tokens: { A: 'a', C: 'C', D: 'd', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-dd.jpg' },
|
||||||
{ name: 'Anthrazit dd', tokens: { A: 'a', C: 'C', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'anthrazit-dd.jpg' },
|
{ name: 'Anthrazit dd', tokens: { A: 'a', C: 'C', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'anthrazit-dd.jpg' },
|
||||||
{ name: 'Agouti CP-Hell', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'E', G: 'G', P: 'P' }, image: 'agouti-cp-hell.JPG' },
|
|
||||||
{ name: 'Blaufuchs CP', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'blaufuchs-cp.jpg' },
|
|
||||||
// GEN-3a: efef gg base = Silberschimmel (breeder C5) — listed before the
|
// GEN-3a: efef gg base = Silberschimmel (breeder C5) — listed before the
|
||||||
// A-specific Polarfuchsschimmel so the canonical efef-gg reverse-matches here.
|
// A-specific Polarfuchsschimmel so the canonical efef-gg reverse-matches here.
|
||||||
{ name: 'Silberschimmel', tokens: { C: 'C', D: 'D', E: 'ef', G: 'g', P: 'P' }, image: 'silberschimmel.jpg' },
|
{ name: 'Silberschimmel', tokens: { C: 'C', D: 'D', E: 'ef', G: 'g', P: 'P' }, image: 'silberschimmel.jpg' },
|
||||||
{ name: 'Polarfuchsschimmel', tokens: { A: 'A', C: 'C', D: 'D', E: 'ef', G: 'g', P: 'P' }, image: 'polarfuchsschimmel.jpg' },
|
{ name: 'Polarfuchsschimmel', tokens: { A: 'A', C: 'C', D: 'D', E: 'ef', G: 'g', P: 'P' }, image: 'polarfuchsschimmel.jpg' },
|
||||||
{ name: 'Algierfuchsschimmel', tokens: { A: 'A', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'P' }, image: 'algierfuchsschimmel.jpg' },
|
{ name: 'Algierfuchsschimmel', tokens: { A: 'A', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'P' }, image: 'algierfuchsschimmel.jpg' },
|
||||||
{ name: 'Polarfuchs-Hell CP', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'polarfuchs-hell-cp.jpg' },
|
|
||||||
{ name: 'Kohlfuchsschimmel', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'P' }, image: 'kohlfuchsschimmel.jpg' },
|
{ name: 'Kohlfuchsschimmel', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'P' }, image: 'kohlfuchsschimmel.jpg' },
|
||||||
{ name: 'Blaufuchsschimmel', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'g', P: 'P' }, image: 'blaufuchsschimmel.jpg' },
|
{ name: 'Blaufuchsschimmel', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'g', P: 'P' }, image: 'blaufuchsschimmel.jpg' },
|
||||||
{ name: 'Kohlfuchs, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-hell.jpg' },
|
{ name: 'Kohlfuchs, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-hell.jpg' },
|
||||||
{ name: 'Goldfuchs, hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'G', P: 'p' }, image: 'goldfuchs-hell.jpg' },
|
{ name: 'Goldfuchs, hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'G', P: 'p' }, image: 'goldfuchs-hell.jpg' },
|
||||||
{ name: 'Goldfuchsschimmel', tokens: { A: 'A', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'p' }, image: 'goldfuchsschimmel.jpg' },
|
{ name: 'Goldfuchsschimmel', tokens: { A: 'A', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'p' }, image: 'goldfuchsschimmel.jpg' },
|
||||||
{ name: 'Gold-Hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'E', G: 'G', P: 'p' }, image: 'gold-hell.jpg' },
|
{ name: 'Gold-Hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'E', G: 'G', P: 'p' }, image: 'gold-hell.jpg' },
|
||||||
{ name: 'Siam (Marder-Hell) dd', tokens: { A: 'a', C: 'cchm', D: 'd', E: 'E', G: 'G', P: 'P' }, image: 'siam-marder-hell-dd.jpg' },
|
|
||||||
{ name: 'Marder dd', tokens: { A: 'a', C: 'cchm', D: 'd', E: 'E', G: 'G', P: 'P' }, image: 'marder-dd.jpg' },
|
|
||||||
{ name: 'Zobel-Hell', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'E', G: 'g', P: 'P' }, image: 'zobel-hell.jpg' },
|
|
||||||
{ name: 'Silberagouti dd CP', tokens: { A: 'A', C: 'cchm', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'silberagouti-dd-cp.jpg' },
|
|
||||||
{ name: 'Silberagouti-Hell dd CP', tokens: { A: 'A', C: 'cchm', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'silberagouti-hell-dd-cp.jpg' },
|
|
||||||
{ name: 'Agouti dd CP', tokens: { A: 'A', C: 'cchm', D: 'd', E: 'E', G: 'G', P: 'P' }, image: 'agouti-dd-cp.jpg' },
|
|
||||||
{ name: 'Agouti-Hell dd CP', tokens: { A: 'A', C: 'cchm', D: 'd', E: 'E', G: 'G', P: 'P' }, image: 'agouti-hell-dd-cp.jpg' },
|
|
||||||
{ name: 'Blaufuchs, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'blaufuchs-hell.jpeg' },
|
{ name: 'Blaufuchs, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'blaufuchs-hell.jpeg' },
|
||||||
{ name: 'Rotfuchsschimmel', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'p' }, image: 'rotfuchsschimmel.jpg' },
|
{ name: 'Rotfuchsschimmel', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'p' }, image: 'rotfuchsschimmel.jpg' },
|
||||||
{ name: 'Polarfuchs, hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'polarfuchs-hell.jpeg' },
|
{ name: 'Polarfuchs, hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'polarfuchs-hell.jpeg' },
|
||||||
{ name: 'Kohlfuchsschimmel, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'P' }, image: 'kohlfuchsschimmel-hell.jpg' },
|
{ name: 'Kohlfuchsschimmel, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'ef', G: 'G', P: 'P' }, image: 'kohlfuchsschimmel-hell.jpg' },
|
||||||
{ name: 'Rotfuchs, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'p' }, image: 'rotfuchs-hell.jpg' },
|
{ name: 'Rotfuchs, hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'p' }, image: 'rotfuchs-hell.jpg' },
|
||||||
{ name: 'Zobel dd', tokens: { A: 'a', C: 'cchm', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'zobel-dd.jpg' },
|
|
||||||
{ name: 'Kohlfuchs-Hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-hell-2.jpg' },
|
{ name: 'Kohlfuchs-Hell', tokens: { A: 'a', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-hell-2.jpg' },
|
||||||
{ name: 'Kohlfuchs CP', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-cp.jpg' },
|
|
||||||
{ name: 'Algierfuchs CP', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'algierfuchs-cp.jpg' },
|
|
||||||
{ name: 'Silberagouti CP', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'E', G: 'g', P: 'P' }, image: 'silberagouti-cp.JPG' },
|
|
||||||
{ name: 'Agouti CP', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'E', G: 'G', P: 'P' }, image: 'agouti-cp.jpg' },
|
|
||||||
{ name: 'Algierfuchs-Hell CP', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'algierfuchs-hell-cp.jpg' },
|
|
||||||
{ name: 'Kohlfuchs,hell CP', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'kohlfuchs-hell-cp.jpg' },
|
|
||||||
{ name: 'Polarfuchs CP', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'polarfuchs-cp.jpg' },
|
|
||||||
{ name: 'Algierfuchs, hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'algierfuchs-hell.JPG' },
|
{ name: 'Algierfuchs, hell', tokens: { A: 'A', C: 'C', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'algierfuchs-hell.JPG' },
|
||||||
{ name: 'Topas dd', tokens: { A: 'A', C: 'C', D: 'd', E: 'E', G: 'G', P: 'p' }, image: 'topas-dd.jpg' },
|
{ name: 'Topas dd', tokens: { A: 'A', C: 'C', D: 'd', E: 'E', G: 'G', P: 'p' }, image: 'topas-dd.jpg' },
|
||||||
{ name: 'Zobel-Hell dd', tokens: { A: 'a', C: 'cchm', D: 'd', E: 'E', G: 'g', P: 'P' }, image: 'zobel-hell-dd.jpg' },
|
|
||||||
{ name: 'Kohlfuchsschimmel CP', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'ef', G: 'G', P: 'P' }, image: 'kohlfuchsschimmel-cp.JPG' },
|
|
||||||
{ name: 'Blaufuchs dd', tokens: { A: 'a', C: 'C', D: 'd', E: 'e', G: 'g', P: 'p' }, image: 'blaufuchs-dd.jpg' },
|
{ name: 'Blaufuchs dd', tokens: { A: 'a', C: 'C', D: 'd', E: 'e', G: 'g', P: 'p' }, image: 'blaufuchs-dd.jpg' },
|
||||||
// GEN-3a: c[chm]c[chm] efef base = CP-Orangeschimmel (breeder C5). A unspecified
|
|
||||||
// (listed after the A-specific cchm-Schimmel entries so they win for those).
|
// ── GEN-3f: c^chm colourpoint varieties, reconciled to the breeder's CP- naming ──
|
||||||
|
// The merged GEN-3e colourpointName() rule is authoritative: aa points are the
|
||||||
|
// marten/sable group (Marder/Siam, +gg Zobel/Zobel-Hell — E and D irrelevant);
|
||||||
|
// A- points take the 'CP-<base colour>' prefix and the '-Hell' shade variants
|
||||||
|
// collapse (other loci irrelevant for the CP prefix). These names == the strings
|
||||||
|
// in her live data (god: extract animals.json) so the re-import name-matches and
|
||||||
|
// the Farbschlag mismatch hint stops. The het cchm/ch points (Siam, Zobel-Hell,
|
||||||
|
// CP-Fuchs-Hell) use the 'cchm/ch' pair token. The agouti fox/dilute points
|
||||||
|
// (CP-Fuchs/CP-Blaufuchs) resolve through the engine's E-family fallback to
|
||||||
|
// 'CP-Fuchs'; their distinct dropdown names remain for hand-pick + import match.
|
||||||
|
{ name: 'Marder', tokens: { A: 'a', C: 'cchm', D: 'D', E: 'E', G: 'G', P: 'P' }, image: 'marder.JPG' },
|
||||||
|
{ name: 'Siam', tokens: { A: 'a', C: 'cchm/ch', D: 'D', E: 'E', G: 'G', P: 'P' }, image: 'siam-marder-hell.JPG' },
|
||||||
|
{ name: 'Zobel-Hell', tokens: { A: 'a', C: 'cchm/ch', D: 'D', E: 'E', G: 'g', P: 'P' }, image: 'zobel-hell.jpg' },
|
||||||
|
{ name: 'CP-Agouti', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'E', G: 'G', P: 'P' }, image: 'agouti-cp.jpg' },
|
||||||
|
{ name: 'CP-Silberagouti', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'E', G: 'g', P: 'P' }, image: 'silberagouti-cp.JPG' },
|
||||||
|
{ name: 'CP-Algierfuchs', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'e', G: 'G', P: 'P' }, image: 'algierfuchs-cp.jpg' },
|
||||||
|
{ name: 'CP-Polarfuchs', tokens: { A: 'A', C: 'cchm', D: 'D', E: 'e', G: 'g', P: 'P' }, image: 'polarfuchs-cp.jpg' },
|
||||||
|
{ name: 'CP-Fuchs', tokens: { A: 'A', C: 'cchm', D: 'd', E: 'e', G: 'G', P: 'P' } },
|
||||||
|
{ name: 'CP-Fuchs-Hell', tokens: { A: 'A', C: 'cchm/ch', D: 'd', E: 'e', G: 'G', P: 'P' } },
|
||||||
|
{ name: 'CP-Blaufuchs', tokens: { A: 'A', C: 'cchm', D: 'd', E: 'e', G: 'g', P: 'P' } },
|
||||||
{ name: 'CP-Orangeschimmel', tokens: { C: 'cchm', D: 'D', E: 'ef', G: 'G', P: 'P' } },
|
{ name: 'CP-Orangeschimmel', tokens: { C: 'cchm', D: 'D', E: 'ef', G: 'G', P: 'P' } },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -270,7 +267,14 @@ export function representativeGenotype(entry: FarbschlagEntry): Genotype {
|
|||||||
const out = {} as Record<LocusKey, AllelePair>
|
const out = {} as Record<LocusKey, AllelePair>
|
||||||
for (const locus of LOCUS_ORDER) {
|
for (const locus of LOCUS_ORDER) {
|
||||||
const token = entry.tokens[locus]
|
const token = entry.tokens[locus]
|
||||||
out[locus] = token ? [token, token] : base[locus]
|
if (!token) {
|
||||||
|
out[locus] = base[locus]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// GEN-3f: a token may encode a HETEROZYGOUS pair as "x/y" (e.g. the het
|
||||||
|
// colourpoints Siam/Zobel-Hell use C: 'cchm/ch'); otherwise it's homozygous.
|
||||||
|
const [a, b] = token.includes('/') ? (token.split('/') as [string, string]) : [token, token]
|
||||||
|
out[locus] = [a, b]
|
||||||
}
|
}
|
||||||
return makeGenotype(out)
|
return makeGenotype(out)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,303 +154,228 @@
|
|||||||
"sortOrder": 22,
|
"sortOrder": 22,
|
||||||
"image": "kohlfuchs.jpg"
|
"image": "kohlfuchs.jpg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Marder",
|
|
||||||
"canonicalGenotype": "aa cchmcchm DD EE GG PP spsp rere",
|
|
||||||
"sortOrder": 23,
|
|
||||||
"image": "marder.JPG"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Siam (Marder-Hell)",
|
|
||||||
"canonicalGenotype": "aa cchmcchm DD EE GG PP spsp rere",
|
|
||||||
"sortOrder": 24,
|
|
||||||
"image": "siam-marder-hell.JPG"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Polarfuchs",
|
"name": "Polarfuchs",
|
||||||
"canonicalGenotype": "AA CC DD ee gg PP spsp rere",
|
"canonicalGenotype": "AA CC DD ee gg PP spsp rere",
|
||||||
"sortOrder": 25,
|
"sortOrder": 23,
|
||||||
"image": "polarfuchs.jpg"
|
"image": "polarfuchs.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Saphir",
|
"name": "Saphir",
|
||||||
"canonicalGenotype": "aa CC DD EE GG pp spsp rere",
|
"canonicalGenotype": "aa CC DD EE GG pp spsp rere",
|
||||||
"sortOrder": 26,
|
"sortOrder": 24,
|
||||||
"image": "saphir.jpg"
|
"image": "saphir.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Orangeschimmel",
|
"name": "Orangeschimmel",
|
||||||
"canonicalGenotype": "AA CC DD efef GG PP spsp rere",
|
"canonicalGenotype": "AA CC DD efef GG PP spsp rere",
|
||||||
"sortOrder": 27,
|
"sortOrder": 25,
|
||||||
"image": "schimmel-orangeschimmel.jpg"
|
"image": "schimmel-orangeschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Topas",
|
"name": "Topas",
|
||||||
"canonicalGenotype": "AA CC DD EE GG pp spsp rere",
|
"canonicalGenotype": "AA CC DD EE GG pp spsp rere",
|
||||||
"sortOrder": 28,
|
"sortOrder": 26,
|
||||||
"image": "topas.jpg"
|
"image": "topas.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Platin-Hell",
|
"name": "Platin-Hell",
|
||||||
"canonicalGenotype": "aa CC DD EE GG pp spsp rere",
|
"canonicalGenotype": "aa CC DD EE GG pp spsp rere",
|
||||||
"sortOrder": 29,
|
"sortOrder": 27,
|
||||||
"image": "platin-hell.jpg"
|
"image": "platin-hell.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Agouti dd",
|
"name": "Agouti dd",
|
||||||
"canonicalGenotype": "AA CC dd EE GG PP spsp rere",
|
"canonicalGenotype": "AA CC dd EE GG PP spsp rere",
|
||||||
"sortOrder": 30,
|
"sortOrder": 28,
|
||||||
"image": "agouti-dd.jpg"
|
"image": "agouti-dd.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Silberagouti dd",
|
"name": "Silberagouti dd",
|
||||||
"canonicalGenotype": "AA CC dd EE gg PP spsp rere",
|
"canonicalGenotype": "AA CC dd EE gg PP spsp rere",
|
||||||
"sortOrder": 31,
|
"sortOrder": 29,
|
||||||
"image": "silberagouti-dd.jpg"
|
"image": "silberagouti-dd.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Kohlfuchs dd",
|
"name": "Kohlfuchs dd",
|
||||||
"canonicalGenotype": "aa CC dd ee GG PP spsp rere",
|
"canonicalGenotype": "aa CC dd ee GG PP spsp rere",
|
||||||
"sortOrder": 32,
|
"sortOrder": 30,
|
||||||
"image": "kohlfuchs-dd.jpg"
|
"image": "kohlfuchs-dd.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Anthrazit dd",
|
"name": "Anthrazit dd",
|
||||||
"canonicalGenotype": "aa CC dd EE gg PP spsp rere",
|
"canonicalGenotype": "aa CC dd EE gg PP spsp rere",
|
||||||
"sortOrder": 33,
|
"sortOrder": 31,
|
||||||
"image": "anthrazit-dd.jpg"
|
"image": "anthrazit-dd.jpg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Agouti CP-Hell",
|
|
||||||
"canonicalGenotype": "AA cchmcchm DD EE GG PP spsp rere",
|
|
||||||
"sortOrder": 34,
|
|
||||||
"image": "agouti-cp-hell.JPG"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Blaufuchs CP",
|
|
||||||
"canonicalGenotype": "aa cchmcchm DD ee gg PP spsp rere",
|
|
||||||
"sortOrder": 35,
|
|
||||||
"image": "blaufuchs-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Silberschimmel",
|
"name": "Silberschimmel",
|
||||||
"canonicalGenotype": "AA CC DD efef gg PP spsp rere",
|
"canonicalGenotype": "AA CC DD efef gg PP spsp rere",
|
||||||
"sortOrder": 36,
|
"sortOrder": 32,
|
||||||
"image": "silberschimmel.jpg"
|
"image": "silberschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Polarfuchsschimmel",
|
"name": "Polarfuchsschimmel",
|
||||||
"canonicalGenotype": "AA CC DD efef gg PP spsp rere",
|
"canonicalGenotype": "AA CC DD efef gg PP spsp rere",
|
||||||
"sortOrder": 37,
|
"sortOrder": 33,
|
||||||
"image": "polarfuchsschimmel.jpg"
|
"image": "polarfuchsschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Algierfuchsschimmel",
|
"name": "Algierfuchsschimmel",
|
||||||
"canonicalGenotype": "AA CC DD efef GG PP spsp rere",
|
"canonicalGenotype": "AA CC DD efef GG PP spsp rere",
|
||||||
"sortOrder": 38,
|
"sortOrder": 34,
|
||||||
"image": "algierfuchsschimmel.jpg"
|
"image": "algierfuchsschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Polarfuchs-Hell CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm DD ee gg PP spsp rere",
|
|
||||||
"sortOrder": 39,
|
|
||||||
"image": "polarfuchs-hell-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Kohlfuchsschimmel",
|
"name": "Kohlfuchsschimmel",
|
||||||
"canonicalGenotype": "aa CC DD efef GG PP spsp rere",
|
"canonicalGenotype": "aa CC DD efef GG PP spsp rere",
|
||||||
"sortOrder": 40,
|
"sortOrder": 35,
|
||||||
"image": "kohlfuchsschimmel.jpg"
|
"image": "kohlfuchsschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Blaufuchsschimmel",
|
"name": "Blaufuchsschimmel",
|
||||||
"canonicalGenotype": "aa CC DD efef gg PP spsp rere",
|
"canonicalGenotype": "aa CC DD efef gg PP spsp rere",
|
||||||
"sortOrder": 41,
|
"sortOrder": 36,
|
||||||
"image": "blaufuchsschimmel.jpg"
|
"image": "blaufuchsschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Kohlfuchs, hell",
|
"name": "Kohlfuchs, hell",
|
||||||
"canonicalGenotype": "aa CC DD ee GG PP spsp rere",
|
"canonicalGenotype": "aa CC DD ee GG PP spsp rere",
|
||||||
"sortOrder": 42,
|
"sortOrder": 37,
|
||||||
"image": "kohlfuchs-hell.jpg"
|
"image": "kohlfuchs-hell.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Goldfuchs, hell",
|
"name": "Goldfuchs, hell",
|
||||||
"canonicalGenotype": "AA CC DD ee GG pp spsp rere",
|
"canonicalGenotype": "AA CC DD ee GG pp spsp rere",
|
||||||
"sortOrder": 43,
|
"sortOrder": 38,
|
||||||
"image": "goldfuchs-hell.jpg"
|
"image": "goldfuchs-hell.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Goldfuchsschimmel",
|
"name": "Goldfuchsschimmel",
|
||||||
"canonicalGenotype": "AA CC DD efef GG pp spsp rere",
|
"canonicalGenotype": "AA CC DD efef GG pp spsp rere",
|
||||||
"sortOrder": 44,
|
"sortOrder": 39,
|
||||||
"image": "goldfuchsschimmel.jpg"
|
"image": "goldfuchsschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Gold-Hell",
|
"name": "Gold-Hell",
|
||||||
"canonicalGenotype": "AA CC DD EE GG pp spsp rere",
|
"canonicalGenotype": "AA CC DD EE GG pp spsp rere",
|
||||||
"sortOrder": 45,
|
"sortOrder": 40,
|
||||||
"image": "gold-hell.jpg"
|
"image": "gold-hell.jpg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Siam (Marder-Hell) dd",
|
|
||||||
"canonicalGenotype": "aa cchmcchm dd EE GG PP spsp rere",
|
|
||||||
"sortOrder": 46,
|
|
||||||
"image": "siam-marder-hell-dd.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Marder dd",
|
|
||||||
"canonicalGenotype": "aa cchmcchm dd EE GG PP spsp rere",
|
|
||||||
"sortOrder": 47,
|
|
||||||
"image": "marder-dd.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Zobel-Hell",
|
|
||||||
"canonicalGenotype": "aa cchmcchm DD EE gg PP spsp rere",
|
|
||||||
"sortOrder": 48,
|
|
||||||
"image": "zobel-hell.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Silberagouti dd CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm dd EE gg PP spsp rere",
|
|
||||||
"sortOrder": 49,
|
|
||||||
"image": "silberagouti-dd-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Silberagouti-Hell dd CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm dd EE gg PP spsp rere",
|
|
||||||
"sortOrder": 50,
|
|
||||||
"image": "silberagouti-hell-dd-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Agouti dd CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm dd EE GG PP spsp rere",
|
|
||||||
"sortOrder": 51,
|
|
||||||
"image": "agouti-dd-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Agouti-Hell dd CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm dd EE GG PP spsp rere",
|
|
||||||
"sortOrder": 52,
|
|
||||||
"image": "agouti-hell-dd-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Blaufuchs, hell",
|
"name": "Blaufuchs, hell",
|
||||||
"canonicalGenotype": "aa CC DD ee gg PP spsp rere",
|
"canonicalGenotype": "aa CC DD ee gg PP spsp rere",
|
||||||
"sortOrder": 53,
|
"sortOrder": 41,
|
||||||
"image": "blaufuchs-hell.jpeg"
|
"image": "blaufuchs-hell.jpeg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Rotfuchsschimmel",
|
"name": "Rotfuchsschimmel",
|
||||||
"canonicalGenotype": "aa CC DD efef GG pp spsp rere",
|
"canonicalGenotype": "aa CC DD efef GG pp spsp rere",
|
||||||
"sortOrder": 54,
|
"sortOrder": 42,
|
||||||
"image": "rotfuchsschimmel.jpg"
|
"image": "rotfuchsschimmel.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Polarfuchs, hell",
|
"name": "Polarfuchs, hell",
|
||||||
"canonicalGenotype": "AA CC DD ee gg PP spsp rere",
|
"canonicalGenotype": "AA CC DD ee gg PP spsp rere",
|
||||||
"sortOrder": 55,
|
"sortOrder": 43,
|
||||||
"image": "polarfuchs-hell.jpeg"
|
"image": "polarfuchs-hell.jpeg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Kohlfuchsschimmel, hell",
|
"name": "Kohlfuchsschimmel, hell",
|
||||||
"canonicalGenotype": "aa CC DD efef GG PP spsp rere",
|
"canonicalGenotype": "aa CC DD efef GG PP spsp rere",
|
||||||
"sortOrder": 56,
|
"sortOrder": 44,
|
||||||
"image": "kohlfuchsschimmel-hell.jpg"
|
"image": "kohlfuchsschimmel-hell.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Rotfuchs, hell",
|
"name": "Rotfuchs, hell",
|
||||||
"canonicalGenotype": "aa CC DD ee GG pp spsp rere",
|
"canonicalGenotype": "aa CC DD ee GG pp spsp rere",
|
||||||
"sortOrder": 57,
|
"sortOrder": 45,
|
||||||
"image": "rotfuchs-hell.jpg"
|
"image": "rotfuchs-hell.jpg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Zobel dd",
|
|
||||||
"canonicalGenotype": "aa cchmcchm dd EE gg PP spsp rere",
|
|
||||||
"sortOrder": 58,
|
|
||||||
"image": "zobel-dd.jpg"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Kohlfuchs-Hell",
|
"name": "Kohlfuchs-Hell",
|
||||||
"canonicalGenotype": "aa CC DD ee GG PP spsp rere",
|
"canonicalGenotype": "aa CC DD ee GG PP spsp rere",
|
||||||
"sortOrder": 59,
|
"sortOrder": 46,
|
||||||
"image": "kohlfuchs-hell-2.jpg"
|
"image": "kohlfuchs-hell-2.jpg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Kohlfuchs CP",
|
|
||||||
"canonicalGenotype": "aa cchmcchm DD ee GG PP spsp rere",
|
|
||||||
"sortOrder": 60,
|
|
||||||
"image": "kohlfuchs-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Algierfuchs CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm DD ee GG PP spsp rere",
|
|
||||||
"sortOrder": 61,
|
|
||||||
"image": "algierfuchs-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Silberagouti CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm DD EE gg PP spsp rere",
|
|
||||||
"sortOrder": 62,
|
|
||||||
"image": "silberagouti-cp.JPG"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Agouti CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm DD EE GG PP spsp rere",
|
|
||||||
"sortOrder": 63,
|
|
||||||
"image": "agouti-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Algierfuchs-Hell CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm DD ee GG PP spsp rere",
|
|
||||||
"sortOrder": 64,
|
|
||||||
"image": "algierfuchs-hell-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Kohlfuchs,hell CP",
|
|
||||||
"canonicalGenotype": "aa cchmcchm DD ee GG PP spsp rere",
|
|
||||||
"sortOrder": 65,
|
|
||||||
"image": "kohlfuchs-hell-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Polarfuchs CP",
|
|
||||||
"canonicalGenotype": "AA cchmcchm DD ee gg PP spsp rere",
|
|
||||||
"sortOrder": 66,
|
|
||||||
"image": "polarfuchs-cp.jpg"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Algierfuchs, hell",
|
"name": "Algierfuchs, hell",
|
||||||
"canonicalGenotype": "AA CC DD ee GG PP spsp rere",
|
"canonicalGenotype": "AA CC DD ee GG PP spsp rere",
|
||||||
"sortOrder": 67,
|
"sortOrder": 47,
|
||||||
"image": "algierfuchs-hell.JPG"
|
"image": "algierfuchs-hell.JPG"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Topas dd",
|
"name": "Topas dd",
|
||||||
"canonicalGenotype": "AA CC dd EE GG pp spsp rere",
|
"canonicalGenotype": "AA CC dd EE GG pp spsp rere",
|
||||||
"sortOrder": 68,
|
"sortOrder": 48,
|
||||||
"image": "topas-dd.jpg"
|
"image": "topas-dd.jpg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Zobel-Hell dd",
|
|
||||||
"canonicalGenotype": "aa cchmcchm dd EE gg PP spsp rere",
|
|
||||||
"sortOrder": 69,
|
|
||||||
"image": "zobel-hell-dd.jpg"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Kohlfuchsschimmel CP",
|
|
||||||
"canonicalGenotype": "aa cchmcchm DD efef GG PP spsp rere",
|
|
||||||
"sortOrder": 70,
|
|
||||||
"image": "kohlfuchsschimmel-cp.JPG"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Blaufuchs dd",
|
"name": "Blaufuchs dd",
|
||||||
"canonicalGenotype": "aa CC dd ee gg pp spsp rere",
|
"canonicalGenotype": "aa CC dd ee gg pp spsp rere",
|
||||||
"sortOrder": 71,
|
"sortOrder": 49,
|
||||||
"image": "blaufuchs-dd.jpg"
|
"image": "blaufuchs-dd.jpg"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Marder",
|
||||||
|
"canonicalGenotype": "aa cchmcchm DD EE GG PP spsp rere",
|
||||||
|
"sortOrder": 50,
|
||||||
|
"image": "marder.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Siam",
|
||||||
|
"canonicalGenotype": "aa cchmch DD EE GG PP spsp rere",
|
||||||
|
"sortOrder": 51,
|
||||||
|
"image": "siam-marder-hell.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zobel-Hell",
|
||||||
|
"canonicalGenotype": "aa cchmch DD EE gg PP spsp rere",
|
||||||
|
"sortOrder": 52,
|
||||||
|
"image": "zobel-hell.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CP-Agouti",
|
||||||
|
"canonicalGenotype": "AA cchmcchm DD EE GG PP spsp rere",
|
||||||
|
"sortOrder": 53,
|
||||||
|
"image": "agouti-cp.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CP-Silberagouti",
|
||||||
|
"canonicalGenotype": "AA cchmcchm DD EE gg PP spsp rere",
|
||||||
|
"sortOrder": 54,
|
||||||
|
"image": "silberagouti-cp.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CP-Algierfuchs",
|
||||||
|
"canonicalGenotype": "AA cchmcchm DD ee GG PP spsp rere",
|
||||||
|
"sortOrder": 55,
|
||||||
|
"image": "algierfuchs-cp.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CP-Polarfuchs",
|
||||||
|
"canonicalGenotype": "AA cchmcchm DD ee gg PP spsp rere",
|
||||||
|
"sortOrder": 56,
|
||||||
|
"image": "polarfuchs-cp.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CP-Fuchs",
|
||||||
|
"canonicalGenotype": "AA cchmcchm dd ee GG PP spsp rere",
|
||||||
|
"sortOrder": 57
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CP-Fuchs-Hell",
|
||||||
|
"canonicalGenotype": "AA cchmch dd ee GG PP spsp rere",
|
||||||
|
"sortOrder": 58
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CP-Blaufuchs",
|
||||||
|
"canonicalGenotype": "AA cchmcchm dd ee gg PP spsp rere",
|
||||||
|
"sortOrder": 59
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "CP-Orangeschimmel",
|
"name": "CP-Orangeschimmel",
|
||||||
"canonicalGenotype": "AA cchmcchm DD efef GG PP spsp rere",
|
"canonicalGenotype": "AA cchmcchm DD efef GG PP spsp rere",
|
||||||
"sortOrder": 72
|
"sortOrder": 60
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -330,6 +330,24 @@ textarea {
|
|||||||
color: #3a6ea5;
|
color: #3a6ea5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* BESTAND-FILTER: subtle marker for external (non-Bestand) animals. Inline next
|
||||||
|
to the name, so it should not be pushed to the grid edge like the status badge. */
|
||||||
|
.badge--external {
|
||||||
|
justify-self: start;
|
||||||
|
margin-left: 0.4rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
background: #f0f0f0;
|
||||||
|
color: #777;
|
||||||
|
border: 1px dashed #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkbox-style filter (label text + box on one row), vs. the stacked .field. */
|
||||||
|
.field--check {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.gerbil-card {
|
.gerbil-card {
|
||||||
grid-template-columns: 2fr 1fr 1.5fr 1fr auto;
|
grid-template-columns: 2fr 1fr 1.5fr 1fr auto;
|
||||||
@@ -741,4 +759,4 @@ textarea {
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 2px solid var(--color-border);
|
border: 2px solid var(--color-border);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ export default function GerbilDetailPage() {
|
|||||||
<GerbilProfilePhoto gerbilId={g.id} />
|
<GerbilProfilePhoto gerbilId={g.id} />
|
||||||
<h2>{g.name}</h2>
|
<h2>{g.name}</h2>
|
||||||
<span className={`badge badge--${g.status.toLowerCase()}`}>{statusLabel(g.status)}</span>
|
<span className={`badge badge--${g.status.toLowerCase()}`}>{statusLabel(g.status)}</span>
|
||||||
|
{g.isResident === false && (
|
||||||
|
<span className="badge badge--external" title={de.pages.gerbils.externalTitle}>
|
||||||
|
{de.pages.gerbils.externalBadge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="head-actions">
|
<div className="head-actions">
|
||||||
<Link to={`/rennmaeuse/${g.id}/bearbeiten`} className="btn btn--primary">
|
<Link to={`/rennmaeuse/${g.id}/bearbeiten`} className="btn btn--primary">
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ interface FormState {
|
|||||||
receiverContactId: string
|
receiverContactId: string
|
||||||
genotype: string
|
genotype: string
|
||||||
notes: string
|
notes: string
|
||||||
|
isResident: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const EMPTY: FormState = {
|
const EMPTY: FormState = {
|
||||||
@@ -41,6 +42,7 @@ const EMPTY: FormState = {
|
|||||||
receiverContactId: '',
|
receiverContactId: '',
|
||||||
genotype: '',
|
genotype: '',
|
||||||
notes: '',
|
notes: '',
|
||||||
|
isResident: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
function formFromGerbil(g: {
|
function formFromGerbil(g: {
|
||||||
@@ -58,6 +60,7 @@ function formFromGerbil(g: {
|
|||||||
receiverContactId: string | null
|
receiverContactId: string | null
|
||||||
genotype: string | null
|
genotype: string | null
|
||||||
notes: string | null
|
notes: string | null
|
||||||
|
isResident?: boolean | null
|
||||||
}): FormState {
|
}): FormState {
|
||||||
return {
|
return {
|
||||||
name: g.name,
|
name: g.name,
|
||||||
@@ -74,6 +77,7 @@ function formFromGerbil(g: {
|
|||||||
receiverContactId: g.receiverContactId ?? '',
|
receiverContactId: g.receiverContactId ?? '',
|
||||||
genotype: g.genotype ?? '',
|
genotype: g.genotype ?? '',
|
||||||
notes: g.notes ?? '',
|
notes: g.notes ?? '',
|
||||||
|
isResident: g.isResident ?? true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,6 +170,7 @@ export default function GerbilFormPage() {
|
|||||||
receiverContactId: nn(form.receiverContactId),
|
receiverContactId: nn(form.receiverContactId),
|
||||||
genotype: nn(form.genotype),
|
genotype: nn(form.genotype),
|
||||||
notes: nn(form.notes),
|
notes: nn(form.notes),
|
||||||
|
isResident: form.isResident,
|
||||||
}
|
}
|
||||||
const result = await mutation.run(body)
|
const result = await mutation.run(body)
|
||||||
if (result.ok) navigate(`/rennmaeuse/${result.value.id}`)
|
if (result.ok) navigate(`/rennmaeuse/${result.value.id}`)
|
||||||
@@ -355,6 +360,15 @@ export default function GerbilFormPage() {
|
|||||||
<textarea value={form.notes} onChange={(e) => set('notes', e.target.value)} />
|
<textarea value={form.notes} onChange={(e) => set('notes', e.target.value)} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<label className="field field--check" title={t.form.isResidentHint}>
|
||||||
|
<span>{t.form.isResidentLabel}</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={form.isResident}
|
||||||
|
onChange={(e) => set('isResident', e.target.checked)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
{mutation.error && <div className="alert alert--error">{mutation.error}</div>}
|
{mutation.error && <div className="alert alert--error">{mutation.error}</div>}
|
||||||
|
|
||||||
<div className="form-actions">
|
<div className="form-actions">
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export default function GerbilsPage() {
|
|||||||
const [gender, setGender] = useState<Gender | ''>('')
|
const [gender, setGender] = useState<Gender | ''>('')
|
||||||
const [colorVarietyId, setColorVarietyId] = useState('')
|
const [colorVarietyId, setColorVarietyId] = useState('')
|
||||||
const [originBreeder, setOriginBreeder] = useState('')
|
const [originBreeder, setOriginBreeder] = useState('')
|
||||||
|
// BESTAND-FILTER: default to the own clan (Bestand); opt in to external ancestors.
|
||||||
|
const [showExternal, setShowExternal] = useState(false)
|
||||||
const [sort, setSort] = useState<SortKey>('nameAsc')
|
const [sort, setSort] = useState<SortKey>('nameAsc')
|
||||||
const [page, setPage] = useState(1)
|
const [page, setPage] = useState(1)
|
||||||
|
|
||||||
@@ -50,6 +52,9 @@ export default function GerbilsPage() {
|
|||||||
gender && condition({ field: 'gender', op: '==', value: gender }),
|
gender && condition({ field: 'gender', op: '==', value: gender }),
|
||||||
colorVarietyId && condition({ field: 'colorVarietyId', op: '==', value: colorVarietyId }),
|
colorVarietyId && condition({ field: 'colorVarietyId', op: '==', value: colorVarietyId }),
|
||||||
originBreeder && condition({ field: 'originBreeder', op: '==', value: originBreeder }),
|
originBreeder && condition({ field: 'originBreeder', op: '==', value: originBreeder }),
|
||||||
|
// Default view = own clan (Bestand). Unless "externe Ahnen einblenden" is on,
|
||||||
|
// restrict to resident animals (server-side, so paging/counts stay correct).
|
||||||
|
!showExternal && condition({ field: 'isResident', op: '==', value: true }),
|
||||||
)
|
)
|
||||||
const orderBy = SORT_ORDER_BY[sort]
|
const orderBy = SORT_ORDER_BY[sort]
|
||||||
const query: GridifyQuery = { filter: filter || undefined, orderBy, page, pageSize: PAGE_SIZE }
|
const query: GridifyQuery = { filter: filter || undefined, orderBy, page, pageSize: PAGE_SIZE }
|
||||||
@@ -62,6 +67,7 @@ export default function GerbilsPage() {
|
|||||||
setGender('')
|
setGender('')
|
||||||
setColorVarietyId('')
|
setColorVarietyId('')
|
||||||
setOriginBreeder('')
|
setOriginBreeder('')
|
||||||
|
setShowExternal(false)
|
||||||
setPage(1)
|
setPage(1)
|
||||||
setSort('nameAsc')
|
setSort('nameAsc')
|
||||||
}
|
}
|
||||||
@@ -186,6 +192,14 @@ export default function GerbilsPage() {
|
|||||||
<option value="birthAsc">{t.sort.birthAsc}</option>
|
<option value="birthAsc">{t.sort.birthAsc}</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label className="field field--check" title={t.filters.showExternalHint}>
|
||||||
|
<span>{t.filters.showExternal}</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={showExternal}
|
||||||
|
onChange={(e) => onFilterChange(setShowExternal)(e.target.checked)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
<button type="button" className="btn" onClick={resetFilters}>
|
<button type="button" className="btn" onClick={resetFilters}>
|
||||||
{t.filters.reset}
|
{t.filters.reset}
|
||||||
</button>
|
</button>
|
||||||
@@ -234,7 +248,14 @@ export default function GerbilsPage() {
|
|||||||
aria-label={g.name}
|
aria-label={g.name}
|
||||||
/>
|
/>
|
||||||
<Link to={`/rennmaeuse/${g.id}`} className="gerbil-card">
|
<Link to={`/rennmaeuse/${g.id}`} className="gerbil-card">
|
||||||
<span className="gerbil-card__name">{g.name}</span>
|
<span className="gerbil-card__name">
|
||||||
|
{g.name}
|
||||||
|
{g.isResident === false && (
|
||||||
|
<span className="badge badge--external" title={t.externalTitle}>
|
||||||
|
{t.externalBadge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
<span className={`badge badge--${g.status.toLowerCase()}`}>
|
<span className={`badge badge--${g.status.toLowerCase()}`}>
|
||||||
{statusLabel(g.status)}
|
{statusLabel(g.status)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ export const de = {
|
|||||||
empty: 'Keine Rennmäuse gefunden.',
|
empty: 'Keine Rennmäuse gefunden.',
|
||||||
countLabel: 'Tiere',
|
countLabel: 'Tiere',
|
||||||
searchPlaceholder: 'Name suchen …',
|
searchPlaceholder: 'Name suchen …',
|
||||||
|
// BESTAND-FILTER: Kennzeichnung externer (nicht zum eigenen Bestand gehörender) Tiere
|
||||||
|
externalBadge: 'Extern',
|
||||||
|
externalTitle: 'Externes Tier — gehört nicht zum eigenen Bestand, nur für den Stammbaum erfasst.',
|
||||||
// Filter-Beschriftungen
|
// Filter-Beschriftungen
|
||||||
filters: {
|
filters: {
|
||||||
title: 'Filter',
|
title: 'Filter',
|
||||||
@@ -58,6 +61,9 @@ export const de = {
|
|||||||
all: 'Alle',
|
all: 'Alle',
|
||||||
reset: 'Filter zurücksetzen',
|
reset: 'Filter zurücksetzen',
|
||||||
sortBy: 'Sortieren nach',
|
sortBy: 'Sortieren nach',
|
||||||
|
// BESTAND-FILTER: eigener Bestand (Clan) vs. externe Ahnen (nur Stammbaum)
|
||||||
|
showExternal: 'Externe Ahnen einblenden',
|
||||||
|
showExternalHint: 'Tiere aus fremden Zuchten, die nur für den Stammbaum erfasst sind.',
|
||||||
},
|
},
|
||||||
// Sortier-Optionen
|
// Sortier-Optionen
|
||||||
sort: {
|
sort: {
|
||||||
@@ -110,6 +116,9 @@ export const de = {
|
|||||||
none: '— keine Angabe —',
|
none: '— keine Angabe —',
|
||||||
genotypeHint:
|
genotypeHint:
|
||||||
'Optional. Format z. B. „Aa CC Dd EE GG Pp Spsp rere“. Unbekannte Allele als „-“.',
|
'Optional. Format z. B. „Aa CC Dd EE GG Pp Spsp rere“. Unbekannte Allele als „-“.',
|
||||||
|
// BESTAND-FILTER: Zugehörigkeit zum eigenen Bestand (sonst externe Ahne)
|
||||||
|
isResidentLabel: 'Gehört zum eigenen Bestand',
|
||||||
|
isResidentHint: 'Abwählen für externe Ahnen, die nur für den Stammbaum erfasst sind.',
|
||||||
save: 'Speichern',
|
save: 'Speichern',
|
||||||
cancel: 'Abbrechen',
|
cancel: 'Abbrechen',
|
||||||
saving: 'Speichern …',
|
saving: 'Speichern …',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"_doc": "Human conflict resolutions for the import quarantine (HUMANQUESTION section D / C6). The importer consumes this to UN-QUARANTINE an animal: for a matching (name + dob) it accepts `genotype` (and/or `farbschlag`) as authoritative and skips the conflict. Key match = normalize(name) + dob, same identity as dedup. Maintained by god (Michael) as Julian/his wife answer the D-conflicts; originals (xlsx) stay read-only.",
|
"_doc": "Human conflict resolutions for the import quarantine (HUMANQUESTION section D / C6). The importer consumes this to UN-QUARANTINE an animal: for a matching (name + dob) it accepts the given authoritative field(s) — `genotype`, `farbschlag`, and/or `dateOfDeath` (DD.MM.YYYY) — and skips the conflict. Special field `correctDob` (DD.MM.YYYY): the matched (name + dob) record is a DUPLICATE with a WRONG birthdate — remap its DOB to `correctDob` BEFORE dedup so it merges into the canonical same-named animal. Key match = normalize(name) + dob, same identity as dedup. Maintained by god (Michael) as Julian/his wife answer the D-conflicts; originals (xlsx) stay read-only.",
|
||||||
"resolutions": [
|
"resolutions": [
|
||||||
{
|
{
|
||||||
"name": "Firefly von den Kleinen Chaoten",
|
"name": "Firefly von den Kleinen Chaoten",
|
||||||
@@ -14,6 +14,76 @@
|
|||||||
"decision": "P-locus = PP (not P-)",
|
"decision": "P-locus = PP (not P-)",
|
||||||
"genotype": "aa c[chm]c[chm] D- Ee gg PP spsp",
|
"genotype": "aa c[chm]c[chm] D- Ee gg PP spsp",
|
||||||
"source": "Julian 2026-06-06 — HUMANQUESTION D3"
|
"source": "Julian 2026-06-06 — HUMANQUESTION D3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Flint von den Kleinen Chaoten",
|
||||||
|
"dob": "23.12.2017",
|
||||||
|
"decision": "death date = 10.05.2021 (the 10.05.2022 variant was a year typo)",
|
||||||
|
"dateOfDeath": "10.05.2021",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Molly of Black Forest",
|
||||||
|
"dob": "13.09.2021",
|
||||||
|
"decision": "death date = 03.05.2022 (source 03.05.2021 was a year typo → fell before birth)",
|
||||||
|
"dateOfDeath": "03.05.2022",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Daja of Little Rose",
|
||||||
|
"dob": "16.05.2021",
|
||||||
|
"decision": "keep spsp (present in one source, omitted in the other) — 'presence wins' rule",
|
||||||
|
"genotype": "aa c[chm]c[chm] D- EE Gg P- spsp",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D3 / Beibehalten-Regel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ichika von den Kleinen Chaoten",
|
||||||
|
"dob": "19.04.2020",
|
||||||
|
"decision": "keep ee[f] (the [f] fox-modifier was present in one source, dropped in the other) — 'presence wins' rule",
|
||||||
|
"genotype": "aa CC D- ee[f] Gg pp spsp",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D3 / Beibehalten-Regel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zuleika von den Kleinen Chaoten",
|
||||||
|
"dob": "24.10.2015",
|
||||||
|
"decision": "D=DD, E=Ee (one small e), G=Gg (one small g), P=PP (two big P)",
|
||||||
|
"genotype": "aa c[chm]c[h] DD Ee Gg PP spsp",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Milka of LennyLengo",
|
||||||
|
"dob": "09.12.2018",
|
||||||
|
"decision": "C-locus = Cc[h], E-locus = EE",
|
||||||
|
"genotype": "aa Cc[h] dd EE Gg P- Spsp",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Silvain von den Kleinen Chaoten",
|
||||||
|
"dob": "27.03.2022",
|
||||||
|
"decision": "E-locus = ee, P-locus = Pp",
|
||||||
|
"genotype": "aa c[chm]c[chm] Dd ee[-] Gg Pp Spsp",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Chelsea von den Kleinen Chaoten",
|
||||||
|
"dob": "15.10.2021",
|
||||||
|
"decision": "duplicate with wrong birthdate — same animal as Chelsea *02.04.2021; merge into it",
|
||||||
|
"correctDob": "02.04.2021",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D3 (Chelsea Dublette)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vestra von den Schlossmäusen",
|
||||||
|
"dob": "08.02.2019",
|
||||||
|
"decision": "D-locus = DD",
|
||||||
|
"genotype": "Aa Cc[chm] DD EE GG PP Spsp [WP]",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Victoria Welby gen. Welby von den Kleinen Chaoten",
|
||||||
|
"dob": "16.01.2023",
|
||||||
|
"decision": "E-locus = ee[f] (Fuchs). NOTE: this is the mother of animal 'C' (c-29042024) — un-quarantining her links C's second parent.",
|
||||||
|
"genotype": "Aa CC D- ee[f] Gg pp Spsp [DP]",
|
||||||
|
"source": "Julian 2026-06-06 — HUMANQUESTION D4"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,6 +211,11 @@ def extract_stammbaum(path):
|
|||||||
farbschlag = ""
|
farbschlag = ""
|
||||||
geno = geno0
|
geno = geno0
|
||||||
breeder = ""
|
breeder = ""
|
||||||
|
# BAND-AWARE (Julian-confirmed): early bands (gen 0-1, cols B/E/H) are 5-cell blocks
|
||||||
|
# WITH a Farbschlag cell; deep bands (gen >= 2, cols K/N/Q...) are 3-cell blocks
|
||||||
|
# (Name/DOB/Genotype) with NO Farbschlag — colour is derived from the genotype. So in
|
||||||
|
# deep bands we must NOT grab the next block's name or a stray health note as Farbschlag.
|
||||||
|
deep_band = gen_of(c) >= 2
|
||||||
for rr in range(r + 1, r + 4):
|
for rr in range(r + 1, r + 4):
|
||||||
cell = cells.get((c, rr))
|
cell = cells.get((c, rr))
|
||||||
if not cell:
|
if not cell:
|
||||||
@@ -221,7 +226,7 @@ def extract_stammbaum(path):
|
|||||||
elif re.search(r"\b(Zucht|Privatzucht)\b", cell) or cell.startswith("("):
|
elif re.search(r"\b(Zucht|Privatzucht)\b", cell) or cell.startswith("("):
|
||||||
breeder = cell
|
breeder = cell
|
||||||
used.add((c, rr))
|
used.add((c, rr))
|
||||||
elif not farbschlag and not re.match(r"^\*?\s?\d", cell) \
|
elif not deep_band and not farbschlag and not re.match(r"^\*?\s?\d", cell) \
|
||||||
and not looks_like_animal_name(cell):
|
and not looks_like_animal_name(cell):
|
||||||
farbschlag = cell
|
farbschlag = cell
|
||||||
used.add((c, rr))
|
used.add((c, rr))
|
||||||
@@ -497,6 +502,52 @@ def _geno_key(genodict):
|
|||||||
return "|".join(f"{locus}:{','.join(sorted(m[locus]))}" for locus in sorted(m))
|
return "|".join(f"{locus}:{','.join(sorted(m[locus]))}" for locus in sorted(m))
|
||||||
|
|
||||||
|
|
||||||
|
# --- "presence wins" merge rule (Julian) -------------------------------------
|
||||||
|
# When two source variants of the SAME animal differ ONLY by a token PRESENT in one and
|
||||||
|
# ABSENT in the other — a whole locus (e.g. spsp recorded in one chart, omitted in another)
|
||||||
|
# or a modifier on the same base allele (e^f vs e, i.e. the [f] marker) — keep the present
|
||||||
|
# token; that is NOT a conflict. A genuine VALUE contradiction (different filled alleles:
|
||||||
|
# E vs e, D vs d, c^h vs c^chm) OR unknown-vs-filled (D- vs DD, the '?' second allele) STILL
|
||||||
|
# quarantines for human decision. (Markers/flags WP/DP/WFNZ/hörend are already tags/flags,
|
||||||
|
# never part of the genotype, so they never reach here.)
|
||||||
|
def _split_allele(a):
|
||||||
|
return tuple(a.split("^", 1)) if "^" in a else (a, "")
|
||||||
|
|
||||||
|
|
||||||
|
def _alleles_compatible(a, b):
|
||||||
|
if a == b:
|
||||||
|
return True
|
||||||
|
if a == "?" or b == "?":
|
||||||
|
return False # unknown vs filled = contradiction (D- vs DD)
|
||||||
|
(ba, ma), (bb, mb) = _split_allele(a), _split_allele(b)
|
||||||
|
if ba != bb:
|
||||||
|
return False # different base allele = real value diff (E vs e)
|
||||||
|
return ma == "" or mb == "" # same base, modifier present-vs-absent -> presence wins
|
||||||
|
|
||||||
|
|
||||||
|
def _pair_compatible(p, q):
|
||||||
|
if len(p) != 2 or len(q) != 2:
|
||||||
|
return p == q
|
||||||
|
return ((_alleles_compatible(p[0], q[0]) and _alleles_compatible(p[1], q[1])) or
|
||||||
|
(_alleles_compatible(p[0], q[1]) and _alleles_compatible(p[1], q[0])))
|
||||||
|
|
||||||
|
|
||||||
|
def _genotype_conflict(mapped_list):
|
||||||
|
"""True only if two variants GENUINELY contradict at a shared locus. A locus present in
|
||||||
|
one variant and absent in another is fine (presence wins); so is a modifier present-vs-
|
||||||
|
absent on the same base allele. Replaces the old `len(distinct geno keys) > 1` test."""
|
||||||
|
loci = set()
|
||||||
|
for m in mapped_list:
|
||||||
|
loci.update(m.keys())
|
||||||
|
for locus in loci:
|
||||||
|
pairs = [m[locus] for m in mapped_list if locus in m]
|
||||||
|
for i in range(len(pairs)):
|
||||||
|
for j in range(i + 1, len(pairs)):
|
||||||
|
if not _pair_compatible(pairs[i], pairs[j]):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def dedup(animals):
|
def dedup(animals):
|
||||||
"""Merge by normalise(call-name)+DOB, with the canonical Zucht as
|
"""Merge by normalise(call-name)+DOB, with the canonical Zucht as
|
||||||
DISCRIMINATOR (Julian: same name+DOB+Zucht = same animal; different Zucht =
|
DISCRIMINATOR (Julian: same name+DOB+Zucht = same animal; different Zucht =
|
||||||
@@ -547,6 +598,7 @@ def dedup(animals):
|
|||||||
parent_refs = list(base["parentRefs"])
|
parent_refs = list(base["parentRefs"])
|
||||||
genos = set()
|
genos = set()
|
||||||
geno_keys = set() # GEN-3b: conflict on NORMALIZED genotype (Uw==G) not raw text
|
geno_keys = set() # GEN-3b: conflict on NORMALIZED genotype (Uw==G) not raw text
|
||||||
|
mapped_variants = [] # mapped8locus per variant — for the 'presence wins' conflict test
|
||||||
farb = set()
|
farb = set()
|
||||||
deaths = set()
|
deaths = set()
|
||||||
deaf_seen = set()
|
deaf_seen = set()
|
||||||
@@ -562,6 +614,7 @@ def dedup(animals):
|
|||||||
if a["genotype"]["mapped8locus"]:
|
if a["genotype"]["mapped8locus"]:
|
||||||
genos.add(a["genotype"]["rawGenotype"])
|
genos.add(a["genotype"]["rawGenotype"])
|
||||||
geno_keys.add(_geno_key(a["genotype"]))
|
geno_keys.add(_geno_key(a["genotype"]))
|
||||||
|
mapped_variants.append(a["genotype"]["mapped8locus"])
|
||||||
if a["farbschlag"]:
|
if a["farbschlag"]:
|
||||||
farb.add(a["farbschlag"])
|
farb.add(a["farbschlag"])
|
||||||
if a["death"]:
|
if a["death"]:
|
||||||
@@ -598,8 +651,9 @@ def dedup(animals):
|
|||||||
"conflict": False,
|
"conflict": False,
|
||||||
}
|
}
|
||||||
merged.append(out)
|
merged.append(out)
|
||||||
# conflict: same animal, disagreeing NORMALIZED genotype (Uw==G) or farbschlag or death
|
# conflict: same animal, GENUINELY disagreeing genotype (presence-vs-absence is NOT a
|
||||||
if len(geno_keys) > 1 or len(farb) > 1 or len(deaths) > 1:
|
# conflict — Julian's 'presence wins') or >1 distinct farbschlag or >1 distinct death.
|
||||||
|
if _genotype_conflict(mapped_variants) or len(farb) > 1 or len(deaths) > 1:
|
||||||
out["conflict"] = True
|
out["conflict"] = True
|
||||||
conflicts.append({
|
conflicts.append({
|
||||||
"id": out["id"], "name": base["name"], "dob": out["dob"],
|
"id": out["id"], "name": base["name"], "dob": out["dob"],
|
||||||
@@ -829,6 +883,68 @@ def write_report(merged, conflicts, orphans, raw_count, litters, photo_count,
|
|||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------ main
|
# ------------------------------------------------------------------------ main
|
||||||
|
def apply_dob_remaps(raw_animals, path):
|
||||||
|
"""PRE-dedup: a conflict-decision carrying `correctDob` marks a record as a DUPLICATE with a
|
||||||
|
wrong birthdate — remap that raw record's DOB to correctDob so dedup MERGES it into the
|
||||||
|
canonical same-named animal (e.g. Chelsea *15.10.2021 -> *02.04.2021). Match =
|
||||||
|
norm_name(name)+norm_dob(dob). Tolerates a missing/garbled file. Returns the remap count.
|
||||||
|
Must run BEFORE dedup (it changes the dedup identity). (god/HUMANQUESTION D — Dubletten.)"""
|
||||||
|
remaps = {}
|
||||||
|
try:
|
||||||
|
with open(path, encoding="utf-8") as fh:
|
||||||
|
for r in (json.load(fh).get("resolutions") or []):
|
||||||
|
if r.get("correctDob"):
|
||||||
|
remaps[(norm_name(r.get("name", "")), norm_dob(r.get("dob", "")))] = r["correctDob"]
|
||||||
|
except (OSError, ValueError):
|
||||||
|
return 0
|
||||||
|
if not remaps:
|
||||||
|
return 0
|
||||||
|
n = 0
|
||||||
|
for a in raw_animals:
|
||||||
|
new = remaps.get((norm_name(a.get("name", "")), norm_dob(a.get("dob", ""))))
|
||||||
|
if new and a.get("dob") != new:
|
||||||
|
a["dob"] = new
|
||||||
|
n += 1
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
def apply_conflict_decisions(merged, conflicts, path):
|
||||||
|
"""Consume human conflict resolutions (tools/import/conflict-decisions.json) so the wife's
|
||||||
|
answers UN-QUARANTINE animals. Schema: {"resolutions":[{name, dob, decision, genotype?,
|
||||||
|
farbschlag?, source}]}. Match = norm_name(name)+norm_dob(dob) (same identity as dedup). A
|
||||||
|
matching animal: clear its conflict, mark resolvedByDecision; an explicit `genotype`
|
||||||
|
(breeder notation) is parsed and becomes authoritative, `farbschlag` overrides too. Tolerates
|
||||||
|
a missing/empty/garbled file. Returns the number of conflicts resolved. (god/HUMANQUESTION D.)"""
|
||||||
|
decisions = {}
|
||||||
|
try:
|
||||||
|
with open(path, encoding="utf-8") as fh:
|
||||||
|
for r in (json.load(fh).get("resolutions") or []):
|
||||||
|
decisions[(norm_name(r.get("name", "")), norm_dob(r.get("dob", "")))] = r
|
||||||
|
except (OSError, ValueError):
|
||||||
|
return 0
|
||||||
|
if not decisions:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
resolved = 0
|
||||||
|
for a in merged:
|
||||||
|
d = decisions.get((norm_name(a["name"]), norm_dob(a["dob"])))
|
||||||
|
if not d:
|
||||||
|
continue
|
||||||
|
a["resolvedByDecision"] = True
|
||||||
|
if d.get("genotype"):
|
||||||
|
a["genotype"] = gt.parse(d["genotype"])
|
||||||
|
if d.get("farbschlag"):
|
||||||
|
a["farbschlag"] = d["farbschlag"]
|
||||||
|
a["farbschlagVariants"] = [d["farbschlag"]]
|
||||||
|
if d.get("dateOfDeath"): # D5 death-date resolutions
|
||||||
|
a["death"] = norm_dob(d["dateOfDeath"])
|
||||||
|
if a.get("conflict"):
|
||||||
|
a["conflict"] = False
|
||||||
|
conflicts[:] = [c for c in conflicts if c.get("id") != a["id"]]
|
||||||
|
resolved += 1
|
||||||
|
return resolved
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||||||
@@ -862,7 +978,10 @@ def main():
|
|||||||
litters = extract_wurfchronik(args.wurfchronik)
|
litters = extract_wurfchronik(args.wurfchronik)
|
||||||
print(f"Wurfchronik: {len(litters)} Würfe")
|
print(f"Wurfchronik: {len(litters)} Würfe")
|
||||||
|
|
||||||
|
decisions_path = os.path.join(HERE, "conflict-decisions.json")
|
||||||
|
dob_remaps = apply_dob_remaps(raw_animals, decisions_path) # before dedup (changes identity)
|
||||||
merged, conflicts, orphans, zucht_splits = dedup(raw_animals)
|
merged, conflicts, orphans, zucht_splits = dedup(raw_animals)
|
||||||
|
resolved_by_decision = apply_conflict_decisions(merged, conflicts, decisions_path)
|
||||||
match_stats = match_litters(merged, litters)
|
match_stats = match_litters(merged, litters)
|
||||||
photo_count = sum(len(a["photos"]) for a in merged)
|
photo_count = sum(len(a["photos"]) for a in merged)
|
||||||
|
|
||||||
@@ -879,7 +998,8 @@ def main():
|
|||||||
zucht_splits, match_stats)
|
zucht_splits, match_stats)
|
||||||
|
|
||||||
print(f"\nRoh: {len(raw_animals)} → eindeutig: {len(merged)} "
|
print(f"\nRoh: {len(raw_animals)} → eindeutig: {len(merged)} "
|
||||||
f"| Konflikte: {len(conflicts)} | Zucht-Splits: {len(zucht_splits)} "
|
f"| Konflikte: {len(conflicts)} | per Entscheidung gelöst: {resolved_by_decision} "
|
||||||
|
f"| DOB-Remaps: {dob_remaps} | Zucht-Splits: {len(zucht_splits)} "
|
||||||
f"| Orphans: {len(orphans)} | Fotos: {photo_count}")
|
f"| Orphans: {len(orphans)} | Fotos: {photo_count}")
|
||||||
print(f"Wurf-Verknüpfung: {match_stats['parents']} (Datum+Eltern), "
|
print(f"Wurf-Verknüpfung: {match_stats['parents']} (Datum+Eltern), "
|
||||||
f"{match_stats['dateOnly']} (nur Datum), {match_stats['ambiguous']} mehrdeutig "
|
f"{match_stats['dateOnly']} (nur Datum), {match_stats['ambiguous']} mehrdeutig "
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ _Automatisch erzeugt von `tools/import/extract.py` — **noch nichts in die Date
|
|||||||
## Überblick
|
## Überblick
|
||||||
|
|
||||||
- Rohe Tier-Einträge aus den Stammbäumen: **950**
|
- Rohe Tier-Einträge aus den Stammbäumen: **950**
|
||||||
- Nach Zusammenführung (eindeutige Tiere): **622**
|
- Nach Zusammenführung (eindeutige Tiere): **621**
|
||||||
- davon mit Geburtsdatum: 327
|
- davon mit Geburtsdatum: 326
|
||||||
- in mehreren Dateien gefunden (Dubletten zusammengeführt): 158
|
- in mehreren Dateien gefunden (Dubletten zusammengeführt): 158
|
||||||
- Konflikte zur Klärung: **21**
|
- Konflikte zur Klärung: **9**
|
||||||
- Mehrdeutige / unvollständige Einträge (ohne Name+Datum): **310**
|
- Mehrdeutige / unvollständige Einträge (ohne Name+Datum): **310**
|
||||||
- Fotos zugeordnet: **137**
|
- Fotos zugeordnet: **137**
|
||||||
- Würfe aus der Wurfchronik: **752**
|
- Würfe aus der Wurfchronik: **752**
|
||||||
@@ -26,22 +26,10 @@ Gleiches Tier (Name+Datum), aber widersprüchliche Angaben in verschiedenen Date
|
|||||||
| Tier | Geburtsdatum | abweichende Genotypen | abweichende Farbschläge | Sterbedaten | Dateien |
|
| Tier | Geburtsdatum | abweichende Genotypen | abweichende Farbschläge | Sterbedaten | Dateien |
|
||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| Ella | 10.06.2019 | Aa C D- ee[f] GG P- spsp // Aa Cc[chm] D- ee[f] UwUw P- spsp | Algierfuchsschimmel, hell | 03.02.2023 | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Valentino Firehearts Kids |
|
| Ella | 10.06.2019 | Aa C D- ee[f] GG P- spsp // Aa Cc[chm] D- ee[f] UwUw P- spsp | Algierfuchsschimmel, hell | 03.02.2023 | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Valentino Firehearts Kids |
|
||||||
| Louis von den Kleinen Chaoten | 15.07.2017 | Aa Cc[] D- Ee Gg P- spsp // Aa Cc[chm] D- Ee Uwuw[d] P- spsp | — | 01.07.2020 | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity |
|
|
||||||
| Firefly von den Kleinen Chaoten | 18.12.2019 | /+, Aa c[chm]c[chm] D- Ee Gg PP Spsp // Aa c[chm]c[chm] DD Ee Gg PP Spsp | — | 2024 | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Fire Kids, Stammbaum von Valentino Firehearts Kids |
|
|
||||||
| Zuleika von den Kleinen Chaoten | 24.10.2015 | aa c[chm]c[h] D- E G P- spsp // aa c[chm]c[h] D- Ee Gg P- spsp // aa c[chm]c[h] DD Ee Gg P- spsp | — | 24.02.2019 | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Valentino Firehearts Kids |
|
|
||||||
| WildFire von den Kleinen Chaoten | 05.10.2017 | aa c[chm]c[chm] D- Ee gg P- spsp // aa c[chm]c[chm] D- Ee gg PP spsp | — | — | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Fire Kids, Stammbaum von Valentino Firehearts Kids |
|
|
||||||
| Vestra von den Schlossmäusen | 08.02.2019 | Aa Cc[chm] D- EE GG PP Spsp [WP] // Aa Cc[chm] DD EE GG PP Spsp [WP] | — | 26.05.2023 | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Fire Kids, Stammbaum von Valentino Firehearts Kids |
|
|
||||||
| Flint von den Kleinen Chaoten | 23.12.2017 | aa Cc[chm] D- ee Gg P- spsp | — | 10.05.2021 // 10.05.2022 | Stammbaum von Akio Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity |
|
|
||||||
| Kazu von den Kleinen Chaoten | 23.04.2013 | Aa Cc[chm] DD e[f]e[f] Gg P Spsp // Aa Cc[chm] DD ee[f] UwUw PP Spsp | — | 03.09.2017 | Stammbaum von Akio Kids, Stammbaum von Vance |
|
| Kazu von den Kleinen Chaoten | 23.04.2013 | Aa Cc[chm] DD e[f]e[f] Gg P Spsp // Aa Cc[chm] DD ee[f] UwUw PP Spsp | — | 03.09.2017 | Stammbaum von Akio Kids, Stammbaum von Vance |
|
||||||
| Milka of LennyLengo | 09.12.2018 | aa C- dd E- Gg P- Spsp // aa Cc[h] dd EE Gg P- Spsp | — | 22.12.2021 | Stammbaum von Alberto Kids, Stammbaum von Stella Kids |
|
|
||||||
| Silvain von den Kleinen Chaoten | 27.03.2022 | aa c[chm]c[chm] Dd Ee[-] Gg P- Spsp // aa c[chm]c[chm] Dd ee[-] Gg Pp Spsp | — | 31.12.2024 | Stammbaum von Alberto Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity |
|
|
||||||
| Enya von den Kleinen Chaoten | 01.11.2017 | Aa c[chm]c[chm] D- ee[-] G- P- spsp // Aa c[chm]c[chm] D- ee[-] Uwuw[d] P- spsp | — | — | Stammbaum von Alberto Kids, Stammbaum von Fire Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Stella Kids |
|
| Enya von den Kleinen Chaoten | 01.11.2017 | Aa c[chm]c[chm] D- ee[-] G- P- spsp // Aa c[chm]c[chm] D- ee[-] Uwuw[d] P- spsp | — | — | Stammbaum von Alberto Kids, Stammbaum von Fire Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Stella Kids |
|
||||||
| Little Hero of Black Forest | 22.02.2018 | AA CC DD EE GG PP [WFNZ] // AA CC DD EE GG PP spsp [WFNZ] | — | 18.06.2021 | Stammbaum von Alberto Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Fire Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Stella Kids, Stammbaum von Valentino Firehearts Kids |
|
|
||||||
| Molly of Black Forest | 13.09.2021 | /+, Aa Cc[chm] D- Ee gg P- spsp // Aa Cc[chm] Dd Ee gg Pp spsp | — | 03.05.2021 | Stammbaum von Alberto Kids, Stammbaum von CP-Fuchs, CP-Sa Sp von Unity |
|
|
||||||
| Little Runner's Big Ben | 03.02.2020 | Aa Cc[chm] DD Ee Gg PP Spsp // Aa Cc[chm] DD Ee Gg Pp Spsp | — | 14.10.2023 | Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Fire Kids, Stammbaum von Goldfuchs Sp (Pikachu) Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Valentino Firehearts Kids, Stammbaum von Watarus Kids |
|
| Little Runner's Big Ben | 03.02.2020 | Aa Cc[chm] DD Ee Gg PP Spsp // Aa Cc[chm] DD Ee Gg Pp Spsp | — | 14.10.2023 | Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Fire Kids, Stammbaum von Goldfuchs Sp (Pikachu) Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Valentino Firehearts Kids, Stammbaum von Watarus Kids |
|
||||||
| Daja of Little Rose | 16.05.2021 | aa chmchm D- EE Gg P- // aa chmchm D- EE Gg P- spsp | — | — | Stammbaum von CP-Fuchs, CP-Sa Sp von Unity, Stammbaum von Fire Kids, Stammbaum von Valentino Firehearts Kids |
|
|
||||||
| Vance Jr. von den Kleinen Chaoten | 10.04.2022 | aa Cc[hm] Dd Ee gg P- Spsp // aa Cc[hm] Dd Ee gg P- spsp | Kohlfuchs, hell | — | Stammbaum von Fire Kids, Stammbaum von Stella Kids |
|
| Vance Jr. von den Kleinen Chaoten | 10.04.2022 | aa Cc[hm] Dd Ee gg P- Spsp // aa Cc[hm] Dd Ee gg P- spsp | Kohlfuchs, hell | — | Stammbaum von Fire Kids, Stammbaum von Stella Kids |
|
||||||
| Ichika von den Kleinen Chaoten | 19.04.2020 | aa CC D- ee Gg pp spsp // aa CC D- ee[f] Gg pp spsp | — | 27.11.2023 | Stammbaum von Goldfuchs Sp (Pikachu) Kids, Stammbaum von Watarus Kids |
|
|
||||||
| Victoria Welby gen. Welby v.d. Kleinen Chaoten | 16.01.2023 | Aa CC D- Ee[f] Gg pp Spsp [DP] // Aa CC D- ee[f] Gg pp Spsp [DP] | Goldfuchsschimmel Punktschecke DP | 17.02.2026 | Stammbaum von Goldfuchs Sp (Pikachu) Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Watarus Kids |
|
| Victoria Welby gen. Welby v.d. Kleinen Chaoten | 16.01.2023 | Aa CC D- Ee[f] Gg pp Spsp [DP] // Aa CC D- ee[f] Gg pp Spsp [DP] | Goldfuchsschimmel Punktschecke DP | 17.02.2026 | Stammbaum von Goldfuchs Sp (Pikachu) Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Watarus Kids |
|
||||||
| Zac gen. Action von den Kleinen Chaoten | 25.12.2020 | aa C- D- Ee G- Pp Spsp [DP] // aa CC D- Ee G- Pp Spsp [DP] | — | 31.01.2025 | Stammbaum von Goldfuchs Sp (Pikachu) Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Watarus Kids |
|
| Zac gen. Action von den Kleinen Chaoten | 25.12.2020 | aa C- D- Ee G- Pp Spsp [DP] // aa CC D- Ee G- Pp Spsp [DP] | — | 31.01.2025 | Stammbaum von Goldfuchs Sp (Pikachu) Kids, Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Watarus Kids |
|
||||||
| Hanami von den Kleinen Chaoten | 10.09.2015 | aa Cc[chm] D- Ee gg P- spsp | — | 12.12.2019 // 14.01.2020 | Stammbaum von Kentucky, Stammbaum von Stella Kids |
|
| Hanami von den Kleinen Chaoten | 10.09.2015 | aa Cc[chm] D- Ee gg P- spsp | — | 12.12.2019 // 14.01.2020 | Stammbaum von Kentucky, Stammbaum von Stella Kids |
|
||||||
@@ -103,7 +91,7 @@ Gleiches Tier (Name+Datum), aber widersprüchliche Angaben in verschiedenen Date
|
|||||||
- „Hagrid Rubeus of Black Forest“ → Hagrid Rubeus of Black Forest (*18.07.2019)
|
- „Hagrid Rubeus of Black Forest“ → Hagrid Rubeus of Black Forest (*18.07.2019)
|
||||||
- „Charly of Golden Lights“ → Charly of Golden Lights (*05.04.2016)
|
- „Charly of Golden Lights“ → Charly of Golden Lights (*05.04.2016)
|
||||||
- „Ziwa of Golden Lights“ → Ziwa of Golden Lights (*29.04.2016)
|
- „Ziwa of Golden Lights“ → Ziwa of Golden Lights (*29.04.2016)
|
||||||
- „Chelsea von den Kleinen Chaoten“ → Chelsea von den Kleinen Chaoten (*02.04.2021); Chelsea von den Kleinen Chaoten (*15.10.2021)
|
- „Chelsea von den Kleinen Chaoten“ → Chelsea von den Kleinen Chaoten (*02.04.2021)
|
||||||
- „Pinto of Fiomi“ → Pinto of Fiomi (*28.08.2016)
|
- „Pinto of Fiomi“ → Pinto of Fiomi (*28.08.2016)
|
||||||
- „Living Force's Idefix“ → Living Force's Idefix (*05.04.2016)
|
- „Living Force's Idefix“ → Living Force's Idefix (*05.04.2016)
|
||||||
- „Scarlett of Samsimar“ → Scarlett of Samsimar (*05.09.2018)
|
- „Scarlett of Samsimar“ → Scarlett of Samsimar (*05.09.2018)
|
||||||
@@ -142,15 +130,15 @@ Diese Tokens stehen weiter in `rawGenotype`/`unmappedTokens` — Entscheidung (M
|
|||||||
|
|
||||||
| Token | Vorkommen | Bedeutung (Vermutung) |
|
| Token | Vorkommen | Bedeutung (Vermutung) |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `/+` | 8 | ? |
|
| `/+` | 7 | ? |
|
||||||
| `-g` | 2 | ? |
|
| `-g` | 2 | ? |
|
||||||
| `C(C)` | 2 | Schreibweise (C trägt c) |
|
| `C(C)` | 2 | Schreibweise (C trägt c) |
|
||||||
| `chmchm` | 2 | Schreibweise (c[chm]c[chm]) |
|
|
||||||
| `Cc[]` | 1 | ? |
|
| `Cc[]` | 1 | ? |
|
||||||
| `-psp` | 1 | ? |
|
| `-psp` | 1 | ? |
|
||||||
| `G(G)` | 1 | ? |
|
| `G(G)` | 1 | ? |
|
||||||
| `/` | 1 | ? |
|
| `/` | 1 | ? |
|
||||||
| `+2018` | 1 | ? |
|
| `+2018` | 1 | ? |
|
||||||
|
| `chmchm` | 1 | Schreibweise (c[chm]c[chm]) |
|
||||||
| `c[chm]chm]` | 1 | ? |
|
| `c[chm]chm]` | 1 | ? |
|
||||||
| `Dea/dea]` | 1 | ? |
|
| `Dea/dea]` | 1 | ? |
|
||||||
| `DD-Tumor` | 1 | ? |
|
| `DD-Tumor` | 1 | ? |
|
||||||
|
|||||||
157
tools/import/test_extract.py
Normal file
157
tools/import/test_extract.py
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
"""Zero-dep tests for extract.py band-aware Farbschlag + name-bleed guard.
|
||||||
|
|
||||||
|
Run: python test_extract.py (exit 0 = all pass)
|
||||||
|
Covers (PEDIGREE-LINK / Julian-confirmed): deep pedigree bands (gen >= 2, cols K/N/Q...)
|
||||||
|
are Name/DOB/Genotype ONLY — no Farbschlag cell — so a stray health note or the next
|
||||||
|
block's name must NOT be captured as Farbschlag; early bands (gen 0-1) keep their real
|
||||||
|
Farbschlag. Plus the looks_like_animal_name guard (a parent name must not be a Farbschlag).
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
|
import tempfile
|
||||||
|
import extract as e
|
||||||
|
|
||||||
|
failed = 0
|
||||||
|
|
||||||
|
|
||||||
|
def check(name, cond):
|
||||||
|
global failed
|
||||||
|
print(("ok: " if cond else "FAIL: ") + name)
|
||||||
|
if not cond:
|
||||||
|
failed += 1
|
||||||
|
|
||||||
|
|
||||||
|
def _cell(ref, text):
|
||||||
|
return f'<c r="{ref}" t="inlineStr"><is><t>{text}</t></is></c>'
|
||||||
|
|
||||||
|
|
||||||
|
def _make_xlsx(path, cells):
|
||||||
|
"""cells: {(colLetter+row): text}. Build a minimal single-sheet xlsx (no styles)."""
|
||||||
|
rows = {}
|
||||||
|
for ref, text in cells.items():
|
||||||
|
r = int("".join(ch for ch in ref if ch.isdigit()))
|
||||||
|
rows.setdefault(r, []).append(_cell(ref, text))
|
||||||
|
body = "".join(f'<row r="{r}">{"".join(cs)}</row>' for r, cs in sorted(rows.items()))
|
||||||
|
sheet = ('<?xml version="1.0"?><worksheet xmlns="http://x"><sheetData>'
|
||||||
|
+ body + "</sheetData></worksheet>")
|
||||||
|
with zipfile.ZipFile(path, "w") as z:
|
||||||
|
z.writestr("xl/worksheets/sheet1.xml", sheet)
|
||||||
|
|
||||||
|
|
||||||
|
# --- band-aware Farbschlag ---
|
||||||
|
# col E = gen 0 (early, HAS Farbschlag); col K = col 11 = gen 2 (deep, NO Farbschlag).
|
||||||
|
tmp = os.path.join(tempfile.gettempdir(), "bandtest.xlsx")
|
||||||
|
_make_xlsx(tmp, {
|
||||||
|
# early band (E): Name / *DOB / Farbschlag / Genotype
|
||||||
|
"E10": "Chesnut",
|
||||||
|
"E11": "*13.11.2019",
|
||||||
|
"E12": "Kohlfuchsschimmel",
|
||||||
|
"E13": "aa CC DD ee GG PP spsp rere",
|
||||||
|
# deep band (K): Name / *DOB / Genotype / stray NOTE (must NOT become Farbschlag)
|
||||||
|
"K10": "DeepAnimal",
|
||||||
|
"K11": "*01.01.2020",
|
||||||
|
"K12": "aa CC DD EE GG PP spsp rere",
|
||||||
|
"K13": "DD-Tumor",
|
||||||
|
})
|
||||||
|
try:
|
||||||
|
animals = e.extract_stammbaum(tmp)
|
||||||
|
by_name = {a["name"]: a for a in animals}
|
||||||
|
check("early band keeps real Farbschlag",
|
||||||
|
by_name.get("Chesnut", {}).get("farbschlag") == "Kohlfuchsschimmel")
|
||||||
|
check("deep band has NO Farbschlag (note not grabbed)",
|
||||||
|
by_name.get("DeepAnimal", {}).get("farbschlag") == "")
|
||||||
|
check("deep-band animal still parsed (Name/DOB/Genotype)",
|
||||||
|
"DeepAnimal" in by_name and by_name["DeepAnimal"]["dob"].startswith("01.01"))
|
||||||
|
finally:
|
||||||
|
try: os.remove(tmp)
|
||||||
|
except OSError: pass
|
||||||
|
|
||||||
|
gen = e.gen_of
|
||||||
|
check("gen_of: early bands < 2 (E,H)", gen(5) < 2 and gen(8) < 2)
|
||||||
|
check("gen_of: deep bands >= 2 (K,N,Q)", gen(11) >= 2 and gen(14) >= 2)
|
||||||
|
|
||||||
|
# --- conflict-decisions consumption (HUMANQUESTION D / C6) ---
|
||||||
|
dec_path = os.path.join(tempfile.gettempdir(), "conflict-decisions-test.json")
|
||||||
|
import json as _json
|
||||||
|
_json.dump({"resolutions": [
|
||||||
|
{"name": "Firefly von den Kleinen Chaoten", "dob": "18.12.2019",
|
||||||
|
"decision": "D-locus = D-", "genotype": "Aa c[chm]c[chm] D- Ee Gg PP Spsp",
|
||||||
|
"source": "test"},
|
||||||
|
{"name": "Flint von den Kleinen Chaoten", "dob": "23.12.2017",
|
||||||
|
"decision": "Todesdatum 10.05.2021 (2022 war Tippfehler)", "dateOfDeath": "10.05.2021",
|
||||||
|
"source": "test"},
|
||||||
|
]}, open(dec_path, "w", encoding="utf-8"))
|
||||||
|
merged = [
|
||||||
|
{"id": "x1", "name": "Firefly von den Kleinen Chaoten", "dob": "18.12.2019",
|
||||||
|
"conflict": True, "farbschlag": "", "death": "",
|
||||||
|
"genotype": {"mapped8locus": {"D": ["D", "D"]}, "rawGenotype": "DD", "unmappedTokens": []}},
|
||||||
|
{"id": "x2", "name": "Flint von den Kleinen Chaoten", "dob": "23.12.2017",
|
||||||
|
"conflict": True, "farbschlag": "", "death": "10.05.2022",
|
||||||
|
"genotype": {"mapped8locus": {}, "rawGenotype": "", "unmappedTokens": []}},
|
||||||
|
]
|
||||||
|
conflicts = [{"id": "x1", "name": "Firefly von den Kleinen Chaoten", "dob": "18.12.2019"},
|
||||||
|
{"id": "x2", "name": "Flint von den Kleinen Chaoten", "dob": "23.12.2017"}]
|
||||||
|
n = e.apply_conflict_decisions(merged, conflicts, dec_path)
|
||||||
|
check("decision un-quarantines (conflict cleared)", merged[0]["conflict"] is False)
|
||||||
|
check("decision marks resolvedByDecision", merged[0].get("resolvedByDecision") is True)
|
||||||
|
check("decision genotype is authoritative (D- not DD)", merged[0]["genotype"]["mapped8locus"]["D"] == ["D", "?"])
|
||||||
|
check("decision dateOfDeath is authoritative (D5)", merged[1]["death"] == "10.05.2021")
|
||||||
|
check("decision removes both entries from conflicts list", conflicts == [])
|
||||||
|
check("apply_conflict_decisions returns resolved count", n == 2)
|
||||||
|
check("missing decisions file tolerated (returns 0)",
|
||||||
|
e.apply_conflict_decisions([], [], os.path.join(tempfile.gettempdir(), "does-not-exist.json")) == 0)
|
||||||
|
|
||||||
|
# --- correctDob: a wrong-birthdate duplicate is remapped BEFORE dedup so it merges ---
|
||||||
|
dec2 = os.path.join(tempfile.gettempdir(), "decisions-dob.json")
|
||||||
|
_json.dump({"resolutions": [
|
||||||
|
{"name": "Chelsea von den Kleinen Chaoten", "dob": "15.10.2021",
|
||||||
|
"decision": "duplicate wrong birthdate", "correctDob": "02.04.2021", "source": "test"},
|
||||||
|
]}, open(dec2, "w", encoding="utf-8"))
|
||||||
|
raw = [
|
||||||
|
{"name": "Chelsea von den Kleinen Chaoten", "dob": "15.10.2021"}, # the wrong-dob duplicate
|
||||||
|
{"name": "Chelsea von den Kleinen Chaoten", "dob": "02.04.2021"}, # canonical
|
||||||
|
{"name": "Other Animal", "dob": "01.01.2020"},
|
||||||
|
]
|
||||||
|
rn = e.apply_dob_remaps(raw, dec2)
|
||||||
|
check("correctDob remaps the wrong-dob record", raw[0]["dob"] == "02.04.2021")
|
||||||
|
check("correctDob leaves the canonical record alone", raw[1]["dob"] == "02.04.2021")
|
||||||
|
check("correctDob leaves unrelated records alone", raw[2]["dob"] == "01.01.2020")
|
||||||
|
check("apply_dob_remaps returns remap count", rn == 1)
|
||||||
|
check("after remap both Chelsea share one dedup identity (name+dob)",
|
||||||
|
e.norm_dob(raw[0]["dob"]) == e.norm_dob(raw[1]["dob"]))
|
||||||
|
check("missing decisions file tolerated for dob remaps (returns 0)",
|
||||||
|
e.apply_dob_remaps([], os.path.join(tempfile.gettempdir(), "nope.json")) == 0)
|
||||||
|
try: os.remove(dec2)
|
||||||
|
except OSError: pass
|
||||||
|
|
||||||
|
try: os.remove(dec_path)
|
||||||
|
except OSError: pass
|
||||||
|
|
||||||
|
# --- "presence wins" conflict rule (Julian) ---
|
||||||
|
# present-vs-absent (whole locus or [f] modifier) is NOT a conflict; differing filled values are.
|
||||||
|
check("spsp present vs locus absent -> no conflict",
|
||||||
|
not e._genotype_conflict([{"Sp": ["sp", "sp"]}, {}]))
|
||||||
|
check("ee[f] vs ee ([f] modifier present/absent) -> no conflict",
|
||||||
|
not e._genotype_conflict([{"E": ["e", "e^f"]}, {"E": ["e", "e"]}]))
|
||||||
|
check("DD vs D- (unknown vs filled) -> conflict",
|
||||||
|
e._genotype_conflict([{"D": ["D", "D"]}, {"D": ["D", "?"]}]))
|
||||||
|
check("Ee vs ee (different base allele) -> conflict",
|
||||||
|
e._genotype_conflict([{"E": ["E", "e"]}, {"E": ["e", "e"]}]))
|
||||||
|
check("C- vs Cc[h] -> conflict",
|
||||||
|
e._genotype_conflict([{"C": ["C", "?"]}, {"C": ["C", "c^h"]}]))
|
||||||
|
check("c[h] vs c[chm] (different modifiers) -> conflict",
|
||||||
|
not e._alleles_compatible("c^h", "c^chm"))
|
||||||
|
check("identical genotypes -> no conflict",
|
||||||
|
not e._genotype_conflict([{"A": ["A", "a"]}, {"A": ["A", "a"]}]))
|
||||||
|
|
||||||
|
# --- name-bleed guard (a parent name is not a Farbschlag) ---
|
||||||
|
check("v.d. name rejected", e.looks_like_animal_name("Tennessee von den Kleinen Chaoten"))
|
||||||
|
check("gen.+v.d. name rejected", e.looks_like_animal_name("Victoria Welby gen. Welby v.d. Kleinen Chaoten"))
|
||||||
|
check("real Farbschlag accepted", not e.looks_like_animal_name("Kohlfuchsschimmel"))
|
||||||
|
check("real Farbschlag accepted 2", not e.looks_like_animal_name("Orangeschimmel, hell"))
|
||||||
|
|
||||||
|
if failed:
|
||||||
|
print(f"\n{failed} test(s) FAILED")
|
||||||
|
sys.exit(1)
|
||||||
|
print("\nALL PASS")
|
||||||
Reference in New Issue
Block a user