Spaces:
Sleeping
Sleeping
| import os | |
| import math | |
| import streamlit as st | |
| import pandas as pd | |
| from pathlib import Path | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| st.set_page_config(page_title="GridCoin Calculator", layout="wide", page_icon="β‘") | |
| st.markdown(""" | |
| <style> | |
| .stNumberInput, .stSelectbox, .stSlider { | |
| margin-bottom: -1rem; | |
| } | |
| div[data-testid="stVerticalBlock"] > div { | |
| gap: 0.5rem; | |
| } | |
| .stSubheader { | |
| margin-top: 0.5rem; | |
| margin-bottom: 0.5rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.title("GridCoin β DER vs Non-DER Dashboard") | |
| left_col, right_col = st.columns([1, 1]) | |
| with left_col: | |
| st.subheader("βοΈ System Configuration") | |
| c1, c2 = st.columns(2) | |
| with c1: | |
| owner = st.selectbox("Household type", ["DER Homeowner", "Non-DER Homeowner"]) | |
| pv_kw = st.number_input("Solar size (kW)", 0.0, 50.0, 7.0, step=0.5) | |
| batt_kwh = st.number_input("Battery (kWh)", 0.0, 40.0, 0.0, step=0.5) | |
| with c2: | |
| annual_load = st.number_input("Annual use (kWh)", 500, 30000, 12000) | |
| retail_rate = st.number_input("Retail rate ($/kWh)", 0.01, 1.0, 0.13, format="%.3f") | |
| upfront = st.number_input("System cost ($)", 0, 100000, 25000) | |
| st.markdown("---") | |
| st.subheader("π° Policy & GridCoin Settings") | |
| c3, c4 = st.columns(2) | |
| with c3: | |
| exp_actual = st.number_input("Export credit ($/kWh)", 0.0, 1.0, 0.075, format="%.3f") | |
| exp_evc = st.number_input("EVC Bonus ($/kWh)", 0.0, 1.0, 0.123, format="%.3f") | |
| grid_fee = st.number_input("Grid fee ($/kW-mo)", 0.0, 20.0, 4.0) | |
| with c4: | |
| peak_start = st.number_input("Peak start (hr)", 0, 23, 17) | |
| peak_end = st.number_input("Peak end (hr)", 0, 23, 21) | |
| coin_value = st.number_input("GridCoin value ($)", 0.0, 1.0, 0.05, format="%.3f") | |
| st.markdown("---") | |
| st.subheader("π GridCoin Calculator") | |
| c5, c6 = st.columns(2) | |
| with c5: | |
| peak_fraction = st.slider("Peak export share", 0.0, 1.0, 0.30, 0.05) | |
| with c6: | |
| dr_kwh = st.number_input("DR savings (kWh)", 0.0, 5000.0, 0.0) | |
| pv_yield = pv_kw * 1250 | |
| self_use_ratio = 0.65 | |
| self_used = pv_yield * self_use_ratio | |
| exports = max(0, pv_yield - self_used - batt_kwh * 200) | |
| peak_exports = exports * peak_fraction | |
| coins_peak = peak_exports * 1.0 | |
| coins_dr = dr_kwh * 0.5 | |
| coins_total = coins_peak + coins_dr | |
| coin_dollars = coins_total * coin_value | |
| bill_nonder = annual_load * retail_rate | |
| imports_der = max(0, annual_load - self_used) | |
| exp_credit = exports * exp_actual | |
| fee_der = grid_fee * pv_kw * 12 | |
| bill_der = imports_der * retail_rate + fee_der - exp_credit - coin_dollars | |
| savings = max(0, bill_nonder - bill_der) | |
| payback = upfront / savings if savings > 0 else math.inf | |
| with right_col: | |
| st.subheader("π Results Dashboard") | |
| m1, m2 = st.columns(2) | |
| m1.metric("GridCoins Earned", f"{coins_total:,.1f}") | |
| m2.metric("GridCoin Value", f"${coin_dollars:,.2f}") | |
| st.markdown("---") | |
| st.markdown("### π΅ Annual Bill Comparison") | |
| b1, b2, b3 = st.columns(3) | |
| b1.metric("Non-DER Bill", f"${bill_nonder:,.0f}") | |
| b2.metric("DER Bill", f"${bill_der:,.0f}", delta=f"${bill_der-bill_nonder:,.0f}") | |
| b3.metric("Payback Period", f"{payback:.1f} yrs" if payback != math.inf else "N/A") | |