From 3f59877aa9533ea6134b9a264a31d6666212dd4f Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Mon, 15 Jun 2026 07:06:48 +0200 Subject: [PATCH] schalter --eh-da und --driver dazu --- cfg/config.json | 3 +- lib/auslegung.py | 35 ++++++--- lib/report_md.py | 188 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 208 insertions(+), 18 deletions(-) diff --git a/cfg/config.json b/cfg/config.json index d77ea4d..50aded0 100644 --- a/cfg/config.json +++ b/cfg/config.json @@ -178,7 +178,8 @@ "_beschreibung": "Betriebswirtschaftliche Annahmen fuer die Anbieterseite. Ermoeglicht die Berechnung von Waerme-Gestehungskosten (ct/kWh) und Marge gegenueber Ersatzbrennstoff. Abschreibung: linear, kein Kapitalzins (konservativ).", "transport_eur_pro_fuhre": 300, - "_kommentar_transport": "Kosten je LKW-Fuhre (Treibstoff, Fahrer, Abschreibung Fahrzeug). Richtwert fuer Kurzstrecke bis ~100 km. Fuer laengere Strecken entsprechend erhoehen.", + "fahrer_eur_pro_fuhre": 120, + "_kommentar_transport": "transport_eur_pro_fuhre: Gesamtkosten je Fuhre (Treibstoff + Fahrer + Fahrzeugabschreibung). fahrer_eur_pro_fuhre: Fahreranteil daran, wird mit --driver abgezogen wenn der Landwirt selbst faehrt. Richtwert Kurzstrecke bis ~100 km.", "netzstrompreis_ct_kWh": 28.0, "_kommentar_netzstrom": "Industriestrompreis (Netzbezug), Stand 06/2026 DE. Fuer Landwirtschaft oft Sondertarif moeglich (~22-28 ct/kWh). Quelle: BDEW Strompreisanalyse (bdew.de).", diff --git a/lib/auslegung.py b/lib/auslegung.py index 755f254..3753783 100644 --- a/lib/auslegung.py +++ b/lib/auslegung.py @@ -126,9 +126,16 @@ def speicher(q_speicher_tag: float, cfg: dict, zyklus: float | None = None) -> d bindend = "Gewicht" if masse_kg / nutzlast >= volumen_m3 / lkw_vol else "Volumen" passt = True - # Wie oft muesste ein voller LKW (nach Gewicht) getauscht werden? + # Tage bis LKW voll (je Grenze, bindende = kleinerer Wert) masse_pro_tag = q_speicher_tag / e_kg voll_lkw_tage = nutzlast / masse_pro_tag if masse_pro_tag > 0 else float("inf") + volumen_pro_tag = masse_pro_tag / (p["dichte_kg_pro_L"] * 1000.0) + voll_vol_tage = lkw_vol / volumen_pro_tag if volumen_pro_tag > 0 else float("inf") + voll_bind_tage = min(voll_lkw_tage, voll_vol_tage) + + # Empfehlung wenn bindende Auslastung < 90 % + auslastung_bind = max(masse_kg / nutzlast, volumen_m3 / lkw_vol) + empf_zyklus = math.ceil(0.90 * voll_bind_tage) if auslastung_bind < 0.90 else None return { "energiedichte_kWh_pro_kg": e_kg, @@ -141,6 +148,7 @@ def speicher(q_speicher_tag: float, cfg: dict, zyklus: float | None = None) -> d "passt_in_einen_lkw": passt, "voller_lkw_tausch_tage": voll_lkw_tage, "voller_lkw_energie_kWh": nutzlast * e_kg, + "empf_zyklus_tage": empf_zyklus, } @@ -280,11 +288,12 @@ def container_invest_total(sp: dict, cfg: dict) -> dict: } -def anbieterkosten(e: dict, cfg: dict) -> dict: +def anbieterkosten(e: dict, cfg: dict, *, eh_da: bool = False, driver: bool = False) -> dict: """Jaehrliche Betriebskosten des Anbieters -> Gestehungskosten und Marge. + eh_da=True : PV und Kuehlung bereits vorhanden -> Kapitalkosten dafuer entfallen. + driver=True : Fahrer stellt der Landwirt selbst -> Fahreranteil wird abgezogen. Abschreibung: linear ohne Kapitalzins (konservativ). - Strombedarf: Netzbezug zum Netzpreis, PV-Eigenanteil zu LCOE-Gestehungskosten. """ a = cfg["anbieter"] inv = a["invest"] @@ -297,7 +306,8 @@ def anbieterkosten(e: dict, cfg: dict) -> dict: energie_jahr = wp["speicher_kWh_tag"] * TAGE_PRO_JAHR fuhren_jahr = TAGE_PRO_JAHR / cfg["abholung"]["zyklus_tage"] - kosten_transport = fuhren_jahr * a["transport_eur_pro_fuhre"] + fahrer_abzug = a.get("fahrer_eur_pro_fuhre", 0.0) if driver else 0.0 + kosten_transport = fuhren_jahr * (a["transport_eur_pro_fuhre"] - fahrer_abzug) netz_eur = netz["netzbezug_kWh"] * a["netzstrompreis_ct_kWh"] / 100.0 pv_kwh = netz["jahresbedarf_kWh"] - netz["netzbezug_kWh"] @@ -306,9 +316,9 @@ def anbieterkosten(e: dict, cfg: dict) -> dict: kosten_wartung = a["wartung_eur_pro_jahr"] - kapital_pv = pv_data["kWp"] * inv["pv_eur_pro_kWp"] / inv["pv_nutzungsdauer_jahre"] + kapital_pv = 0.0 if eh_da else pv_data["kWp"] * inv["pv_eur_pro_kWp"] / inv["pv_nutzungsdauer_jahre"] kapital_bat = bat["nominal_kWh"] * inv["batterie_eur_pro_kWh"] / inv["batterie_nutzungsdauer_jahre"] - kapital_wp = inv["waermepumpe_eur"] / inv["waermepumpe_nutzungsdauer_jahre"] + kapital_wp = 0.0 if eh_da else inv["waermepumpe_eur"] / inv["waermepumpe_nutzungsdauer_jahre"] ci = container_invest_total(sp, cfg) kapital_speicher = ci["gesamt_eur"] / inv["speicher_nutzungsdauer_jahre"] kosten_kapital = kapital_pv + kapital_bat + kapital_wp + kapital_speicher @@ -349,10 +359,13 @@ def anbieterkosten(e: dict, cfg: dict) -> dict: "gestehungskosten_ct_kWh": gestehung_ct, "container_invest": ci, "marge": marge, + "eh_da": eh_da, + "driver": driver, + "fahrer_abzug_eur_pro_fuhre": fahrer_abzug, } -def rechne(milch_l_tag: float, cfg: dict) -> dict: +def rechne(milch_l_tag: float, cfg: dict, *, eh_da: bool = False, driver: bool = False) -> dict: q_milch = milch_kuehllast(milch_l_tag, cfg) wp = waermepumpe(q_milch, cfg) sp = speicher(wp["speicher_kWh_tag"], cfg) @@ -373,7 +386,7 @@ def rechne(milch_l_tag: float, cfg: dict) -> dict: if "brennstoffe" in cfg: e["brennstoffkosten"] = brennstoffkosten(e, cfg) if "anbieter" in cfg and "container_invest" in cfg: - e["anbieter"] = anbieterkosten(e, cfg) + e["anbieter"] = anbieterkosten(e, cfg, eh_da=eh_da, driver=driver) return e @@ -593,6 +606,10 @@ def main() -> 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") + ap.add_argument("--eh-da", action="store_true", + help="PV und Kuehlung bereits vorhanden: Kapitalkosten dafuer entfallen") + ap.add_argument("--driver", action="store_true", + help="Fahrer stellt der Landwirt selbst: Fahreranteil aus Transportkosten abziehen") ap.add_argument("-v", "--verbose", action="store_true", help="Ausgaben an der Konsole anzeigen") args = ap.parse_args() @@ -623,7 +640,7 @@ def main() -> None: 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, eh_da=args.eh_da, driver=args.driver) if args.suggest_size: text = vorschlag_report(ergebnis, cfg) diff --git a/lib/report_md.py b/lib/report_md.py index 445d305..1b08991 100644 --- a/lib/report_md.py +++ b/lib/report_md.py @@ -20,8 +20,12 @@ def _tbl_header(cols: list[str]) -> list[str]: " | ".join(["---"] * len(cols))] +def _code(lines: list[str]) -> list[str]: + return ["```"] + lines + ["```", ""] + + def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: - """Vollstaendiger Markdown-Report: je Block erst Voraussetzungen, dann Ergebnisse.""" + """Vollstaendiger Markdown-Report: je Block Voraussetzungen → Formeln → Ergebnisse.""" q = e["milch_kuehllast_kWh_tag"] wp = e["waermepumpe"] sp = e["speicher"] @@ -57,6 +61,16 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: L.append(f"| Dichte | {m_cfg['dichte_kg_pro_L']:.2f} kg/L |") L.append(f"| Spez. Waerme | {m_cfg['spez_waerme_kJ_pro_kgK']:.3f} kJ/(kg·K) |") L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "Q = V × ρ × c × ΔT / 3600 [kWh/Tag]", + " = (Milchmenge × Dichte) × spez_Waerme × (T_ein − T_aus) / 3600", + "", + f" = ({milch:.0f} L/Tag × {m_cfg['dichte_kg_pro_L']:.2f} kg/L)" + f" × {m_cfg['spez_waerme_kJ_pro_kgK']:.3f} kJ/(kg·K)" + f" × ({m_cfg['temp_ein_C']:.0f} − {m_cfg['temp_aus_C']:.0f}) K / 3600", + f" = {q:.1f} kWh/Tag", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kenngroesse", "Wert"])) L.append(f"| Taegl. Kuehllast | **{q:.1f} kWh/Tag** |") @@ -69,6 +83,26 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: L.append(f"| Laufzeit | {wp_cfg['laufzeit_h_pro_tag']:.0f} h/Tag |") L.append(f"| Kuehllast (aus Milchblock) | {q:.1f} kWh/Tag |") L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "Leistungsauslegung aus Kuehllast und Laufzeit:", + " P_Kaelte = Q_Tag / Laufzeit [kW] (Verdampfer)", + " P_Heiz = P_Kaelte × COP / (COP − 1) [kW] (Kondensator)", + " P_el = P_Kaelte / (COP − 1) [kW] (Antrieb)", + "", + "Tageswerte:", + " W_el = P_el × Laufzeit [kWh/Tag]", + " Q_Speicher = P_Heiz × Laufzeit [kWh/Tag]", + "", + f" P_Kaelte = {q:.1f} / {wp_cfg['laufzeit_h_pro_tag']:.0f}" + f" = {wp['kaelteleistung_kW']:.1f} kW", + f" P_Heiz = {wp['kaelteleistung_kW']:.1f}" + f" × {wp_cfg['cop']:.2f} / ({wp_cfg['cop']:.2f} − 1)" + f" = {wp['heizleistung_kW']:.1f} kW", + f" P_el = {wp['kaelteleistung_kW']:.1f}" + f" / ({wp_cfg['cop']:.2f} − 1)" + f" = {wp['elektrische_leistung_kW']:.1f} kW", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kenngroesse", "Wert"])) L.append(f"| Kaelteleistung (Verdampfer) | {wp['kaelteleistung_kW']:.1f} kW |") @@ -85,6 +119,16 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: L.append(f"| Spez. Jahresertrag | {pv_cfg['spez_ertrag_kWh_pro_kWp_jahr']} kWh/(kWp·a) |") L.append(f"| Dachflaeche je kWp | {pv_cfg['flaeche_m2_pro_kWp']:.1f} m2/kWp |") L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "Jahresbedarf = W_el_Tag × 365 [kWh/a]", + "kWp = Jahresbedarf / spez_Ertrag [kWp]", + "Flaeche = kWp × Flaeche_je_kWp [m²]", + "", + f"kWp = {pv['jahresbedarf_kWh']:.0f} kWh/a" + f" / {pv_cfg['spez_ertrag_kWh_pro_kWp_jahr']} kWh/(kWp·a)" + f" = {pv['kWp']:.1f} kWp", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kenngroesse", "Wert"])) L.append(f"| Jahresstrombedarf WP | {pv['jahresbedarf_kWh']:.0f} kWh/a |") @@ -101,6 +145,18 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: f" Feb {pv_cfg['monatsertrag_kWh_pro_kWp']['Feb']}," f" ... Dez {pv_cfg['monatsertrag_kWh_pro_kWp']['Dez']} kWh/kWp |") L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "je Monat (n = Tage im Monat):", + " PV_Monat = kWp × Monatsertrag_kWh_pro_kWp [kWh]", + " Bedarf_Monat = W_el_Tag × n [kWh]", + " Zukauf = max(0, Bedarf_Monat − PV_Monat) [kWh]", + " Ueberschuss = max(0, PV_Monat − Bedarf_Monat) [kWh]", + "", + "Jahreswerte:", + " Netzbezug = Σ Zukauf [kWh/a]", + " Anteil = Netzbezug / Jahresbedarf [%]", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kenngroesse", "Wert"])) L.append(f"| Netzbezug | **{netz['netzbezug_kWh']:.0f} kWh/a = {netz['netzbezug_anteil']*100:.0f} %** |") @@ -122,6 +178,22 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: L.append(f"| Nutzbarer Anteil (Entladetiefe LFP) | {bat_cfg['nutzbar_anteil']*100:.0f} % |") L.append(f"| Reservefaktor | {bat_cfg['reserve_faktor']:.1f} |") L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "Pufferbedarf = W_el × (24 − Direkt_PV_h) / 24 [kWh]", + " (Anteil des Tages ohne direkten PV-Strom)", + "C_nutzbar = Pufferbedarf × Reservefaktor [kWh]", + "C_nominal = C_nutzbar / Entladetiefe_DoD [kWh]", + "", + f"Pufferbedarf = {wp['strom_kWh_tag']:.1f}" + f" × (24 − {bat_cfg['direkt_pv_stunden']:.0f}) / 24" + f" = {wp['strom_kWh_tag'] * (24 - bat_cfg['direkt_pv_stunden']) / 24:.1f} kWh", + f"C_nutzbar = … × {bat_cfg['reserve_faktor']:.1f}" + f" = {bat['nutzbar_kWh']:.1f} kWh", + f"C_nominal = {bat['nutzbar_kWh']:.1f}" + f" / {bat_cfg['nutzbar_anteil']:.1f}" + f" = {bat['nominal_kWh']:.1f} kWh", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kenngroesse", "Wert"])) L.append(f"| Nutzbare Kapazitaet | {bat['nutzbar_kWh']:.1f} kWh |") @@ -147,6 +219,62 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: L.append(f"| LKW-Volumen | {abh_cfg['lkw_volumen_m3']} m3 |") L.append(f"| Waerme je Tag (aus WP-Block) | {wp['speicher_kWh_tag']:.1f} kWh/Tag |") L.append("") + L.extend(_h3("Formeln")) + if pcm_cfg["modus"] == "latent_plus_hub": + dt_uh = max(0.0, pcm_cfg["ladetemp_C"] - pcm_cfg["schmelzpunkt_C"]) + dt_uk = max(0.0, pcm_cfg["schmelzpunkt_C"] - pcm_cfg["entladetemp_C"]) + e_kj = (pcm_cfg["latentwaerme_kJ_pro_kg"] + + pcm_cfg["cp_fluessig_kJ_pro_kgK"] * dt_uh + + pcm_cfg["cp_fest_kJ_pro_kgK"] * dt_uk) + L.extend(_code([ + "Energiedichte (Modus latent_plus_hub):", + " E = (L + cp_fl · ΔT_üh + cp_fest · ΔT_uk) / 3600 [kWh/kg]", + " mit ΔT_üh = max(0, T_Lade − T_Schmelz) (Ueberhitzung, fluessig)", + " ΔT_uk = max(0, T_Schmelz − T_Entlade) (Unterkuehlung, fest)", + "", + f" ΔT_üh = max(0, {pcm_cfg['ladetemp_C']:.0f} − {pcm_cfg['schmelzpunkt_C']:.0f})" + f" = {dt_uh:.0f} K", + f" ΔT_uk = max(0, {pcm_cfg['schmelzpunkt_C']:.0f} − {pcm_cfg['entladetemp_C']:.0f})" + f" = {dt_uk:.0f} K", + f" E = ({pcm_cfg['latentwaerme_kJ_pro_kg']:.0f}" + f" + {pcm_cfg['cp_fluessig_kJ_pro_kgK']:.1f}·{dt_uh:.0f}" + f" + {pcm_cfg['cp_fest_kJ_pro_kgK']:.1f}·{dt_uk:.0f}) / 3600" + f" = {e_kj:.1f} / 3600" + f" = {sp['energiedichte_kWh_pro_kg']*1000:.1f} Wh/kg", + "", + "Speichergroesse:", + " E_Zyklus = Q_Speicher_Tag × Zyklus [kWh]", + " m = E_Zyklus / E [kg]", + " V = m / (ρ × 1000) [m³]", + "", + f" E_Zyklus = {wp['speicher_kWh_tag']:.1f} kWh/Tag × {z} Tage" + f" = {sp['energie_pro_zyklus_kWh']:.0f} kWh", + f" m = {sp['energie_pro_zyklus_kWh']:.0f}" + f" / {sp['energiedichte_kWh_pro_kg']:.4f}" + f" = {sp['masse_kg']:.0f} kg", + f" V = {sp['masse_kg']:.0f}" + f" / ({pcm_cfg['dichte_kg_pro_L']:.1f} × 1000)" + f" = {sp['volumen_m3']:.1f} m³", + ])) + else: + L.extend(_code([ + "Energiedichte (Modus latent_only):", + " E = L / 3600 [kWh/kg]", + "", + "Speichergroesse:", + " E_Zyklus = Q_Speicher_Tag × Zyklus [kWh]", + " m = E_Zyklus / E [kg]", + " V = m / (ρ × 1000) [m³]", + "", + f" E_Zyklus = {wp['speicher_kWh_tag']:.1f} × {z}" + f" = {sp['energie_pro_zyklus_kWh']:.0f} kWh", + f" m = {sp['energie_pro_zyklus_kWh']:.0f}" + f" / {sp['energiedichte_kWh_pro_kg']:.4f}" + f" = {sp['masse_kg']:.0f} kg", + f" V = {sp['masse_kg']:.0f}" + f" / ({pcm_cfg['dichte_kg_pro_L']:.1f} × 1000)" + f" = {sp['volumen_m3']:.1f} m³", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kenngroesse", "Wert"])) L.append(f"| Energiedichte | {sp['energiedichte_kWh_pro_kg']*1000:.1f} Wh/kg |") @@ -159,6 +287,10 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: 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 |") + if sp.get("empf_zyklus_tage") is not None: + L.append("") + L.append(f"**empfohlene Zyklenzahl = {sp['empf_zyklus_tage']} Tage**" + f" (ergibt ≥ 90 % LKW-Auslastung)") # ── Haushalte ──────────────────────────────────────────────────── L.extend(_h2(f"Versorgte Haushalte" @@ -172,6 +304,22 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: L.append(f"| Heizbedarf Winter | {hh_cfg['heizbedarf_winter_kWh_tag']:.0f} kWh/Tag/HH |") L.append(f"| Waerme je Tag (aus WP-Block) | {wp['speicher_kWh_tag']:.1f} kWh/Tag |") L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "WW_je_HH = n_Erw × WW_Erw + n_Kind × WW_Kind [kWh/Tag]", + "HH_WW = Q_Speicher / WW_je_HH [Haushalte, ganzjaehrig]", + "HH_Winter = Q_Speicher / (WW_je_HH + Heiz_Winter) [Haushalte, Winter]", + "", + f"WW_je_HH = {hh_cfg['erwachsene']} × {hh_cfg['ww_erwachsener_kWh_tag']:.1f}" + f" + {hh_cfg['kinder']} × {hh_cfg['ww_kind_kWh_tag']:.1f}" + f" = {hh['ww_pro_haushalt_kWh_tag']:.1f} kWh/Tag", + f"HH_WW = {wp['speicher_kWh_tag']:.1f}" + f" / {hh['ww_pro_haushalt_kWh_tag']:.1f}" + f" = {hh['haushalte_warmwasser']:.1f} HH", + f"HH_Winter = {wp['speicher_kWh_tag']:.1f}" + f" / {hh['winter_pro_haushalt_kWh_tag']:.1f}" + f" = {hh['haushalte_winter']:.1f} HH", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kenngroesse", "Wert"])) L.append(f"| WW-Bedarf je Haushalt | {hh['ww_pro_haushalt_kWh_tag']:.1f} kWh/Tag |") @@ -188,8 +336,12 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: for b in cfg.get("brennstoffe", []): L.append(f"| {b['name']} | {b['preis_ct_kWh']:.1f} | {b['wirkungsgrad']*100:.0f} % |") L.append("") - L.append("*Nutzwaermekosten = Brennstoffpreis ÷ Kesselwirkungsgrad*") - L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "Nutzwaermekosten = Preis_ct_kWh / Wirkungsgrad [ct/kWh]", + "EUR_je_LKW = E_LKW_kWh × Nutzwaermekosten / 100 [EUR]", + "EUR_je_Jahr = E_Jahr_kWh × Nutzwaermekosten / 100 [EUR/a]", + ])) L.extend(_h3("Ergebnisse")) L.append(f"Bewertet: voller LKW **{bk['energie_lkw_kWh']:.0f} kWh**," f" Jahreserzeugung **{bk['energie_jahr_kWh']:.0f} kWh/a**") @@ -220,6 +372,12 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: f" {inv['waermepumpe_nutzungsdauer_jahre']} J |") L.append(f"| Speicher-Invest | {ci['anzahl_module']} Module," f" {inv['speicher_nutzungsdauer_jahre']} J Nutzung |") + if ak["eh_da"]: + L.append("| ~~Kapital PV~~ | *eh-da: bereits vorhanden, entfaellt* |") + L.append("| ~~Kapital WP~~ | *eh-da: bereits vorhanden, entfaellt* |") + if ak["driver"]: + L.append(f"| Fahrerabzug | {ak['fahrer_abzug_eur_pro_fuhre']:.0f} EUR/Fuhre" + f" (--driver: Betreiber oder Landwirt faehrt selbst) |") L.append("") L.append("**Aufschluesselung Speicher-Invest**") L.append("") @@ -233,8 +391,19 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: L.append(f"| **Gesamt** | **{ci['gesamt_eur']:,.0f}** |") L.append(f"| entspricht | {ci['eur_pro_kwh_kapazitaet']:.0f} EUR/kWh Speicherkapazitaet |") L.append("") - L.append("*Abschreibung: linear, kein Kapitalzins.*") - L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "Kapital_X = Invest_X / Nutzungsdauer_X [EUR/a] (lineare AfA)", + "Kosten_Transport = Fuhren_Jahr × Kosten_je_Fuhre [EUR/a]", + "Kosten_Strom = kWh_Netz × p_Netz + kWh_PV × p_LCOE [EUR/a]", + "Jahreskosten = Σ(alle Kostenblöcke) [EUR/a]", + "", + "Gestehungskosten = Jahreskosten / Energie_Jahr × 100 [ct/kWh]", + "", + f"Gestehungskosten = {ak['jahreskosten_eur']:.0f} EUR/a" + f" / {ak['energie_jahr_kWh']:.0f} kWh/a × 100" + f" = {ak['gestehungskosten_ct_kWh']:.1f} ct/kWh", + ])) L.extend(_h3("Ergebnisse")) L.extend(_tbl_header(["Kostenblock", "EUR/Jahr"])) L.append(f"| Transport ({ak['fuhren_jahr']:.0f} Fuhren/a)" @@ -264,10 +433,13 @@ def report_md(e: dict, cfg: dict, quelldateien: list[str] | None = None) -> str: for m in ak["marge"]: L.append(f"| Nutzwaerme {m['name']} | {m['nutzwaerme_ct_kWh']:.1f} ct/kWh |") L.append("") + L.extend(_h3("Formeln")) + L.extend(_code([ + "Marge_ct = Nutzwaerme_Brennstoff − Gestehungskosten [ct/kWh]", + " Positiv = System kostendeckend gegenueber diesem Brennstoff", + "Marge_EUR = Marge_ct × Energie_Jahr / 100 [EUR/a]", + ])) L.extend(_h3("Ergebnisse")) - L.append("Marge = Nutzwaermekosten Brennstoff − Mindestverkaufspreis." - " Positiv = System kostendeckend.") - L.append("") L.extend(_tbl_header( ["Brennstoff", "ct/kWh (Nutzw.)", "Marge ct/kWh", "Marge EUR/Jahr"])) for m in ak["marge"]: