openstudio-workflow 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -1
  3. data/README.md +24 -63
  4. data/lib/openstudio/extended_runner.rb +94 -0
  5. data/lib/openstudio/workflow/adapter.rb +10 -0
  6. data/lib/openstudio/workflow/adapters/mongo.rb +1 -1
  7. data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +12 -17
  8. data/lib/openstudio/workflow/jobs/{run_openstudio → run_energyplus}/monthly_report.idf +8 -4
  9. data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +132 -21
  10. data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +6 -11
  11. data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +7 -6
  12. data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +2 -1
  13. data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +27 -148
  14. data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +31 -10
  15. data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +4 -3
  16. data/lib/openstudio/workflow/run.rb +4 -5
  17. data/lib/openstudio/workflow/version.rb +1 -1
  18. data/lib/openstudio-workflow.rb +6 -10
  19. metadata +9 -12
  20. data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/README.md +0 -5
  21. data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.rb +0 -206
  22. data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.xml +0 -53
  23. 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>&nbsp;</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 ? "&mdash;" : 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 ? "&mdash;" : 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 ? "&mdash;" : 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>