jethrovic commited on
Commit
daef116
Β·
verified Β·
1 Parent(s): 06be911

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1006 -19
  3. prompts.txt +2 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Energy Redux
3
- emoji: πŸ†
4
- colorFrom: red
5
- colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: energy-redux
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1006 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Household Energy Savings Dashboard</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ .gradient-bg {
13
+ background: linear-gradient(135deg, #6b73ff 0%, #000dff 100%);
14
+ }
15
+ .sidebar {
16
+ transition: all 0.3s;
17
+ }
18
+ .chart-container {
19
+ height: 100%;
20
+ min-height: 300px;
21
+ }
22
+ .chat-message {
23
+ animation: fadeIn 0.3s ease-in-out;
24
+ }
25
+ @keyframes fadeIn {
26
+ from { opacity: 0; transform: translateY(10px); }
27
+ to { opacity: 1; transform: translateY(0); }
28
+ }
29
+ .pulse {
30
+ animation: pulse 2s infinite;
31
+ }
32
+ @keyframes pulse {
33
+ 0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); }
34
+ 70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
35
+ 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
36
+ }
37
+ #map {
38
+ height: 300px;
39
+ width: 100%;
40
+ border-radius: 0.5rem;
41
+ }
42
+ </style>
43
+ </head>
44
+ <body class="bg-gray-100 font-sans">
45
+ <div class="flex h-screen overflow-hidden">
46
+ <!-- Sidebar -->
47
+ <div class="sidebar bg-white w-64 flex-shrink-0 shadow-lg">
48
+ <div class="p-4 gradient-bg text-white">
49
+ <h1 class="text-2xl font-bold flex items-center">
50
+ <i class="fas fa-piggy-bank mr-2"></i> EnergySavings
51
+ </h1>
52
+ <p class="text-sm opacity-80">Track your household energy savings</p>
53
+ </div>
54
+ <nav class="mt-6">
55
+ <div class="px-4">
56
+ <div class="relative">
57
+ <input type="text" placeholder="Search..." class="w-full px-4 py-2 rounded-lg bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">
58
+ <i class="fas fa-search absolute right-4 top-3 text-gray-400"></i>
59
+ </div>
60
+ </div>
61
+ <div class="mt-6">
62
+ <a href="#" class="flex items-center px-6 py-3 text-blue-600 bg-blue-50 border-l-4 border-blue-600">
63
+ <i class="fas fa-home mr-3"></i>
64
+ <span>Dashboard</span>
65
+ </a>
66
+ <a href="#" class="flex items-center px-6 py-3 text-gray-600 hover:bg-gray-50">
67
+ <i class="fas fa-chart-line mr-3"></i>
68
+ <span>Analytics</span>
69
+ </a>
70
+ <a href="#" class="flex items-center px-6 py-3 text-gray-600 hover:bg-gray-50">
71
+ <i class="fas fa-wallet mr-3"></i>
72
+ <span>Budget</span>
73
+ </a>
74
+ <a href="#" class="flex items-center px-6 py-3 text-gray-600 hover:bg-gray-50">
75
+ <i class="fas fa-lightbulb mr-3"></i>
76
+ <span>Energy</span>
77
+ </a>
78
+ </div>
79
+ </nav>
80
+ </div>
81
+
82
+ <!-- Main Content -->
83
+ <div class="flex-1 overflow-auto">
84
+ <!-- Header -->
85
+ <header class="bg-white shadow-sm">
86
+ <div class="flex items-center justify-between px-6 py-4">
87
+ <div class="flex items-center">
88
+ <button class="text-gray-500 focus:outline-none lg:hidden">
89
+ <i class="fas fa-bars"></i>
90
+ </button>
91
+ <h2 class="ml-4 text-xl font-semibold text-gray-800">Household Energy Savings Dashboard</h2>
92
+ </div>
93
+ <div class="flex items-center space-x-4">
94
+ <div id="addressSearchContainer" class="relative w-64">
95
+ <input id="addressSearch" type="text" placeholder="Enter your address..."
96
+ class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500">
97
+ <div id="addressSuggestions" class="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-lg shadow-lg hidden"></div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </header>
102
+
103
+ <!-- Dashboard Content -->
104
+ <main class="p-6">
105
+ <!-- Address Confirmation -->
106
+ <div id="addressConfirmation" class="hidden bg-white rounded-lg shadow p-6 mb-6">
107
+ <div class="flex justify-between items-center">
108
+ <div>
109
+ <h3 class="text-lg font-semibold">Location Confirmed</h3>
110
+ <p id="confirmedAddress" class="text-gray-600"></p>
111
+ </div>
112
+ <button id="changeAddress" class="text-blue-600 hover:text-blue-800">Change Address</button>
113
+ </div>
114
+ <div class="mt-4" id="map"></div>
115
+ </div>
116
+
117
+ <!-- Stats Cards -->
118
+ <div id="statsCards" class="hidden grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
119
+ <div class="bg-white rounded-lg shadow p-6 flex items-center">
120
+ <div class="p-3 rounded-full bg-blue-100 text-blue-600 mr-4">
121
+ <i class="fas fa-dollar-sign text-xl"></i>
122
+ </div>
123
+ <div>
124
+ <p class="text-gray-500">Monthly Savings</p>
125
+ <h3 id="monthlySavings" class="text-2xl font-bold">$---</h3>
126
+ <p id="savingsChange" class="text-sm flex items-center">
127
+ <i class="fas fa-arrow-up mr-1"></i> --% from last month
128
+ </p>
129
+ </div>
130
+ </div>
131
+ <div class="bg-white rounded-lg shadow p-6 flex items-center">
132
+ <div class="p-3 rounded-full bg-green-100 text-green-600 mr-4">
133
+ <i class="fas fa-bolt text-xl"></i>
134
+ </div>
135
+ <div>
136
+ <p class="text-gray-500">Energy Savings</p>
137
+ <h3 id="energySavings" class="text-2xl font-bold">$---</h3>
138
+ <p id="energyChange" class="text-sm flex items-center">
139
+ <i class="fas fa-arrow-up mr-1"></i> --% from last month
140
+ </p>
141
+ </div>
142
+ </div>
143
+ <div class="bg-white rounded-lg shadow p-6 flex items-center">
144
+ <div class="p-3 rounded-full bg-purple-100 text-purple-600 mr-4">
145
+ <i class="fas fa-water text-xl"></i>
146
+ </div>
147
+ <div>
148
+ <p class="text-gray-500">Water Savings</p>
149
+ <h3 id="waterSavings" class="text-2xl font-bold">$---</h3>
150
+ <p id="waterChange" class="text-sm flex items-center">
151
+ <i class="fas fa-arrow-up mr-1"></i> --% from last month
152
+ </p>
153
+ </div>
154
+ </div>
155
+ <div class="bg-white rounded-lg shadow p-6 flex items-center">
156
+ <div class="p-3 rounded-full bg-yellow-100 text-yellow-600 mr-4">
157
+ <i class="fas fa-recycle text-xl"></i>
158
+ </div>
159
+ <div>
160
+ <p class="text-gray-500">Waste Reduction</p>
161
+ <h3 id="wasteReduction" class="text-2xl font-bold">$---</h3>
162
+ <p id="wasteChange" class="text-sm flex items-center">
163
+ <i class="fas fa-arrow-up mr-1"></i> --% from last month
164
+ </p>
165
+ </div>
166
+ </div>
167
+ </div>
168
+
169
+ <!-- Main Charts -->
170
+ <div id="mainCharts" class="hidden grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
171
+ <!-- Savings Trend Chart -->
172
+ <div class="bg-white rounded-lg shadow p-6 lg:col-span-2">
173
+ <div class="flex justify-between items-center mb-4">
174
+ <h3 class="text-lg font-semibold">Energy Usage Trend</h3>
175
+ <div class="flex space-x-2">
176
+ <button class="px-3 py-1 text-sm bg-blue-100 text-blue-600 rounded-lg">Month</button>
177
+ <button class="px-3 py-1 text-sm bg-gray-100 text-gray-600 rounded-lg">Quarter</button>
178
+ <button class="px-3 py-1 text-sm bg-gray-100 text-gray-600 rounded-lg">Year</button>
179
+ </div>
180
+ </div>
181
+ <div class="chart-container">
182
+ <canvas id="energyTrendChart"></canvas>
183
+ </div>
184
+ </div>
185
+
186
+ <!-- Savings Distribution -->
187
+ <div class="bg-white rounded-lg shadow p-6">
188
+ <h3 class="text-lg font-semibold mb-4">Energy Distribution</h3>
189
+ <div class="chart-container">
190
+ <canvas id="energyDistributionChart"></canvas>
191
+ </div>
192
+ </div>
193
+ </div>
194
+
195
+ <!-- Energy Analysis Section -->
196
+ <div id="energyAnalysis" class="hidden bg-white rounded-lg shadow p-6 mb-6">
197
+ <div class="flex justify-between items-center mb-4">
198
+ <h3 class="text-lg font-semibold">Energy Consumption Analysis</h3>
199
+ <div class="flex items-center space-x-2">
200
+ <select id="timeRange" class="px-3 py-1 text-sm bg-gray-100 text-gray-600 rounded-lg focus:outline-none">
201
+ <option value="30">Last 30 Days</option>
202
+ <option value="90">Last 90 Days</option>
203
+ <option value="365">This Year</option>
204
+ </select>
205
+ <button id="fetchEnergyData" class="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition">
206
+ <i class="fas fa-sync-alt mr-1"></i> Update Data
207
+ </button>
208
+ </div>
209
+ </div>
210
+
211
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
212
+ <!-- Energy Consumption Chart -->
213
+ <div class="bg-gray-50 rounded-lg p-4">
214
+ <h4 class="font-medium text-gray-700 mb-3">Hourly Energy Consumption</h4>
215
+ <div class="chart-container">
216
+ <div id="energyConsumptionChart"></div>
217
+ </div>
218
+ </div>
219
+
220
+ <!-- Energy Cost Chart -->
221
+ <div class="bg-gray-50 rounded-lg p-4">
222
+ <h4 class="font-medium text-gray-700 mb-3">Energy Cost Breakdown</h4>
223
+ <div class="chart-container">
224
+ <div id="energyCostChart"></div>
225
+ </div>
226
+ </div>
227
+ </div>
228
+
229
+ <!-- AI Recommendations -->
230
+ <div class="bg-blue-50 rounded-lg p-4 border border-blue-100">
231
+ <div class="flex items-center mb-3">
232
+ <div class="p-2 bg-blue-100 rounded-full mr-3">
233
+ <i class="fas fa-robot text-blue-600"></i>
234
+ </div>
235
+ <h4 class="font-medium text-gray-700">AI-Powered Savings Recommendations</h4>
236
+ </div>
237
+ <div id="aiRecommendations" class="space-y-3">
238
+ <p class="text-gray-600">Enter your address to get personalized energy savings recommendations.</p>
239
+ </div>
240
+ <button id="generateMoreRecommendations" class="mt-3 px-3 py-1 text-sm bg-white text-blue-600 rounded-lg border border-blue-200 hover:bg-blue-50 transition">
241
+ <i class="fas fa-magic mr-1"></i> Generate Recommendations
242
+ </button>
243
+ </div>
244
+ </div>
245
+
246
+ <!-- Recent Transactions -->
247
+ <div id="recentTransactions" class="hidden bg-white rounded-lg shadow overflow-hidden mb-6">
248
+ <div class="px-6 py-4 border-b">
249
+ <h3 class="text-lg font-semibold">Recent Energy Savings</h3>
250
+ </div>
251
+ <div id="transactionsList" class="divide-y">
252
+ <div class="grid grid-cols-12 items-center px-6 py-4 hover:bg-gray-50">
253
+ <div class="col-span-9 text-center">
254
+ <p class="text-gray-600">Enter your address to view your energy savings history.</p>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ <div class="px-6 py-3 bg-gray-50 text-center">
259
+ <button class="text-blue-600 hover:text-blue-800 font-medium">View All Transactions</button>
260
+ </div>
261
+ </div>
262
+ </main>
263
+ </div>
264
+
265
+ <!-- Chatbot Panel -->
266
+ <div class="fixed bottom-6 right-6 z-10">
267
+ <div id="chatbotContainer" class="hidden w-80 bg-white rounded-t-lg shadow-xl overflow-hidden">
268
+ <div class="bg-blue-600 text-white px-4 py-3 flex justify-between items-center">
269
+ <h3 class="font-medium">Energy Assistant</h3>
270
+ <button id="closeChatbot" class="text-white hover:text-blue-200">
271
+ <i class="fas fa-times"></i>
272
+ </button>
273
+ </div>
274
+ <div id="chatbotMessages" class="h-80 overflow-y-auto p-4 bg-gray-50 space-y-3">
275
+ <div class="chat-message">
276
+ <div class="flex items-start">
277
+ <div class="flex-shrink-0 h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center">
278
+ <i class="fas fa-robot text-blue-600"></i>
279
+ </div>
280
+ <div class="ml-3">
281
+ <div class="bg-white p-3 rounded-lg shadow-sm">
282
+ <p>Hello! I'm your energy savings assistant. How can I help you today?</p>
283
+ </div>
284
+ <p class="text-xs text-gray-500 mt-1">Just now</p>
285
+ </div>
286
+ </div>
287
+ </div>
288
+ </div>
289
+ <div class="border-t p-3 bg-white">
290
+ <div class="flex">
291
+ <input id="chatbotInput" type="text" placeholder="Ask about energy savings..." class="flex-1 px-3 py-2 border rounded-l-lg focus:outline-none focus:ring-1 focus:ring-blue-500">
292
+ <button id="sendChatbotMessage" class="px-4 py-2 bg-blue-600 text-white rounded-r-lg hover:bg-blue-700">
293
+ <i class="fas fa-paper-plane"></i>
294
+ </button>
295
+ </div>
296
+ </div>
297
+ </div>
298
+ <button id="openChatbot" class="w-14 h-14 rounded-full gradient-bg text-white shadow-lg hover:shadow-xl transition-all flex items-center justify-center pulse">
299
+ <i class="fas fa-comment-dots text-2xl"></i>
300
+ </button>
301
+ </div>
302
+ </div>
303
+
304
+ <!-- Load Leaflet for maps -->
305
+ <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
306
+ <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
307
+
308
+ <script>
309
+ // Global variables
310
+ let map;
311
+ let marker;
312
+ let confirmedAddress = '';
313
+ let confirmedCoords = null;
314
+ let energyTrendChart;
315
+ let energyDistributionChart;
316
+ let energyConsumptionChart;
317
+ let energyCostChart;
318
+
319
+ // Initialize when DOM is loaded
320
+ document.addEventListener('DOMContentLoaded', function() {
321
+ // Initialize chatbot functionality
322
+ initChatbot();
323
+
324
+ // Set up address search
325
+ const addressSearch = document.getElementById('addressSearch');
326
+ const addressSuggestions = document.getElementById('addressSuggestions');
327
+
328
+ addressSearch.addEventListener('input', debounce(function(e) {
329
+ const query = e.target.value.trim();
330
+ if (query.length > 2) {
331
+ searchAddress(query);
332
+ } else {
333
+ addressSuggestions.classList.add('hidden');
334
+ }
335
+ }, 300));
336
+
337
+ // Change address button
338
+ document.getElementById('changeAddress').addEventListener('click', function() {
339
+ document.getElementById('addressConfirmation').classList.add('hidden');
340
+ document.getElementById('statsCards').classList.add('hidden');
341
+ document.getElementById('mainCharts').classList.add('hidden');
342
+ document.getElementById('energyAnalysis').classList.add('hidden');
343
+ document.getElementById('recentTransactions').classList.add('hidden');
344
+ addressSearch.value = '';
345
+ addressSearch.focus();
346
+ });
347
+
348
+ // Time range change
349
+ document.getElementById('timeRange').addEventListener('change', function() {
350
+ if (confirmedCoords) {
351
+ fetchEnergyData();
352
+ }
353
+ });
354
+
355
+ // Generate recommendations button
356
+ document.getElementById('generateMoreRecommendations').addEventListener('click', function() {
357
+ generateRecommendations();
358
+ });
359
+ });
360
+
361
+ // Debounce function to limit API calls
362
+ function debounce(func, wait) {
363
+ let timeout;
364
+ return function(...args) {
365
+ clearTimeout(timeout);
366
+ timeout = setTimeout(() => func.apply(this, args), wait);
367
+ };
368
+ }
369
+
370
+ // Search address using Nominatim API
371
+ function searchAddress(query) {
372
+ const url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&limit=5`;
373
+
374
+ fetch(url)
375
+ .then(response => response.json())
376
+ .then(data => {
377
+ const suggestions = document.getElementById('addressSuggestions');
378
+ suggestions.innerHTML = '';
379
+
380
+ if (data.length === 0) {
381
+ const item = document.createElement('div');
382
+ item.className = 'px-4 py-2 text-gray-500';
383
+ item.textContent = 'No addresses found';
384
+ suggestions.appendChild(item);
385
+ } else {
386
+ data.forEach(result => {
387
+ const item = document.createElement('div');
388
+ item.className = 'px-4 py-2 hover:bg-gray-100 cursor-pointer';
389
+ item.textContent = result.display_name;
390
+ item.addEventListener('click', function() {
391
+ confirmAddress(result.display_name, parseFloat(result.lon), parseFloat(result.lat));
392
+ });
393
+ suggestions.appendChild(item);
394
+ });
395
+ }
396
+
397
+ suggestions.classList.remove('hidden');
398
+ })
399
+ .catch(error => {
400
+ console.error('Error searching address:', error);
401
+ });
402
+ }
403
+
404
+ // Confirm address and show map
405
+ function confirmAddress(address, lon, lat) {
406
+ confirmedAddress = address;
407
+ confirmedCoords = { lon, lat };
408
+
409
+ // Hide suggestions
410
+ document.getElementById('addressSuggestions').classList.add('hidden');
411
+
412
+ // Update UI
413
+ document.getElementById('addressSearch').value = address;
414
+ document.getElementById('confirmedAddress').textContent = address;
415
+ document.getElementById('addressConfirmation').classList.remove('hidden');
416
+
417
+ // Initialize or update map
418
+ if (!map) {
419
+ initMap(lon, lat);
420
+ } else {
421
+ map.setView([lat, lon], 15);
422
+ marker.setLatLng([lat, lon]);
423
+ }
424
+
425
+ // Show dashboard sections
426
+ document.getElementById('statsCards').classList.remove('hidden');
427
+ document.getElementById('mainCharts').classList.remove('hidden');
428
+ document.getElementById('energyAnalysis').classList.remove('hidden');
429
+ document.getElementById('recentTransactions').classList.remove('hidden');
430
+
431
+ // Fetch energy data
432
+ fetchEnergyData();
433
+ }
434
+
435
+ // Initialize Leaflet map
436
+ function initMap(lon, lat) {
437
+ map = L.map('map').setView([lat, lon], 15);
438
+
439
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
440
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
441
+ }).addTo(map);
442
+
443
+ marker = L.marker([lat, lon]).addTo(map)
444
+ .bindPopup(confirmedAddress)
445
+ .openPopup();
446
+ }
447
+
448
+ // Fetch energy data (simulated API call)
449
+ function fetchEnergyData() {
450
+ const button = document.getElementById('fetchEnergyData');
451
+ const originalText = button.innerHTML;
452
+ button.disabled = true;
453
+ button.innerHTML = '<i class="fas fa-spinner fa-spin mr-1"></i> Loading...';
454
+
455
+ // Simulate API call with timeout
456
+ setTimeout(() => {
457
+ // Generate realistic mock data based on time range
458
+ const timeRange = document.getElementById('timeRange').value;
459
+ const days = parseInt(timeRange);
460
+
461
+ // Update stats
462
+ updateStatsCards();
463
+
464
+ // Update charts
465
+ updateCharts(days);
466
+
467
+ // Generate initial recommendations
468
+ generateRecommendations();
469
+
470
+ // Update transactions
471
+ updateTransactions();
472
+
473
+ // Reset button
474
+ button.innerHTML = originalText;
475
+ button.disabled = false;
476
+
477
+ // Show success notification
478
+ showNotification('Energy data updated successfully!', 'green');
479
+ }, 1500);
480
+ }
481
+
482
+ // Update stats cards with mock data
483
+ function updateStatsCards() {
484
+ // Generate random but realistic values
485
+ const monthlySavings = (Math.random() * 500 + 800).toFixed(2);
486
+ const energySavings = (Math.random() * 50 + 50).toFixed(2);
487
+ const waterSavings = (Math.random() * 30 + 20).toFixed(2);
488
+ const wasteReduction = (Math.random() * 20 + 10).toFixed(2);
489
+
490
+ const savingsChange = (Math.random() * 5 + 8).toFixed(0);
491
+ const energyChange = (Math.random() * 4 + 6).toFixed(0);
492
+ const waterChange = (Math.random() * 3 + 4).toFixed(0);
493
+ const wasteChange = (Math.random() * 2 + 3).toFixed(0);
494
+
495
+ // Update DOM
496
+ document.getElementById('monthlySavings').textContent = `$${monthlySavings}`;
497
+ document.getElementById('energySavings').textContent = `$${energySavings}`;
498
+ document.getElementById('waterSavings').textContent = `$${waterSavings}`;
499
+ document.getElementById('wasteReduction').textContent = `$${wasteReduction}`;
500
+
501
+ document.getElementById('savingsChange').innerHTML = `<i class="fas fa-arrow-up mr-1"></i> ${savingsChange}% from last month`;
502
+ document.getElementById('energyChange').innerHTML = `<i class="fas fa-arrow-up mr-1"></i> ${energyChange}% from last month`;
503
+ document.getElementById('waterChange').innerHTML = `<i class="fas fa-arrow-up mr-1"></i> ${waterChange}% from last month`;
504
+ document.getElementById('wasteChange').innerHTML = `<i class="fas fa-arrow-up mr-1"></i> ${wasteChange}% from last month`;
505
+ }
506
+
507
+ // Update all charts
508
+ function updateCharts(days) {
509
+ // Destroy existing charts if they exist
510
+ if (energyTrendChart) {
511
+ energyTrendChart.destroy();
512
+ }
513
+ if (energyDistributionChart) {
514
+ energyDistributionChart.destroy();
515
+ }
516
+
517
+ // Generate labels based on time range
518
+ let labels;
519
+ if (days <= 30) {
520
+ labels = Array.from({length: 30}, (_, i) => `Day ${i+1}`);
521
+ } else if (days <= 90) {
522
+ labels = Array.from({length: 12}, (_, i) => `Week ${i+1}`);
523
+ } else {
524
+ labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
525
+ }
526
+
527
+ // Energy Trend Chart (Line Chart)
528
+ const energyTrendCtx = document.getElementById('energyTrendChart').getContext('2d');
529
+ energyTrendChart = new Chart(energyTrendCtx, {
530
+ type: 'line',
531
+ data: {
532
+ labels: labels,
533
+ datasets: [
534
+ {
535
+ label: 'Energy Usage (kWh)',
536
+ data: generateRandomData(labels.length, 10, 30),
537
+ borderColor: '#4f46e5',
538
+ backgroundColor: 'rgba(79, 70, 229, 0.1)',
539
+ borderWidth: 2,
540
+ tension: 0.3,
541
+ fill: true
542
+ },
543
+ {
544
+ label: 'Energy Cost ($)',
545
+ data: generateRandomData(labels.length, 5, 15),
546
+ borderColor: '#10b981',
547
+ backgroundColor: 'rgba(16, 185, 129, 0.1)',
548
+ borderWidth: 2,
549
+ tension: 0.3,
550
+ fill: true
551
+ }
552
+ ]
553
+ },
554
+ options: {
555
+ responsive: true,
556
+ maintainAspectRatio: false,
557
+ plugins: {
558
+ legend: {
559
+ position: 'top',
560
+ },
561
+ tooltip: {
562
+ mode: 'index',
563
+ intersect: false,
564
+ }
565
+ },
566
+ scales: {
567
+ y: {
568
+ beginAtZero: true,
569
+ grid: {
570
+ drawBorder: false
571
+ }
572
+ },
573
+ x: {
574
+ grid: {
575
+ display: false
576
+ }
577
+ }
578
+ }
579
+ }
580
+ });
581
+
582
+ // Energy Distribution Chart (Doughnut Chart)
583
+ const energyDistributionCtx = document.getElementById('energyDistributionChart').getContext('2d');
584
+ energyDistributionChart = new Chart(energyDistributionCtx, {
585
+ type: 'doughnut',
586
+ data: {
587
+ labels: ['HVAC', 'Lighting', 'Appliances', 'Water Heating', 'Other'],
588
+ datasets: [{
589
+ data: [35, 20, 25, 15, 5],
590
+ backgroundColor: [
591
+ '#10b981',
592
+ '#3b82f6',
593
+ '#f59e0b',
594
+ '#8b5cf6',
595
+ '#64748b'
596
+ ],
597
+ borderWidth: 0
598
+ }]
599
+ },
600
+ options: {
601
+ responsive: true,
602
+ maintainAspectRatio: false,
603
+ cutout: '70%',
604
+ plugins: {
605
+ legend: {
606
+ position: 'right',
607
+ }
608
+ }
609
+ }
610
+ });
611
+
612
+ // Energy Consumption Chart (ApexCharts)
613
+ const energyConsumptionOptions = {
614
+ series: [{
615
+ name: 'Consumption',
616
+ data: generateRandomData(24, 2, 8)
617
+ }],
618
+ chart: {
619
+ height: '100%',
620
+ type: 'area',
621
+ toolbar: {
622
+ show: false
623
+ },
624
+ zoom: {
625
+ enabled: false
626
+ }
627
+ },
628
+ colors: ['#3b82f6'],
629
+ dataLabels: {
630
+ enabled: false
631
+ },
632
+ stroke: {
633
+ curve: 'smooth',
634
+ width: 2
635
+ },
636
+ fill: {
637
+ type: 'gradient',
638
+ gradient: {
639
+ shadeIntensity: 1,
640
+ opacityFrom: 0.7,
641
+ opacityTo: 0.3,
642
+ stops: [0, 90, 100]
643
+ }
644
+ },
645
+ xaxis: {
646
+ categories: Array.from({length: 24}, (_, i) => `${i}:00`),
647
+ labels: {
648
+ style: {
649
+ colors: '#6b7280',
650
+ fontSize: '12px'
651
+ }
652
+ },
653
+ axisBorder: {
654
+ show: false
655
+ },
656
+ axisTicks: {
657
+ show: false
658
+ }
659
+ },
660
+ yaxis: {
661
+ labels: {
662
+ style: {
663
+ colors: '#6b7280',
664
+ fontSize: '12px'
665
+ },
666
+ formatter: function (value) {
667
+ return value + ' kWh';
668
+ }
669
+ }
670
+ },
671
+ grid: {
672
+ borderColor: '#e5e7eb',
673
+ strokeDashArray: 4,
674
+ padding: {
675
+ top: 0,
676
+ right: 20,
677
+ bottom: 0,
678
+ left: 20
679
+ }
680
+ },
681
+ tooltip: {
682
+ y: {
683
+ formatter: function (value) {
684
+ return value + ' kWh';
685
+ }
686
+ }
687
+ }
688
+ };
689
+
690
+ if (energyConsumptionChart) {
691
+ energyConsumptionChart.destroy();
692
+ }
693
+ energyConsumptionChart = new ApexCharts(document.querySelector("#energyConsumptionChart"), energyConsumptionOptions);
694
+ energyConsumptionChart.render();
695
+
696
+ // Energy Cost Chart (ApexCharts)
697
+ const energyCostOptions = {
698
+ series: [44, 55, 13, 43, 22],
699
+ labels: ['Electricity', 'Natural Gas', 'Water', 'HVAC', 'Other'],
700
+ chart: {
701
+ type: 'donut',
702
+ height: '100%'
703
+ },
704
+ colors: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#64748b'],
705
+ plotOptions: {
706
+ pie: {
707
+ donut: {
708
+ size: '65%',
709
+ labels: {
710
+ show: true,
711
+ total: {
712
+ show: true,
713
+ label: 'Total Cost',
714
+ formatter: function () {
715
+ return '$156';
716
+ }
717
+ }
718
+ }
719
+ }
720
+ }
721
+ },
722
+ dataLabels: {
723
+ enabled: false
724
+ },
725
+ legend: {
726
+ position: 'right'
727
+ },
728
+ responsive: [{
729
+ breakpoint: 480,
730
+ options: {
731
+ chart: {
732
+ width: 200
733
+ },
734
+ legend: {
735
+ position: 'bottom'
736
+ }
737
+ }
738
+ }]
739
+ };
740
+
741
+ if (energyCostChart) {
742
+ energyCostChart.destroy();
743
+ }
744
+ energyCostChart = new ApexCharts(document.querySelector("#energyCostChart"), energyCostOptions);
745
+ energyCostChart.render();
746
+ }
747
+
748
+ // Generate random data for charts
749
+ function generateRandomData(count, min, max) {
750
+ return Array.from({length: count}, () => (Math.random() * (max - min) + min).toFixed(1));
751
+ }
752
+
753
+ // Generate AI recommendations
754
+ function generateRecommendations() {
755
+ const button = document.getElementById('generateMoreRecommendations');
756
+ const originalText = button.innerHTML;
757
+ button.disabled = true;
758
+ button.innerHTML = '<i class="fas fa-spinner fa-spin mr-1"></i> Analyzing...';
759
+
760
+ // Simulate AI analysis
761
+ setTimeout(() => {
762
+ const recommendations = [
763
+ `Your HVAC system accounts for 35% of your energy bill. Consider upgrading to a more efficient model which could save ~$${(Math.random() * 100 + 100).toFixed(0)}/year.`,
764
+ `Your lighting accounts for 20% of your electric bill. Switching to LED bulbs could cut this by half, saving ~$${(Math.random() * 50 + 50).toFixed(0)}/year.`,
765
+ `Your water heater is set to 140Β°F. Lowering it to 120Β°F could save ~$${(Math.random() * 30 + 20).toFixed(0)}/year with no noticeable difference.`,
766
+ `You have several always-on devices consuming 'phantom load'. Using smart plugs could save ~$${(Math.random() * 25 + 15).toFixed(0)}/year.`,
767
+ `Based on your location in ${confirmedAddress.split(',')[0]}, installing solar panels could reduce your energy costs by 40-60%.`
768
+ ];
769
+
770
+ const recommendationsContainer = document.getElementById('aiRecommendations');
771
+ recommendationsContainer.innerHTML = '';
772
+
773
+ recommendations.forEach(rec => {
774
+ const div = document.createElement('div');
775
+ div.className = 'flex items-start';
776
+ div.innerHTML = `
777
+ <div class="flex-shrink-0 mt-1">
778
+ <div class="w-2 h-2 bg-blue-500 rounded-full"></div>
779
+ </div>
780
+ <p class="ml-2 text-gray-600">${rec}</p>
781
+ `;
782
+ recommendationsContainer.appendChild(div);
783
+ });
784
+
785
+ button.innerHTML = originalText;
786
+ button.disabled = false;
787
+ }, 1500);
788
+ }
789
+
790
+ // Update transactions list
791
+ function updateTransactions() {
792
+ const transactions = [
793
+ {
794
+ type: 'energy',
795
+ description: 'Reduced AC usage during peak hours',
796
+ amount: (Math.random() * 30 + 15).toFixed(2),
797
+ date: randomDate(new Date(2023, 5, 1), new Date())
798
+ },
799
+ {
800
+ type: 'water',
801
+ description: 'Installed low-flow showerheads',
802
+ amount: (Math.random() * 15 + 5).toFixed(2),
803
+ date: randomDate(new Date(2023, 5, 1), new Date())
804
+ },
805
+ {
806
+ type: 'appliance',
807
+ description: 'Upgraded to ENERGY STAR refrigerator',
808
+ amount: (Math.random() * 40 + 20).toFixed(2),
809
+ date: randomDate(new Date(2023, 5, 1), new Date())
810
+ }
811
+ ];
812
+
813
+ // Sort by date (newest first)
814
+ transactions.sort((a, b) => new Date(b.date) - new Date(a.date));
815
+
816
+ const transactionsList = document.getElementById('transactionsList');
817
+ transactionsList.innerHTML = '';
818
+
819
+ transactions.forEach(trans => {
820
+ const div = document.createElement('div');
821
+ div.className = 'grid grid-cols-12 items-center px-6 py-4 hover:bg-gray-50';
822
+
823
+ let iconClass, iconColor;
824
+ switch(trans.type) {
825
+ case 'energy':
826
+ iconClass = 'fa-bolt';
827
+ iconColor = 'text-green-600 bg-green-100';
828
+ break;
829
+ case 'water':
830
+ iconClass = 'fa-tint';
831
+ iconColor = 'text-blue-600 bg-blue-100';
832
+ break;
833
+ default:
834
+ iconClass = 'fa-plug';
835
+ iconColor = 'text-yellow-600 bg-yellow-100';
836
+ }
837
+
838
+ div.innerHTML = `
839
+ <div class="col-span-6 flex items-center">
840
+ <div class="p-2 rounded-full ${iconColor} mr-3">
841
+ <i class="fas ${iconClass}"></i>
842
+ </div>
843
+ <div>
844
+ <p class="font-medium">${trans.description}</p>
845
+ <p class="text-sm text-gray-500">${formatDate(trans.date)}</p>
846
+ </div>
847
+ </div>
848
+ <div class="col-span-3 text-right">
849
+ <p class="text-green-500 font-medium">+$${trans.amount}</p>
850
+ <p class="text-sm text-gray-500">${trans.type.replace(/^\w/, c => c.toUpperCase())} Savings</p>
851
+ </div>
852
+ <div class="col-span-3 text-right">
853
+ <button class="px-3 py-1 text-sm bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200">Details</button>
854
+ </div>
855
+ `;
856
+
857
+ transactionsList.appendChild(div);
858
+ });
859
+ }
860
+
861
+ // Generate random date
862
+ function randomDate(start, end) {
863
+ return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
864
+ }
865
+
866
+ // Format date as "Jun 12, 2023"
867
+ function formatDate(date) {
868
+ return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
869
+ }
870
+
871
+ // Show notification
872
+ function showNotification(message, type = 'blue') {
873
+ const colors = {
874
+ blue: 'bg-blue-500',
875
+ green: 'bg-green-500',
876
+ red: 'bg-red-500'
877
+ };
878
+
879
+ const notification = document.createElement('div');
880
+ notification.className = `fixed bottom-4 right-4 ${colors[type]} text-white px-4 py-2 rounded-lg shadow-lg flex items-center animate-fade-in`;
881
+ notification.innerHTML = `
882
+ <i class="fas fa-check-circle mr-2"></i>
883
+ <span>${message}</span>
884
+ `;
885
+ document.body.appendChild(notification);
886
+
887
+ setTimeout(() => {
888
+ notification.classList.add('animate-fade-out');
889
+ setTimeout(() => {
890
+ notification.remove();
891
+ }, 300);
892
+ }, 3000);
893
+ }
894
+
895
+ // Initialize chatbot
896
+ function initChatbot() {
897
+ const chatbotContainer = document.getElementById('chatbotContainer');
898
+ const openChatbot = document.getElementById('openChatbot');
899
+ const closeChatbot = document.getElementById('closeChatbot');
900
+ const chatbotMessages = document.getElementById('chatbotMessages');
901
+ const chatbotInput = document.getElementById('chatbotInput');
902
+ const sendChatbotMessage = document.getElementById('sendChatbotMessage');
903
+
904
+ openChatbot.addEventListener('click', function() {
905
+ chatbotContainer.classList.remove('hidden');
906
+ openChatbot.classList.add('hidden');
907
+ });
908
+
909
+ closeChatbot.addEventListener('click', function() {
910
+ chatbotContainer.classList.add('hidden');
911
+ openChatbot.classList.remove('hidden');
912
+ });
913
+
914
+ function addBotMessage(message) {
915
+ const messageDiv = document.createElement('div');
916
+ messageDiv.className = 'chat-message';
917
+ messageDiv.innerHTML = `
918
+ <div class="flex items-start">
919
+ <div class="flex-shrink-0 h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center">
920
+ <i class="fas fa-robot text-blue-600"></i>
921
+ </div>
922
+ <div class="ml-3">
923
+ <div class="bg-white p-3 rounded-lg shadow-sm">
924
+ <p>${message}</p>
925
+ </div>
926
+ <p class="text-xs text-gray-500 mt-1">Just now</p>
927
+ </div>
928
+ </div>
929
+ `;
930
+ chatbotMessages.appendChild(messageDiv);
931
+ chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
932
+ }
933
+
934
+ function addUserMessage(message) {
935
+ const messageDiv = document.createElement('div');
936
+ messageDiv.className = 'chat-message';
937
+ messageDiv.innerHTML = `
938
+ <div class="flex items-start justify-end">
939
+ <div class="ml-3 text-right">
940
+ <div class="bg-blue-600 text-white p-3 rounded-lg shadow-sm">
941
+ <p>${message}</p>
942
+ </div>
943
+ <p class="text-xs text-gray-500 mt-1">Just now</p>
944
+ </div>
945
+ <div class="flex-shrink-0 h-8 w-8 rounded-full bg-blue-600 flex items-center justify-center">
946
+ <i class="fas fa-user text-white"></i>
947
+ </div>
948
+ </div>
949
+ `;
950
+ chatbotMessages.appendChild(messageDiv);
951
+ chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
952
+ }
953
+
954
+ sendChatbotMessage.addEventListener('click', function() {
955
+ const message = chatbotInput.value.trim();
956
+ if (message) {
957
+ addUserMessage(message);
958
+ chatbotInput.value = '';
959
+
960
+ // Simulate bot response
961
+ setTimeout(() => {
962
+ let response;
963
+
964
+ if (message.toLowerCase().includes('address') || message.toLowerCase().includes('location')) {
965
+ if (confirmedAddress) {
966
+ response = `Your current location is set to ${confirmedAddress}. Would you like to change it?`;
967
+ } else {
968
+ response = "Please enter your address in the search bar above to get personalized recommendations.";
969
+ }
970
+ }
971
+ else if (message.toLowerCase().includes('savings') || message.toLowerCase().includes('save')) {
972
+ if (confirmedAddress) {
973
+ const savings = document.getElementById('energySavings').textContent;
974
+ response = `Based on your current usage at ${confirmedAddress.split(',')[0]}, you're saving ${savings} this month on energy.`;
975
+ } else {
976
+ response = "I can provide more specific savings recommendations if you enter your address above.";
977
+ }
978
+ }
979
+ else if (message.toLowerCase().includes('recommend') || message.toLowerCase().includes('tip')) {
980
+ const tips = [
981
+ "Consider using a programmable thermostat to reduce HVAC costs.",
982
+ "Wash clothes in cold water to save on water heating costs.",
983
+ "Unplug devices when not in use to avoid phantom loads.",
984
+ "Seal windows and doors to prevent air leaks.",
985
+ "Use natural light during the day to reduce lighting costs."
986
+ ];
987
+ response = tips[Math.floor(Math.random() * tips.length)];
988
+ }
989
+ else {
990
+ response = "I'm your energy savings assistant. You can ask me about your energy usage, savings tips, or recommendations.";
991
+ }
992
+
993
+ addBotMessage(response);
994
+ }, 1000);
995
+ }
996
+ });
997
+
998
+ chatbotInput.addEventListener('keypress', function(e) {
999
+ if (e.key === 'Enter') {
1000
+ sendChatbotMessage.click();
1001
+ }
1002
+ });
1003
+ }
1004
+ </script>
1005
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=jethrovic/energy-redux" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1006
+ </html>
prompts.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ i want to make a beautiful dashboard for household savings using the api call to get the data and a visual to choose time range and the second file to clclualte teh most interesting points and crunch data before sending key points to open ai and a small caht bot on the side to ask more questions import streamlit as st import requests import pandas as pd import openai # Geocode an address using OpenStreetMap Nominatim def geocode_address(address): url = "https://nominatim.openstreetmap.org/search" params = {"q": address, "format": "json"} headers = {"User-Agent": "streamlit-app"} resp = requests.get(url, params=params, headers=headers) resp.raise_for_status() results = resp.json() if not results: return None, None lon = float(results[0]["lon"]) lat = float(results[0]["lat"]) return lon, lat # Call Palmetto BEM API with correct parameters def get_bem_data(palmetto_key, lon, lat): url = "https://ei.palmetto.com/api/v0/bem/calculate" payload = { "location": {"longitude": lon, "latitude": lat}, "parameters": { "from_datetime": "2025-03-19T00:00:00", "to_datetime": "2025-04-21T00:00:00", "interval_format": "long", "group_by": "hour", "clip_by": "inner", "variables": "all_non_zero" } } headers = { "accept": "application/json", "content-type": "application/json", "X-API-Key": palmetto_key } resp = requests.post(url, json=payload, headers=headers) resp.raise_for_status() return resp.json() # Analyze BEM output with OpenAI to recommend strategies def analyze_with_openai(openai_key, bem_json): openai.api_key = openai_key # Extract monthly consumption series intervals = bem_json.get("data", {}).get("intervals", []) if not intervals: return "No interval data to analyze." # Format prompt prompt = ( "You are an energy consultant. Given the following monthly energy consumption data for a residential building, " "provide list of appliances both present and absent and 5 concise, practical strategies to reduce energy usage.\n\n" f"Monthly Consumption:\n{intervals}\n\n" "Strategies:" ) # Use new OpenAI v1 interface for chat completions response = openai.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": prompt}], max_tokens=3000 ) return response.choices[0].message.content.strip() # Streamlit UI def main(): st.title("🏠 Residential Energy Analysis & Recommendations") palmetto_key = st.text_input("Palmetto API Key", type="password") openai_key = st.text_input("OpenAI API Key", type="password") address = st.text_input("Enter your street address:") if st.button("Analyze Energy Data"): if not all([palmetto_key, openai_key, address]): st.error("Please provide your Palmetto key, OpenAI key, and an address.") return # Geocode try: lon, lat = geocode_address(address) except Exception as e: st.error(f"Geocoding error: {e}") return if lon is None: st.error("Could not geocode the provided address.") return st.success(f"Location: {address} β†’ Lon: {lon:.5f}, Lat: {lat:.5f}") # Fetch BEM data try: bem = get_bem_data(palmetto_key, lon, lat) except Exception as e: st.error(f"BEM API error: {e}") return # Display monthly consumption intervals = bem.get("data", {}).get("intervals", []) if intervals: df = pd.DataFrame(intervals) st.subheader("Monthly Energy Consumption (kWh)") st.dataframe(df) else: st.warning("No monthly data returned. Consider requesting additional variables.") # Generate AI-driven recommendations try: recommendations = analyze_with_openai(openai_key, bem) st.subheader("Recommended Energy-Saving Strategies") st.markdown(recommendations) except Exception as e: st.error(f"OpenAI analysis error: {e}") if __name__ == "__main__": main()import streamlit as st import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import numpy as np import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots # Set page configuration st.set_page_config( page_title="Energy Consumption Dashboard", page_icon="⚑", layout="wide" ) # Title and instructions st.title("⚑ Energy Consumption Dashboard") st.markdown("Upload your energy consumption CSV file to visualize and analyze your energy usage patterns.") # File uploader uploaded_file = st.file_uploader("Choose a CSV file", type="csv") # Function to process and analyze data def analyze_energy_data(df): # Basic data cleaning and preparation # Convert datetime strings to datetime objects df['from_datetime'] = pd.to_datetime(df['from_datetime']) df['to_datetime'] = pd.to_datetime(df['to_datetime']) # Create a date column for easier grouping (just the date part) df['date'] = df['from_datetime'].dt.date # Extract hour for time-of-day analysis df['hour'] = df['from_datetime'].dt.hour # Categorize variables all_vars = df['variable'].unique() electricity_vars = [var for var in all_vars if 'electricity' in var] fossil_fuel_vars = [var for var in all_vars if 'fossil_fuel' in var] thermal_vars = [var for var in all_vars if 'thermal' in var] grid_vars = [var for var in all_vars if 'grid' in var] cost_vars = [var for var in all_vars if 'costs' in var] emission_vars = [var for var in all_vars if 'emissions' in var] return df, electricity_vars, fossil_fuel_vars, thermal_vars, grid_vars, cost_vars, emission_vars # Function to display dashboard def create_dashboard(df, electricity_vars, fossil_fuel_vars, thermal_vars, grid_vars, cost_vars, emission_vars): # Data overview st.subheader("πŸ“Š Data Overview") # Key metrics in columns col1, col2, col3, col4 = st.columns(4) with col1: st.metric("Date Range", f"{df['from_datetime'].min().date()} to {df['to_datetime'].max().date()}") with col2: st.metric("Total Records", f"{len(df):,}") with col3: st.metric("Variables", f"{df['variable'].nunique()}") with col4: # Calculate total electricity consumption if 'consumption.electricity' in df['variable'].values: total_elec = df[df['variable'] == 'consumption.electricity']['value'].sum() st.metric("Total Electricity", f"{total_elec:.2f} kWh") else: st.metric("Total Electricity", "N/A") # Tabs for different analyses tab1, tab2, tab3, tab4 = st.tabs(["Consumption Overview", "Time Patterns", "Detailed Analysis", "Raw Data"]) ################################# # TAB 1: CONSUMPTION OVERVIEW ################################# with tab1: st.subheader("Energy Consumption by Category") # Total consumption by category category_totals = df.groupby('variable')['value'].sum().sort_values(ascending=False) # Filter for visualization (top categories) top_categories = category_totals.head(10) # Create bar chart using Plotly fig = px.bar( x=top_categories.values, y=top_categories.index, orientation='h', title="Top 10 Energy Consumption Categories", labels={'x': 'Total Consumption', 'y': 'Category'} ) st.plotly_chart(fig) # Component breakdown st.subheader("Electricity Consumption by Component") # Get specific electricity components elec_components = [var for var in electricity_vars if len(var.split('.')) > 2] if elec_components: component_data = df[df['variable'].isin(elec_components)].groupby('variable')['value'].sum() # Create pie chart fig = px.pie( values=component_data.values, names=component_data.index, title="Electricity Consumption by Component" ) st.plotly_chart(fig) else: st.info("No detailed electricity component data available") ################################# # TAB 2: TIME PATTERNS ################################# with tab2: st.subheader("Energy Consumption Over Time") # Daily consumption patterns main_categories = ['consumption.electricity', 'consumption.fossil_fuel'] available_categories = [cat for cat in main_categories if cat in df['variable'].values] if available_categories: daily_consumption = df[df['variable'].isin(available_categories)].groupby(['date', 'variable'])['value'].sum().reset_index() # Create line chart for daily patterns fig = px.line( daily_consumption, x='date', y='value', color='variable', title="Daily Energy Consumption", labels={'value': 'Consumption', 'date': 'Date', 'variable': 'Energy Type'} ) st.plotly_chart(fig) # Hourly patterns st.subheader("Hourly Energy Patterns") hourly_data = df[df['variable'].isin(available_categories)].groupby(['hour', 'variable'])['value'].mean().reset_index() # Create line chart for hourly patterns fig = px.line( hourly_data, x='hour', y='value', color='variable', title="Average Hourly Consumption", labels={'value': 'Average Consumption', 'hour': 'Hour of Day', 'variable': 'Energy Type'} ) fig.update_xaxes(tickvals=list(range(0, 24))) st.plotly_chart(fig) # Heatmap st.subheader("Electricity Consumption Heatmap") if 'consumption.electricity' in df['variable'].values: elec_hourly = df[df['variable'] == 'consumption.electricity'].copy() elec_pivot = elec_hourly.pivot_table(index='date', columns='hour', values='value', aggfunc='mean') # Create heatmap fig = px.imshow( elec_pivot, labels=dict(x="Hour of Day", y="Date", color="Consumption"), x=elec_pivot.columns, y=elec_pivot.index, color_continuous_scale='YlOrRd' ) st.plotly_chart(fig) else: st.info("No main category data available for time-based analysis") ################################# # TAB 3: DETAILED ANALYSIS ################################# with tab3: st.subheader("Statistical Summary") # Statistical summary for main consumption categories if available_categories: stats_cols = st.columns(len(available_categories)) for i, category in enumerate(available_categories): with stats_cols[i]: category_data = df[df['variable'] == category]['value'] st.subheader(f"{category.split('.')[-1].capitalize()}") st.metric("Mean", f"{category_data.mean():.3f}") st.metric("Median", f"{category_data.median():.3f}") st.metric("Min", f"{category_data.min():.3f}") st.metric("Max", f"{category_data.max():.3f}") st.metric("Std Dev", f"{category_data.std():.3f}") # Correlation analysis st.subheader("Correlation Analysis") if len(available_categories) > 1: # Prepare data for correlation pivot_data = df[df['variable'].isin(available_categories)].pivot_table( index=['from_datetime'], columns='variable', values='value' ).reset_index() correlation = pivot_data[available_categories].corr() # Create heatmap for correlation fig = px.imshow( correlation, text_auto=True, labels=dict(x="Category", y="Category", color="Correlation"), x=correlation.columns, y=correlation.index, color_continuous_scale='RdBu_r', range_color=[-1, 1] ) st.plotly_chart(fig) # Emissions and costs st.subheader("Emissions and Costs") metrics = ['costs', 'emissions'] available_metrics = [m for m in metrics if m in df['variable'].values] if available_metrics: metrics_data = df[df['variable'].isin(available_metrics)].groupby(['date', 'variable'])['value'].sum().reset_index() # Create bar chart fig = px.bar( metrics_data, x='date', y='value', color='variable', barmode='group', title="Daily Costs vs Emissions", labels={'value': 'Amount', 'date': 'Date', 'variable': 'Metric'} ) st.plotly_chart(fig) ################################# # TAB 4: RAW DATA ################################# with tab4: st.subheader("Raw Data") # Filter options st.markdown("### Filter Data") # Variable filter all_vars = sorted(df['variable'].unique()) selected_vars = st.multiselect("Select Variables", all_vars, default=all_vars[:5] if len(all_vars) > 5 else all_vars) # Date range filter date_range = st.date_input( "Select Date Range", value=(df['from_datetime'].min().date(), df['to_datetime'].max().date()), min_value=df['from_datetime'].min().date(), max_value=df['to_datetime'].max().date() ) # Apply filters filtered_df = df.copy() if selected_vars: filtered_df = filtered_df[filtered_df['variable'].isin(selected_vars)] if len(date_range) == 2: start_date, end_date = date_range filtered_df = filtered_df[(filtered_df['date'] >= start_date) & (filtered_df['date'] <= end_date)] # Display filtered data st.dataframe(filtered_df) # Download link for filtered data csv = filtered_df.to_csv(index=False) st.download_button( label="Download Filtered Data as CSV", data=csv, file_name="filtered_energy_data.csv", mime="text/csv" ) # Main logic if uploaded_file is not None: # Load and process the data df = pd.read_csv(uploaded_file) # Check if the file has the expected structure required_columns = ['from_datetime', 'to_datetime', 'variable', 'value'] if all(col in df.columns for col in required_columns): # Process the data df, electricity_vars, fossil_fuel_vars, thermal_vars, grid_vars, cost_vars, emission_vars = analyze_energy_data(df) # Create the dashboard create_dashboard(df, electricity_vars, fossil_fuel_vars, thermal_vars, grid_vars, cost_vars, emission_vars) else: st.error("The uploaded file doesn't have the required columns. Please ensure it has: from_datetime, to_datetime, variable, and value.") else: # Sample data message st.info("πŸ‘† Upload a CSV file to begin. Your file should contain columns: from_datetime, to_datetime, variable, and value.") # Example format st.markdown(""" ### Expected CSV Format: ``` ,from_datetime,to_datetime,variable,value 0,2025-04-19T00:00:00,2025-04-19T01:00:00,consumption.electricity.refrigerator,0.0474 1,2025-04-19T01:00:00,2025-04-19T02:00:00,consumption.electricity.refrigerator,0.0462 ... ``` """)
2
+ make it use search to find address ingore premium user and fake data api call veruy important