openstudio-workflow 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +24 -63
- data/lib/openstudio/extended_runner.rb +94 -0
- data/lib/openstudio/workflow/adapter.rb +10 -0
- data/lib/openstudio/workflow/adapters/mongo.rb +1 -1
- data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +12 -17
- data/lib/openstudio/workflow/jobs/{run_openstudio → run_energyplus}/monthly_report.idf +8 -4
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +132 -21
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +6 -11
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +7 -6
- data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +2 -1
- data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +27 -148
- data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +31 -10
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +4 -3
- data/lib/openstudio/workflow/run.rb +4 -5
- data/lib/openstudio/workflow/version.rb +1 -1
- data/lib/openstudio-workflow.rb +6 -10
- metadata +9 -12
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/README.md +0 -5
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.rb +0 -206
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.xml +0 -53
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/resources/report.html.erb +0 -298
@@ -1,206 +0,0 @@
|
|
1
|
-
require 'erb'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
# start the measure
|
5
|
-
class StandardReports < OpenStudio::Ruleset::ReportingUserScript
|
6
|
-
# define the name that a user will see, this method may be deprecated as
|
7
|
-
# the display name in PAT comes from the name field in measure.xml
|
8
|
-
def name
|
9
|
-
'Standard Reports'
|
10
|
-
end
|
11
|
-
|
12
|
-
# define the arguments that the user will input
|
13
|
-
def arguments
|
14
|
-
args = OpenStudio::Ruleset::OSArgumentVector.new
|
15
|
-
|
16
|
-
args
|
17
|
-
end # end the arguments method
|
18
|
-
|
19
|
-
# sql_query method
|
20
|
-
def sql_query(sql, report_name, query)
|
21
|
-
val = 10e9
|
22
|
-
result = sql.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='#{report_name}' AND #{query}")
|
23
|
-
unless result.empty?
|
24
|
-
val = result.get
|
25
|
-
end
|
26
|
-
val
|
27
|
-
end
|
28
|
-
|
29
|
-
# define what happens when the measure is run
|
30
|
-
def run(runner, user_arguments)
|
31
|
-
super(runner, user_arguments)
|
32
|
-
|
33
|
-
# use the built-in error checking
|
34
|
-
unless runner.validateUserArguments(arguments, user_arguments)
|
35
|
-
return false
|
36
|
-
end
|
37
|
-
|
38
|
-
os_version = OpenStudio::VersionString.new(OpenStudio.openStudioVersion)
|
39
|
-
min_version_feature1 = OpenStudio::VersionString.new('1.2.3')
|
40
|
-
|
41
|
-
# get the last model and sql file
|
42
|
-
model = runner.lastOpenStudioModel
|
43
|
-
if model.empty?
|
44
|
-
runner.registerError('Cannot find last model.')
|
45
|
-
return false
|
46
|
-
end
|
47
|
-
model = model.get
|
48
|
-
|
49
|
-
sqlFile = runner.lastEnergyPlusSqlFile
|
50
|
-
if sqlFile.empty?
|
51
|
-
runner.registerError('Cannot find last sql file.')
|
52
|
-
return false
|
53
|
-
end
|
54
|
-
sqlFile = sqlFile.get
|
55
|
-
model.setSqlFile(sqlFile)
|
56
|
-
|
57
|
-
# put data into variables, these are available in the local scope binding
|
58
|
-
# building_name = model.getBuilding.name.get
|
59
|
-
|
60
|
-
web_asset_path = OpenStudio.getSharedResourcesPath / OpenStudio::Path.new('web_assets')
|
61
|
-
|
62
|
-
energy = "var consumption = {\n"
|
63
|
-
fuel_type = ''
|
64
|
-
units = ''
|
65
|
-
|
66
|
-
site_energy_use = 0.0
|
67
|
-
OpenStudio::EndUseFuelType.getValues.each do |fuel_type|
|
68
|
-
energy << "\t\""
|
69
|
-
fuel_type = OpenStudio::EndUseFuelType.new(fuel_type).valueDescription
|
70
|
-
energy << OpenStudio::EndUseFuelType.new(fuel_type).valueDescription # append this to remove whitespace between words ".delete(' ')"
|
71
|
-
energy << " Consumption\":{\n\t\t\"units\":"
|
72
|
-
if fuel_type == 'Electricity'
|
73
|
-
units = "\"kWh\""
|
74
|
-
unit_str = 'kWh'
|
75
|
-
else
|
76
|
-
units = "\"Million Btu\""
|
77
|
-
unit_str = 'MBtu'
|
78
|
-
end
|
79
|
-
fuel_type_aggregation = 0.0
|
80
|
-
energy << units
|
81
|
-
energy << ",\n\t\t\"data\":{\n\t\t\t\""
|
82
|
-
OpenStudio::EndUseCategoryType.getValues.each do |category_type|
|
83
|
-
fuel_and_category_aggregation = 0.0
|
84
|
-
category_str = OpenStudio::EndUseCategoryType.new(category_type).valueDescription
|
85
|
-
energy << category_str # append this to remove whitespace between words ".delete(' ')"
|
86
|
-
energy << "\":["
|
87
|
-
OpenStudio::MonthOfYear.getValues.each do |month|
|
88
|
-
if month >= 1 and month <= 12
|
89
|
-
if not sqlFile.energyConsumptionByMonth(OpenStudio::EndUseFuelType.new(fuel_type),
|
90
|
-
OpenStudio::EndUseCategoryType.new(category_type),
|
91
|
-
OpenStudio::MonthOfYear.new(month)).empty?
|
92
|
-
valInJ = sqlFile.energyConsumptionByMonth(OpenStudio::EndUseFuelType.new(fuel_type),
|
93
|
-
OpenStudio::EndUseCategoryType.new(category_type),
|
94
|
-
OpenStudio::MonthOfYear.new(month)).get
|
95
|
-
fuel_and_category_aggregation += valInJ
|
96
|
-
valInUnits = OpenStudio.convert(valInJ, 'J', unit_str).get
|
97
|
-
temp = sprintf '%.3f', valInUnits
|
98
|
-
energy << temp.to_s
|
99
|
-
energy << ','
|
100
|
-
if os_version >= min_version_feature1
|
101
|
-
month_str = OpenStudio::MonthOfYear.new(month).valueDescription
|
102
|
-
prefix_str = OpenStudio.toUnderscoreCase("#{fuel_type}_#{category_str}_#{month_str}")
|
103
|
-
runner.registerValue("#{prefix_str}_si", valInJ, 'J')
|
104
|
-
runner.registerValue("#{prefix_str}_ip", valInUnits, unit_str)
|
105
|
-
end
|
106
|
-
else
|
107
|
-
energy << '0,'
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
energy = energy[0..-2]
|
112
|
-
energy << "],\n\t\t\t\""
|
113
|
-
if (os_version >= min_version_feature1)
|
114
|
-
prefix_str = OpenStudio.toUnderscoreCase("#{fuel_type}_#{category_str}")
|
115
|
-
runner.registerValue("#{prefix_str}_si", fuel_and_category_aggregation, 'J')
|
116
|
-
runner.registerValue("#{prefix_str}_ip", OpenStudio.convert(fuel_and_category_aggregation, 'J', unit_str).get, unit_str)
|
117
|
-
end
|
118
|
-
fuel_type_aggregation += fuel_and_category_aggregation
|
119
|
-
end
|
120
|
-
energy = energy[0..-7]
|
121
|
-
energy << "\n\t\t}\n\t},\n"
|
122
|
-
if (os_version >= min_version_feature1)
|
123
|
-
runner.registerValue(OpenStudio.toUnderscoreCase("#{fuel_type}_si"), fuel_type_aggregation, 'J')
|
124
|
-
runner.registerValue(OpenStudio.toUnderscoreCase("#{fuel_type}_ip"),
|
125
|
-
OpenStudio.convert(fuel_type_aggregation, 'J', unit_str).get,
|
126
|
-
unit_str)
|
127
|
-
end
|
128
|
-
site_energy_use += fuel_type_aggregation
|
129
|
-
end
|
130
|
-
energy = energy[0..-3]
|
131
|
-
energy << "\n};\n"
|
132
|
-
if (os_version >= min_version_feature1)
|
133
|
-
runner.registerValue('site_energy_use_si', OpenStudio.convert(site_energy_use, 'J', 'GJ').get, 'GJ')
|
134
|
-
runner.registerValue('site_energy_use_ip', OpenStudio.convert(site_energy_use, 'J', 'MBtu').get, 'MBtu')
|
135
|
-
|
136
|
-
# queries that don't have API methods yet
|
137
|
-
total_building_area = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Total Building Area' AND ColumnName='Area'")
|
138
|
-
runner.registerValue('total_building_area', total_building_area, 'm2')
|
139
|
-
|
140
|
-
net_conditioned_building_area = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
|
141
|
-
runner.registerValue('net_conditioned_building_area', net_conditioned_building_area, 'm2')
|
142
|
-
|
143
|
-
unconditioned_building_area = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Unconditioned Building Area' AND ColumnName='Area'")
|
144
|
-
runner.registerValue('unconditioned_building_area', unconditioned_building_area, 'm2')
|
145
|
-
|
146
|
-
total_site_energy_eui = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Total Site Energy' AND ColumnName='Energy Per Conditioned Building Area'")
|
147
|
-
runner.registerValue('total_site_energy_eui', total_site_energy_eui, 'MJ/m2')
|
148
|
-
|
149
|
-
total_source_energy_eui = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Energy Per Conditioned Building Area'")
|
150
|
-
runner.registerValue('total_source_energy_eui', total_source_energy_eui, 'MJ/m2')
|
151
|
-
|
152
|
-
time_setpoint_not_met_during_occupied_heating = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Heating' AND ColumnName='Facility'")
|
153
|
-
runner.registerValue('time_setpoint_not_met_during_occupied_heating', time_setpoint_not_met_during_occupied_heating, 'hr')
|
154
|
-
|
155
|
-
time_setpoint_not_met_during_occupied_cooling = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Cooling' AND ColumnName='Facility'")
|
156
|
-
runner.registerValue('time_setpoint_not_met_during_occupied_cooling', time_setpoint_not_met_during_occupied_cooling, 'hr')
|
157
|
-
|
158
|
-
time_setpoint_not_met_during_occupied_hours = time_setpoint_not_met_during_occupied_heating + time_setpoint_not_met_during_occupied_cooling
|
159
|
-
runner.registerValue('time_setpoint_not_met_during_occupied_hours', time_setpoint_not_met_during_occupied_hours, 'hr')
|
160
|
-
|
161
|
-
total_life_cycle_cost = sql_query(sqlFile, 'Life-Cycle Cost Report', "TableName='Present Value by Category' AND RowName='Grand Total' AND ColumnName='Present Value'")
|
162
|
-
runner.registerValue('total_life_cycle_cost', total_life_cycle_cost, '$')
|
163
|
-
|
164
|
-
end
|
165
|
-
|
166
|
-
# echo out our values
|
167
|
-
# runner.registerInfo("This building is named #{building_name}.")
|
168
|
-
|
169
|
-
# read in template
|
170
|
-
html_in_path = "#{File.dirname(__FILE__)}/resources/report.html.erb"
|
171
|
-
if File.exist?(html_in_path)
|
172
|
-
html_in_path = html_in_path
|
173
|
-
else
|
174
|
-
html_in_path = "#{File.dirname(__FILE__)}/report.html.erb"
|
175
|
-
end
|
176
|
-
|
177
|
-
# configure template with variable values
|
178
|
-
renderer = ERB.new(File.read(html_in_path))
|
179
|
-
html_out = renderer.result(binding)
|
180
|
-
|
181
|
-
# write html file
|
182
|
-
html_out_path = './report.html'
|
183
|
-
|
184
|
-
File.open(html_out_path, 'w') do |file|
|
185
|
-
file << html_out
|
186
|
-
|
187
|
-
# make sure data is written to the disk one way or the other
|
188
|
-
begin
|
189
|
-
file.fsync
|
190
|
-
rescue
|
191
|
-
file.flush
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# closing the sql file
|
196
|
-
sqlFile.close
|
197
|
-
|
198
|
-
# reporting final condition
|
199
|
-
runner.registerFinalCondition('Standard Report generated successfully.')
|
200
|
-
|
201
|
-
true
|
202
|
-
end # end the run method
|
203
|
-
end # end the measure
|
204
|
-
|
205
|
-
# this allows the measure to be use by the application
|
206
|
-
StandardReports.new.registerWithApplication
|
@@ -1,53 +0,0 @@
|
|
1
|
-
<measure>
|
2
|
-
<name>Standard Reports</name>
|
3
|
-
<uid>fc337100-8634-404e-8966-01243d292a79</uid>
|
4
|
-
<version_id>4f1230e3-0954-43ab-a772-c345030ab14b</version_id>
|
5
|
-
<description>Change me</description>
|
6
|
-
<modeler_description>Change me</modeler_description>
|
7
|
-
<provenances/>
|
8
|
-
<tags>
|
9
|
-
<tag>Reporting.QAQC</tag>
|
10
|
-
</tags>
|
11
|
-
<attributes>
|
12
|
-
<attribute>
|
13
|
-
<name>Measure Type</name>
|
14
|
-
<value>ReportingMeasure</value>
|
15
|
-
<datatype>string</datatype>
|
16
|
-
</attribute>
|
17
|
-
<attribute>
|
18
|
-
<name>Uses SketchUp API</name>
|
19
|
-
<value>false</value>
|
20
|
-
<datatype>boolean</datatype>
|
21
|
-
</attribute>
|
22
|
-
</attributes>
|
23
|
-
<files>
|
24
|
-
<file>
|
25
|
-
<filename>ExampleModel.osm</filename>
|
26
|
-
<filetype>osm</filetype>
|
27
|
-
<usage_type>test</usage_type>
|
28
|
-
<checksum>0D4162D2</checksum>
|
29
|
-
</file>
|
30
|
-
<file>
|
31
|
-
<filename>report.html.erb</filename>
|
32
|
-
<filetype>in</filetype>
|
33
|
-
<usage_type>resource</usage_type>
|
34
|
-
<checksum>093FE760</checksum>
|
35
|
-
</file>
|
36
|
-
<file>
|
37
|
-
<filename>StandardReports_Test.rb</filename>
|
38
|
-
<filetype>rb</filetype>
|
39
|
-
<usage_type>test</usage_type>
|
40
|
-
<checksum>6790E2F5</checksum>
|
41
|
-
</file>
|
42
|
-
<file>
|
43
|
-
<version>
|
44
|
-
<software_program>OpenStudio</software_program>
|
45
|
-
<identifier>1.1.2</identifier>
|
46
|
-
</version>
|
47
|
-
<filename>measure.rb</filename>
|
48
|
-
<filetype>rb</filetype>
|
49
|
-
<usage_type>script</usage_type>
|
50
|
-
<checksum>4263B498</checksum>
|
51
|
-
</file>
|
52
|
-
</files>
|
53
|
-
</measure>
|
@@ -1,298 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta charset="utf-8">
|
5
|
-
<title>Results | OpenStudio</title>
|
6
|
-
<link href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
|
7
|
-
<link href="file:///<%= web_asset_path %>/bootstrap.min.css" rel="stylesheet">
|
8
|
-
<style type="text/css">
|
9
|
-
body {
|
10
|
-
font: 10px sans-serif;
|
11
|
-
min-width: 1280px;
|
12
|
-
}
|
13
|
-
table {
|
14
|
-
max-width:800px;
|
15
|
-
}
|
16
|
-
.axis path, .axis line {
|
17
|
-
fill: none;
|
18
|
-
stroke: #000;
|
19
|
-
shape-rendering: crispEdges;
|
20
|
-
}
|
21
|
-
.bar {
|
22
|
-
fill: steelblue;
|
23
|
-
}
|
24
|
-
.x.axis path {
|
25
|
-
display: none;
|
26
|
-
}
|
27
|
-
.d3-tip {
|
28
|
-
line-height: 1;
|
29
|
-
font-weight: bold;
|
30
|
-
padding: 12px;
|
31
|
-
background: rgba(0, 0, 0, 0.8);
|
32
|
-
color: #fff;
|
33
|
-
border-radius: 2px;
|
34
|
-
}
|
35
|
-
/* Creates a small triangle extender for the tooltip */
|
36
|
-
.d3-tip:after {
|
37
|
-
box-sizing: border-box;
|
38
|
-
display: inline;
|
39
|
-
font-size: 10px;
|
40
|
-
width: 100%;
|
41
|
-
line-height: 1;
|
42
|
-
color: rgba(0, 0, 0, 0.8);
|
43
|
-
content:"\25BC";
|
44
|
-
position: absolute;
|
45
|
-
text-align: center;
|
46
|
-
}
|
47
|
-
/* Style northward tooltips differently */
|
48
|
-
.d3-tip.n:after {
|
49
|
-
margin: -1px 0 0 0;
|
50
|
-
top: 100%;
|
51
|
-
left: 0;
|
52
|
-
}
|
53
|
-
</style>
|
54
|
-
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
55
|
-
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.3.9/d3.min.js"></script>
|
56
|
-
<script type="text/javascript" src="file:///<%= web_asset_path %>/jquery.min.js"></script>
|
57
|
-
<script type="text/javascript" src="file:///<%= web_asset_path %>/d3.min.js"></script>
|
58
|
-
<script type="text/javascript">
|
59
|
-
// http://labratrevenge.com/d3-tip/javascripts/d3.tip.min.js
|
60
|
-
d3.tip=function(){function t(t){v=m(t),w=v.createSVGPoint(),document.body.appendChild(x)}function e(){return"n"}function n(){return[0,0]}function r(){return" "}function o(){var t=p();return{top:t.n.y-x.offsetHeight,left:t.n.x-x.offsetWidth/2}}function s(){var t=p();return{top:t.s.y,left:t.s.x-x.offsetWidth/2}}function l(){var t=p();return{top:t.e.y-x.offsetHeight/2,left:t.e.x}}function u(){var t=p();return{top:t.w.y-x.offsetHeight/2,left:t.w.x-x.offsetWidth}}function f(){var t=p();return{top:t.nw.y-x.offsetHeight,left:t.nw.x-x.offsetWidth}}function i(){var t=p();return{top:t.ne.y-x.offsetHeight,left:t.ne.x}}function a(){var t=p();return{top:t.sw.y,left:t.sw.x-x.offsetWidth}}function c(){var t=p();return{top:t.se.y,left:t.e.x}}function d(){var t=d3.select(document.createElement("div"));return t.style({position:"absolute",opacity:0,pointerEvents:"none",boxSizing:"border-box"}),t.node()}function m(t){return t=t.node(),"svg"==t.tagName.toLowerCase()?t:t.ownerSVGElement}function p(){var t=d3.event.target,e={},n=t.getScreenCTM(),r=t.getBBox(),o=r.width,s=r.height,l=r.x,u=r.y,f=document.body.scrollTop,i=document.body.scrollLeft;return document.documentElement&&document.documentElement.scrollTop&&(f=document.documentElement.scrollTop,i=document.documentElement.scrollLeft),w.x=l+i,w.y=u+f,e.nw=w.matrixTransform(n),w.x+=o,e.ne=w.matrixTransform(n),w.y+=s,e.se=w.matrixTransform(n),w.x-=o,e.sw=w.matrixTransform(n),w.y-=s/2,e.w=w.matrixTransform(n),w.x+=o,e.e=w.matrixTransform(n),w.x-=o/2,w.y-=s/2,e.n=w.matrixTransform(n),w.y+=s,e.s=w.matrixTransform(n),e}var y=e,g=n,h=r,x=d(),v=null,w=null;t.show=function(){var e,n=h.apply(this,arguments),r=g.apply(this,arguments),o=y.apply(this,arguments),s=d3.select(x),l=0;for(s.html(n).style({opacity:1,pointerEvents:"all"});l--;)s.classed(E[l],!1);return e=T.get(o).apply(this),s.classed(o,!0).style({top:e.top+r[0]+"px",left:e.left+r[1]+"px"}),t},t.hide=function(){return nodel=d3.select(x),nodel.style({opacity:0,pointerEvents:"none"}),t},t.attr=function(e){if(2>arguments.length&&"string"==typeof e)return d3.select(x).attr(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.attr.apply(d3.select(x),n),t},t.style=function(e){if(2>arguments.length&&"string"==typeof e)return d3.select(x).style(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.style.apply(d3.select(x),n),t},t.direction=function(e){return arguments.length?(y=null==e?e:d3.functor(e),t):y},t.offset=function(e){return arguments.length?(g=null==e?e:d3.functor(e),t):g},t.html=function(e){return arguments.length?(h=null==e?e:d3.functor(e),t):h};var T=d3.map({n:o,s:s,e:l,w:u,nw:f,ne:i,sw:a,se:c}),E=T.keys();return t};
|
61
|
-
</script>
|
62
|
-
</head>
|
63
|
-
<body>
|
64
|
-
<div class="row-fluid">
|
65
|
-
<div class="span5">
|
66
|
-
<h4 id="title-0"></h4>
|
67
|
-
<div id="chart-0"></div>
|
68
|
-
</div>
|
69
|
-
<div class="span7">
|
70
|
-
<h4 id="title-1"></h4>
|
71
|
-
<div id="chart-1"></div>
|
72
|
-
</div>
|
73
|
-
</div>
|
74
|
-
<script type="text/javascript">
|
75
|
-
function numFormat(n) {
|
76
|
-
var parts = n.toString().split(".");
|
77
|
-
return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
|
78
|
-
}
|
79
|
-
|
80
|
-
var months = [
|
81
|
-
"Jan",
|
82
|
-
"Feb",
|
83
|
-
"Mar",
|
84
|
-
"Apr",
|
85
|
-
"May",
|
86
|
-
"Jun",
|
87
|
-
"Jul",
|
88
|
-
"Aug",
|
89
|
-
"Sep",
|
90
|
-
"Oct",
|
91
|
-
"Nov",
|
92
|
-
"Dec"];
|
93
|
-
|
94
|
-
<%= energy %>
|
95
|
-
|
96
|
-
function outputTable(name, units, obj) {
|
97
|
-
if (name == "Electricity Consumption" | name == "Natural Gas Consumption" | name == "District Cooling Consumption" | name == "District Heating Consumption") {
|
98
|
-
$('<h4>').text(name + " (" + units + ")").appendTo('body');
|
99
|
-
var $table = $('<table id="' + name.toLowerCase().replace(/ /g, '-') + '">').addClass("table table-striped table-bordered table-condensed");
|
100
|
-
$table.append('<thead>').children('thead').append('<tr />').children('tr').append('<th> </th><th>Jan</th><th>Feb</th><th>Mar</th><th>Apr</th><th>May</th><th>Jun</th><th>Jul</th><th>Aug</th><th>Sep</th><th>Oct</th><th>Nov</th><th>Dec</th><th>Total</th>');
|
101
|
-
var $tbody = $table.append('<tbody />').children('tbody');
|
102
|
-
var key;
|
103
|
-
var totalTotal = 0;
|
104
|
-
var columnTotal = [];
|
105
|
-
for (key in obj) {
|
106
|
-
if (obj.hasOwnProperty(key)) {
|
107
|
-
var $row = $tbody.append('<tr />').children('tr:last');
|
108
|
-
$row.append("<td>" + key + "</td>");
|
109
|
-
var total = 0;
|
110
|
-
for (i = 0; i < obj[key].length; i++) {
|
111
|
-
if (columnTotal[i] === undefined) columnTotal[i] = 0;
|
112
|
-
$row.append("<td>" + (obj[key][i] === 0 ? "—" : numFormat(obj[key][i])) + "</td>");
|
113
|
-
total += obj[key][i];
|
114
|
-
columnTotal[i] += obj[key][i];
|
115
|
-
}
|
116
|
-
totalTotal += total;
|
117
|
-
$row.append("<td>" + (total === 0 ? "—" : numFormat(total.toFixed(3))) + "</td>");
|
118
|
-
}
|
119
|
-
}
|
120
|
-
// Append column totals as new, last row of table
|
121
|
-
if (columnTotal[columnTotal.length] === undefined) columnTotal[columnTotal.length] = 0;
|
122
|
-
columnTotal[columnTotal.length - 1] = totalTotal;
|
123
|
-
var $row = $tbody.append('<tr />').children('tr:last');
|
124
|
-
$row.append("<td>Total</td>");
|
125
|
-
for (i = 0; i < columnTotal.length; i++) {
|
126
|
-
$row.append("<td>" + (columnTotal[i] === 0 ? "—" : numFormat(columnTotal[i].toFixed(3))) + "</td>");
|
127
|
-
}
|
128
|
-
$table.appendTo('body');
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
$.each(consumption, function (key, obj) {
|
133
|
-
outputTable(key, obj.units, obj.data);
|
134
|
-
});
|
135
|
-
|
136
|
-
var margin = {
|
137
|
-
top: 20.5,
|
138
|
-
right: 20,
|
139
|
-
bottom: 30,
|
140
|
-
left: 40.5
|
141
|
-
},
|
142
|
-
width = 560 - margin.left - margin.right,
|
143
|
-
height = 300 - margin.top - margin.bottom;
|
144
|
-
|
145
|
-
var x = d3.scale.ordinal()
|
146
|
-
.rangeRoundBands([0, width], 0.1);
|
147
|
-
|
148
|
-
var y = d3.scale.linear()
|
149
|
-
.rangeRound([height, 0]);
|
150
|
-
|
151
|
-
var color = d3.scale.ordinal()
|
152
|
-
.range(["#EF1C21", "#0071BD", "#F7DF10", "#DEC310", "#4A4D4A", "#B5B2B5", "#FF79AD", "#632C94", "#F75921", "#293094", "#CE5921", "#FFB239", "#29AAE7", "#8CC739"]);
|
153
|
-
|
154
|
-
var xAxis = d3.svg.axis()
|
155
|
-
.scale(x)
|
156
|
-
.orient("bottom");
|
157
|
-
|
158
|
-
var yAxis = d3.svg.axis()
|
159
|
-
.scale(y)
|
160
|
-
.orient("left")
|
161
|
-
.tickFormat(d3.format(".2s"));
|
162
|
-
|
163
|
-
var tip = d3.tip()
|
164
|
-
.attr('class', 'd3-tip')
|
165
|
-
.offset([-10, 0])
|
166
|
-
.html(function (d) {
|
167
|
-
return "<strong>" + d.name + ":</strong> <span style='color:red'>" + (d.y1 - d.y0).toFixed(2) + "</span>";
|
168
|
-
});
|
169
|
-
|
170
|
-
var charts = ["Electricity Consumption", "Natural Gas Consumption"];
|
171
|
-
|
172
|
-
for (var c in charts) {
|
173
|
-
|
174
|
-
if (c == charts.length - 1) {
|
175
|
-
margin.right = 125;
|
176
|
-
}
|
177
|
-
|
178
|
-
$('#title-' + c).text(charts[c]);
|
179
|
-
|
180
|
-
var svg = d3.select("#chart-" + c).append("svg")
|
181
|
-
.attr("width", width + margin.left + margin.right)
|
182
|
-
.attr("height", height + margin.top + margin.bottom)
|
183
|
-
.append("g")
|
184
|
-
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
185
|
-
svg.call(tip);
|
186
|
-
|
187
|
-
data = [];
|
188
|
-
for (var enduse in consumption[charts[c]].data) {
|
189
|
-
var enduse_data = consumption[charts[c]].data[enduse];
|
190
|
-
for (var month = 0; month < months.length; month++) {
|
191
|
-
if (data.length < months.length) {
|
192
|
-
var temp = {
|
193
|
-
"Month": months[month]
|
194
|
-
};
|
195
|
-
temp[enduse] = enduse_data[month];
|
196
|
-
data.push(temp);
|
197
|
-
} else {
|
198
|
-
data[month][enduse] = enduse_data[month];
|
199
|
-
}
|
200
|
-
}
|
201
|
-
}
|
202
|
-
color.domain(d3.keys(data[0]).filter(function (key) {
|
203
|
-
return key !== "Month";
|
204
|
-
}));
|
205
|
-
|
206
|
-
data.forEach(function (d) {
|
207
|
-
var y0 = 0;
|
208
|
-
d.consumption = color.domain().map(function (name) {
|
209
|
-
return {
|
210
|
-
name: name,
|
211
|
-
y0: y0,
|
212
|
-
y1: y0 += +d[name]
|
213
|
-
};
|
214
|
-
});
|
215
|
-
d.total = d.consumption[d.consumption.length - 1].y1;
|
216
|
-
});
|
217
|
-
|
218
|
-
//data.sort(function(a, b) { return b.total - a.total; });
|
219
|
-
|
220
|
-
x.domain(data.map(function (d) {
|
221
|
-
return d.Month;
|
222
|
-
}));
|
223
|
-
y.domain([0, d3.max(data, function (d) {
|
224
|
-
return d.total;
|
225
|
-
})]);
|
226
|
-
|
227
|
-
svg.append("g")
|
228
|
-
.attr("class", "x axis")
|
229
|
-
.attr("transform", "translate(0," + height + ")")
|
230
|
-
.call(xAxis);
|
231
|
-
|
232
|
-
svg.append("g")
|
233
|
-
.attr("class", "y axis")
|
234
|
-
.call(yAxis)
|
235
|
-
.append("text")
|
236
|
-
.attr("transform", "rotate(-90)")
|
237
|
-
.attr("y", -36)
|
238
|
-
.attr("dy", ".71em")
|
239
|
-
.style("text-anchor", "end")
|
240
|
-
.text(consumption[charts[c]].units);
|
241
|
-
|
242
|
-
var month = svg.selectAll(".month")
|
243
|
-
.data(data)
|
244
|
-
.enter().append("g")
|
245
|
-
.attr("class", "g")
|
246
|
-
.attr("transform", function (d) {
|
247
|
-
return "translate(" + x(d.Month) + ",0)";
|
248
|
-
});
|
249
|
-
|
250
|
-
month.selectAll("rect")
|
251
|
-
.data(function (d) {
|
252
|
-
return d.consumption;
|
253
|
-
})
|
254
|
-
.enter().append("rect")
|
255
|
-
.attr("width", x.rangeBand())
|
256
|
-
.attr("y", function (d) {
|
257
|
-
return y(d.y1);
|
258
|
-
})
|
259
|
-
.attr("height", function (d) {
|
260
|
-
return y(d.y0) - y(d.y1);
|
261
|
-
})
|
262
|
-
.style("fill", function (d) {
|
263
|
-
return color(d.name);
|
264
|
-
})
|
265
|
-
.on('mouseover', tip.show)
|
266
|
-
.on('mouseout', tip.hide);
|
267
|
-
|
268
|
-
if (c == charts.length - 1) {
|
269
|
-
var legend = svg.selectAll(".legend")
|
270
|
-
.data(color.domain().slice())
|
271
|
-
.enter().append("g")
|
272
|
-
.attr("class", "legend")
|
273
|
-
.attr("transform", function (d, i) {
|
274
|
-
return "translate(0," + i * 20 + ")";
|
275
|
-
});
|
276
|
-
|
277
|
-
legend.append("rect")
|
278
|
-
.attr("x", width + 105)
|
279
|
-
.attr("width", 18)
|
280
|
-
.attr("height", 18)
|
281
|
-
.style("fill", color);
|
282
|
-
|
283
|
-
legend.append("text")
|
284
|
-
.attr("x", width + 105 - 3)
|
285
|
-
.attr("y", 9)
|
286
|
-
.attr("dy", ".35em")
|
287
|
-
.style("text-anchor", "end")
|
288
|
-
.text(function (d) {
|
289
|
-
return d;
|
290
|
-
});
|
291
|
-
}
|
292
|
-
|
293
|
-
svg.selectAll(".g").attr("stroke", "black")
|
294
|
-
.attr("stroke-width", "1");
|
295
|
-
}
|
296
|
-
</script>
|
297
|
-
</body>
|
298
|
-
</html>
|