asif-coder commited on
Commit
49b643d
·
verified ·
1 Parent(s): 6b55b85

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +262 -0
app.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import math
5
+ import matplotlib.pyplot as plt
6
+ import numpy_financial as npf
7
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
8
+ from reportlab.lib.pagesizes import A4
9
+ from reportlab.lib.styles import getSampleStyleSheet
10
+ import io
11
+ import xlsxwriter
12
+
13
+ # ===============================
14
+ # PAGE CONFIG
15
+ # ===============================
16
+ st.set_page_config(layout="wide")
17
+ st.title("🇵🇰 Pakistan Solar Engineering & Financial Dashboard")
18
+
19
+ # ===============================
20
+ # CONFIGURATION
21
+ # ===============================
22
+
23
+ SYSTEM_LOSSES = 0.20
24
+ PANEL_COST_PER_WATT = 55
25
+ INSTALLATION_COST_PER_WATT = 35
26
+ LITHIUM_BATTERY_COST_5KWH = 95000
27
+
28
+ CITY_SUNLIGHT = {
29
+ "Karachi": 6.2,
30
+ "Lahore": 5.5,
31
+ "Islamabad": 5.2,
32
+ "Peshawar": 5.6,
33
+ "Quetta": 6.5,
34
+ }
35
+
36
+ # Appliance Database
37
+ APPLIANCES_RESIDENTIAL = {
38
+ "LED Bulb (12W)": 12,
39
+ "Fan (80W)": 80,
40
+ "Refrigerator (200W)": 200,
41
+ "LED TV (150W)": 150,
42
+ "Air Conditioner 1.5 Ton (1500W)": 1500,
43
+ "Washing Machine (500W)": 500,
44
+ "Water Pump (750W)": 750,
45
+ "Laptop (65W)": 65,
46
+ "Iron (1000W)": 1000,
47
+ }
48
+
49
+ APPLIANCES_COMMERCIAL = {
50
+ "CNC Machine (2kW)": 2000,
51
+ "Industrial AC (5kW)": 5000,
52
+ "Lighting System (1kW)": 1000,
53
+ "Water Pump 3HP (2.2kW)": 2200,
54
+ "Server Rack (1.5kW)": 1500,
55
+ }
56
+
57
+ # Demo Load Profiles
58
+ DEMO_SELECTIONS = {
59
+ "Homeowner": ["LED Bulb (12W)", "Fan (80W)", "Refrigerator (200W)", "LED TV (150W)"],
60
+ "Solar Company": ["LED Bulb (12W)", "Fan (80W)", "CNC Machine (2kW)", "Industrial AC (5kW)"],
61
+ "Industrial Investor": ["CNC Machine (2kW)", "Industrial AC (5kW)", "Water Pump 3HP (2.2kW)", "Server Rack (1.5kW)"]
62
+ }
63
+
64
+ # Tariffs
65
+ RESIDENTIAL_TARIFF = [
66
+ (100, 22),
67
+ (100, 32),
68
+ (100, 38),
69
+ (100, 42),
70
+ (100, 48),
71
+ (np.inf, 65),
72
+ ]
73
+
74
+ COMMERCIAL_TARIFF = 72
75
+
76
+ # ===============================
77
+ # CALCULATION FUNCTIONS
78
+ # ===============================
79
+
80
+ def calculate_residential_bill(units):
81
+ remaining = units
82
+ bill = 0
83
+ for slab_units, rate in RESIDENTIAL_TARIFF:
84
+ if remaining > slab_units:
85
+ bill += slab_units * rate
86
+ remaining -= slab_units
87
+ else:
88
+ bill += remaining * rate
89
+ break
90
+ return bill
91
+
92
+ def calculate_commercial_bill(units):
93
+ return units * COMMERCIAL_TARIFF
94
+
95
+ def calculate_system(load_watts, hours, sunlight):
96
+ daily_kwh = (load_watts * hours) / 1000
97
+ adjusted_kwh = daily_kwh / (1 - SYSTEM_LOSSES)
98
+ required_kw = adjusted_kwh / sunlight
99
+ return daily_kwh, round(required_kw, 2)
100
+
101
+ def calculate_battery(daily_kwh, backup_hours):
102
+ backup_kwh = (daily_kwh / 24) * backup_hours
103
+ return math.ceil(backup_kwh / 5)
104
+
105
+ def calculate_cost(system_kw, batteries, system_type):
106
+ base_cost = system_kw * 1000 * (PANEL_COST_PER_WATT + INSTALLATION_COST_PER_WATT)
107
+ battery_cost = batteries * LITHIUM_BATTERY_COST_5KWH
108
+
109
+ if system_type == "On-Grid":
110
+ return base_cost
111
+ elif system_type == "Off-Grid":
112
+ return base_cost + battery_cost
113
+ else:
114
+ return base_cost * 1.1 + battery_cost
115
+
116
+ def emi_calculator(principal, annual_rate, years):
117
+ r = annual_rate / 100 / 12
118
+ n = years * 12
119
+ return round(principal * r * (1 + r)**n / ((1 + r)**n - 1))
120
+
121
+ def financial_projection(total_cost, daily_kwh, mode, years=25):
122
+ monthly_units = daily_kwh * 30
123
+ cashflows = []
124
+
125
+ for year in range(1, years + 1):
126
+ price_increase = (1 + 0.07) ** (year - 1)
127
+
128
+ if mode == "Homeowner":
129
+ monthly_bill = calculate_residential_bill(monthly_units * price_increase)
130
+ else:
131
+ monthly_bill = calculate_commercial_bill(monthly_units * price_increase)
132
+
133
+ cashflows.append(monthly_bill * 12)
134
+
135
+ npv = npf.npv(0.05, [-total_cost] + cashflows)
136
+ irr = npf.irr([-total_cost] + cashflows)
137
+ payback_year = next((i for i, cf in enumerate(np.cumsum(cashflows), 1) if cf >= total_cost), None)
138
+
139
+ return cashflows, round(npv, 2), round(irr * 100, 2), payback_year, np.cumsum(cashflows)
140
+
141
+ # ===============================
142
+ # PDF REPORT
143
+ # ===============================
144
+
145
+ def generate_pdf(report_data):
146
+ file_path = "solar_report.pdf"
147
+ doc = SimpleDocTemplate(file_path, pagesize=A4)
148
+ elements = []
149
+ styles = getSampleStyleSheet()
150
+
151
+ elements.append(Paragraph("Pakistan Solar Feasibility Report", styles['Title']))
152
+ elements.append(Spacer(1, 12))
153
+
154
+ for k, v in report_data.items():
155
+ elements.append(Paragraph(f"{k}: {v}", styles['Normal']))
156
+ elements.append(Spacer(1, 6))
157
+
158
+ doc.build(elements)
159
+ return file_path
160
+
161
+ # ===============================
162
+ # STREAMLIT UI
163
+ # ===============================
164
+
165
+ audience = st.selectbox("Select Audience", ["Homeowner", "Solar Company", "Industrial Investor"])
166
+ city = st.selectbox("Select City", list(CITY_SUNLIGHT.keys()))
167
+ sunlight = CITY_SUNLIGHT[city]
168
+
169
+ # Demo Settings Buttons
170
+ if st.button("🎯 Load Demo Appliances"):
171
+ if audience in DEMO_SELECTIONS:
172
+ st.session_state["demo_appliances"] = DEMO_SELECTIONS[audience]
173
+ st.success("Demo appliances loaded!")
174
+
175
+ if "demo_appliances" in st.session_state:
176
+ default_selection = st.session_state["demo_appliances"]
177
+ else:
178
+ default_selection = []
179
+
180
+ # Appliance Selection
181
+ if audience == "Homeowner":
182
+ appliances = st.multiselect("Select Appliances", list(APPLIANCES_RESIDENTIAL.keys()),
183
+ default=default_selection)
184
+
185
+ elif audience == "Solar Company":
186
+ appliances = st.multiselect("Select Appliances",
187
+ list(APPLIANCES_RESIDENTIAL.keys()) + list(APPLIANCES_COMMERCIAL.keys()),
188
+ default=default_selection)
189
+
190
+ else:
191
+ appliances = st.multiselect("Select Industrial Equipment",
192
+ list(APPLIANCES_COMMERCIAL.keys()),
193
+ default=default_selection)
194
+
195
+ # Demo Settings Button
196
+ if st.button("🎯 Load Demo City & Settings"):
197
+ city = "Karachi"
198
+ sunlight = CITY_SUNLIGHT[city]
199
+ hours = 8
200
+ backup_hours = 4
201
+ st.success("Demo settings loaded!")
202
+
203
+ hours = st.slider("Usage Hours per Day", 1, 24, 8)
204
+ system_type = st.radio("System Type", ["On-Grid", "Off-Grid", "Hybrid"])
205
+ backup_hours = st.slider("Battery Backup Hours", 0, 24, 4)
206
+
207
+ # Calculation Trigger
208
+ if st.button("⚡ Calculate Solar System"):
209
+
210
+ if not appliances:
211
+ st.error("Please select appliances")
212
+ else:
213
+
214
+ total_load = sum(APPLIANCES_RESIDENTIAL.get(a, 0) + APPLIANCES_COMMERCIAL.get(a, 0) for a in appliances)
215
+
216
+ daily_kwh, system_kw = calculate_system(total_load, hours, sunlight)
217
+
218
+ batteries = calculate_battery(daily_kwh, backup_hours)
219
+
220
+ total_cost = calculate_cost(system_kw, batteries, system_type)
221
+
222
+ interest = st.slider("Bank Interest Rate (%)", 5, 25, 15)
223
+ years_loan = st.slider("Loan Duration (Years)", 1, 10, 5)
224
+
225
+ emi = emi_calculator(total_cost, interest, years_loan)
226
+
227
+ cashflows, npv, irr, payback_year, cumulative_savings = financial_projection(total_cost, daily_kwh, audience)
228
+
229
+ # Results
230
+ st.subheader("System Results")
231
+ st.write(f"Total Load: {total_load} W")
232
+ st.write(f"Daily Energy: {round(daily_kwh,2)} kWh")
233
+ st.write(f"System Size: {system_kw} kW")
234
+ st.write(f"Battery Units: {batteries}")
235
+ st.write(f"Total Cost: PKR {round(total_cost):,}")
236
+ st.write(f"EMI: PKR {emi:,}")
237
+ st.write(f"NPV: PKR {npv:,}")
238
+ st.write(f"IRR: {irr}%")
239
+ st.write(f"Payback Year: {payback_year}")
240
+
241
+ # Charts
242
+ st.subheader("Savings Growth")
243
+ plt.figure(figsize=(10,4))
244
+ plt.plot(range(1,26), cumulative_savings)
245
+ plt.axhline(total_cost, linestyle="--")
246
+ st.pyplot(plt)
247
+
248
+ # PDF + Excel
249
+ report_data = {
250
+ "Audience": audience,
251
+ "City": city,
252
+ "System Size (kW)": system_kw,
253
+ "Total Cost": total_cost,
254
+ "IRR": irr,
255
+ "NPV": npv,
256
+ "Payback Year": payback_year
257
+ }
258
+
259
+ pdf_file = generate_pdf(report_data)
260
+
261
+ with open(pdf_file, "rb") as f:
262
+ st.download_button("Download PDF Report", f, file_name="Solar_Report.pdf")