-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsolar.js
More file actions
399 lines (323 loc) · 26.2 KB
/
solar.js
File metadata and controls
399 lines (323 loc) · 26.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
'use strict'
// ----------------------------------------------------------------------------------------
// Copyright 2020 David Slik, All rights reserved
// Library for solar-related visualizations
// ----------------------------------------------------------------------------------------
var debug = false;
// Convenience function that creates an SVG element from type, value and text strings
function svgen(n, v, t) {
n = document.createElementNS("http://www.w3.org/2000/svg", n);
for (var p in v)
if(p == "xlink:href") { n.setAttributeNS("http://www.w3.org/1999/xlink", p, v[p]); }
else if(p == "xmlns:xlink") { n.setAttributeNS("http://www.w3.org/2000/xmlns/", p, v[p]); }
else if(p == "xmlns") { n.setAttributeNS("http://www.w3.org/2000/xmlns/", p, v[p]); }
else if(p == "xml:space") { n.setAttributeNS("http://www.w3.org/XML/1998/namespace", p, v[p]); }
else { n.setAttributeNS(null, p, v[p]); }
if(t) n.innerHTML = t;
return n
}
// Math utility functions
function circleX(centerx, angle, distance) {
return(distance * Math.cos(-1 * angle / (180/Math.PI)) + centerx);
}
function circleY(centery, angle, distance) {
return(distance * Math.sin(-1 * angle / (180/Math.PI)) + centery);
}
function tanX(centerx, angle, distance, tandist) {
return(distance * Math.cos(-1 * angle / (180/Math.PI)) + centerx + tandist * Math.cos(-1 * (angle - 90) / (180/Math.PI)));
}
function tanY(centery, angle, distance, tandist) {
return(distance * Math.sin(-1 * angle / (180/Math.PI)) + centery + tandist * Math.sin(-1 * (angle - 90) / (180/Math.PI)));
}
// ----------------------------------------------------------------------------------------
// Solar Power Flow Visualization
// ----------------------------------------------------------------------------------------
function solar_draw(svg, day, cloudy, sol_watts, grid_connected, grid_watts, load_watts, bat_watts = null, bat_soc = null, background_color = "#FFFFFF") {
if(bat_watts == null) { bat_soc = null; }
if(grid_connected == null) { grid_watts = 0; }
svg.appendChild(svgen('ellipse', { cx: 300, cy: 300, rx: 128, ry: 128, "stroke-width": 40, stroke:'#22220A', "fill": 'none' }));
if(grid_connected != null) {
flow_draw(svg, 180, 90, 40, 0, 0, 0, '#22220A', false, false);
flow_draw(svg, 90, 0, 40, 0, 0, 0, '#22220A', false, false);
}
if(bat_watts != null) {
flow_draw(svg, 0, 270, 40, 0, 0, 0, '#22220A', false, false);
flow_draw(svg, 270, 180, 40, 0, 0, 0, '#22220A', false, false);
}
// Debug gridlines (Set debug to true at top of file to enable)
if(debug) { svg.appendChild(svgen('path', { d: "M300,0 l0,600", stroke:'#444444', "stroke-width": 1 })) }
if(debug) { svg.appendChild(svgen('path', { d: "M0,300 l600,0", stroke:'#444444', "stroke-width": 1 })) }
var panels = svgen('g', {transform:"translate(0 245)" });
panels_draw(panels, day, cloudy);
svg.appendChild(panels)
var house = svgen('g', {transform:"translate(500 245)" });
house_draw(house);
svg.appendChild(house)
if(grid_connected != null) {
var grid = svgen('g', {transform:"translate(253 10)" });
grid_draw(grid, grid_connected);
svg.appendChild(grid)
}
if(bat_watts != null) {
var battery = svgen('g', {transform:"translate(252 470)" });
battery_draw(battery, bat_soc);
svg.appendChild(battery)
}
if(bat_watts == null) { bat_watts = 0; }
// -------------------------------------
if(grid_watts == 0 && bat_watts == 0 && sol_watts > 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "01" )) }
flow_draw(svg, 180, 0, 40, 0, 0, 0, '#FFCC99',);
}
if(grid_watts == 0 && bat_watts < 0 && sol_watts > 0 && load_watts == 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "02" )) }
flow_draw(svg, 270, 180, 40, 0, 0, 0, '#FFCC99', true);
}
if(grid_watts < 0 && bat_watts == 0 && sol_watts > 0 && load_watts == 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "03" )) }
flow_draw(svg, 180, 90, 40, 0, 0, 0, '#FFCC99');
}
if(grid_watts == 0 && bat_watts > 0 && sol_watts == 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "04" )) }
flow_draw(svg, 0, 270, 40, 0, 0, 0, '#9999CC', true);
}
if(grid_watts < 0 && bat_watts > 0 && sol_watts == 0 && load_watts == 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "05" )) }
flow_draw(svg, 90, 270, 40, 0, 0, 0, '#9999CC', true);
}
if(grid_watts > 0 && bat_watts == 0 && sol_watts == 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "06" )) }
flow_draw(svg, 90, 0, 40, 0, 0, 0, '#CC6666');
}
if(grid_watts > 0 && bat_watts < 0 && sol_watts == 0 && load_watts == 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "07" )) }
flow_draw(svg, 90, 270, 40, 0, 0, 0, '#CC6666');
}
// -------------------------------------
if(grid_watts < 0 && bat_watts == 0 && sol_watts > 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "11" )) }
flow_draw(svg, 180, 90, 40 * ((grid_watts * -1) / sol_watts), 20 * (load_watts / sol_watts), 0, 20 * (load_watts / sol_watts), '#FFCC99', false, true, 40);
flow_draw(svg, 180, 0, 40 * (load_watts / sol_watts), -20 * ((grid_watts * -1) / sol_watts), 0, -20 * ((grid_watts * -1) / sol_watts), '#FFCC99', false, true, 0);
}
if(grid_watts == 0 && bat_watts < 0 && sol_watts > 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "12" )) }
flow_draw(svg, 180, 0, 40 * (load_watts / sol_watts), 20 * ((bat_watts * -1) / sol_watts), 0, 0, '#FFCC99', false, true, 40);
flow_draw(svg, 270, 180, 40 * ((bat_watts * -1) / sol_watts), 0, -20 * (load_watts / sol_watts), 0, '#FFCC99', true, true, 0);
}
if(grid_watts < 0 && bat_watts < 0 && sol_watts > 0 && load_watts == 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "13" )) }
flow_draw(svg, 180, 90, 40 * ((grid_watts * -1) / sol_watts), 20 * ((bat_watts * -1) / sol_watts), 0, 0, '#FFCC99', false, true, 40);
flow_draw(svg, 270, 180, 40 * ((bat_watts * -1) / sol_watts), 0, -20 * ((grid_watts * -1) / sol_watts), 0, '#FFCC99', true, true, 0);
}
if(bat_watts > 0 && sol_watts == 0 && load_watts > 0 && grid_watts < 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "14" )) }
flow_draw(svg, 0, 270, 40 * (load_watts / bat_watts), 0, -20 * ((grid_watts * -1) / bat_watts), 20 * ((grid_watts * -1) / bat_watts), '#9999CC', true, true, 40);
flow_draw(svg, 90, 270, 40 * ((grid_watts * -1) / bat_watts), 0, 20 * (load_watts / bat_watts), -20 * (load_watts / bat_watts), '#9999CC', true, true, 0);
}
if(grid_watts > 0 && (bat_watts * -1) > 0 && sol_watts == 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "15" )) }
flow_draw(svg, 90, 0, 40 * (load_watts/grid_watts), 20 * ((bat_watts * -1) / grid_watts), 0, 20 * ((bat_watts * -1) / grid_watts), '#CC6666', false, true, 40);
flow_draw(svg, 90, 270, 40 * ((bat_watts * -1) / grid_watts), -20 * (load_watts/grid_watts), 0, -20 * (load_watts/grid_watts), '#CC6666', false, true, 0);
}
if(grid_watts > 0 && bat_watts == 0 && sol_watts > 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "16" )) }
flow_draw(svg, 180, 0, 40 * (sol_watts / load_watts), 0, 20 * (grid_watts / load_watts), -20 * (grid_watts / load_watts), '#FFCC99');
flow_draw(svg, 90, 0, 40 * (grid_watts / load_watts), 0, -20 * (sol_watts / load_watts), 20 * (sol_watts / load_watts), '#CC6666');
}
if(grid_watts > 0 && bat_watts < 0 && sol_watts > 0 && load_watts == 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "17" )) }
flow_draw(svg, 270, 180, 40 * (sol_watts / (bat_watts * -1)), 20 * (grid_watts / (bat_watts * -1)), 0, 0, '#FFCC99', true);
flow_draw(svg, 90, 270, 40 * (grid_watts / (bat_watts * -1)), 0, -20 * (sol_watts / (bat_watts * -1)), 0, '#CC6666');
}
if(grid_watts > 0 && bat_watts > 0 && sol_watts == 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "18" )) }
flow_draw(svg, 90, 0, 40 * (grid_watts / load_watts), 0, -20 * (bat_watts / load_watts), 0, '#CC6666');
flow_draw(svg, 0, 270, 40 * (bat_watts / load_watts), 20 * (grid_watts / load_watts), 0, 0, '#9999CC', true);
}
if(grid_watts == 0 && bat_watts > 0 && sol_watts > 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "19" )) }
flow_draw(svg, 180, 0, 40 * (sol_watts / load_watts), 0, -20 * (bat_watts / load_watts), 0, '#FFCC99');
flow_draw(svg, 0, 270, 40 * (bat_watts / load_watts), 20 * (sol_watts / load_watts), 0, 0, '#9999CC', true);
}
// -------------------------------------
if(grid_watts < 0 && bat_watts < 0 && sol_watts > 0 && load_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "21" )) }
var grid_width = 40 * ((grid_watts * -1) / (load_watts + (grid_watts * -1) + (bat_watts * -1)));
var load_width = 40 * (load_watts / (load_watts + (grid_watts * -1) + (bat_watts * -1)));
var bat_width = 40 * ((bat_watts * -1) / (load_watts + (grid_watts * -1) + (bat_watts * -1)));
var sol_grid_offset = ((grid_width + load_width) / 2) - (grid_width / 2);
var sol_load_offset = -1 * ((grid_width + load_width) / 2) + (load_width / 2);
flow_draw(svg, 180, 90, grid_width, 20 * ((load_watts + (bat_watts * -1)) / sol_watts), 0, sol_grid_offset, '#FFCC99', false, true, 40);
flow_draw(svg, 180, 0, load_width, -20 * ((grid_watts * -1) / sol_watts) + bat_width / 2, 0, sol_load_offset, '#FFCC99', false, true, 0);
flow_draw(svg, 270, 180, bat_width, 0, -20 * ((load_watts + (grid_watts * -1)) / sol_watts), 0, '#FFCC99', true, true, 0);
}
if((bat_watts * -1) + load_watts == sol_watts + grid_watts && (bat_watts * -1) < sol_watts && grid_watts < load_watts && sol_watts > 0 && load_watts > 0 && grid_watts > 0 && bat_watts < 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "22" )) }
var grid_load_width = 40 * (grid_watts / (load_watts + (bat_watts * -1)));
var sol_load_width = 40 * ((sol_watts - (bat_watts * -1)) / (load_watts + (bat_watts * -1)));
var sol_bat_width = 40 * ((bat_watts * -1) / (load_watts + (bat_watts * -1)));
var sol_total_width = sol_load_width + sol_bat_width;
var load_total_width = sol_load_width + grid_load_width;
var sol_load_offset = -1 * (load_total_width / 2) + (sol_load_width / 2);
var grid_load_offset = (load_total_width / 2) - (grid_load_width / 2);
flow_draw(svg, 90, 0, grid_load_width, 0, -1 * grid_load_offset, grid_load_offset, '#CC6666');
flow_draw(svg, 180, 0, sol_load_width, 20 * ((bat_watts * -1) / sol_watts) - (grid_load_width / 2), -1 * sol_load_offset, sol_load_offset, '#FFCC99');
flow_draw(svg, 270, 180, sol_bat_width, 0, -20 * ((load_watts - grid_watts) / sol_watts), 0, '#FFCC99', true);
}
if((bat_watts * -1) + load_watts == sol_watts + grid_watts && (bat_watts * -1) > sol_watts && grid_watts > load_watts && sol_watts > 0 && load_watts > 0 && grid_watts > 0 && bat_watts < 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "23" )) }
var grid_width = 40 * (grid_watts) / (load_watts + (bat_watts * -1));
var grid_load_width = 40 * ((grid_watts - (bat_watts * -1 - sol_watts)) / (load_watts + (bat_watts * -1)));
var grid_bat_width = 40 * ((grid_watts - load_watts) / (load_watts + (bat_watts * -1)));
var sol_bat_width = 40 * (sol_watts / (load_watts + (bat_watts * -1)));
var sol_bat_offset = (grid_bat_width / 2);
var grid_bat_offset = -1 * (sol_bat_width / 2);
var grid_load_offset = (grid_width / 2) - (grid_load_width / 2);
flow_draw(svg, 90, 0, grid_load_width, grid_load_offset, 0, grid_load_offset, '#CC6666', false, true, grid_width);
flow_draw(svg, 90, 270, grid_bat_width, -20 * (load_watts / (grid_watts + sol_watts)), grid_bat_offset, -20 * (load_watts / (grid_watts + sol_watts)), '#CC6666', false, true, 0);
flow_draw(svg, 270, 180, sol_bat_width, sol_bat_offset, 0, 0, '#FFCC99', true);
}
if(sol_watts > 0 && load_watts > 0 && grid_watts > 0 && bat_watts > 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "24" )) }
var grid_width = 40 * (grid_watts / (sol_watts + grid_watts + bat_watts));
var sol_width = 40 * (sol_watts / (sol_watts + grid_watts + bat_watts));
var total_width = grid_width + sol_width;
var grid_offset = (total_width / 2) - (grid_width / 2);
var sol_offset = -1 * (total_width / 2) + (sol_width / 2);
flow_draw(svg, 90, 0, grid_width, 0, -20 * ((bat_watts + sol_watts) / (load_watts)), grid_offset, '#CC6666');
flow_draw(svg, 180, 0, sol_width, 0, 20 * ((grid_watts) / (load_watts)) - 20 * ((bat_watts) / (load_watts)), sol_offset, '#FFCC99');
flow_draw(svg, 0, 270, 40 * (bat_watts / (sol_watts + grid_watts + bat_watts)), 20 * ((grid_watts + sol_watts) / (sol_watts + grid_watts + bat_watts)), 0, 0, '#9999CC', true);
}
if(grid_watts == load_watts && sol_watts == (bat_watts * -1) && sol_watts != 0 && grid_watts != 0 && load_watts >= 0) {
if(debug) { svg.appendChild(svgen('text', { x: 10, y: 40, "text-anchor":"start", "fill":"#CCCCCC", "font-size":32, "font-family":"Arial"}, "25" )) }
flow_draw(svg, 90, 0, 40 * (grid_watts / (sol_watts + grid_watts)), 0, 0, 0, '#CC6666');
flow_draw(svg, 270, 180, 40 * (sol_watts / (sol_watts + grid_watts)), 0, 0, 0, '#FFCC99', true);
}
}
// Draw individual flows
function flow_draw(svg, startAngle, endAngle, width, startoffset, endoffset, inneroffset, color, reverse = false, arrow = true, startarrowwidth = null) {
var centerx = 300;
var centery = 300;
var inner = 0;
if(startoffset < 0 && endoffset > 0 && inneroffset > 0) inner = 1;
svg.appendChild(svgen('path', { d: "M" + tanX(centerx, startAngle, 172, startoffset) + "," + tanY(centery, startAngle, 172, startoffset) + " " +
"L" + tanX(centerx, startAngle, 156 + inneroffset, startoffset) + "," + tanY(centery, startAngle, 156 + inneroffset, startoffset) + " " +
"A28,28 0 0,0 " + circleX(centerx, startAngle - (10 - inneroffset/4) - startoffset/2, 128 + inneroffset) + "," + circleY(centery, startAngle - (10 - inneroffset/4) - startoffset/2, 128 + inneroffset) + " " +
"A" + (128 + inneroffset) + "," + (128 + inneroffset) + " 0 " + inner + "1 " + circleX(centerx, endAngle + (10 - inneroffset/4) - endoffset/2, 128+ inneroffset) + "," + circleY(centery, endAngle + (10 - inneroffset/4) - endoffset/2, 128 + inneroffset) + " " +
"A28,28 0 0,0 " + tanX(centerx, endAngle, 156 + inneroffset, endoffset) + "," + tanY(centery, endAngle, 156 + inneroffset, endoffset) + " " +
"L" + tanX(centerx, endAngle, 172, endoffset) + "," + tanY(centery, endAngle, 172, endoffset)
, fill:'none', stroke: color, 'stroke-width': width }));
if(arrow) {
if(!reverse) {
[startAngle, endAngle] = [endAngle, startAngle];
[startoffset, endoffset] = [endoffset, startoffset];
}
svg.appendChild(svgen('path', { d: "M" + tanX(centerx, startAngle, 172, startoffset + width/2) + "," + tanY(centery, startAngle, 172, startoffset + width/2) + " " +
"L" + tanX(centerx, startAngle, 172 + width/4, startoffset) + "," + tanY(centery, startAngle, 172 + width/4, startoffset) + " " +
"L" + tanX(centerx, startAngle, 172, startoffset - width/2) + "," + tanY(centery, startAngle, 172, startoffset - width/2)
, fill: color }));
[startAngle, endAngle] = [endAngle, startAngle];
[startoffset, endoffset] = [endoffset, startoffset];
if(startarrowwidth != null && startarrowwidth > 0) {
width = startarrowwidth;
startoffset = 0;
}
if(startarrowwidth == null || startarrowwidth > 0) {
svg.appendChild(svgen('path', { d: "M" + tanX(centerx, startAngle, 172, startoffset + width/2) + "," + tanY(centery, startAngle, 172, startoffset + width/2) + " " +
"L" + tanX(centerx, startAngle, 172 + width/4, startoffset + width/2) + "," + tanY(centery, startAngle, 172 + width/4, startoffset + width/2) + " " +
"L" + tanX(centerx, startAngle, 172, startoffset) + "," + tanY(centery, startAngle, 172, startoffset) + " " +
"L" + tanX(centerx, startAngle, 172 + width/4, startoffset - width/2) + "," + tanY(centery, startAngle, 172 + width/4, startoffset - width/2) + " " +
"L" + tanX(centerx, startAngle, 172, startoffset - width/2) + "," + tanY(centery, startAngle, 172, startoffset - width/2), fill: color }));
}
}
}
// ----------------------------------------------------------------------------------------
// Icons
// ----------------------------------------------------------------------------------------
function panels_draw(svg, is_day, cloudcover) {
var panelFill = "#6666FF";
var sunStroke = "#FFCC22";
// Uncomment to show bounding rect
//svg.appendChild(svgen('rect', { x: 0, y: 0, width: 100, height: 100, stroke:'#FF0000', "stroke-width": 5 }));
if(cloudcover >= 75) {
sunStroke = "#FFCC22";
}
if(is_day == true) {
svg.appendChild(svgen('path', { d: "M30,56 A28,28 0 0,1 86,56 Z", "stroke-linejoin": "round", fill: sunStroke }));
svg.appendChild(svgen('path', { d: "M" + circleX(58, 5, 34) + "," + circleY(56, 5, 34) + " L" + circleX(58, 5, 44) + "," + circleY(56, 5, 44), "stroke-linecap": "round", "stroke-width": 5, stroke: sunStroke }));
svg.appendChild(svgen('path', { d: "M" + circleX(58, 33, 34) + "," + circleY(56, 33, 34) + " L" + circleX(58, 33, 44) + "," + circleY(56, 33, 44), "stroke-linecap": "round", "stroke-width": 5, stroke: sunStroke }));
svg.appendChild(svgen('path', { d: "M" + circleX(58, 61, 34) + "," + circleY(56, 61, 34) + " L" + circleX(58, 61, 44) + "," + circleY(56, 61, 44), "stroke-linecap": "round", "stroke-width": 5, stroke: sunStroke }));
svg.appendChild(svgen('path', { d: "M" + circleX(58, 90, 34) + "," + circleY(56, 90, 34) + " L" + circleX(58, 90, 44) + "," + circleY(56, 90, 44), "stroke-linecap": "round", "stroke-width": 5, stroke: sunStroke }));
svg.appendChild(svgen('path', { d: "M" + circleX(58, 118, 34) + "," + circleY(56, 118, 34) + " L" + circleX(58, 118, 44) + "," + circleY(56, 118, 44), "stroke-linecap": "round", "stroke-width": 5, stroke: sunStroke }));
svg.appendChild(svgen('path', { d: "M" + circleX(58, 146, 34) + "," + circleY(56, 146, 34) + " L" + circleX(58, 146, 44) + "," + circleY(56, 146, 44), "stroke-linecap": "round", "stroke-width": 5, stroke: sunStroke }));
svg.appendChild(svgen('path', { d: "M" + circleX(58, 175, 34) + "," + circleY(56, 175, 34) + " L" + circleX(58, 175, 44) + "," + circleY(56, 175, 44), "stroke-linecap": "round", "stroke-width": 5, stroke: sunStroke }));
} else {
panelFill = "#333399";
svg.appendChild(svgen('path', { d: "M30,56 A28,28 0 0,1 86,56 Z", "stroke-linejoin": "round", fill: "#DDDDDD" }));
svg.appendChild(svgen('ellipse', { cx: 44, cy: 42, rx: 6, ry: 6, "fill": '#AAAAAA' }));
svg.appendChild(svgen('ellipse', { cx: 49, cy: 49, rx: 5, ry: 5, "fill": '#999999' }));
svg.appendChild(svgen('ellipse', { cx: 64, cy: 46, rx: 5, ry: 5, "fill": '#BBBBBB' }));
}
if(cloudcover >= 50) {
svg.appendChild(svgen('ellipse', { cx: 30, cy: 36, rx: 10, ry: 10, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('ellipse', { cx: 45, cy: 31, rx: 12, ry: 12, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('ellipse', { cx: 58, cy: 38, rx: 7.5, ry: 7.5, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('ellipse', { cx: 66, cy: 42, rx: 4, ry: 4, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('rect', { x: 30, y: 33, width: 15, height: 10, fill:'#FFFFFF'}));
svg.appendChild(svgen('rect', { x: 30, y: 41, width: 36, height: 5, fill:'#FFFFFF'}));
svg.appendChild(svgen('path', { d: "M30,46 l36,0", stroke:'#EEEEEE', "stroke-width": 1 }));
}
if(cloudcover >= 75) {
svg.appendChild(svgen('ellipse', { cx: 60, cy: 46, rx: 10, ry: 10, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('ellipse', { cx: 75, cy: 41, rx: 12, ry: 12, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('ellipse', { cx: 88, cy: 48, rx: 7.5, ry: 7.5, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('ellipse', { cx: 96, cy: 52, rx: 4, ry: 4, "fill": '#FFFFFF', stroke:'#EEEEEE', "stroke-width": 1 }));
svg.appendChild(svgen('rect', { x: 60, y: 43, width: 15, height: 10, fill:'#FFFFFF'}));
svg.appendChild(svgen('rect', { x: 60, y: 51, width: 36, height: 5, fill:'#FFFFFF'}));
svg.appendChild(svgen('path', { d: "M60,56 l36,0", stroke:'#EEEEEE', "stroke-width": 1 }));
}
svg.appendChild(svgen('path', { d: "M0,90 l20,0 l20,-30 l-20,0 l-20,30 Z", "stroke-linejoin": "round", fill: panelFill }));
svg.appendChild(svgen('path', { d: "M28,90 l20,0 l20,-30 l-20,0 l-20,30 Z", "stroke-linejoin": "round", fill: panelFill }));
svg.appendChild(svgen('path', { d: "M56,90 l20,0 l20,-30 l-20,0 l-20,30 Z", "stroke-linejoin": "round", fill: panelFill }));
}
function battery_draw(svg, percent) {
var width = (percent / 100) * 72;
var color = "#99CC99";
if(percent <= 70) color = "#FFFF66";
if(percent <= 50) color = "#CC6666";
// Uncomment to show bounding rect
// svg.appendChild(svgen('rect', { x: 0, y: 0, width: 100, height: 100, stroke:'#FF0000', "stroke-width": 5 }));
svg.appendChild(svgen('path', { d: "M10,35 l" + width + ",0 l0,30 l-" + width + ",0 Z", "stroke-linejoin": "round", fill: color }));
svg.appendChild(svgen('path', { d: "M10,35 l73,0 l0,9 l7,0 l0,14 l-7,0 l0,9 l-73,0 Z", "stroke-linejoin": "round", "stroke-width": 5, stroke: "#9999CC", fill: "none" }));
}
function house_draw(svg) {
// Uncomment to show bounding rect
// svg.appendChild(svgen('rect', { x: 0, y: 0, width: 100, height: 100, stroke:'#FF0000', "stroke-width": 5 }));
svg.appendChild(svgen('path', { d: "M20,86 l20,0 l0,-30 l20,0 l0,30 l20,0 l0,-50 l-30,-10 l-30,10 Z", "stroke-linejoin": "round", fill: "#CC99CC" }));
svg.appendChild(svgen('path', { d: "M50,15 l-40,14 l2,5 L50,21 L50,15 l40,14 l-2,5 L50,21 Z", "stroke-linejoin": "round", "stroke-width": 5, fill: "#CC99CC" }));
svg.appendChild(svgen('path', { d: "M80,15 l-10,0 l0,10 l10,4 Z", "stroke-linejoin": "round", "stroke-width": 5, fill: "#CC99CC" }));
}
function grid_draw(svg, energized) {
// Uncomment to show bounding rect
// svg.appendChild(svgen('rect', { x: 0, y: 0, width: 100, height: 100, stroke:'#FF0000', "stroke-width": 5 }));
svg.appendChild(svgen('path', { d: "M27,90 l15,-50", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M67,90 l-15,-50", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M27,90 l32,-25 l-24,0 l32,25", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M41,40 l16,25", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M53,40 l-16,25", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M27,40 l40,0 l-20,-10 Z", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M27,20 l40,0 l-20,-10 Z", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M41,40 l0,-25", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M53,40 l0,-25", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M33,40 l0,5", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M61,40 l0,5", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M33,20 l0,5", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
svg.appendChild(svgen('path', { d: "M61,20 l0,5", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": 3, stroke: "#AAAAAA", fill: "none" }));
if(energized) {
svg.appendChild(svgen('path', { d: "M75,20 l0,5 l5,0 l-5,10 l0,-5 l-5,0 l5,-10 Z", fill: "#FFFF66" }));
svg.appendChild(svgen('path', { d: "M25,50 l0,5 l5,0 l-5,10 l0,-5 l-5,0 l5,-10 Z", fill: "#FFFF66" }));
} else {
svg.appendChild(svgen('path', { d: "M75,20 l0,5 l5,0 l-5,10 l0,-5 l-5,0 l5,-10 Z", "stroke-width": 1, stroke: "#AAAAAA" }));
svg.appendChild(svgen('path', { d: "M25,50 l0,5 l5,0 l-5,10 l0,-5 l-5,0 l5,-10 Z", "stroke-width": 1, stroke: "#AAAAAA" }));
}
}