import streamlit as st import pandas as pd import numpy as np import math import matplotlib.pyplot as plt import numpy_financial as npf from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import getSampleStyleSheet import io import xlsxwriter # =============================== # PAGE CONFIG # =============================== st.set_page_config(layout="wide") st.title("🇵🇰 Pakistan Solar Engineering & Financial Dashboard") # =============================== # CONFIGURATION # =============================== SYSTEM_LOSSES = 0.20 PANEL_COST_PER_WATT = 55 INSTALLATION_COST_PER_WATT = 35 LITHIUM_BATTERY_COST_5KWH = 95000 CITY_SUNLIGHT = { "Karachi": 6.2, "Lahore": 5.5, "Islamabad": 5.2, "Peshawar": 5.6, "Quetta": 6.5, } # Appliance Database APPLIANCES_RESIDENTIAL = { "LED Bulb (12W)": 12, "Fan (80W)": 80, "Refrigerator (200W)": 200, "LED TV (150W)": 150, "Air Conditioner 1.5 Ton (1500W)": 1500, "Washing Machine (500W)": 500, "Water Pump (750W)": 750, "Laptop (65W)": 65, "Iron (1000W)": 1000, } APPLIANCES_COMMERCIAL = { "CNC Machine (2kW)": 2000, "Industrial AC (5kW)": 5000, "Lighting System (1kW)": 1000, "Water Pump 3HP (2.2kW)": 2200, "Server Rack (1.5kW)": 1500, } # Demo Load Profiles DEMO_SELECTIONS = { "Homeowner": ["LED Bulb (12W)", "Fan (80W)", "Refrigerator (200W)", "LED TV (150W)"], "Solar Company": ["LED Bulb (12W)", "Fan (80W)", "CNC Machine (2kW)", "Industrial AC (5kW)"], "Industrial Investor": ["CNC Machine (2kW)", "Industrial AC (5kW)", "Water Pump 3HP (2.2kW)", "Server Rack (1.5kW)"] } # Tariffs RESIDENTIAL_TARIFF = [ (100, 22), (100, 32), (100, 38), (100, 42), (100, 48), (np.inf, 65), ] COMMERCIAL_TARIFF = 72 # =============================== # CALCULATION FUNCTIONS # =============================== def calculate_residential_bill(units): remaining = units bill = 0 for slab_units, rate in RESIDENTIAL_TARIFF: if remaining > slab_units: bill += slab_units * rate remaining -= slab_units else: bill += remaining * rate break return bill def calculate_commercial_bill(units): return units * COMMERCIAL_TARIFF def calculate_system(load_watts, hours, sunlight): daily_kwh = (load_watts * hours) / 1000 adjusted_kwh = daily_kwh / (1 - SYSTEM_LOSSES) required_kw = adjusted_kwh / sunlight return daily_kwh, round(required_kw, 2) def calculate_battery(daily_kwh, backup_hours): backup_kwh = (daily_kwh / 24) * backup_hours return math.ceil(backup_kwh / 5) def calculate_cost(system_kw, batteries, system_type): base_cost = system_kw * 1000 * (PANEL_COST_PER_WATT + INSTALLATION_COST_PER_WATT) battery_cost = batteries * LITHIUM_BATTERY_COST_5KWH if system_type == "On-Grid": return base_cost elif system_type == "Off-Grid": return base_cost + battery_cost else: return base_cost * 1.1 + battery_cost def emi_calculator(principal, annual_rate, years): r = annual_rate / 100 / 12 n = years * 12 return round(principal * r * (1 + r)**n / ((1 + r)**n - 1)) def financial_projection(total_cost, daily_kwh, mode, years=25): monthly_units = daily_kwh * 30 cashflows = [] for year in range(1, years + 1): price_increase = (1 + 0.07) ** (year - 1) if mode == "Homeowner": monthly_bill = calculate_residential_bill(monthly_units * price_increase) else: monthly_bill = calculate_commercial_bill(monthly_units * price_increase) cashflows.append(monthly_bill * 12) npv = npf.npv(0.05, [-total_cost] + cashflows) irr = npf.irr([-total_cost] + cashflows) payback_year = next((i for i, cf in enumerate(np.cumsum(cashflows), 1) if cf >= total_cost), None) return cashflows, round(npv, 2), round(irr * 100, 2), payback_year, np.cumsum(cashflows) # =============================== # PDF REPORT # =============================== def generate_pdf(report_data): file_path = "solar_report.pdf" doc = SimpleDocTemplate(file_path, pagesize=A4) elements = [] styles = getSampleStyleSheet() elements.append(Paragraph("Pakistan Solar Feasibility Report", styles['Title'])) elements.append(Spacer(1, 12)) for k, v in report_data.items(): elements.append(Paragraph(f"{k}: {v}", styles['Normal'])) elements.append(Spacer(1, 6)) doc.build(elements) return file_path # =============================== # STREAMLIT UI # =============================== audience = st.selectbox("Select Audience", ["Homeowner", "Solar Company", "Industrial Investor"]) city = st.selectbox("Select City", list(CITY_SUNLIGHT.keys())) sunlight = CITY_SUNLIGHT[city] # Demo Settings Buttons if st.button("🎯 Load Demo Appliances"): if audience in DEMO_SELECTIONS: st.session_state["demo_appliances"] = DEMO_SELECTIONS[audience] st.success("Demo appliances loaded!") if "demo_appliances" in st.session_state: default_selection = st.session_state["demo_appliances"] else: default_selection = [] # Appliance Selection if audience == "Homeowner": appliances = st.multiselect("Select Appliances", list(APPLIANCES_RESIDENTIAL.keys()), default=default_selection) elif audience == "Solar Company": appliances = st.multiselect("Select Appliances", list(APPLIANCES_RESIDENTIAL.keys()) + list(APPLIANCES_COMMERCIAL.keys()), default=default_selection) else: appliances = st.multiselect("Select Industrial Equipment", list(APPLIANCES_COMMERCIAL.keys()), default=default_selection) # Demo Settings Button if st.button("🎯 Load Demo City & Settings"): city = "Karachi" sunlight = CITY_SUNLIGHT[city] hours = 8 backup_hours = 4 st.success("Demo settings loaded!") hours = st.slider("Usage Hours per Day", 1, 24, 8) system_type = st.radio("System Type", ["On-Grid", "Off-Grid", "Hybrid"]) backup_hours = st.slider("Battery Backup Hours", 0, 24, 4) # Calculation Trigger if st.button("⚡ Calculate Solar System"): if not appliances: st.error("Please select appliances") else: total_load = sum(APPLIANCES_RESIDENTIAL.get(a, 0) + APPLIANCES_COMMERCIAL.get(a, 0) for a in appliances) daily_kwh, system_kw = calculate_system(total_load, hours, sunlight) batteries = calculate_battery(daily_kwh, backup_hours) total_cost = calculate_cost(system_kw, batteries, system_type) interest = st.slider("Bank Interest Rate (%)", 5, 25, 15) years_loan = st.slider("Loan Duration (Years)", 1, 10, 5) emi = emi_calculator(total_cost, interest, years_loan) cashflows, npv, irr, payback_year, cumulative_savings = financial_projection(total_cost, daily_kwh, audience) # Results st.subheader("System Results") st.write(f"Total Load: {total_load} W") st.write(f"Daily Energy: {round(daily_kwh,2)} kWh") st.write(f"System Size: {system_kw} kW") st.write(f"Battery Units: {batteries}") st.write(f"Total Cost: PKR {round(total_cost):,}") st.write(f"EMI: PKR {emi:,}") st.write(f"NPV: PKR {npv:,}") st.write(f"IRR: {irr}%") st.write(f"Payback Year: {payback_year}") # Charts st.subheader("Savings Growth") plt.figure(figsize=(10,4)) plt.plot(range(1,26), cumulative_savings) plt.axhline(total_cost, linestyle="--") st.pyplot(plt) # PDF + Excel report_data = { "Audience": audience, "City": city, "System Size (kW)": system_kw, "Total Cost": total_cost, "IRR": irr, "NPV": npv, "Payback Year": payback_year } pdf_file = generate_pdf(report_data) with open(pdf_file, "rb") as f: st.download_button("Download PDF Report", f, file_name="Solar_Report.pdf")