From f392239eb0d717c3d5bff9cfe7e9ff89a6eebc61 Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Mon, 15 Jun 2026 11:28:31 +0200 Subject: [PATCH] =?UTF-8?q?Tausender=20Zahlen=20mit=20Einfachhochkomma=20g?= =?UTF-8?q?etrennt.=20Komma=20ist=20verwirrend.=20COP=20f=C3=BCr=20Luft=20?= =?UTF-8?q?und=20Wasser=20WP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cfg/config.json | 7 ++- lib/auslegung.py | 115 ++++++++++++++++++++++++++--------------------- 2 files changed, 68 insertions(+), 54 deletions(-) diff --git a/cfg/config.json b/cfg/config.json index 50aded0..b480584 100644 --- a/cfg/config.json +++ b/cfg/config.json @@ -11,8 +11,9 @@ "waermepumpe": { "cop": 2.6, + "cop_wasser": 4.0, "laufzeit_h_pro_tag": 18.0, - "_kommentar": "COP fuer den Hub von ~0 C (Verdampfer) auf >58 C (Kondensator). Laufzeit bestimmt die Leistungsauslegung (kW)." + "_kommentar": "cop = Luft-WP fuer den Hub von ~0 C (Verdampfer) auf >58 C (Kondensator). cop_wasser = Wasser/Wasser-WP mit Grundwasser/Geothermie als Quelle (~10-15 C). Laufzeit bestimmt die Leistungsauslegung (kW)." }, "pcm": { @@ -42,7 +43,9 @@ "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." + "einspeiseverguetung_ct_kWh": 8.1, + "direktvermarktung_ct_kWh": 7.0, + "_kommentar": "Werte fuer optimal geneigte Suedflaeche, Standort Suedbayern. Summe der Monate ~ spez_ertrag. Einspeiseverguetung: EEG 2026 fuer Anlagen >100 kWp (Anzulegender Wert). Direktvermarktung: Boersenstrom abzgl. Vermarktungskosten." }, "batterie": { diff --git a/lib/auslegung.py b/lib/auslegung.py index 3753783..7d38c52 100644 --- a/lib/auslegung.py +++ b/lib/auslegung.py @@ -26,6 +26,15 @@ from pathlib import Path from report_md import report_md +def t(wert: float, nachkomma: int = 0) -> str: + """Zahl mit Hochkomma als Tausendertrenner formatieren.""" + if nachkomma > 0: + s = f"{wert:,.{nachkomma}f}" + else: + s = f"{wert:,.0f}" + return s.replace(",", "'") + + KJ_PER_KWH = 3600.0 TAGE_PRO_JAHR = 365.0 @@ -451,9 +460,9 @@ def vorschlag_report(e: dict, cfg: dict) -> str: 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)") + f"({t(sp['energie_pro_zyklus_kWh'])} kWh je Fuhre)") L.append(f" -> ein voller LKW waere nach {v['voll_lkw_tage']:.0f} Tagen erreicht") - L.append(f" -> Energieinhalt eines vollen LKW: ~{sp['voller_lkw_energie_kWh']:.0f} kWh") + L.append(f" -> Energieinhalt eines vollen LKW: ~{t(sp['voller_lkw_energie_kWh'])} kWh") L.append("") L.append(f"Versorgte Haushalte (2 Erw. + 2 Kinder):") L.append(f" Warmwasser ganzjaehrig ... ~{hh['haushalte_warmwasser']:.0f} Haushalte") @@ -487,50 +496,50 @@ def report(e: dict, cfg: dict) -> str: 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(f"Kuehllast der Milch ........... {t(q, 1):>8} 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(f" Kaelteleistung (Verdampfer) . {t(wp['kaelteleistung_kW'], 1):>8} kW") + L.append(f" Heizleistung (Kondensator) .. {t(wp['heizleistung_kW'], 1):>8} kW") + L.append(f" el. Leistung ................ {t(wp['elektrische_leistung_kW'], 1):>8} kW") + L.append(f" Strombedarf ................. {t(wp['strom_kWh_tag'], 1):>8} kWh/Tag") + L.append(f" Waerme in den Speicher ...... {t(wp['speicher_kWh_tag'], 1):>8} 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(f" Jahresstrombedarf WP ........ {t(pv['jahresbedarf_kWh']):>8} kWh/a") + L.append(f" Leistung .................... {t(pv['kWp'], 1):>8} kWp") + L.append(f" Dachflaeche ................. {t(pv['flaeche_m2']):>8} m2") L.append("") L.append(f"NETZBEZUG (durch Wintermonate, Monatsbilanz)") - L.append(f" Netzbezug ................... {netz['netzbezug_kWh']:8.0f} kWh/a" + L.append(f" Netzbezug ................... {t(netz['netzbezug_kWh']):>8} kWh/a" f" = {netz['netzbezug_anteil']*100:.0f} %") - L.append(f" Sommerueberschuss ........... {netz['ueberschuss_kWh']:8.0f} kWh/a") + L.append(f" Sommerueberschuss ........... {t(netz['ueberschuss_kWh']):>8} 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(f" nutzbare Kapazitaet ......... {t(bat['nutzbar_kWh'], 1):>8} kWh") + L.append(f" Nennkapazitaet .............. {t(bat['nominal_kWh'], 1):>8} kWh") L.append("") L.append("VERSORGTE HAUSHALTE ({} Erw. + {} Kinder)".format( cfg["haushalt"]["erwachsene"], cfg["haushalt"]["kinder"])) - L.append(f" Warmwasser je Haushalt ...... {hh['ww_pro_haushalt_kWh_tag']:8.1f} kWh/Tag") - L.append(f" -> Warmwasser ganzjaehrig ... {hh['haushalte_warmwasser']:8.1f} Haushalte") - L.append(f" max. Heizbedarf Winter ...... {hh['heizbedarf_winter_kWh_tag']:8.1f} kWh/Tag/HH") - L.append(f" Winterbedarf (Heiz+WW) ...... {hh['winter_pro_haushalt_kWh_tag']:8.1f} kWh/Tag/HH") - L.append(f" -> im Winter ................ {hh['haushalte_winter']:8.1f} Haushalte") + L.append(f" Warmwasser je Haushalt ...... {t(hh['ww_pro_haushalt_kWh_tag'], 1):>8} kWh/Tag") + L.append(f" -> Warmwasser ganzjaehrig ... {t(hh['haushalte_warmwasser'], 1):>8} Haushalte") + L.append(f" max. Heizbedarf Winter ...... {t(hh['heizbedarf_winter_kWh_tag'], 1):>8} kWh/Tag/HH") + L.append(f" Winterbedarf (Heiz+WW) ...... {t(hh['winter_pro_haushalt_kWh_tag'], 1):>8} kWh/Tag/HH") + L.append(f" -> im Winter ................ {t(hh['haushalte_winter'], 1):>8} Haushalte") 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" Energiedichte ............... {t(sp['energiedichte_kWh_pro_kg']*1000, 1):>8} Wh/kg") + L.append(f" Energie je Zyklus ({z:>2} Tage) . {t(sp['energie_pro_zyklus_kWh']):>8} kWh") + L.append(f" Masse ....................... {t(sp['masse_kg']):>8} kg") + L.append(f" Volumen ..................... {t(sp['volumen_m3'], 1):>8} m3") + L.append(f" LKW-Auslastung Gewicht ...... {t(sp['auslastung_gewicht']*100):>8} %") + L.append(f" LKW-Auslastung Volumen ...... {t(sp['auslastung_volumen']*100):>8} %") 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(f" Energieinhalt voller LKW .... {sp['voller_lkw_energie_kWh']:8.0f} kWh") + L.append(f" voller LKW voll nach ........ {t(sp['voller_lkw_tausch_tage'], 1):>8} Tagen") + L.append(f" Energieinhalt voller LKW .... {t(sp['voller_lkw_energie_kWh']):>8} kWh") bk = e.get("brennstoffkosten") if bk and bk["vergleich"]: L.append("") @@ -538,10 +547,10 @@ def report(e: dict, cfg: dict) -> str: L.append(f" {'Brennstoff':<10} | {'ct/kWh':>7} | {'EUR/LKW':>9} | {'EUR/Jahr':>9}") L.append(f" {'-'*10}-+-{'-'*7}-+-{'-'*9}-+-{'-'*9}") for v in bk["vergleich"]: - L.append(f" {v['name']:<10} | {v['nutzwaerme_ct_kWh']:>7.1f} | " - f"{v['eur_pro_lkw']:>9.0f} | {v['eur_pro_jahr']:>9.0f}") - L.append(f" Bewertet: voller LKW ~{bk['energie_lkw_kWh']:.0f} kWh, " - f"Jahreserzeugung ~{bk['energie_jahr_kWh']:.0f} kWh") + L.append(f" {v['name']:<10} | {t(v['nutzwaerme_ct_kWh'], 1):>7} | " + f"{t(v['eur_pro_lkw']):>9} | {t(v['eur_pro_jahr']):>9}") + L.append(f" Bewertet: voller LKW ~{t(bk['energie_lkw_kWh'])} kWh, " + f"Jahreserzeugung ~{t(bk['energie_jahr_kWh'])} kWh") ak = e.get("anbieter") if ak: inv = cfg["anbieter"]["invest"] @@ -550,28 +559,28 @@ def report(e: dict, cfg: dict) -> str: L.append("") L.append("WAERME-GESTEHUNGSKOSTEN ANBIETER (linear, kein Kapitalzins)") L.append(f" Transport ({ak['fuhren_jahr']:.0f} Fuhren/a) ........" - f" {ak['kosten_transport_eur']:>8.0f} EUR/a") - L.append(f" WP-Strom ({sd['netz_kWh']:.0f} kWh Netz" - f" @ {sd['netz_ct_kWh']:.0f} ct + {sd['pv_kWh']:.0f} kWh PV" - f" @ {sd['pv_ct_kWh']:.0f} ct) .. {ak['kosten_strom_eur']:>6.0f} EUR/a") - L.append(f" Wartung .......................... {ak['kosten_wartung_eur']:>8.0f} EUR/a") + f" {t(ak['kosten_transport_eur']):>8} EUR/a") + L.append(f" WP-Strom ({t(sd['netz_kWh'])} kWh Netz" + f" @ {sd['netz_ct_kWh']:.0f} ct + {t(sd['pv_kWh'])} kWh PV" + f" @ {sd['pv_ct_kWh']:.0f} ct) .. {t(ak['kosten_strom_eur']):>6} EUR/a") + L.append(f" Wartung .......................... {t(ak['kosten_wartung_eur']):>8} EUR/a") L.append(f" Kapital PV ({pv['kWp']:.1f} kWp, {inv['pv_nutzungsdauer_jahre']} J) ......" - f" {ak['kapital_pv_eur']:>8.0f} EUR/a") + f" {t(ak['kapital_pv_eur']):>8} EUR/a") L.append(f" Kapital Batterie ({bat['nominal_kWh']:.0f} kWh, {inv['batterie_nutzungsdauer_jahre']} J) ." - f" {ak['kapital_batterie_eur']:>8.0f} EUR/a") + f" {t(ak['kapital_batterie_eur']):>8} EUR/a") L.append(f" Kapital WP ({inv['waermepumpe_nutzungsdauer_jahre']} J) ............." - f" {ak['kapital_waermepumpe_eur']:>8.0f} EUR/a") + f" {t(ak['kapital_waermepumpe_eur']):>8} EUR/a") L.append(f" Kapital Speicher ({ci['anzahl_module']} Module, {inv['speicher_nutzungsdauer_jahre']} J)" - f" {ak['kapital_speicher_eur']:>8.0f} EUR/a") + f" {t(ak['kapital_speicher_eur']):>8} EUR/a") L.append(f" {'-'*46}") - L.append(f" Jahreskosten gesamt .............. {ak['jahreskosten_eur']:>8.0f} EUR/a") - L.append(f" Jahreserzeugung .................. {ak['energie_jahr_kWh']:>8.0f} kWh/a") - L.append(f" -> Mindestverkaufspreis .......... {ak['gestehungskosten_ct_kWh']:>8.1f} ct/kWh") - L.append(f" Speicher-Invest ({ci['anzahl_module']} Module): {ci['gesamt_eur']:,.0f} EUR" - f" = {ci['eur_pro_kwh_kapazitaet']:.0f} EUR/kWh Kapazitaet") - L.append(f" PCM {ci['pcm_eur']:,.0f} | Behaelter {ci['behaelter_eur']:,.0f}" - f" | WT+Hydr. {ci['wt_hydraulik_eur']:,.0f}" - f" | Elektr. {ci['elektronik_eur']:,.0f} | Montage {ci['montage_eur']:,.0f}") + L.append(f" Jahreskosten gesamt .............. {t(ak['jahreskosten_eur']):>8} EUR/a") + L.append(f" Jahreserzeugung .................. {t(ak['energie_jahr_kWh']):>8} kWh/a") + L.append(f" -> Mindestverkaufspreis .......... {t(ak['gestehungskosten_ct_kWh'], 1):>8} ct/kWh") + L.append(f" Speicher-Invest ({ci['anzahl_module']} Module): {t(ci['gesamt_eur'])} EUR" + f" = {t(ci['eur_pro_kwh_kapazitaet'])} EUR/kWh Kapazitaet") + L.append(f" PCM {t(ci['pcm_eur'])} | Behaelter {t(ci['behaelter_eur'])}" + f" | WT+Hydr. {t(ci['wt_hydraulik_eur'])}" + f" | Elektr. {t(ci['elektronik_eur'])} | Montage {t(ci['montage_eur'])}") if ak["marge"]: L.append("") L.append("MARGE GEGEN ERSATZBRENNSTOFF") @@ -579,9 +588,11 @@ def report(e: dict, cfg: dict) -> str: L.append(f" {'-'*10}-+-{'-'*7}-+-{'-'*12}-+-{'-'*14}") for m in ak["marge"]: haertester = " <== haertester Massstab" if m == ak["marge"][-1] else "" - L.append(f" {m['name']:<10} | {m['nutzwaerme_ct_kWh']:>7.1f} |" - f" {m['marge_ct_kWh']:>+12.1f} |" - f" {m['marge_eur_jahr']:>+14.0f}{haertester}") + vorzeichen_ct = "+" if m['marge_ct_kWh'] >= 0 else "" + vorzeichen_eur = "+" if m['marge_eur_jahr'] >= 0 else "" + L.append(f" {m['name']:<10} | {t(m['nutzwaerme_ct_kWh'], 1):>7} |" + f" {vorzeichen_ct}{t(m['marge_ct_kWh'], 1):>11} |" + f" {vorzeichen_eur}{t(m['marge_eur_jahr']):>13}{haertester}") L.append("=" * 62) return "\n".join(L)