ein und Ausgabeverzeichnisse hinzu gemacht.
This commit is contained in:
-356
@@ -1,356 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Auslegung einer Waermerueckgewinnung aus der Milchkuehlung.
|
|
||||||
|
|
||||||
Eingangsgroesse: zu kuehlende Milchmenge pro Tag (Liter).
|
|
||||||
Ausgabe: erforderliche Groesse von Waermepumpe, PV-Anlage, Latentspeicher
|
|
||||||
(Natriumacetat) und Batterie.
|
|
||||||
|
|
||||||
Alle Annahmen stehen in einer JSON-Datei (Standard: config.json), damit sich
|
|
||||||
Varianten leicht nachrechnen lassen.
|
|
||||||
|
|
||||||
Aufruf:
|
|
||||||
python auslegung.py 1000
|
|
||||||
python auslegung.py 1500 --config variante_winterautark.json
|
|
||||||
python auslegung.py 1000 --json ergebnis.json
|
|
||||||
"""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
KJ_PER_KWH = 3600.0
|
|
||||||
TAGE_PRO_JAHR = 365.0
|
|
||||||
|
|
||||||
# Tage je Monat (Schluessel muessen zu pv.monatsertrag_kWh_pro_kWp passen)
|
|
||||||
MONATSTAGE = {
|
|
||||||
"Jan": 31, "Feb": 28, "Mae": 31, "Apr": 30, "Mai": 31, "Jun": 30,
|
|
||||||
"Jul": 31, "Aug": 31, "Sep": 30, "Okt": 31, "Nov": 30, "Dez": 31,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def lade_config(pfad: Path) -> dict:
|
|
||||||
with pfad.open(encoding="utf-8") as f:
|
|
||||||
return json.load(f)
|
|
||||||
|
|
||||||
|
|
||||||
def milch_kuehllast(milch_l_tag: float, cfg: dict) -> float:
|
|
||||||
"""Taeglich der Milch zu entziehende Waerme in kWh/Tag."""
|
|
||||||
m = cfg["milch"]
|
|
||||||
masse = milch_l_tag * m["dichte_kg_pro_L"]
|
|
||||||
dT = m["temp_ein_C"] - m["temp_aus_C"]
|
|
||||||
q_kj = masse * m["spez_waerme_kJ_pro_kgK"] * dT
|
|
||||||
return q_kj / KJ_PER_KWH
|
|
||||||
|
|
||||||
|
|
||||||
def waermepumpe(q_milch_tag: float, cfg: dict) -> dict:
|
|
||||||
"""Strombedarf und Leistungsdaten der Waermepumpe.
|
|
||||||
|
|
||||||
Q_speicher = Q_milch + W_el (die Verdichterarbeit landet als Waerme im Speicher).
|
|
||||||
"""
|
|
||||||
hp = cfg["waermepumpe"]
|
|
||||||
cop = hp["cop"]
|
|
||||||
if cop <= 1.0:
|
|
||||||
raise ValueError("COP muss > 1 sein.")
|
|
||||||
w_el_tag = q_milch_tag / (cop - 1.0)
|
|
||||||
q_speicher_tag = q_milch_tag + w_el_tag
|
|
||||||
laufzeit = hp["laufzeit_h_pro_tag"]
|
|
||||||
return {
|
|
||||||
"strom_kWh_tag": w_el_tag,
|
|
||||||
"speicher_kWh_tag": q_speicher_tag,
|
|
||||||
"kaelteleistung_kW": q_milch_tag / laufzeit, # Verdampferseite
|
|
||||||
"heizleistung_kW": q_speicher_tag / laufzeit, # Kondensatorseite
|
|
||||||
"elektrische_leistung_kW": w_el_tag / laufzeit,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def pcm_energiedichte_kWh_pro_kg(cfg: dict) -> float:
|
|
||||||
"""Nutzbare Energiedichte des PCM je nach Modus."""
|
|
||||||
p = cfg["pcm"]
|
|
||||||
e_kj = p["latentwaerme_kJ_pro_kg"]
|
|
||||||
modus = p["modus"]
|
|
||||||
if modus == "latent_only":
|
|
||||||
pass
|
|
||||||
elif modus == "latent_plus_hub":
|
|
||||||
ueberhitzung = max(0.0, p["ladetemp_C"] - p["schmelzpunkt_C"])
|
|
||||||
unterkuehlung = max(0.0, p["schmelzpunkt_C"] - p["entladetemp_C"])
|
|
||||||
e_kj += p["cp_fluessig_kJ_pro_kgK"] * ueberhitzung
|
|
||||||
e_kj += p["cp_fest_kJ_pro_kgK"] * unterkuehlung
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unbekannter pcm.modus: {modus!r}")
|
|
||||||
return e_kj / KJ_PER_KWH
|
|
||||||
|
|
||||||
|
|
||||||
def speicher(q_speicher_tag: float, cfg: dict, zyklus: float | None = None) -> dict:
|
|
||||||
"""Groesse des Latentspeichers fuer einen Abholzyklus + LKW-Abgleich.
|
|
||||||
|
|
||||||
zyklus: Abholzyklus in Tagen. None -> Wert aus der Config.
|
|
||||||
"""
|
|
||||||
a = cfg["abholung"]
|
|
||||||
p = cfg["pcm"]
|
|
||||||
if zyklus is None:
|
|
||||||
zyklus = a["zyklus_tage"]
|
|
||||||
e_kg = pcm_energiedichte_kWh_pro_kg(cfg)
|
|
||||||
|
|
||||||
e_zyklus = q_speicher_tag * zyklus # kWh je Abholzyklus
|
|
||||||
masse_kg = e_zyklus / e_kg
|
|
||||||
volumen_m3 = masse_kg / (p["dichte_kg_pro_L"] * 1000.0)
|
|
||||||
|
|
||||||
nutzlast = a["lkw_nutzlast_kg"]
|
|
||||||
lkw_vol = a["lkw_volumen_m3"]
|
|
||||||
# Welche Grenze bindet?
|
|
||||||
if masse_kg > nutzlast or volumen_m3 > lkw_vol:
|
|
||||||
bindend = "Gewicht" if masse_kg / nutzlast >= volumen_m3 / lkw_vol else "Volumen"
|
|
||||||
passt = False
|
|
||||||
else:
|
|
||||||
bindend = "Gewicht" if masse_kg / nutzlast >= volumen_m3 / lkw_vol else "Volumen"
|
|
||||||
passt = True
|
|
||||||
|
|
||||||
# Wie oft muesste ein voller LKW (nach Gewicht) getauscht werden?
|
|
||||||
masse_pro_tag = q_speicher_tag / e_kg
|
|
||||||
voll_lkw_tage = nutzlast / masse_pro_tag if masse_pro_tag > 0 else float("inf")
|
|
||||||
|
|
||||||
return {
|
|
||||||
"energiedichte_kWh_pro_kg": e_kg,
|
|
||||||
"energie_pro_zyklus_kWh": e_zyklus,
|
|
||||||
"masse_kg": masse_kg,
|
|
||||||
"volumen_m3": volumen_m3,
|
|
||||||
"auslastung_gewicht": masse_kg / nutzlast,
|
|
||||||
"auslastung_volumen": volumen_m3 / lkw_vol,
|
|
||||||
"bindende_grenze": bindend,
|
|
||||||
"passt_in_einen_lkw": passt,
|
|
||||||
"voller_lkw_tausch_tage": voll_lkw_tage,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def pv_anlage(w_el_tag: float, cfg: dict) -> dict:
|
|
||||||
"""PV-Groesse fuer Jahresbilanz des WP-Strombedarfs."""
|
|
||||||
pv = cfg["pv"]
|
|
||||||
jahresbedarf = w_el_tag * TAGE_PRO_JAHR
|
|
||||||
kwp = jahresbedarf / pv["spez_ertrag_kWh_pro_kWp_jahr"]
|
|
||||||
flaeche = kwp * pv["flaeche_m2_pro_kWp"]
|
|
||||||
return {
|
|
||||||
"jahresbedarf_kWh": jahresbedarf,
|
|
||||||
"kWp": kwp,
|
|
||||||
"flaeche_m2": flaeche,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def netzbezug(w_el_tag: float, kwp: float, cfg: dict) -> dict:
|
|
||||||
"""Monatsbilanz -> jaehrlicher Netzbezug durch den Winter."""
|
|
||||||
monats = cfg["pv"]["monatsertrag_kWh_pro_kWp"]
|
|
||||||
bezug = 0.0
|
|
||||||
ueberschuss = 0.0
|
|
||||||
jahresbedarf = 0.0
|
|
||||||
monatsdetail = {}
|
|
||||||
for monat, tage in MONATSTAGE.items():
|
|
||||||
bedarf = w_el_tag * tage
|
|
||||||
erzeugung = monats[monat] * kwp
|
|
||||||
jahresbedarf += bedarf
|
|
||||||
defizit = max(0.0, bedarf - erzeugung)
|
|
||||||
ueber = max(0.0, erzeugung - bedarf)
|
|
||||||
bezug += defizit
|
|
||||||
ueberschuss += ueber
|
|
||||||
monatsdetail[monat] = {
|
|
||||||
"bedarf_kWh": bedarf,
|
|
||||||
"pv_kWh": erzeugung,
|
|
||||||
"zukauf_kWh": defizit,
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
"netzbezug_kWh": bezug,
|
|
||||||
"ueberschuss_kWh": ueberschuss,
|
|
||||||
"jahresbedarf_kWh": jahresbedarf,
|
|
||||||
"netzbezug_anteil": bezug / jahresbedarf if jahresbedarf else 0.0,
|
|
||||||
"monate": monatsdetail,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def batterie(w_el_tag: float, cfg: dict) -> dict:
|
|
||||||
"""Batteriegroesse zur Ueberbbrueckung des Tag-/Nacht-Versatzes."""
|
|
||||||
b = cfg["batterie"]
|
|
||||||
nacht_anteil = 1.0 - b["direkt_pv_stunden"] / 24.0
|
|
||||||
nutzbar = w_el_tag * nacht_anteil * b["reserve_faktor"]
|
|
||||||
nominal = nutzbar / b["nutzbar_anteil"]
|
|
||||||
return {
|
|
||||||
"nutzbar_kWh": nutzbar,
|
|
||||||
"nominal_kWh": nominal,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def rechne(milch_l_tag: float, cfg: dict) -> dict:
|
|
||||||
q_milch = milch_kuehllast(milch_l_tag, cfg)
|
|
||||||
wp = waermepumpe(q_milch, cfg)
|
|
||||||
sp = speicher(wp["speicher_kWh_tag"], cfg)
|
|
||||||
pv = pv_anlage(wp["strom_kWh_tag"], cfg)
|
|
||||||
netz = netzbezug(wp["strom_kWh_tag"], pv["kWp"], cfg)
|
|
||||||
bat = batterie(wp["strom_kWh_tag"], cfg)
|
|
||||||
return {
|
|
||||||
"eingang": {"milch_l_tag": milch_l_tag},
|
|
||||||
"milch_kuehllast_kWh_tag": q_milch,
|
|
||||||
"waermepumpe": wp,
|
|
||||||
"speicher": sp,
|
|
||||||
"pv": pv,
|
|
||||||
"netzbezug": netz,
|
|
||||||
"batterie": bat,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def runde_auf(wert: float, schritt: float) -> float:
|
|
||||||
"""Auf das naechste Vielfache von 'schritt' aufrunden (praktische Groessen)."""
|
|
||||||
return math.ceil(wert / schritt) * schritt
|
|
||||||
|
|
||||||
|
|
||||||
def vorschlag(e: dict, cfg: dict) -> dict:
|
|
||||||
"""Empfohlene, auf praktische Groessen gerundete Auslegung.
|
|
||||||
|
|
||||||
PV und Batterie sind unabhaengig vom Abholzyklus. Fuer den Speicher wird
|
|
||||||
der groesste Wochen-Zyklus empfohlen, der noch in einen LKW passt
|
|
||||||
(beste Transportauslastung, wenigste Fahrten).
|
|
||||||
"""
|
|
||||||
wp = e["waermepumpe"]
|
|
||||||
pv = e["pv"]
|
|
||||||
bat = e["batterie"]
|
|
||||||
q_speicher_tag = wp["speicher_kWh_tag"]
|
|
||||||
|
|
||||||
e_kg = pcm_energiedichte_kWh_pro_kg(cfg)
|
|
||||||
masse_pro_tag = q_speicher_tag / e_kg
|
|
||||||
nutzlast = cfg["abholung"]["lkw_nutzlast_kg"]
|
|
||||||
voll_lkw_tage = nutzlast / masse_pro_tag if masse_pro_tag > 0 else float("inf")
|
|
||||||
|
|
||||||
# Kandidaten im Wochenraster, die in einen LKW passen
|
|
||||||
kandidaten = []
|
|
||||||
z = 7
|
|
||||||
while z <= voll_lkw_tage:
|
|
||||||
kandidaten.append((z, speicher(q_speicher_tag, cfg, zyklus=z)))
|
|
||||||
z += 7
|
|
||||||
|
|
||||||
if kandidaten:
|
|
||||||
empf_zyklus = kandidaten[-1][0]
|
|
||||||
else:
|
|
||||||
# LKW schon vor einer Woche voll -> haeufige Abholung noetig
|
|
||||||
empf_zyklus = max(1, math.floor(voll_lkw_tage))
|
|
||||||
empf_speicher = speicher(q_speicher_tag, cfg, zyklus=empf_zyklus)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"pv_kWp": runde_auf(pv["kWp"], 0.5),
|
|
||||||
"pv_flaeche_m2": runde_auf(pv["flaeche_m2"], 5),
|
|
||||||
"batterie_kWh": runde_auf(bat["nominal_kWh"], 5),
|
|
||||||
"voll_lkw_tage": voll_lkw_tage,
|
|
||||||
"empf_zyklus_tage": empf_zyklus,
|
|
||||||
"empf_speicher": empf_speicher,
|
|
||||||
"kandidaten": kandidaten,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def vorschlag_report(e: dict, cfg: dict) -> str:
|
|
||||||
v = vorschlag(e, cfg)
|
|
||||||
sp = v["empf_speicher"]
|
|
||||||
L = []
|
|
||||||
L.append("=" * 62)
|
|
||||||
L.append(f" EMPFOHLENE AUSLEGUNG ({e['eingang']['milch_l_tag']:.0f} L Milch/Tag)")
|
|
||||||
L.append("=" * 62)
|
|
||||||
L.append(f"PV-Anlage ............ ~{v['pv_kWp']:.1f} kWp (~{v['pv_flaeche_m2']:.0f} m2 Dachflaeche)")
|
|
||||||
L.append(f"Stromspeicher ........ ~{v['batterie_kWh']:.0f} kWh (Nennkapazitaet, LFP)")
|
|
||||||
L.append(f"Waermespeicher ....... ~{sp['masse_kg']/1000:.1f} t (~{sp['volumen_m3']:.1f} m3 {cfg['pcm']['name']})")
|
|
||||||
L.append(f"Abholzyklus .......... alle {v['empf_zyklus_tage']:.0f} Tage")
|
|
||||||
L.append("")
|
|
||||||
L.append(f" -> LKW dann zu {sp['auslastung_gewicht']*100:.0f} % ausgelastet "
|
|
||||||
f"({sp['energie_pro_zyklus_kWh']:.0f} kWh je Fuhre)")
|
|
||||||
L.append(f" -> ein voller LKW waere nach {v['voll_lkw_tage']:.0f} Tagen erreicht")
|
|
||||||
L.append("")
|
|
||||||
L.append("Abholoptionen (Latentspeicher je Zyklus):")
|
|
||||||
L.append(f" {'Zyklus':>8} | {'Masse':>8} | {'Volumen':>8} | {'LKW-Ausl.':>9}")
|
|
||||||
L.append(f" {'-'*8}-+-{'-'*8}-+-{'-'*8}-+-{'-'*9}")
|
|
||||||
for z, s in v["kandidaten"]:
|
|
||||||
marker = " <== empfohlen" if z == v["empf_zyklus_tage"] else ""
|
|
||||||
L.append(f" {z:>5.0f} Tg | {s['masse_kg']/1000:>6.1f} t | "
|
|
||||||
f"{s['volumen_m3']:>6.1f} m3 | {s['auslastung_gewicht']*100:>7.0f} %{marker}")
|
|
||||||
if not v["kandidaten"]:
|
|
||||||
L.append(" (LKW bereits vor einer Woche voll - haeufigere Abholung noetig)")
|
|
||||||
L.append("=" * 62)
|
|
||||||
return "\n".join(L)
|
|
||||||
|
|
||||||
|
|
||||||
def report(e: dict, cfg: dict) -> str:
|
|
||||||
q = e["milch_kuehllast_kWh_tag"]
|
|
||||||
wp = e["waermepumpe"]
|
|
||||||
sp = e["speicher"]
|
|
||||||
pv = e["pv"]
|
|
||||||
netz = e["netzbezug"]
|
|
||||||
bat = e["batterie"]
|
|
||||||
z = cfg["abholung"]["zyklus_tage"]
|
|
||||||
L = []
|
|
||||||
L.append("=" * 62)
|
|
||||||
L.append(f" AUSLEGUNG WAERMERUECKGEWINNUNG MILCHKUEHLUNG")
|
|
||||||
L.append(f" Eingang: {e['eingang']['milch_l_tag']:.0f} L Milch/Tag"
|
|
||||||
f" ({cfg['milch']['temp_ein_C']:.0f} -> {cfg['milch']['temp_aus_C']:.0f} C)")
|
|
||||||
L.append("=" * 62)
|
|
||||||
L.append(f"Kuehllast der Milch ........... {q:8.1f} kWh/Tag")
|
|
||||||
L.append("")
|
|
||||||
L.append("WAERMEPUMPE (COP {:.2f}, Laufzeit {:.0f} h/Tag)".format(
|
|
||||||
cfg["waermepumpe"]["cop"], cfg["waermepumpe"]["laufzeit_h_pro_tag"]))
|
|
||||||
L.append(f" Kaelteleistung (Verdampfer) . {wp['kaelteleistung_kW']:8.1f} kW")
|
|
||||||
L.append(f" Heizleistung (Kondensator) .. {wp['heizleistung_kW']:8.1f} kW")
|
|
||||||
L.append(f" el. Leistung ................ {wp['elektrische_leistung_kW']:8.1f} kW")
|
|
||||||
L.append(f" Strombedarf ................. {wp['strom_kWh_tag']:8.1f} kWh/Tag")
|
|
||||||
L.append(f" Waerme in den Speicher ...... {wp['speicher_kWh_tag']:8.1f} kWh/Tag")
|
|
||||||
L.append("")
|
|
||||||
L.append("PV-ANLAGE (Jahresbilanz)")
|
|
||||||
L.append(f" Jahresstrombedarf WP ........ {pv['jahresbedarf_kWh']:8.0f} kWh/a")
|
|
||||||
L.append(f" Leistung .................... {pv['kWp']:8.1f} kWp")
|
|
||||||
L.append(f" Dachflaeche ................. {pv['flaeche_m2']:8.0f} m2")
|
|
||||||
L.append("")
|
|
||||||
L.append(f"NETZBEZUG (durch Wintermonate, Monatsbilanz)")
|
|
||||||
L.append(f" Netzbezug ................... {netz['netzbezug_kWh']:8.0f} kWh/a"
|
|
||||||
f" = {netz['netzbezug_anteil']*100:.0f} %")
|
|
||||||
L.append(f" Sommerueberschuss ........... {netz['ueberschuss_kWh']:8.0f} kWh/a")
|
|
||||||
L.append("")
|
|
||||||
L.append("BATTERIE (Tag-/Nacht-Ueberbbrueckung)")
|
|
||||||
L.append(f" nutzbare Kapazitaet ......... {bat['nutzbar_kWh']:8.1f} kWh")
|
|
||||||
L.append(f" Nennkapazitaet .............. {bat['nominal_kWh']:8.1f} kWh")
|
|
||||||
L.append("")
|
|
||||||
L.append(f"LATENTSPEICHER ({cfg['pcm']['name']}, Modus: {cfg['pcm']['modus']})")
|
|
||||||
L.append(f" Energiedichte ............... {sp['energiedichte_kWh_pro_kg']*1000:8.1f} Wh/kg")
|
|
||||||
L.append(f" Energie je Zyklus ({z:>2} Tage) . {sp['energie_pro_zyklus_kWh']:8.0f} kWh")
|
|
||||||
L.append(f" Masse ....................... {sp['masse_kg']:8.0f} kg")
|
|
||||||
L.append(f" Volumen ..................... {sp['volumen_m3']:8.1f} m3")
|
|
||||||
L.append(f" LKW-Auslastung Gewicht ...... {sp['auslastung_gewicht']*100:8.0f} %")
|
|
||||||
L.append(f" LKW-Auslastung Volumen ...... {sp['auslastung_volumen']*100:8.0f} %")
|
|
||||||
L.append(f" bindende Grenze ............. {sp['bindende_grenze']:>8}")
|
|
||||||
passt = "ja" if sp["passt_in_einen_lkw"] else "NEIN -> mehrere Behaelter noetig"
|
|
||||||
L.append(f" passt in einen LKW .......... {passt:>8}")
|
|
||||||
L.append(f" voller LKW voll nach ........ {sp['voller_lkw_tausch_tage']:8.1f} Tagen")
|
|
||||||
L.append("=" * 62)
|
|
||||||
return "\n".join(L)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
ap = argparse.ArgumentParser(description=__doc__,
|
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
||||||
ap.add_argument("milch_l_tag", type=float, help="Milchmenge pro Tag in Litern")
|
|
||||||
ap.add_argument("--config", type=Path, default=Path(__file__).with_name("config.json"),
|
|
||||||
help="Pfad zur JSON-Konfiguration (Standard: config.json)")
|
|
||||||
ap.add_argument("--json", type=Path, default=None,
|
|
||||||
help="Ergebnis zusaetzlich als JSON in diese Datei schreiben")
|
|
||||||
ap.add_argument("--suggest-size", action="store_true",
|
|
||||||
help="Kompakte Empfehlung (gerundete Groessen + Abholzyklus) statt Detailreport")
|
|
||||||
args = ap.parse_args()
|
|
||||||
|
|
||||||
cfg = lade_config(args.config)
|
|
||||||
ergebnis = rechne(args.milch_l_tag, cfg)
|
|
||||||
|
|
||||||
if args.suggest_size:
|
|
||||||
print(vorschlag_report(ergebnis, cfg))
|
|
||||||
ergebnis["vorschlag"] = vorschlag(ergebnis, cfg)
|
|
||||||
else:
|
|
||||||
print(report(ergebnis, cfg))
|
|
||||||
|
|
||||||
if args.json:
|
|
||||||
with args.json.open("w", encoding="utf-8") as f:
|
|
||||||
json.dump(ergebnis, f, ensure_ascii=False, indent=2)
|
|
||||||
print(f"\nErgebnis geschrieben: {args.json}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
+3
-1
@@ -6,4 +6,6 @@ IF NOT DEFINED MILCH_HOME (
|
|||||||
)
|
)
|
||||||
IF NOT DEFINED MILCH_LIB SET MILCH_LIB=%MILCH_HOME%\lib
|
IF NOT DEFINED MILCH_LIB SET MILCH_LIB=%MILCH_HOME%\lib
|
||||||
IF NOT DEFINED MILCH_CFG SET MILCH_CFG=%MILCH_HOME%\cfg
|
IF NOT DEFINED MILCH_CFG SET MILCH_CFG=%MILCH_HOME%\cfg
|
||||||
python "%MILCH_LIB%\auslegung.py" --config "%MILCH_CFG%\config.json" %*
|
IF NOT DEFINED MILCH_IN SET MILCH_IN=%MILCH_HOME%\in
|
||||||
|
IF NOT DEFINED MILCH_OUT SET MILCH_OUT=%MILCH_HOME%\out
|
||||||
|
python "%MILCH_LIB%\auslegung.py" --config "%MILCH_CFG%\config.json" --out "%MILCH_OUT%" %*
|
||||||
|
|||||||
+3
-1
@@ -4,4 +4,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
MILCH_HOME="${MILCH_HOME:-$(dirname "$SCRIPT_DIR")}"
|
MILCH_HOME="${MILCH_HOME:-$(dirname "$SCRIPT_DIR")}"
|
||||||
MILCH_LIB="${MILCH_LIB:-$MILCH_HOME/lib}"
|
MILCH_LIB="${MILCH_LIB:-$MILCH_HOME/lib}"
|
||||||
MILCH_CFG="${MILCH_CFG:-$MILCH_HOME/cfg}"
|
MILCH_CFG="${MILCH_CFG:-$MILCH_HOME/cfg}"
|
||||||
exec python3 "$MILCH_LIB/auslegung.py" --config "$MILCH_CFG/config.json" "$@"
|
MILCH_IN="${MILCH_IN:-$MILCH_HOME/in}"
|
||||||
|
MILCH_OUT="${MILCH_OUT:-$MILCH_HOME/out}"
|
||||||
|
exec python3 "$MILCH_LIB/auslegung.py" --config "$MILCH_CFG/config.json" --out "$MILCH_OUT" "$@"
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ IF "%MILCH_HOME:~-1%"=="\" SET MILCH_HOME=%MILCH_HOME:~0,-1%
|
|||||||
SET MILCH_BIN=%MILCH_HOME%\bin
|
SET MILCH_BIN=%MILCH_HOME%\bin
|
||||||
SET MILCH_LIB=%MILCH_HOME%\lib
|
SET MILCH_LIB=%MILCH_HOME%\lib
|
||||||
SET MILCH_CFG=%MILCH_HOME%\cfg
|
SET MILCH_CFG=%MILCH_HOME%\cfg
|
||||||
|
SET MILCH_IN=%MILCH_HOME%\in
|
||||||
|
SET MILCH_OUT=%MILCH_HOME%\out
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ export MILCH_HOME="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|||||||
export MILCH_BIN="$MILCH_HOME/bin"
|
export MILCH_BIN="$MILCH_HOME/bin"
|
||||||
export MILCH_LIB="$MILCH_HOME/lib"
|
export MILCH_LIB="$MILCH_HOME/lib"
|
||||||
export MILCH_CFG="$MILCH_HOME/cfg"
|
export MILCH_CFG="$MILCH_HOME/cfg"
|
||||||
|
export MILCH_IN="$MILCH_HOME/in"
|
||||||
|
export MILCH_OUT="$MILCH_HOME/out"
|
||||||
|
|||||||
@@ -59,5 +59,12 @@
|
|||||||
"ww_kind_kWh_tag": 1.0,
|
"ww_kind_kWh_tag": 1.0,
|
||||||
"heizbedarf_winter_kWh_tag": 60.0,
|
"heizbedarf_winter_kWh_tag": 60.0,
|
||||||
"_kommentar": "Warmwasser je Person/Tag. heizbedarf_winter = max. taeglicher Raumheizbedarf eines Haushalts im tiefsten Winter, stark gebaeudeabhaengig (Neubau/saniert ~40, Altbau ~100). Auf 0 setzen, wenn nur Warmwasser betrachtet werden soll."
|
"_kommentar": "Warmwasser je Person/Tag. heizbedarf_winter = max. taeglicher Raumheizbedarf eines Haushalts im tiefsten Winter, stark gebaeudeabhaengig (Neubau/saniert ~40, Altbau ~100). Auf 0 setzen, wenn nur Warmwasser betrachtet werden soll."
|
||||||
|
},
|
||||||
|
|
||||||
|
"brennstoffe": {
|
||||||
|
"gas": {"preis_ct_pro_kWh": 11.0, "wirkungsgrad": 0.95},
|
||||||
|
"oel": {"preis_ct_pro_kWh": 11.5, "wirkungsgrad": 0.90},
|
||||||
|
"pellets": {"preis_ct_pro_kWh": 7.0, "wirkungsgrad": 0.88},
|
||||||
|
"_kommentar": "Vergleichswert: was der Kaeufer fuer dieselbe Nutzwaerme aus fossilen/Holz-Brennstoffen zahlen wuerde. preis_ct_pro_kWh = Brennstoffpreis je kWh Brennstoffenergie (Stand Juni 2026, Deutschland: Gas ~11, Oel ~11.5 (=115 ct/L bei 10 kWh/L), Pellets ~7 (=350 EUR/t bei 5 kWh/kg)). wirkungsgrad = Kesselwirkungsgrad. Nutzwaermekosten = preis/wirkungsgrad."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-54
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
"_beschreibung": "Annahmen fuer die Auslegung der Waermerueckgewinnung aus der Milchkuehlung. Eine Variante laesst sich nachrechnen, indem man diese Datei kopiert und Werte aendert.",
|
|
||||||
|
|
||||||
"milch": {
|
|
||||||
"temp_ein_C": 37.0,
|
|
||||||
"temp_aus_C": 4.0,
|
|
||||||
"dichte_kg_pro_L": 1.0,
|
|
||||||
"spez_waerme_kJ_pro_kgK": 4.186,
|
|
||||||
"_kommentar": "Milch wird als Wasser gerechnet. Eutertemperatur -> Lagertemperatur."
|
|
||||||
},
|
|
||||||
|
|
||||||
"waermepumpe": {
|
|
||||||
"cop": 2.6,
|
|
||||||
"laufzeit_h_pro_tag": 18.0,
|
|
||||||
"_kommentar": "COP fuer den Hub von ~0 C (Verdampfer) auf >58 C (Kondensator). Laufzeit bestimmt die Leistungsauslegung (kW)."
|
|
||||||
},
|
|
||||||
|
|
||||||
"pcm": {
|
|
||||||
"name": "Natriumacetat-Trihydrat",
|
|
||||||
"schmelzpunkt_C": 58.0,
|
|
||||||
"latentwaerme_kJ_pro_kg": 264.0,
|
|
||||||
"dichte_kg_pro_L": 1.3,
|
|
||||||
"cp_fluessig_kJ_pro_kgK": 2.9,
|
|
||||||
"cp_fest_kJ_pro_kgK": 1.9,
|
|
||||||
"modus": "latent_plus_hub",
|
|
||||||
"ladetemp_C": 80.0,
|
|
||||||
"entladetemp_C": 58.0,
|
|
||||||
"_kommentar": "modus = 'latent_only' (nur Phasenwechsel) oder 'latent_plus_hub' (zusaetzlich fuehlbare Waerme durch Ueberhitzung der Schmelze auf ladetemp_C und optionale Unterkuehlung des Feststoffs bis entladetemp_C)."
|
|
||||||
},
|
|
||||||
|
|
||||||
"abholung": {
|
|
||||||
"zyklus_tage": 14,
|
|
||||||
"lkw_nutzlast_kg": 24000,
|
|
||||||
"lkw_volumen_m3": 90,
|
|
||||||
"_kommentar": "zyklus_tage = wie oft der Speicher geleert/abgeholt wird. LKW-Grenzen = Standard-Sattelauflieger."
|
|
||||||
},
|
|
||||||
|
|
||||||
"pv": {
|
|
||||||
"spez_ertrag_kWh_pro_kWp_jahr": 1000,
|
|
||||||
"flaeche_m2_pro_kWp": 5.0,
|
|
||||||
"monatsertrag_kWh_pro_kWp": {
|
|
||||||
"Jan": 30, "Feb": 45, "Mae": 85, "Apr": 115, "Mai": 130, "Jun": 130,
|
|
||||||
"Jul": 135, "Aug": 120, "Sep": 95, "Okt": 60, "Nov": 32, "Dez": 25
|
|
||||||
},
|
|
||||||
"_kommentar": "Werte fuer optimal geneigte Suedflaeche, Standort Suedbayern. Summe der Monate ~ spez_ertrag."
|
|
||||||
},
|
|
||||||
|
|
||||||
"batterie": {
|
|
||||||
"direkt_pv_stunden": 9.0,
|
|
||||||
"nutzbar_anteil": 0.9,
|
|
||||||
"reserve_faktor": 1.2,
|
|
||||||
"_kommentar": "direkt_pv_stunden = Stunden/Tag, in denen die WP direkt aus PV laeuft. Rest wird ueber die Batterie ueberbrueckt. reserve_faktor = Sicherheitszuschlag, nutzbar_anteil = Entladetiefe (LFP ~0.9)."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+170
-9
@@ -5,24 +5,30 @@ Eingangsgroesse: zu kuehlende Milchmenge pro Tag (Liter).
|
|||||||
Ausgabe: erforderliche Groesse von Waermepumpe, PV-Anlage, Latentspeicher
|
Ausgabe: erforderliche Groesse von Waermepumpe, PV-Anlage, Latentspeicher
|
||||||
(Natriumacetat) und Batterie.
|
(Natriumacetat) und Batterie.
|
||||||
|
|
||||||
Alle Annahmen stehen in einer JSON-Datei (Standard: config.json), damit sich
|
Alle Annahmen stehen in einer JSON-Datei (Standard: cfg/config.json), damit sich
|
||||||
Varianten leicht nachrechnen lassen.
|
Varianten leicht nachrechnen lassen. Eine Datei im in/-Ordner (oder --file) kann
|
||||||
|
einzelne Werte gezielt ueberschreiben.
|
||||||
|
|
||||||
Aufruf:
|
Aufruf:
|
||||||
python auslegung.py 1000
|
python auslegung.py 1000
|
||||||
python auslegung.py 1500 --config variante_winterautark.json
|
python auslegung.py 1500 --file in/variante_winter.json
|
||||||
python auslegung.py 1000 --json ergebnis.json
|
python auslegung.py 1000 -v
|
||||||
|
python auslegung.py 1000 --json ergebnis.json -v
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import datetime
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
KJ_PER_KWH = 3600.0
|
KJ_PER_KWH = 3600.0
|
||||||
TAGE_PRO_JAHR = 365.0
|
TAGE_PRO_JAHR = 365.0
|
||||||
|
|
||||||
|
PROJECT_ROOT = Path(__file__).parent.parent
|
||||||
|
|
||||||
# Tage je Monat (Schluessel muessen zu pv.monatsertrag_kWh_pro_kWp passen)
|
# Tage je Monat (Schluessel muessen zu pv.monatsertrag_kWh_pro_kWp passen)
|
||||||
MONATSTAGE = {
|
MONATSTAGE = {
|
||||||
"Jan": 31, "Feb": 28, "Mae": 31, "Apr": 30, "Mai": 31, "Jun": 30,
|
"Jan": 31, "Feb": 28, "Mae": 31, "Apr": 30, "Mai": 31, "Jun": 30,
|
||||||
@@ -35,6 +41,17 @@ def lade_config(pfad: Path) -> dict:
|
|||||||
return json.load(f)
|
return json.load(f)
|
||||||
|
|
||||||
|
|
||||||
|
def deep_merge(base: dict, override: dict) -> dict:
|
||||||
|
"""Rekursives Zusammenfuehren zweier Dicts; override gewinnt bei Konflikten."""
|
||||||
|
result = base.copy()
|
||||||
|
for key, value in override.items():
|
||||||
|
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
||||||
|
result[key] = deep_merge(result[key], value)
|
||||||
|
else:
|
||||||
|
result[key] = value
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def milch_kuehllast(milch_l_tag: float, cfg: dict) -> float:
|
def milch_kuehllast(milch_l_tag: float, cfg: dict) -> float:
|
||||||
"""Taeglich der Milch zu entziehende Waerme in kWh/Tag."""
|
"""Taeglich der Milch zu entziehende Waerme in kWh/Tag."""
|
||||||
m = cfg["milch"]
|
m = cfg["milch"]
|
||||||
@@ -363,31 +380,175 @@ def report(e: dict, cfg: dict) -> str:
|
|||||||
return "\n".join(L)
|
return "\n".join(L)
|
||||||
|
|
||||||
|
|
||||||
|
def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str:
|
||||||
|
q = e["milch_kuehllast_kWh_tag"]
|
||||||
|
wp = e["waermepumpe"]
|
||||||
|
sp = e["speicher"]
|
||||||
|
pv = e["pv"]
|
||||||
|
netz = e["netzbezug"]
|
||||||
|
bat = e["batterie"]
|
||||||
|
hh = e["haushalte"]
|
||||||
|
z = cfg["abholung"]["zyklus_tage"]
|
||||||
|
milch = e["eingang"]["milch_l_tag"]
|
||||||
|
ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||||
|
|
||||||
|
L = []
|
||||||
|
L.append("# Auslegung Waermerueckgewinnung Milchkuehlung")
|
||||||
|
L.append("")
|
||||||
|
L.append(f"**Erstellt:** {ts}")
|
||||||
|
L.append(f"**Eingang:** {milch:.0f} L Milch/Tag"
|
||||||
|
f" ({cfg['milch']['temp_ein_C']:.0f} -> {cfg['milch']['temp_aus_C']:.0f} C)")
|
||||||
|
if quelldateien:
|
||||||
|
L.append(f"**Konfiguration:** {', '.join(quelldateien)}")
|
||||||
|
L.append("")
|
||||||
|
L.append(f"**Kuehllast der Milch:** {q:.1f} kWh/Tag")
|
||||||
|
L.append("")
|
||||||
|
|
||||||
|
L.append("## Waermepumpe")
|
||||||
|
L.append(f"COP {cfg['waermepumpe']['cop']:.2f}, Laufzeit {cfg['waermepumpe']['laufzeit_h_pro_tag']:.0f} h/Tag")
|
||||||
|
L.append("")
|
||||||
|
L.append("| Kenngroesse | Wert |")
|
||||||
|
L.append("|-------------|------|")
|
||||||
|
L.append(f"| Kaelteleistung (Verdampfer) | {wp['kaelteleistung_kW']:.1f} kW |")
|
||||||
|
L.append(f"| Heizleistung (Kondensator) | {wp['heizleistung_kW']:.1f} kW |")
|
||||||
|
L.append(f"| el. Leistung | {wp['elektrische_leistung_kW']:.1f} kW |")
|
||||||
|
L.append(f"| Strombedarf | {wp['strom_kWh_tag']:.1f} kWh/Tag |")
|
||||||
|
L.append(f"| Waerme in den Speicher | {wp['speicher_kWh_tag']:.1f} kWh/Tag |")
|
||||||
|
L.append("")
|
||||||
|
|
||||||
|
L.append("## PV-Anlage (Jahresbilanz)")
|
||||||
|
L.append("")
|
||||||
|
L.append("| Kenngroesse | Wert |")
|
||||||
|
L.append("|-------------|------|")
|
||||||
|
L.append(f"| Jahresstrombedarf WP | {pv['jahresbedarf_kWh']:.0f} kWh/a |")
|
||||||
|
L.append(f"| Leistung | {pv['kWp']:.1f} kWp |")
|
||||||
|
L.append(f"| Dachflaeche | {pv['flaeche_m2']:.0f} m2 |")
|
||||||
|
L.append("")
|
||||||
|
|
||||||
|
L.append("## Netzbezug (Wintermonate, Monatsbilanz)")
|
||||||
|
L.append("")
|
||||||
|
L.append("| Kenngroesse | Wert |")
|
||||||
|
L.append("|-------------|------|")
|
||||||
|
L.append(f"| Netzbezug | {netz['netzbezug_kWh']:.0f} kWh/a = {netz['netzbezug_anteil']*100:.0f} % |")
|
||||||
|
L.append(f"| Sommerueberschuss | {netz['ueberschuss_kWh']:.0f} kWh/a |")
|
||||||
|
L.append("")
|
||||||
|
L.append("### Monatsbilanz")
|
||||||
|
L.append("")
|
||||||
|
L.append("| Monat | Bedarf kWh | PV kWh | Zukauf kWh |")
|
||||||
|
L.append("|-------|-----------|--------|-----------|")
|
||||||
|
for monat, werte in netz["monate"].items():
|
||||||
|
L.append(f"| {monat} | {werte['bedarf_kWh']:.0f} | {werte['pv_kWh']:.0f} | {werte['zukauf_kWh']:.0f} |")
|
||||||
|
L.append("")
|
||||||
|
|
||||||
|
L.append("## Batterie (Tag-/Nacht-Ueberbbrueckung)")
|
||||||
|
L.append("")
|
||||||
|
L.append("| Kenngroesse | Wert |")
|
||||||
|
L.append("|-------------|------|")
|
||||||
|
L.append(f"| nutzbare Kapazitaet | {bat['nutzbar_kWh']:.1f} kWh |")
|
||||||
|
L.append(f"| Nennkapazitaet | {bat['nominal_kWh']:.1f} kWh |")
|
||||||
|
L.append("")
|
||||||
|
|
||||||
|
L.append(f"## Versorgte Haushalte ({cfg['haushalt']['erwachsene']} Erw. + {cfg['haushalt']['kinder']} Kinder)")
|
||||||
|
L.append("")
|
||||||
|
L.append("| Kenngroesse | Wert |")
|
||||||
|
L.append("|-------------|------|")
|
||||||
|
L.append(f"| Warmwasser je Haushalt | {hh['ww_pro_haushalt_kWh_tag']:.1f} kWh/Tag |")
|
||||||
|
L.append(f"| Warmwasser ganzjaehrig | {hh['haushalte_warmwasser']:.1f} Haushalte |")
|
||||||
|
L.append(f"| max. Heizbedarf Winter | {hh['heizbedarf_winter_kWh_tag']:.1f} kWh/Tag/HH |")
|
||||||
|
L.append(f"| Winterbedarf (Heiz+WW) | {hh['winter_pro_haushalt_kWh_tag']:.1f} kWh/Tag/HH |")
|
||||||
|
L.append(f"| im Winter | {hh['haushalte_winter']:.1f} Haushalte |")
|
||||||
|
L.append("")
|
||||||
|
|
||||||
|
passt = "ja" if sp["passt_in_einen_lkw"] else "NEIN - mehrere Behaelter noetig"
|
||||||
|
L.append(f"## Latentspeicher ({cfg['pcm']['name']}, Modus: {cfg['pcm']['modus']})")
|
||||||
|
L.append("")
|
||||||
|
L.append("| Kenngroesse | Wert |")
|
||||||
|
L.append("|-------------|------|")
|
||||||
|
L.append(f"| Energiedichte | {sp['energiedichte_kWh_pro_kg']*1000:.1f} Wh/kg |")
|
||||||
|
L.append(f"| Energie je Zyklus ({z} Tage) | {sp['energie_pro_zyklus_kWh']:.0f} kWh |")
|
||||||
|
L.append(f"| Masse | {sp['masse_kg']:.0f} kg |")
|
||||||
|
L.append(f"| Volumen | {sp['volumen_m3']:.1f} m3 |")
|
||||||
|
L.append(f"| LKW-Auslastung Gewicht | {sp['auslastung_gewicht']*100:.0f} % |")
|
||||||
|
L.append(f"| LKW-Auslastung Volumen | {sp['auslastung_volumen']*100:.0f} % |")
|
||||||
|
L.append(f"| bindende Grenze | {sp['bindende_grenze']} |")
|
||||||
|
L.append(f"| passt in einen LKW | {passt} |")
|
||||||
|
L.append(f"| voller LKW nach | {sp['voller_lkw_tausch_tage']:.1f} Tagen |")
|
||||||
|
L.append(f"| Energieinhalt voller LKW | {sp['voller_lkw_energie_kWh']:.0f} kWh |")
|
||||||
|
|
||||||
|
return "\n".join(L)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
ap = argparse.ArgumentParser(description=__doc__,
|
ap = argparse.ArgumentParser(description=__doc__,
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
ap.add_argument("milch_l_tag", type=float, help="Milchmenge pro Tag in Litern")
|
ap.add_argument("milch_l_tag", type=float, help="Milchmenge pro Tag in Litern")
|
||||||
ap.add_argument("--config", type=Path, default=Path(__file__).with_name("config.json"),
|
ap.add_argument("--config", type=Path,
|
||||||
help="Pfad zur JSON-Konfiguration (Standard: config.json)")
|
default=PROJECT_ROOT / "cfg" / "config.json",
|
||||||
|
help="Basis-Konfiguration (Standard: cfg/config.json)")
|
||||||
|
ap.add_argument("--file", type=Path, default=None,
|
||||||
|
help="Override-Datei, die cfg/config.json selektiv ueberschreibt "
|
||||||
|
"(Standard: alle *.json im in/-Ordner)")
|
||||||
|
ap.add_argument("--out", type=Path, default=None,
|
||||||
|
help="Ausgabeverzeichnis fuer die .md-Datei "
|
||||||
|
"(Standard: $MILCH_OUT oder out/)")
|
||||||
ap.add_argument("--json", type=Path, default=None,
|
ap.add_argument("--json", type=Path, default=None,
|
||||||
help="Ergebnis zusaetzlich als JSON in diese Datei schreiben")
|
help="Ergebnis zusaetzlich als JSON in diese Datei schreiben")
|
||||||
ap.add_argument("--suggest-size", action="store_true",
|
ap.add_argument("--suggest-size", action="store_true",
|
||||||
help="Kompakte Empfehlung (gerundete Groessen + Abholzyklus) statt Detailreport")
|
help="Kompakte Empfehlung (gerundete Groessen + Abholzyklus) statt Detailreport")
|
||||||
|
ap.add_argument("-v", "--verbose", action="store_true",
|
||||||
|
help="Ausgaben an der Konsole anzeigen")
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
# Ausgabeverzeichnis bestimmen
|
||||||
|
out_ordner = (
|
||||||
|
args.out
|
||||||
|
or Path(os.environ.get("MILCH_OUT", ""))
|
||||||
|
or PROJECT_ROOT / "out"
|
||||||
|
)
|
||||||
|
if not out_ordner or str(out_ordner) == ".":
|
||||||
|
out_ordner = PROJECT_ROOT / "out"
|
||||||
|
out_ordner = Path(out_ordner)
|
||||||
|
out_ordner.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# In-Ordner bestimmen
|
||||||
|
in_ordner = Path(os.environ.get("MILCH_IN", PROJECT_ROOT / "in"))
|
||||||
|
|
||||||
|
# Konfiguration laden: Basis + Override
|
||||||
cfg = lade_config(args.config)
|
cfg = lade_config(args.config)
|
||||||
|
quelldateien = [args.config.name]
|
||||||
|
|
||||||
|
if args.file:
|
||||||
|
cfg = deep_merge(cfg, lade_config(args.file))
|
||||||
|
quelldateien.append(args.file.name)
|
||||||
|
elif in_ordner.is_dir():
|
||||||
|
for f in sorted(in_ordner.glob("*.json")):
|
||||||
|
cfg = deep_merge(cfg, lade_config(f))
|
||||||
|
quelldateien.append(f.name)
|
||||||
|
|
||||||
ergebnis = rechne(args.milch_l_tag, cfg)
|
ergebnis = rechne(args.milch_l_tag, cfg)
|
||||||
|
|
||||||
if args.suggest_size:
|
if args.suggest_size:
|
||||||
print(vorschlag_report(ergebnis, cfg))
|
text = vorschlag_report(ergebnis, cfg)
|
||||||
ergebnis["vorschlag"] = vorschlag(ergebnis, cfg)
|
ergebnis["vorschlag"] = vorschlag(ergebnis, cfg)
|
||||||
else:
|
else:
|
||||||
print(report(ergebnis, cfg))
|
text = report(ergebnis, cfg)
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
# Markdown-Ergebnis in out/ schreiben
|
||||||
|
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
md_name = f"auslegung_{args.milch_l_tag:.0f}L_{ts}.md"
|
||||||
|
md_path = out_ordner / md_name
|
||||||
|
md_path.write_text(report_md(ergebnis, cfg, quelldateien), encoding="utf-8")
|
||||||
|
if args.verbose:
|
||||||
|
print(f"\nMarkdown geschrieben: {md_path}")
|
||||||
|
|
||||||
if args.json:
|
if args.json:
|
||||||
with args.json.open("w", encoding="utf-8") as f:
|
with args.json.open("w", encoding="utf-8") as f:
|
||||||
json.dump(ergebnis, f, ensure_ascii=False, indent=2)
|
json.dump(ergebnis, f, ensure_ascii=False, indent=2)
|
||||||
print(f"\nErgebnis geschrieben: {args.json}")
|
if args.verbose:
|
||||||
|
print(f"JSON geschrieben: {args.json}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user