diff --git a/GerbilManager.Tests/ExportTests.cs b/GerbilManager.Tests/ExportTests.cs index 3e56061..be1cf46 100644 --- a/GerbilManager.Tests/ExportTests.cs +++ b/GerbilManager.Tests/ExportTests.cs @@ -104,7 +104,7 @@ namespace GerbilManager.Tests Assert.Equal(1, root.GetProperty("gerbils").GetArrayLength()); Assert.Equal(1, root.GetProperty("litters").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]; 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()); diff --git a/GerbilManager.Tests/ImportServiceTests.cs b/GerbilManager.Tests/ImportServiceTests.cs index 4dd10b3..16f1bda 100644 --- a/GerbilManager.Tests/ImportServiceTests.cs +++ b/GerbilManager.Tests/ImportServiceTests.cs @@ -278,6 +278,33 @@ namespace GerbilManager.Tests 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] public void ComposeGenotype_strips_carets_and_fills_missing_loci() { diff --git a/GerbilManagerWebAPI/ApplicationContext.cs b/GerbilManagerWebAPI/ApplicationContext.cs index 673d67f..1db676b 100644 --- a/GerbilManagerWebAPI/ApplicationContext.cs +++ b/GerbilManagerWebAPI/ApplicationContext.cs @@ -256,8 +256,6 @@ public class ApplicationContext : DbContext ("C-Separator", "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"), - ("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"), ("Saphir", "aa CC DD EE 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"), ("Kohlfuchs 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"), ("Polarfuchsschimmel", "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"), ("Blaufuchsschimmel", "aa CC DD efef gg PP spsp rere"), ("Kohlfuchs, 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"), ("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"), ("Rotfuchsschimmel", "aa CC DD efef GG pp spsp rere"), ("Polarfuchs, hell", "AA CC DD ee gg PP spsp rere"), ("Kohlfuchsschimmel, hell", "aa CC DD efef 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 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"), ("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"), + ("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"), }; diff --git a/GerbilManagerWebAPI/Import/ImportModels.cs b/GerbilManagerWebAPI/Import/ImportModels.cs index 79019f7..51a76cf 100644 --- a/GerbilManagerWebAPI/Import/ImportModels.cs +++ b/GerbilManagerWebAPI/Import/ImportModels.cs @@ -27,6 +27,10 @@ namespace GerbilManagerWebAPI.Import // provenance/breeding tags (WFNZ/RV/GV/DP) — neither is genotype. public bool? Deaf { get; set; } public List 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 @@ -92,7 +96,8 @@ namespace GerbilManagerWebAPI.Import int FarbschlagUnmatched, int AlreadyImported, QuarantineSummary Quarantined, - int ParentLinksFromChart = 0); + int ParentLinksFromChart = 0, + int ConflictsResolvedByDecision = 0); public sealed record QuarantineSummary( int Conflicts, diff --git a/GerbilManagerWebAPI/Import/ImportService.cs b/GerbilManagerWebAPI/Import/ImportService.cs index 0971fe0..f664126 100644 --- a/GerbilManagerWebAPI/Import/ImportService.cs +++ b/GerbilManagerWebAPI/Import/ImportService.cs @@ -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($"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)."); + 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."); return new ImportReport( @@ -412,7 +415,7 @@ namespace GerbilManagerWebAPI.Import Animals: new AnimalSummary( animals.Count, animalsCreated, linked, fbMatched, fbUnmatched, animalsExisting, new QuarantineSummary(conflicts, stubs, dateOnly, ambiguous, conflicts + stubs), - parentLinksAdded), + parentLinksAdded, conflictsResolvedByDecision), Photos: new PhotoSummary(photosAttached, photosMissing), Samples: samples, Notes: notes, diff --git a/GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.Designer.cs b/GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.Designer.cs new file mode 100644 index 0000000..49140da --- /dev/null +++ b/GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.Designer.cs @@ -0,0 +1,1302 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace GerbilManagerWebAPI.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20260606095755_ReseedColorVarietiesGen3f")] + partial class ReseedColorVarietiesGen3f + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Block", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Data") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("PageId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("PageId"); + + b.ToTable("Blocks"); + + b.HasData( + new + { + Id = new Guid("51720002-0000-0000-0000-000000000001"), + Data = "{\"text\":\"Startseite\",\"level\":1}", + Order = 0, + PageId = new Guid("51720001-0000-0000-0000-000000000001"), + Type = "Heading" + }, + new + { + Id = new Guid("51720002-0000-0000-0000-000000000002"), + Data = "{\"text\":\"Über die Zucht\",\"level\":1}", + Order = 0, + PageId = new Guid("51720001-0000-0000-0000-000000000002"), + Type = "Heading" + }, + new + { + Id = new Guid("51720002-0000-0000-0000-000000000003"), + Data = "{\"text\":\"Abgabetiere\",\"level\":1}", + Order = 0, + PageId = new Guid("51720001-0000-0000-0000-000000000003"), + Type = "Heading" + }, + new + { + Id = new Guid("51720002-0000-0000-0000-000000000004"), + Data = "{\"text\":\"Abgabebedingungen\",\"level\":1}", + Order = 0, + PageId = new Guid("51720001-0000-0000-0000-000000000004"), + Type = "Heading" + }, + new + { + Id = new Guid("51720002-0000-0000-0000-000000000005"), + Data = "{\"text\":\"Farben & Genetik\",\"level\":1}", + Order = 0, + PageId = new Guid("51720001-0000-0000-0000-000000000005"), + Type = "Heading" + }, + new + { + Id = new Guid("51720002-0000-0000-0000-000000000006"), + Data = "{\"text\":\"Kontakt\",\"level\":1}", + Order = 0, + PageId = new Guid("51720001-0000-0000-0000-000000000006"), + Type = "Heading" + }, + new + { + Id = new Guid("51720002-0000-0000-0000-000000000010"), + Data = "{\"mode\":\"auto\",\"intro\":\"\"}", + Order = 1, + PageId = new Guid("51720001-0000-0000-0000-000000000003"), + Type = "AbgabetiereList" + }); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.BreederSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .IsRequired() + .HasColumnType("text"); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("Homepage") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("ZuchtName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("BreederSettings"); + + b.HasData( + new + { + Id = new Guid("11111111-1111-1111-1111-000000000001"), + Address = "", + City = "", + Email = "", + Homepage = "", + Name = "", + Phone = "", + ZuchtName = "" + }); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.ColorVariety", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CanonicalGenotype") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ColorVarieties"); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0000-000000000001"), + CanonicalGenotype = "AA chch DD EE GG pp spsp rere", + Name = "Pink Eyed White (PEW)", + SortOrder = 0 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000002"), + CanonicalGenotype = "aa chch DD EE GG PP spsp rere", + Name = "Hermelin", + SortOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000003"), + CanonicalGenotype = "AA chch DD EE GG PP spsp rere", + Name = "Himalaya", + SortOrder = 2 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000004"), + CanonicalGenotype = "aa cchmcchm DD EE gg PP spsp rere", + Name = "Zobel", + SortOrder = 3 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000005"), + CanonicalGenotype = "AA CC DD efef GG pp spsp rere", + Name = "Rotaugenschimmel", + SortOrder = 4 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000006"), + CanonicalGenotype = "AA CC DD EE GG PP spsp rere", + Name = "Agouti", + SortOrder = 5 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000007"), + CanonicalGenotype = "aa CC DD EE GG PP spsp rere", + Name = "Schwarz", + SortOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000008"), + CanonicalGenotype = "AA CC DD EE gg PP spsp rere", + Name = "Silberagouti", + SortOrder = 7 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000009"), + CanonicalGenotype = "aa CC DD EE gg PP spsp rere", + Name = "Anthrazit", + SortOrder = 8 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000010"), + CanonicalGenotype = "AA CC DD ee GG PP spsp rere", + Name = "Algierfuchs", + SortOrder = 9 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000011"), + CanonicalGenotype = "aa CC dd EE GG PP spsp rere", + Name = "Blau", + SortOrder = 10 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000012"), + CanonicalGenotype = "AA CC DD EE GG pp spsp rere", + Name = "Gold", + SortOrder = 11 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000013"), + CanonicalGenotype = "aa CC DD EE GG pp spsp rere", + Name = "Platin", + SortOrder = 12 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000014"), + CanonicalGenotype = "AA CC DD ee GG pp spsp rere", + Name = "Goldfuchs", + SortOrder = 13 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000015"), + CanonicalGenotype = "aa CC DD ee GG pp spsp rere", + Name = "Rotfuchs", + SortOrder = 14 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000016"), + CanonicalGenotype = "AA CC dd EE GG pp spsp rere", + Name = "dd Gold", + SortOrder = 15 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000017"), + CanonicalGenotype = "aa CC dd EE GG pp spsp rere", + Name = "dd Platin", + SortOrder = 16 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000018"), + CanonicalGenotype = "aa CC DD EE gg pp spsp rere", + Name = "Altweiss (REW)", + SortOrder = 17 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000019"), + CanonicalGenotype = "AA CC DD ee gg pp spsp rere", + Name = "Apricot (Blassfuchs)", + SortOrder = 18 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000020"), + CanonicalGenotype = "aa CC DD ee gg PP spsp rere", + Name = "Blaufuchs", + SortOrder = 19 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000021"), + CanonicalGenotype = "aa CC DD ee gg pp spsp rere", + Name = "C-Separator", + SortOrder = 20 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000022"), + CanonicalGenotype = "AA CC DD EE gg pp spsp rere", + Name = "Elfenbein", + SortOrder = 21 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000023"), + CanonicalGenotype = "aa CC DD ee GG PP spsp rere", + Name = "Kohlfuchs", + SortOrder = 22 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000024"), + CanonicalGenotype = "AA CC DD ee gg PP spsp rere", + Name = "Polarfuchs", + SortOrder = 23 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000025"), + CanonicalGenotype = "aa CC DD EE GG pp spsp rere", + Name = "Saphir", + SortOrder = 24 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000026"), + CanonicalGenotype = "AA CC DD efef GG PP spsp rere", + Name = "Orangeschimmel", + SortOrder = 25 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000027"), + CanonicalGenotype = "AA CC DD EE GG pp spsp rere", + Name = "Topas", + SortOrder = 26 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000028"), + CanonicalGenotype = "aa CC DD EE GG pp spsp rere", + Name = "Platin-Hell", + SortOrder = 27 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000029"), + CanonicalGenotype = "AA CC dd EE GG PP spsp rere", + Name = "Agouti dd", + SortOrder = 28 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000030"), + CanonicalGenotype = "AA CC dd EE gg PP spsp rere", + Name = "Silberagouti dd", + SortOrder = 29 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000031"), + CanonicalGenotype = "aa CC dd ee GG PP spsp rere", + Name = "Kohlfuchs dd", + SortOrder = 30 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000032"), + CanonicalGenotype = "aa CC dd EE gg PP spsp rere", + Name = "Anthrazit dd", + SortOrder = 31 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000033"), + CanonicalGenotype = "AA CC DD efef gg PP spsp rere", + Name = "Silberschimmel", + SortOrder = 32 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000034"), + CanonicalGenotype = "AA CC DD efef gg PP spsp rere", + Name = "Polarfuchsschimmel", + SortOrder = 33 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000035"), + CanonicalGenotype = "AA CC DD efef GG PP spsp rere", + Name = "Algierfuchsschimmel", + SortOrder = 34 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000036"), + CanonicalGenotype = "aa CC DD efef GG PP spsp rere", + Name = "Kohlfuchsschimmel", + SortOrder = 35 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000037"), + CanonicalGenotype = "aa CC DD efef gg PP spsp rere", + Name = "Blaufuchsschimmel", + SortOrder = 36 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000038"), + CanonicalGenotype = "aa CC DD ee GG PP spsp rere", + Name = "Kohlfuchs, hell", + SortOrder = 37 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000039"), + CanonicalGenotype = "AA CC DD ee GG pp spsp rere", + Name = "Goldfuchs, hell", + SortOrder = 38 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000040"), + CanonicalGenotype = "AA CC DD efef GG pp spsp rere", + Name = "Goldfuchsschimmel", + SortOrder = 39 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000041"), + CanonicalGenotype = "AA CC DD EE GG pp spsp rere", + Name = "Gold-Hell", + SortOrder = 40 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000042"), + CanonicalGenotype = "aa CC DD ee gg PP spsp rere", + Name = "Blaufuchs, hell", + SortOrder = 41 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000043"), + CanonicalGenotype = "aa CC DD efef GG pp spsp rere", + Name = "Rotfuchsschimmel", + SortOrder = 42 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000044"), + CanonicalGenotype = "AA CC DD ee gg PP spsp rere", + Name = "Polarfuchs, hell", + SortOrder = 43 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000045"), + CanonicalGenotype = "aa CC DD efef GG PP spsp rere", + Name = "Kohlfuchsschimmel, hell", + SortOrder = 44 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000046"), + CanonicalGenotype = "aa CC DD ee GG pp spsp rere", + Name = "Rotfuchs, hell", + SortOrder = 45 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000047"), + CanonicalGenotype = "aa CC DD ee GG PP spsp rere", + Name = "Kohlfuchs-Hell", + SortOrder = 46 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000048"), + CanonicalGenotype = "AA CC DD ee GG PP spsp rere", + Name = "Algierfuchs, hell", + SortOrder = 47 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000049"), + CanonicalGenotype = "AA CC dd EE GG pp spsp rere", + Name = "Topas dd", + SortOrder = 48 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000050"), + CanonicalGenotype = "aa CC dd ee gg pp spsp rere", + Name = "Blaufuchs dd", + SortOrder = 49 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000051"), + CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere", + Name = "Marder", + SortOrder = 50 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000052"), + CanonicalGenotype = "aa cchmch DD EE GG PP spsp rere", + Name = "Siam", + SortOrder = 51 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000053"), + CanonicalGenotype = "aa cchmch DD EE gg PP spsp rere", + Name = "Zobel-Hell", + SortOrder = 52 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000054"), + CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere", + Name = "CP-Agouti", + SortOrder = 53 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000055"), + CanonicalGenotype = "AA cchmcchm DD EE gg PP spsp rere", + Name = "CP-Silberagouti", + SortOrder = 54 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000056"), + CanonicalGenotype = "AA cchmcchm DD ee GG PP spsp rere", + Name = "CP-Algierfuchs", + SortOrder = 55 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000057"), + CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere", + Name = "CP-Polarfuchs", + SortOrder = 56 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000058"), + CanonicalGenotype = "AA cchmcchm dd ee GG PP spsp rere", + Name = "CP-Fuchs", + SortOrder = 57 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000059"), + CanonicalGenotype = "AA cchmch dd ee GG PP spsp rere", + Name = "CP-Fuchs-Hell", + SortOrder = 58 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000060"), + CanonicalGenotype = "AA cchmcchm dd ee gg PP spsp rere", + Name = "CP-Blaufuchs", + SortOrder = 59 + }, + new + { + Id = new Guid("00000000-0000-0000-0000-000000000061"), + CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere", + Name = "CP-Orangeschimmel", + SortOrder = 60 + }); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Contacts"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Enclosure", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Enclosures"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Gerbil", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CauseOfDeath") + .HasColumnType("text"); + + b.Property("CharacterNote") + .HasColumnType("text"); + + b.Property("CharacterTraits") + .IsRequired() + .HasColumnType("text"); + + b.Property("ColorVarietyId") + .HasColumnType("uuid"); + + b.Property("DateOfBirth") + .HasColumnType("date"); + + b.Property("DateOfDeath") + .HasColumnType("date"); + + b.Property("EnclosureId") + .HasColumnType("uuid"); + + b.Property("ExternalRef") + .HasColumnType("text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text"); + + b.Property("Genotype") + .HasColumnType("text"); + + b.Property("GoHomeDate") + .HasColumnType("date"); + + b.Property("ImportSource") + .HasColumnType("text"); + + b.Property("IsDeaf") + .HasColumnType("boolean"); + + b.Property("IsResident") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("LitterId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("NameSearch") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("OriginBreeder") + .HasColumnType("text"); + + b.Property("OriginContactId") + .HasColumnType("uuid"); + + b.Property("RawImportData") + .HasColumnType("text"); + + b.Property("ReceiverContactId") + .HasColumnType("uuid"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ColorVarietyId"); + + b.HasIndex("EnclosureId"); + + b.HasIndex("LitterId"); + + b.HasIndex("OriginContactId"); + + b.HasIndex("ReceiverContactId"); + + b.ToTable("Gerbils"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.GerbilPhoto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Caption") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("GerbilId") + .HasColumnType("uuid"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GerbilId"); + + b.ToTable("GerbilPhotos"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.HealthRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GerbilId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.Property("Veterinarian") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GerbilId"); + + b.ToTable("HealthRecords"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Litter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("ExpectedGoHomeDate") + .HasColumnType("date"); + + b.Property("FatherId") + .HasColumnType("uuid"); + + b.Property("MotherId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("PairingCode") + .HasColumnType("text"); + + b.Property("TotalBorn") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("FatherId"); + + b.HasIndex("MotherId"); + + b.ToTable("Litters"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.MailSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppPasswordProtected") + .HasColumnType("text"); + + b.Property("BackgroundPollEnabled") + .HasColumnType("boolean"); + + b.Property("Folder") + .IsRequired() + .HasColumnType("text"); + + b.Property("GmailAddress") + .HasColumnType("text"); + + b.Property("LastUid") + .HasColumnType("bigint"); + + b.Property("PollIntervalMinutes") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("MailSettings"); + + b.HasData( + new + { + Id = new Guid("ab0c0000-0000-0000-0000-000000000001"), + BackgroundPollEnabled = false, + Folder = "INBOX", + LastUid = 0L, + PollIntervalMinutes = 15 + }); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Alt") + .HasColumnType("text"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("integer"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.Property("Width") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Page", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("SeoDescription") + .HasColumnType("text"); + + b.Property("Slug") + .IsRequired() + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.ToTable("Pages"); + + b.HasData( + new + { + Id = new Guid("51720001-0000-0000-0000-000000000001"), + Slug = "start", + Status = "Published", + Title = "Startseite" + }, + new + { + Id = new Guid("51720001-0000-0000-0000-000000000002"), + Slug = "ueber-die-zucht", + Status = "Published", + Title = "Über die Zucht" + }, + new + { + Id = new Guid("51720001-0000-0000-0000-000000000003"), + Slug = "abgabetiere", + Status = "Published", + Title = "Abgabetiere" + }, + new + { + Id = new Guid("51720001-0000-0000-0000-000000000004"), + Slug = "abgabebedingungen", + Status = "Published", + Title = "Abgabebedingungen" + }, + new + { + Id = new Guid("51720001-0000-0000-0000-000000000005"), + Slug = "farben-genetik", + Status = "Published", + Title = "Farben & Genetik" + }, + new + { + Id = new Guid("51720001-0000-0000-0000-000000000006"), + Slug = "kontakt", + Status = "Published", + Title = "Kontakt" + }); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Request", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AnsweredAt") + .HasColumnType("timestamp with time zone"); + + b.Property("AssignedContactId") + .HasColumnType("uuid"); + + b.Property("BodyText") + .HasColumnType("text"); + + b.Property("DraftReply") + .HasColumnType("text"); + + b.Property("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("FromName") + .HasColumnType("text"); + + b.Property("GmailMessageId") + .IsRequired() + .HasColumnType("text"); + + b.Property("InReplyToMessageId") + .HasColumnType("text"); + + b.Property("ReceivedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReferencesHeader") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .HasColumnType("text"); + + b.Property("ThreadId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AssignedContactId"); + + b.HasIndex("GmailMessageId") + .IsUnique(); + + b.ToTable("Requests"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContract", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContactId") + .HasColumnType("uuid"); + + b.Property("ContractDate") + .HasColumnType("date"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("HandoverDate") + .HasColumnType("date"); + + b.Property("Price") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("SaleContracts"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContractAnimal", b => + { + b.Property("SaleContractId") + .HasColumnType("uuid"); + + b.Property("GerbilId") + .HasColumnType("uuid"); + + b.HasKey("SaleContractId", "GerbilId"); + + b.HasIndex("GerbilId"); + + b.ToTable("SaleContractAnimal"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultLocale") + .IsRequired() + .HasColumnType("text"); + + b.Property("NavOrder") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Sites"); + + b.HasData( + new + { + Id = new Guid("5172e000-0000-0000-0000-000000000001"), + DefaultLocale = "de", + NavOrder = "[\"51720001-0000-0000-0000-000000000001\",\"51720001-0000-0000-0000-000000000002\",\"51720001-0000-0000-0000-000000000003\",\"51720001-0000-0000-0000-000000000004\",\"51720001-0000-0000-0000-000000000005\",\"51720001-0000-0000-0000-000000000006\"]" + }); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.WeightRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("GerbilId") + .HasColumnType("uuid"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("WeightGrams") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GerbilId"); + + b.ToTable("WeightRecords"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Block", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Page", null) + .WithMany("Blocks") + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Gerbil", b => + { + b.HasOne("GerbilManagerWebAPI.Models.ColorVariety", "ColorVariety") + .WithMany() + .HasForeignKey("ColorVarietyId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("GerbilManagerWebAPI.Models.Enclosure", "Enclosure") + .WithMany("Gerbils") + .HasForeignKey("EnclosureId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("GerbilManagerWebAPI.Models.Litter", "Litter") + .WithMany() + .HasForeignKey("LitterId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("GerbilManagerWebAPI.Models.Contact", "OriginContact") + .WithMany() + .HasForeignKey("OriginContactId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("GerbilManagerWebAPI.Models.Contact", "ReceiverContact") + .WithMany() + .HasForeignKey("ReceiverContactId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ColorVariety"); + + b.Navigation("Enclosure"); + + b.Navigation("Litter"); + + b.Navigation("OriginContact"); + + b.Navigation("ReceiverContact"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.GerbilPhoto", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Gerbil", null) + .WithMany() + .HasForeignKey("GerbilId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.HealthRecord", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Gerbil", null) + .WithMany() + .HasForeignKey("GerbilId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Litter", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Gerbil", "Father") + .WithMany() + .HasForeignKey("FatherId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("GerbilManagerWebAPI.Models.Gerbil", "Mother") + .WithMany() + .HasForeignKey("MotherId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Father"); + + b.Navigation("Mother"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Request", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Contact", "AssignedContact") + .WithMany() + .HasForeignKey("AssignedContactId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AssignedContact"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContract", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContractAnimal", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Gerbil", "Gerbil") + .WithMany() + .HasForeignKey("GerbilId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GerbilManagerWebAPI.Models.SaleContract", null) + .WithMany("Animals") + .HasForeignKey("SaleContractId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Gerbil"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.WeightRecord", b => + { + b.HasOne("GerbilManagerWebAPI.Models.Gerbil", null) + .WithMany() + .HasForeignKey("GerbilId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Enclosure", b => + { + b.Navigation("Gerbils"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.Page", b => + { + b.Navigation("Blocks"); + }); + + modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContract", b => + { + b.Navigation("Animals"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.cs b/GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.cs new file mode 100644 index 0000000..811e990 --- /dev/null +++ b/GerbilManagerWebAPI/Migrations/20260606095755_ReseedColorVarietiesGen3f.cs @@ -0,0 +1,632 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace GerbilManagerWebAPI.Migrations +{ + /// + public partial class ReseedColorVarietiesGen3f : Migration + { + /// + 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" }); + } + + /// + 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 } + }); + } + } +} diff --git a/GerbilManagerWebAPI/Migrations/ApplicationContextModelSnapshot.cs b/GerbilManagerWebAPI/Migrations/ApplicationContextModelSnapshot.cs index 7320bc4..0149023 100644 --- a/GerbilManagerWebAPI/Migrations/ApplicationContextModelSnapshot.cs +++ b/GerbilManagerWebAPI/Migrations/ApplicationContextModelSnapshot.cs @@ -343,352 +343,268 @@ namespace GerbilManagerWebAPI.Migrations new { Id = new Guid("00000000-0000-0000-0000-000000000024"), - CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere", - Name = "Marder", + CanonicalGenotype = "AA CC DD ee gg PP spsp rere", + Name = "Polarfuchs", SortOrder = 23 }, new { Id = new Guid("00000000-0000-0000-0000-000000000025"), - CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere", - Name = "Siam (Marder-Hell)", + CanonicalGenotype = "aa CC DD EE GG pp spsp rere", + Name = "Saphir", SortOrder = 24 }, new { Id = new Guid("00000000-0000-0000-0000-000000000026"), - CanonicalGenotype = "AA CC DD ee gg PP spsp rere", - Name = "Polarfuchs", + CanonicalGenotype = "AA CC DD efef GG PP spsp rere", + Name = "Orangeschimmel", SortOrder = 25 }, new { Id = new Guid("00000000-0000-0000-0000-000000000027"), - CanonicalGenotype = "aa CC DD EE GG pp spsp rere", - Name = "Saphir", + CanonicalGenotype = "AA CC DD EE GG pp spsp rere", + Name = "Topas", SortOrder = 26 }, new { Id = new Guid("00000000-0000-0000-0000-000000000028"), - CanonicalGenotype = "AA CC DD efef GG PP spsp rere", - Name = "Orangeschimmel", + CanonicalGenotype = "aa CC DD EE GG pp spsp rere", + Name = "Platin-Hell", SortOrder = 27 }, new { Id = new Guid("00000000-0000-0000-0000-000000000029"), - CanonicalGenotype = "AA CC DD EE GG pp spsp rere", - Name = "Topas", + CanonicalGenotype = "AA CC dd EE GG PP spsp rere", + Name = "Agouti dd", SortOrder = 28 }, new { Id = new Guid("00000000-0000-0000-0000-000000000030"), - CanonicalGenotype = "aa CC DD EE GG pp spsp rere", - Name = "Platin-Hell", + CanonicalGenotype = "AA CC dd EE gg PP spsp rere", + Name = "Silberagouti dd", SortOrder = 29 }, new { Id = new Guid("00000000-0000-0000-0000-000000000031"), - CanonicalGenotype = "AA CC dd EE GG PP spsp rere", - Name = "Agouti dd", + CanonicalGenotype = "aa CC dd ee GG PP spsp rere", + Name = "Kohlfuchs dd", SortOrder = 30 }, new { Id = new Guid("00000000-0000-0000-0000-000000000032"), - CanonicalGenotype = "AA CC dd EE gg PP spsp rere", - Name = "Silberagouti dd", + CanonicalGenotype = "aa CC dd EE gg PP spsp rere", + Name = "Anthrazit dd", SortOrder = 31 }, new { Id = new Guid("00000000-0000-0000-0000-000000000033"), - CanonicalGenotype = "aa CC dd ee GG PP spsp rere", - Name = "Kohlfuchs dd", + CanonicalGenotype = "AA CC DD efef gg PP spsp rere", + Name = "Silberschimmel", SortOrder = 32 }, new { Id = new Guid("00000000-0000-0000-0000-000000000034"), - CanonicalGenotype = "aa CC dd EE gg PP spsp rere", - Name = "Anthrazit dd", + CanonicalGenotype = "AA CC DD efef gg PP spsp rere", + Name = "Polarfuchsschimmel", SortOrder = 33 }, new { Id = new Guid("00000000-0000-0000-0000-000000000035"), - CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere", - Name = "Agouti CP-Hell", + CanonicalGenotype = "AA CC DD efef GG PP spsp rere", + Name = "Algierfuchsschimmel", SortOrder = 34 }, new { Id = new Guid("00000000-0000-0000-0000-000000000036"), - CanonicalGenotype = "aa cchmcchm DD ee gg PP spsp rere", - Name = "Blaufuchs CP", + CanonicalGenotype = "aa CC DD efef GG PP spsp rere", + Name = "Kohlfuchsschimmel", SortOrder = 35 }, new { Id = new Guid("00000000-0000-0000-0000-000000000037"), - CanonicalGenotype = "AA CC DD efef gg PP spsp rere", - Name = "Silberschimmel", + CanonicalGenotype = "aa CC DD efef gg PP spsp rere", + Name = "Blaufuchsschimmel", SortOrder = 36 }, new { Id = new Guid("00000000-0000-0000-0000-000000000038"), - CanonicalGenotype = "AA CC DD efef gg PP spsp rere", - Name = "Polarfuchsschimmel", + CanonicalGenotype = "aa CC DD ee GG PP spsp rere", + Name = "Kohlfuchs, hell", SortOrder = 37 }, new { Id = new Guid("00000000-0000-0000-0000-000000000039"), - CanonicalGenotype = "AA CC DD efef GG PP spsp rere", - Name = "Algierfuchsschimmel", + CanonicalGenotype = "AA CC DD ee GG pp spsp rere", + Name = "Goldfuchs, hell", SortOrder = 38 }, new { Id = new Guid("00000000-0000-0000-0000-000000000040"), - CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere", - Name = "Polarfuchs-Hell CP", + CanonicalGenotype = "AA CC DD efef GG pp spsp rere", + Name = "Goldfuchsschimmel", SortOrder = 39 }, new { Id = new Guid("00000000-0000-0000-0000-000000000041"), - CanonicalGenotype = "aa CC DD efef GG PP spsp rere", - Name = "Kohlfuchsschimmel", + CanonicalGenotype = "AA CC DD EE GG pp spsp rere", + Name = "Gold-Hell", SortOrder = 40 }, new { Id = new Guid("00000000-0000-0000-0000-000000000042"), - CanonicalGenotype = "aa CC DD efef gg PP spsp rere", - Name = "Blaufuchsschimmel", + CanonicalGenotype = "aa CC DD ee gg PP spsp rere", + Name = "Blaufuchs, hell", SortOrder = 41 }, new { Id = new Guid("00000000-0000-0000-0000-000000000043"), - CanonicalGenotype = "aa CC DD ee GG PP spsp rere", - Name = "Kohlfuchs, hell", + CanonicalGenotype = "aa CC DD efef GG pp spsp rere", + Name = "Rotfuchsschimmel", SortOrder = 42 }, new { Id = new Guid("00000000-0000-0000-0000-000000000044"), - CanonicalGenotype = "AA CC DD ee GG pp spsp rere", - Name = "Goldfuchs, hell", + CanonicalGenotype = "AA CC DD ee gg PP spsp rere", + Name = "Polarfuchs, hell", SortOrder = 43 }, new { Id = new Guid("00000000-0000-0000-0000-000000000045"), - CanonicalGenotype = "AA CC DD efef GG pp spsp rere", - Name = "Goldfuchsschimmel", + CanonicalGenotype = "aa CC DD efef GG PP spsp rere", + Name = "Kohlfuchsschimmel, hell", SortOrder = 44 }, new { Id = new Guid("00000000-0000-0000-0000-000000000046"), - CanonicalGenotype = "AA CC DD EE GG pp spsp rere", - Name = "Gold-Hell", + CanonicalGenotype = "aa CC DD ee GG pp spsp rere", + Name = "Rotfuchs, hell", SortOrder = 45 }, new { Id = new Guid("00000000-0000-0000-0000-000000000047"), - CanonicalGenotype = "aa cchmcchm dd EE GG PP spsp rere", - Name = "Siam (Marder-Hell) dd", + CanonicalGenotype = "aa CC DD ee GG PP spsp rere", + Name = "Kohlfuchs-Hell", SortOrder = 46 }, new { Id = new Guid("00000000-0000-0000-0000-000000000048"), - CanonicalGenotype = "aa cchmcchm dd EE GG PP spsp rere", - Name = "Marder dd", + CanonicalGenotype = "AA CC DD ee GG PP spsp rere", + Name = "Algierfuchs, hell", SortOrder = 47 }, new { Id = new Guid("00000000-0000-0000-0000-000000000049"), - CanonicalGenotype = "aa cchmcchm DD EE gg PP spsp rere", - Name = "Zobel-Hell", + CanonicalGenotype = "AA CC dd EE GG pp spsp rere", + Name = "Topas dd", SortOrder = 48 }, new { Id = new Guid("00000000-0000-0000-0000-000000000050"), - CanonicalGenotype = "AA cchmcchm dd EE gg PP spsp rere", - Name = "Silberagouti dd CP", + CanonicalGenotype = "aa CC dd ee gg pp spsp rere", + Name = "Blaufuchs dd", SortOrder = 49 }, new { Id = new Guid("00000000-0000-0000-0000-000000000051"), - CanonicalGenotype = "AA cchmcchm dd EE gg PP spsp rere", - Name = "Silberagouti-Hell dd CP", + CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere", + Name = "Marder", SortOrder = 50 }, new { Id = new Guid("00000000-0000-0000-0000-000000000052"), - CanonicalGenotype = "AA cchmcchm dd EE GG PP spsp rere", - Name = "Agouti dd CP", + CanonicalGenotype = "aa cchmch DD EE GG PP spsp rere", + Name = "Siam", SortOrder = 51 }, new { Id = new Guid("00000000-0000-0000-0000-000000000053"), - CanonicalGenotype = "AA cchmcchm dd EE GG PP spsp rere", - Name = "Agouti-Hell dd CP", + CanonicalGenotype = "aa cchmch DD EE gg PP spsp rere", + Name = "Zobel-Hell", SortOrder = 52 }, new { Id = new Guid("00000000-0000-0000-0000-000000000054"), - CanonicalGenotype = "aa CC DD ee gg PP spsp rere", - Name = "Blaufuchs, hell", + CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere", + Name = "CP-Agouti", SortOrder = 53 }, new { Id = new Guid("00000000-0000-0000-0000-000000000055"), - CanonicalGenotype = "aa CC DD efef GG pp spsp rere", - Name = "Rotfuchsschimmel", + CanonicalGenotype = "AA cchmcchm DD EE gg PP spsp rere", + Name = "CP-Silberagouti", SortOrder = 54 }, new { Id = new Guid("00000000-0000-0000-0000-000000000056"), - CanonicalGenotype = "AA CC DD ee gg PP spsp rere", - Name = "Polarfuchs, hell", + CanonicalGenotype = "AA cchmcchm DD ee GG PP spsp rere", + Name = "CP-Algierfuchs", SortOrder = 55 }, new { Id = new Guid("00000000-0000-0000-0000-000000000057"), - CanonicalGenotype = "aa CC DD efef GG PP spsp rere", - Name = "Kohlfuchsschimmel, hell", + CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere", + Name = "CP-Polarfuchs", SortOrder = 56 }, new { Id = new Guid("00000000-0000-0000-0000-000000000058"), - CanonicalGenotype = "aa CC DD ee GG pp spsp rere", - Name = "Rotfuchs, hell", + CanonicalGenotype = "AA cchmcchm dd ee GG PP spsp rere", + Name = "CP-Fuchs", SortOrder = 57 }, new { Id = new Guid("00000000-0000-0000-0000-000000000059"), - CanonicalGenotype = "aa cchmcchm dd EE gg PP spsp rere", - Name = "Zobel dd", + CanonicalGenotype = "AA cchmch dd ee GG PP spsp rere", + Name = "CP-Fuchs-Hell", SortOrder = 58 }, new { Id = new Guid("00000000-0000-0000-0000-000000000060"), - CanonicalGenotype = "aa CC DD ee GG PP spsp rere", - Name = "Kohlfuchs-Hell", + CanonicalGenotype = "AA cchmcchm dd ee gg PP spsp rere", + Name = "CP-Blaufuchs", SortOrder = 59 }, new { 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", Name = "CP-Orangeschimmel", - SortOrder = 72 + SortOrder = 60 }); }); diff --git a/tools/import/extract.py b/tools/import/extract.py index 24e9cb9..ba5e8d5 100644 --- a/tools/import/extract.py +++ b/tools/import/extract.py @@ -211,6 +211,11 @@ def extract_stammbaum(path): farbschlag = "" geno = geno0 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): cell = cells.get((c, rr)) if not cell: @@ -221,7 +226,7 @@ def extract_stammbaum(path): elif re.search(r"\b(Zucht|Privatzucht)\b", cell) or cell.startswith("("): breeder = cell 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): farbschlag = cell used.add((c, rr)) @@ -829,6 +834,43 @@ def write_report(merged, conflicts, orphans, raw_count, litters, photo_count, # ------------------------------------------------------------------------ main +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(): try: sys.stdout.reconfigure(encoding="utf-8", errors="replace") @@ -863,6 +905,8 @@ def main(): print(f"Wurfchronik: {len(litters)} Würfe") merged, conflicts, orphans, zucht_splits = dedup(raw_animals) + decisions_path = os.path.join(HERE, "conflict-decisions.json") + resolved_by_decision = apply_conflict_decisions(merged, conflicts, decisions_path) match_stats = match_litters(merged, litters) photo_count = sum(len(a["photos"]) for a in merged) @@ -879,7 +923,8 @@ def main(): zucht_splits, match_stats) 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"| Zucht-Splits: {len(zucht_splits)} " f"| Orphans: {len(orphans)} | Fotos: {photo_count}") print(f"Wurf-Verknüpfung: {match_stats['parents']} (Datum+Eltern), " f"{match_stats['dateOnly']} (nur Datum), {match_stats['ambiguous']} mehrdeutig " diff --git a/tools/import/output/review-report.md b/tools/import/output/review-report.md index 0f109ca..167b53a 100644 --- a/tools/import/output/review-report.md +++ b/tools/import/output/review-report.md @@ -8,7 +8,7 @@ _Automatisch erzeugt von `tools/import/extract.py` — **noch nichts in die Date - Nach Zusammenführung (eindeutige Tiere): **622** - davon mit Geburtsdatum: 327 - in mehreren Dateien gefunden (Dubletten zusammengeführt): 158 -- Konflikte zur Klärung: **21** +- Konflikte zur Klärung: **19** - Mehrdeutige / unvollständige Einträge (ohne Name+Datum): **310** - Fotos zugeordnet: **137** - Würfe aus der Wurfchronik: **752** @@ -27,9 +27,7 @@ Gleiches Tier (Name+Datum), aber widersprüchliche Angaben in verschiedenen Date |---|---|---|---|---|---| | 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 | @@ -142,7 +140,7 @@ Diese Tokens stehen weiter in `rawGenotype`/`unmappedTokens` — Entscheidung (M | Token | Vorkommen | Bedeutung (Vermutung) | |---|---|---| -| `/+` | 8 | ? | +| `/+` | 7 | ? | | `-g` | 2 | ? | | `C(C)` | 2 | Schreibweise (C trägt c) | | `chmchm` | 2 | Schreibweise (c[chm]c[chm]) | diff --git a/tools/import/test_extract.py b/tools/import/test_extract.py new file mode 100644 index 0000000..8caaf28 --- /dev/null +++ b/tools/import/test_extract.py @@ -0,0 +1,116 @@ +"""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'{text}' + + +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'{"".join(cs)}' for r, cs in sorted(rows.items())) + sheet = ('' + + body + "") + 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) +try: os.remove(dec_path) +except OSError: pass + +# --- 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")