"""BAN YARO — Tierschutz-Check für Züchter Regelbasierte Prüfung bei Verpaarungen und Wurfanlage. Läuft immer automatisch, ist nicht abschaltbar. """ import logging from datetime import date logger = logging.getLogger(__name__) # VDH-Richtwerte (Orientierung, nicht Gesetz) MIN_ALTER_MONATE = 18 # Mindestalter Zuchthündin MAX_ALTER_JAHRE = 8 # Empfohlenes Höchstalter MAX_WUERFE_LIFETIME = 4 # VDH-Empfehlung MIN_PAUSE_TAGE_WARN = 365 # 12 Monate Mindestpause (Warnung) MIN_PAUSE_TAGE_KRIT = 270 # 9 Monate (Kritisch) IK_WARN_PROZENT = 6.25 IK_KRIT_PROZENT = 12.5 def _level_max(a, b): order = {"ok": 0, "info": 1, "warning": 2, "critical": 3} return a if order.get(a, 0) >= order.get(b, 0) else b def check_welfare(conn, breeder_id: int, vater_id: int = None, mutter_id: int = None, ik_prozent: float = None, genetic_risks: list = None) -> dict: """ Gibt zurück: { "level": "ok" | "info" | "warning" | "critical", "issues": [{"code": str, "level": str, "text": str}], "ok_points": [str] # Positive Punkte } """ issues = [] ok_pts = [] level = "ok" # ------------------------------------------------------------------ # 1. Inzuchtkoeffizient # ------------------------------------------------------------------ if ik_prozent is not None: if ik_prozent >= IK_KRIT_PROZENT: issues.append({ "code": "IK_KRITISCH", "level": "critical", "text": f"Inzuchtkoeffizient {ik_prozent:.1f}% — kritisch (≥{IK_KRIT_PROZENT}%). " "Das erhöht das Risiko für erbliche Erkrankungen und Vitalitätsverlust erheblich.", }) elif ik_prozent >= IK_WARN_PROZENT: issues.append({ "code": "IK_ERHOEHT", "level": "warning", "text": f"Inzuchtkoeffizient {ik_prozent:.1f}% — erhöht (≥{IK_WARN_PROZENT}%). " "VDH-Empfehlung liegt unter 6,25%.", }) elif ik_prozent < 2.5: ok_pts.append(f"Sehr niedriger Inzuchtkoeffizient ({ik_prozent:.1f}%) — genetische Vielfalt ist gut.") # ------------------------------------------------------------------ # 2. Genetische Risiken (Träger × Träger / Affected) # ------------------------------------------------------------------ if genetic_risks: for r in genetic_risks: if r.get("offspring_risk") and "betroffen" in r.get("offspring_risk", ""): pct_text = r["offspring_risk"] if "100%" in pct_text: issues.append({ "code": f"GENETIK_KRITISCH_{r['marker']}", "level": "critical", "text": f"Genetisches Risiko {r['marker']}: {pct_text}. " "Alle Nachkommen wären betroffen.", }) elif "50%" in pct_text: issues.append({ "code": f"GENETIK_HOCH_{r['marker']}", "level": "critical", "text": f"Genetisches Risiko {r['marker']}: {pct_text}.", }) elif "25%" in pct_text: issues.append({ "code": f"GENETIK_WARN_{r['marker']}", "level": "warning", "text": f"Genetisches Risiko {r['marker']}: {pct_text}. " "Jeder 4. Welpe könnte betroffen sein.", }) # ------------------------------------------------------------------ # 3. Zuchthündin-Checks # ------------------------------------------------------------------ if mutter_id: try: hund = conn.execute( "SELECT name, geburtsdatum FROM zucht_hunde WHERE id=?", (mutter_id,) ).fetchone() if hund: hund_name = hund["name"] or "Zuchthündin" # Alterscheck if hund["geburtsdatum"]: try: geb = date.fromisoformat(str(hund["geburtsdatum"])[:10]) alter_tage = (date.today() - geb).days alter_monate = alter_tage / 30.44 if alter_monate < MIN_ALTER_MONATE: issues.append({ "code": "MUTTER_ZU_JUNG", "level": "critical", "text": f"{hund_name} ist erst {int(alter_monate)} Monate alt. " f"Mindestalter für Erstzucht: {MIN_ALTER_MONATE} Monate. " "Frühzucht belastet Körper und Psyche des Tieres erheblich.", }) elif alter_monate > MAX_ALTER_JAHRE * 12: issues.append({ "code": "MUTTER_ZU_ALT", "level": "warning", "text": f"{hund_name} ist {int(alter_monate / 12)} Jahre alt " f"(empfohlenes Höchstalter: {MAX_ALTER_JAHRE} Jahre). " "Ältere Hündinnen tragen ein höheres Geburtsrisiko.", }) else: ok_pts.append(f"{hund_name} ist in einem geeigneten Zuchtalter ({int(alter_monate)} Monate).") except ValueError: pass # Wurfanzahl wuerfe_gesamt = conn.execute( "SELECT COUNT(*) FROM litters WHERE breeder_id=? AND mutter_id=?", (breeder_id, mutter_id) ).fetchone()[0] if wuerfe_gesamt > 5: issues.append({ "code": "ZU_VIELE_WUERFE", "level": "critical", "text": f"{hund_name} hatte bereits {wuerfe_gesamt} Würfe. " f"Die VDH-Empfehlung liegt bei maximal {MAX_WUERFE_LIFETIME} Würfen pro Hündin.", }) elif wuerfe_gesamt >= MAX_WUERFE_LIFETIME: issues.append({ "code": "WUERFE_GRENZE", "level": "warning", "text": f"{hund_name} hat bereits {wuerfe_gesamt} Würfe — " f"das entspricht der VDH-Empfehlung von max. {MAX_WUERFE_LIFETIME} Würfen.", }) elif wuerfe_gesamt == 0: ok_pts.append(f"{hund_name} ist noch ohne Vorwürfe.") # Pause seit letztem Wurf letzter = conn.execute( "SELECT MAX(geburt_datum) FROM litters " "WHERE breeder_id=? AND mutter_id=? AND geburt_datum IS NOT NULL", (breeder_id, mutter_id) ).fetchone()[0] if letzter: try: letzter_date = date.fromisoformat(str(letzter)[:10]) abstand = (date.today() - letzter_date).days if abstand < MIN_PAUSE_TAGE_KRIT: issues.append({ "code": "PAUSE_KRITISCH", "level": "critical", "text": f"Letzter Wurf von {hund_name} liegt erst {abstand} Tage zurück " f"({abstand // 30} Monate). " "Für die Erholung von Körper und Hormonhaushalt werden " "mindestens 12–15 Monate empfohlen.", }) elif abstand < MIN_PAUSE_TAGE_WARN: issues.append({ "code": "PAUSE_KURZ", "level": "warning", "text": f"Letzter Wurf von {hund_name}: {abstand // 30} Monate her. " "VDH empfiehlt mindestens 12–15 Monate Pause zwischen Würfen.", }) else: ok_pts.append(f"Ausreichende Pause seit letztem Wurf von {hund_name} ({abstand // 30} Monate).") except ValueError: pass except Exception as e: logger.warning(f"Welfare-Check Mutter fehlgeschlagen: {e}") # ------------------------------------------------------------------ # Vater-Alterscheck (weniger kritisch, aber der Vollständigkeit halber) # ------------------------------------------------------------------ if vater_id: try: rüde = conn.execute( "SELECT name, geburtsdatum FROM zucht_hunde WHERE id=?", (vater_id,) ).fetchone() if rüde and rüde["geburtsdatum"]: geb = date.fromisoformat(str(rüde["geburtsdatum"])[:10]) alter_monate = (date.today() - geb).days / 30.44 if alter_monate < 12: issues.append({ "code": "VATER_ZU_JUNG", "level": "warning", "text": f"Deckrüde {rüde['name']} ist erst {int(alter_monate)} Monate alt. " "Empfohlenes Mindestalter: 12 Monate.", }) except Exception: pass # ------------------------------------------------------------------ # Gesamtlevel # ------------------------------------------------------------------ for issue in issues: level = _level_max(level, issue["level"]) if level == "ok" and not ok_pts: ok_pts.append("Alle geprüften Tierschutz-Kriterien sind erfüllt.") return {"level": level, "issues": issues, "ok_points": ok_pts}