Compare commits
3 Commits
feat/akte-
...
cb2ee03a14
| Author | SHA1 | Date | |
|---|---|---|---|
| cb2ee03a14 | |||
| 41ff973f9a | |||
| d2993418b6 |
@@ -242,6 +242,29 @@
|
||||
"decision": "Genotype is aa CC D- Ee Gg pp Spsp [DP] (C locus is CC, full color, duplicate colourpoint record resolved).",
|
||||
"genotype": "aa CC D- Ee Gg pp Spsp [DP]",
|
||||
"source": "Julian 2026-06-12"
|
||||
},
|
||||
{
|
||||
"name": "Kazuya von den Kleinen Chaoten",
|
||||
"dob": "22.08.2018",
|
||||
"decision": "duplicate with wrong birthdate and parents — same animal as Kazuya *14.07.2019; merge into it and correct parents to Wilbur + Naho",
|
||||
"correctDob": "14.07.2019",
|
||||
"source": "Stammbaum von Kazuya.xlsx"
|
||||
},
|
||||
{
|
||||
"name": "Kazuya von den Kleinen Chaoten",
|
||||
"dob": "14.07.2019",
|
||||
"decision": "father = Wilbur von den Kleinen Chaoten, mother = Naho von den Kleinen Chaoten (from Stammbaum von Kazuya.xlsx)",
|
||||
"father": "Wilbur von den Kleinen Chaoten",
|
||||
"mother": "Naho von den Kleinen Chaoten",
|
||||
"source": "Stammbaum von Kazuya.xlsx"
|
||||
},
|
||||
{
|
||||
"name": "Naho von den Kleinen Chaoten",
|
||||
"dob": "20.07.2017",
|
||||
"decision": "father = Osamu von den Kleinen Chaoten, mother = Montana v.d. Kleinen Chaoten (from Stammbaum von Kazuya.xlsx)",
|
||||
"father": "Osamu von den Kleinen Chaoten",
|
||||
"mother": "Montana v.d. Kleinen Chaoten",
|
||||
"source": "Stammbaum von Kazuya.xlsx"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -340,13 +340,37 @@ def _attach_photos(z, sheets, animals, fname):
|
||||
anchors = [a for a in xu.image_anchors(z)]
|
||||
if not anchors:
|
||||
return
|
||||
|
||||
# Detect left_style: whether photo is to the left or to the right of the name cell
|
||||
a_count = sum(1 for a in anchors if a[1] == 1)
|
||||
d_count = sum(1 for a in anchors if a[1] == 4)
|
||||
has_proband_in_d = any(a[1] == 4 and 50 <= a[2] <= 70 for a in anchors)
|
||||
left_style = a_count > 0 or (d_count > 0 and not has_proband_in_d)
|
||||
|
||||
def get_anchor_gen(colnum, offset=0):
|
||||
effective_col = colnum - offset
|
||||
if left_style:
|
||||
if effective_col <= 3: return 0
|
||||
if effective_col <= 6: return 1
|
||||
if effective_col <= 9: return 2
|
||||
if effective_col <= 12: return 3
|
||||
if effective_col <= 15: return 4
|
||||
return 5
|
||||
else:
|
||||
if effective_col <= 4: return 0
|
||||
if effective_col <= 7: return 1
|
||||
if effective_col <= 10: return 2
|
||||
if effective_col <= 13: return 3
|
||||
if effective_col <= 16: return 4
|
||||
return 5
|
||||
|
||||
by_gen = {}
|
||||
for a in animals:
|
||||
by_gen.setdefault(a["_gen"], []).append(a)
|
||||
media_dir = os.path.join(OUT, "photos")
|
||||
col_offset = 0 if any(a["_col"] == 2 for a in animals) else 3
|
||||
for i, (sp, col, row, media) in enumerate(anchors):
|
||||
g = gen_of(col, col_offset)
|
||||
g = get_anchor_gen(col, col_offset)
|
||||
cands = by_gen.get(g, [])
|
||||
if not cands:
|
||||
# fall back to nearest animal by row across all gens
|
||||
@@ -362,7 +386,8 @@ def _attach_photos(z, sheets, animals, fname):
|
||||
try:
|
||||
with z.open(media) as src, open(os.path.join(OUT, rel), "wb") as dst:
|
||||
shutil.copyfileobj(src, dst)
|
||||
target["photos"].append(rel)
|
||||
if rel not in target["photos"]:
|
||||
target["photos"].append(rel)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
@@ -612,6 +637,49 @@ def dedup(animals):
|
||||
"files": sorted(set(f for a in grp for f in a["sourceFiles"])),
|
||||
})
|
||||
|
||||
# 2. Merge groups that have different DOBs but same call-name (and Zucht) and matching parents
|
||||
def get_parent_keys(a):
|
||||
parent_refs = a.get("parentRefs", [])
|
||||
f_name = next((p["name"] for p in parent_refs if p.get("roleGuess") == "father"), "")
|
||||
m_name = next((p["name"] for p in parent_refs if p.get("roleGuess") == "mother"), "")
|
||||
return norm_name(f_name), norm_name(m_name)
|
||||
|
||||
def groups_parents_match(g1, g2):
|
||||
for a1 in g1:
|
||||
for a2 in g2:
|
||||
f1, m1 = get_parent_keys(a1)
|
||||
f2, m2 = get_parent_keys(a2)
|
||||
if f1 and f2 and f1 == f2 and m1 and m2 and m1 == m2:
|
||||
return True
|
||||
return False
|
||||
|
||||
i = 0
|
||||
while i < len(final_groups):
|
||||
g1 = final_groups[i]
|
||||
call1, _ = split_name_zucht(g1[0]["name"])
|
||||
n_call1 = norm_name(call1)
|
||||
zucht1 = g1[0].get("_zucht", "")
|
||||
|
||||
j = i + 1
|
||||
merged_any = False
|
||||
while j < len(final_groups):
|
||||
g2 = final_groups[j]
|
||||
call2, _ = split_name_zucht(g2[0]["name"])
|
||||
n_call2 = norm_name(call2)
|
||||
zucht2 = g2[0].get("_zucht", "")
|
||||
|
||||
if n_call1 == n_call2:
|
||||
if zucht1 == zucht2 or not zucht1 or not zucht2:
|
||||
if groups_parents_match(g1, g2):
|
||||
g1.extend(g2)
|
||||
final_groups.pop(j)
|
||||
merged_any = True
|
||||
continue
|
||||
j += 1
|
||||
if merged_any:
|
||||
continue
|
||||
i += 1
|
||||
|
||||
merged = []
|
||||
conflicts = []
|
||||
for grp in final_groups:
|
||||
@@ -652,11 +720,25 @@ def dedup(animals):
|
||||
return sum(1 for pair in gd["mapped8locus"].values() for a in pair if a != "?")
|
||||
best = max((a["genotype"] for a in grp),
|
||||
key=lambda gd: (len(gd["mapped8locus"]), _specificity(gd), len(gd["rawGenotype"])))
|
||||
|
||||
# Find best DOB (proband first)
|
||||
best_dob = ""
|
||||
for a in grp:
|
||||
if a.get("_gen") == 0 and a.get("dob"):
|
||||
best_dob = a["dob"]
|
||||
break
|
||||
if not best_dob:
|
||||
for a in grp:
|
||||
if a.get("dob"):
|
||||
best_dob = a["dob"]
|
||||
break
|
||||
chosen_dob = norm_dob(best_dob or base["dob"])
|
||||
|
||||
out = {
|
||||
"id": slug(base["name"], base["dob"]),
|
||||
"id": slug(base["name"], chosen_dob),
|
||||
"name": base["name"],
|
||||
"nameVariants": sorted(v for v in variants if v),
|
||||
"dob": norm_dob(base["dob"]),
|
||||
"dob": chosen_dob,
|
||||
"death": sorted(deaths)[0] if deaths else "",
|
||||
# box-colour sex (blue=male, white=female): majority across mentions, else None.
|
||||
"gender": Counter(genders).most_common(1)[0][0] if genders else None,
|
||||
@@ -999,6 +1081,25 @@ def apply_conflict_decisions(merged, conflicts, path):
|
||||
a["farbschlagVariants"] = [d["farbschlag"]]
|
||||
if d.get("dateOfDeath"): # D5 death-date resolutions
|
||||
a["death"] = norm_dob(d["dateOfDeath"])
|
||||
if "father" in d or "mother" in d:
|
||||
new_refs = []
|
||||
if d.get("father"):
|
||||
new_refs.append({
|
||||
"name": d["father"],
|
||||
"dob": "",
|
||||
"roleGuess": "father",
|
||||
"method": "decision",
|
||||
"confidence": "high"
|
||||
})
|
||||
if d.get("mother"):
|
||||
new_refs.append({
|
||||
"name": d["mother"],
|
||||
"dob": "",
|
||||
"roleGuess": "mother",
|
||||
"method": "decision",
|
||||
"confidence": "high"
|
||||
})
|
||||
a["parentRefs"] = new_refs
|
||||
if a.get("conflict"):
|
||||
a["conflict"] = False
|
||||
conflicts[:] = [c for c in conflicts if c.get("id") != a["id"]]
|
||||
|
||||
@@ -1173,6 +1173,17 @@ def main():
|
||||
norm_b, keep_b = get_normalized_contact_name(raw_breeder)
|
||||
raw_breeder = norm_b if keep_b else None
|
||||
|
||||
parent_refs = []
|
||||
if old_litter_id:
|
||||
rl = next((l for l in raw_litters if l.get("_scoped_id") == old_litter_id), None)
|
||||
if rl:
|
||||
f_name = rl.get("FatherName") or rl.get("fatherName") or rl.get("ParentMaleName") or rl.get("parentMaleName") or rl.get("_father_name")
|
||||
m_name = rl.get("MotherName") or rl.get("motherName") or rl.get("ParentFemaleName") or rl.get("parentFemaleName") or rl.get("_mother_name")
|
||||
if f_name:
|
||||
parent_refs.append({"name": f_name, "roleGuess": "father"})
|
||||
if m_name:
|
||||
parent_refs.append({"name": m_name, "roleGuess": "mother"})
|
||||
|
||||
all_processed_gerbils.append({
|
||||
"Id": new_guid,
|
||||
"Name": name_val,
|
||||
@@ -1198,6 +1209,7 @@ def main():
|
||||
"CharacterNote": char_note,
|
||||
"IsDeaf": is_deaf,
|
||||
"IsResident": is_resident,
|
||||
"parentRefs": parent_refs,
|
||||
"_photos": rg.get("photos", []),
|
||||
"_old_scoped_litter_id": old_litter_id,
|
||||
"_eff_dob": eff_dob_val,
|
||||
@@ -1306,6 +1318,7 @@ def main():
|
||||
"CharacterNote": None,
|
||||
"IsDeaf": is_deaf,
|
||||
"IsResident": a_id in stammbaum_resident_ids,
|
||||
"parentRefs": a.get("parentRefs", []),
|
||||
"_photos": a.get("photos", []),
|
||||
"_old_scoped_litter_id": scoped_litter_id,
|
||||
"_eff_dob": dob_val or "2010-01-01",
|
||||
@@ -1364,6 +1377,15 @@ def main():
|
||||
# Residents: if sold/given away, it's not a resident
|
||||
is_resident = not bool(o_name)
|
||||
|
||||
parent_refs = []
|
||||
if scoped_litter_id:
|
||||
dl = next((l for l in docx_litters if docx_litter_id_map.get((l["wsCode"], parse_date(l["dob"]))) == scoped_litter_id), None)
|
||||
if dl:
|
||||
if dl.get("fatherName"):
|
||||
parent_refs.append({"name": dl["fatherName"], "roleGuess": "father"})
|
||||
if dl.get("motherName"):
|
||||
parent_refs.append({"name": dl["motherName"], "roleGuess": "mother"})
|
||||
|
||||
all_processed_gerbils.append({
|
||||
"Id": scoped_id,
|
||||
"Name": name_val,
|
||||
@@ -1389,6 +1411,7 @@ def main():
|
||||
"CharacterNote": None,
|
||||
"IsDeaf": None,
|
||||
"IsResident": is_resident,
|
||||
"parentRefs": parent_refs,
|
||||
"_photos": da.get("photos", []),
|
||||
"_old_scoped_litter_id": scoped_litter_id,
|
||||
"_eff_dob": dob_val or "2020-01-01",
|
||||
@@ -1418,13 +1441,27 @@ def main():
|
||||
bd1 = g1.get("_birth_date")
|
||||
bd2 = g2.get("_birth_date")
|
||||
|
||||
# If both have explicit birth dates, they must match within 30 days
|
||||
if bd1 and bd2:
|
||||
days1 = date_to_days(bd1)
|
||||
days2 = date_to_days(bd2)
|
||||
if days1 is not None and days2 is not None:
|
||||
if abs(days1 - days2) > 30:
|
||||
return False
|
||||
# New rule: if name and parents match, they are compatible regardless of DOB!
|
||||
p1 = g1.get("parentRefs", [])
|
||||
p2 = g2.get("parentRefs", [])
|
||||
f1 = next((p["name"] for p in p1 if p.get("roleGuess") == "father"), "")
|
||||
m1 = next((p["name"] for p in p1 if p.get("roleGuess") == "mother"), "")
|
||||
f2 = next((p["name"] for p in p2 if p.get("roleGuess") == "father"), "")
|
||||
m2 = next((p["name"] for p in p2 if p.get("roleGuess") == "mother"), "")
|
||||
|
||||
parents_match = False
|
||||
if f1 and f2 and m1 and m2:
|
||||
if normalize_name(f1) == normalize_name(f2) and normalize_name(m1) == normalize_name(m2):
|
||||
parents_match = True
|
||||
|
||||
if not parents_match:
|
||||
# If both have explicit birth dates, they must match within 30 days
|
||||
if bd1 and bd2:
|
||||
days1 = date_to_days(bd1)
|
||||
days2 = date_to_days(bd2)
|
||||
if days1 is not None and days2 is not None:
|
||||
if abs(days1 - days2) > 30:
|
||||
return False
|
||||
|
||||
# If g1 has birth date, and g2 has parenting dates, birth date must be before parenting dates
|
||||
p_dates2 = parent_litter_dates.get(g2["Id"], [])
|
||||
|
||||
@@ -5,20 +5,31 @@ _Automatisch erzeugt von `tools/import/extract.py` — **noch nichts in die Date
|
||||
## Überblick
|
||||
|
||||
- Rohe Tier-Einträge aus den Stammbäumen: **2449**
|
||||
- Nach Zusammenführung (eindeutige Tiere): **1006**
|
||||
- davon mit Geburtsdatum: 681
|
||||
- in mehreren Dateien gefunden (Dubletten zusammengeführt): 460
|
||||
- Konflikte zur Klärung: **2**
|
||||
- Nach Zusammenführung (eindeutige Tiere): **1000**
|
||||
- davon mit Geburtsdatum: 677
|
||||
- in mehreren Dateien gefunden (Dubletten zusammengeführt): 462
|
||||
- Konflikte zur Klärung: **4**
|
||||
- Mehrdeutige / unvollständige Einträge (ohne Name+Datum): **342**
|
||||
- Fotos zugeordnet: **416**
|
||||
- Fotos zugeordnet: **422**
|
||||
- Würfe aus der Wurfchronik: **752**
|
||||
- Tiere mit Wurf verknüpft: **271** (davon über Geburtsdatum **und** Eltern: 166, nur über Geburtsdatum: 105; mehrdeutig: 16)
|
||||
- Tiere mit Wurf verknüpft: **269** (davon über Geburtsdatum **und** Eltern: 165, nur über Geburtsdatum: 104; mehrdeutig: 16)
|
||||
- Würfe mit Datenqualitäts-Hinweisen: 113 (+ 138 Zeilen mit abweichendem Spaltenschema)
|
||||
|
||||
## Zusammenführungs-Schlüssel
|
||||
|
||||
Tiere wurden zusammengeführt über **normalisierter Rufname + Geburtsdatum**, mit der **Zucht als Unterscheidungsmerkmal** (Julians Regel: die `[Klammern]` in der Wurfchronik und das `of/von <Linie>`-Suffix der Stammbäume bezeichnen beide die Zucht und werden zusammengeführt — z. B. `[ZdkC]` ≙ `von den Kleinen Chaoten`). Namensvarianten (z. B. `v.d.` ↔ `von den`, `gen.`-Spitznamen) werden als `nameVariants` erhalten.
|
||||
|
||||
### Erweiterte Zusammenführungsregel: Gleicher Name + gleiche Eltern
|
||||
|
||||
Wenn zwei Einträge denselben Rufnamen **und** dieselben Eltern (Vater + Mutter) tragen, werden sie als dasselbe Tier betrachtet — auch wenn das Geburtsdatum abweicht. Das DOB des Eintrags, in dem das Tier Proband ist (`_gen == 0`), hat Priorität. Diese Regel greift als Sicherheitsnetz für Datenfehler beim Geburtsdatum.
|
||||
|
||||
**Im aktuellen Datensatz ausgelöst für:**
|
||||
|
||||
| Tier | DOB (falsch) | DOB (korrekt) | Vater | Mutter | Lösung |
|
||||
|---|---|---|---|---|---|
|
||||
| Kazuya von den Kleinen Chaoten | 22.08.2018 | 14.07.2019 | Wilbur von den Kleinen Chaoten | Naho von den Kleinen Chaoten | `correctDob`-Eintrag in conflict-decisions.json → DOB vor Dedup remapped |
|
||||
|
||||
|
||||
### Gleicher Name + Geburtsdatum, aber unterschiedliche Zucht (NICHT zusammengeführt — bitte prüfen)
|
||||
|
||||
| Tier | Geburtsdatum | Zuchten | Dateien |
|
||||
@@ -35,7 +46,9 @@ Gleiches Tier (Name+Datum), aber widersprüchliche Angaben in verschiedenen Date
|
||||
| Tier | Geburtsdatum | abweichende Genotypen | abweichende Farbschläge | Sterbedaten | Dateien |
|
||||
|---|---|---|---|---|---|
|
||||
| Osamu | 10.12.2015 | AA CC DD ee gg P- spsp // AA CC DD ee gg PP spsp // AA CC DD ee uw[d]uw[d] PP spsp | — | 01.10.2020 // 18.12.2020 | Stammbaum von Danako, Stammbaum von Ella, Stammbaum von Jin, Stammbaum von Kazuya, Stammbaum von Kentucky, Stammbaum von Martin, Stammbaum von Rainny, Stammbaum von Ren, Stammbaum von South Dakota, Stammbaum von Stella Kids, Stammbaum von Tennessee, Stammbaum von Zenon von Elea |
|
||||
| | 20.04.2024 | Aa C- dd Ee Gg P- Spsp | Dilute Agouti Kragenschecke // Dilute Kohlfuchs Kragenschecke DP | — | Stammbaum von Fire Kids, Stammbaum von Stella Kids |
|
||||
| Hanami | 10.09.2015 | aa Cc[chm] D- Ee gg P- spsp // aa Cc[chm] D- Ee uw[d]uw[d] P- spsp | — | 02.01.2020 // 12.12.2019 // 14.01.2020 | Stammbaum von Hana, Stammbaum von Kentucky, Stammbaum von Rainny, Stammbaum von Ren, Stammbaum von Stella Kids, Stammbaum von Vance, Stammbaum von Zac (Vance.Dorie) |
|
||||
| | 13.08.2025 | Aa C- D- ee[f] G(G) pp Spsp // aa Cc[chm] D- ee[f] Gg Pp Spsp | Goldfuchsschimmel Kragenschecke // Kohlfuchsschimmel, hell | — | Stammbaum von Kohlief, Goldfuchsef Sp von Chrissi, Stammbaum von Watarus Kids |
|
||||
|
||||
## Mehrdeutige / unvollständige Einträge
|
||||
|
||||
@@ -84,7 +97,7 @@ Gleiches Tier (Name+Datum), aber widersprüchliche Angaben in verschiedenen Date
|
||||
|
||||
## Wahrscheinliche Zuordnungen unvollständiger Einträge
|
||||
|
||||
91 namenlose/datenlose Einträge tragen denselben Namen wie ein vollständiges Tier — vermutlich dasselbe Tier (zur Bestätigung):
|
||||
89 namenlose/datenlose Einträge tragen denselben Namen wie ein vollständiges Tier — vermutlich dasselbe Tier (zur Bestätigung):
|
||||
|
||||
- „Tai of Lennylengo“ → Tai of Lennylengo (*01.10.2011)
|
||||
- „Arrow PZ Niederlande“ → Arrow PZ Niederlande (*20.05.2014)
|
||||
@@ -95,7 +108,6 @@ Gleiches Tier (Name+Datum), aber widersprüchliche Angaben in verschiedenen Date
|
||||
- „Oscar of Black Forest“ → Oscar of Black Forest (*12.06.2019)
|
||||
- „Hagrid Rubeus of Black Forest“ → Hagrid Rubeus of Black Forest (*18.07.2019)
|
||||
- „Lilo of LennyLengo“ → Lilo of LennyLengo (*04.11.2018)
|
||||
- „Kazuya“ → Kazuya (*14.07.2019)
|
||||
- „Harumi“ → Harumi (*21.02.2015)
|
||||
- „Pan“ → Pan (*09.12.2014)
|
||||
- „Gin“ → Gin (*05.02.2015)
|
||||
@@ -146,6 +158,7 @@ Gleiches Tier (Name+Datum), aber widersprüchliche Angaben in verschiedenen Date
|
||||
- „Zenon von Elea“ → Zenon von Elea (*06.10.2019)
|
||||
- „Nisha of Black Forest“ → Nisha of Black Forest (*28.03.2018)
|
||||
- „Zenon von Elea“ → Zenon von Elea (*06.10.2019)
|
||||
- „Nisha of Black Forest“ → Nisha of Black Forest (*28.03.2018)
|
||||
|
||||
## Nicht ins 8-Loci-Modell abgebildete Tokens (verbatim erhalten)
|
||||
|
||||
@@ -173,11 +186,11 @@ Diese Tokens stehen weiter in `rawGenotype`/`unmappedTokens` — Entscheidung (M
|
||||
| `/+Dezember'2014` | 1 | ? |
|
||||
| `(Ansatz)` | 1 | ? |
|
||||
| `-psp` | 1 | ? |
|
||||
| `G(G)` | 1 | ? |
|
||||
| `!Niereninsuffizienz!` | 1 | ? |
|
||||
| `+09.07.2017` | 1 | ? |
|
||||
| `+2018` | 1 | ? |
|
||||
| `AAA` | 1 | ? |
|
||||
| `chmchm` | 1 | Schreibweise (c[chm]c[chm]) |
|
||||
|
||||
## Wurfchronik — Datenqualitäts-Hinweise
|
||||
|
||||
|
||||
@@ -111,10 +111,15 @@ def main():
|
||||
# Index animals for fast lookup by slug ID and by normalized name+dob
|
||||
animal_by_id = {a["id"]: a for a in animals}
|
||||
animal_by_name_dob = {}
|
||||
animal_by_name = {}
|
||||
for a in animals:
|
||||
key = (ex.norm_name(a["name"]), ex.norm_dob(a["dob"]))
|
||||
if key[0] and key[1]:
|
||||
animal_by_name_dob.setdefault(key, []).append(a)
|
||||
nk = ex.norm_name(a["name"])
|
||||
if nk:
|
||||
animal_by_name.setdefault(nk, []).append(a)
|
||||
|
||||
|
||||
# 2. Extract and resolve unique Contacts (Breeders & Zuchten)
|
||||
print("Extracting unique contacts...")
|
||||
@@ -163,8 +168,36 @@ def main():
|
||||
l_parents = litter_parent_map.setdefault(l_id, [None, None]) # [father, mother]
|
||||
|
||||
for p_ref in a.get("parentRefs", []):
|
||||
p_key = (ex.norm_name(p_ref["name"]), ex.norm_dob(p_ref["dob"]))
|
||||
p_dob = ex.norm_dob(p_ref.get("dob", ""))
|
||||
p_key = (ex.norm_name(p_ref["name"]), p_dob)
|
||||
p_candidates = animal_by_name_dob.get(p_key, [])
|
||||
if not p_candidates:
|
||||
# Fallback to name-only lookup when parent DOB is empty/not found
|
||||
p_norm = ex.norm_name(p_ref["name"])
|
||||
candidates = animal_by_name.get(p_norm, [])
|
||||
if candidates:
|
||||
offspring_dob_str = parse_date_only(a["dob"])
|
||||
if offspring_dob_str:
|
||||
try:
|
||||
o_dob = datetime.strptime(offspring_dob_str, "%Y-%m-%d")
|
||||
valid_candidates = []
|
||||
for cand in candidates:
|
||||
cand_dob_str = parse_date_only(cand["dob"])
|
||||
if cand_dob_str:
|
||||
try:
|
||||
c_dob = datetime.strptime(cand_dob_str, "%Y-%m-%d")
|
||||
if c_dob < o_dob:
|
||||
valid_candidates.append(cand)
|
||||
except ValueError:
|
||||
valid_candidates.append(cand)
|
||||
else:
|
||||
valid_candidates.append(cand)
|
||||
if valid_candidates:
|
||||
p_candidates = [valid_candidates[0]]
|
||||
except ValueError:
|
||||
p_candidates = [candidates[0]]
|
||||
else:
|
||||
p_candidates = [candidates[0]]
|
||||
if p_candidates:
|
||||
p_guid = animal_guid_map[p_candidates[0]["id"]]
|
||||
if p_ref["roleGuess"] == "father":
|
||||
|
||||
Reference in New Issue
Block a user