Built with blockbuilder.org
forked from chriswmackey's block: Explore Facade Options
forked from chriswmackey's block: Parametric Energy Model Results
forked from chriswmackey's block: Parametric Energy Model
forked from chriswmackey's block: Parametric Lab Energy Model
xxxxxxxxxx
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta charset = "UTF-8" />
<!-- ====================== CDN scripts ======================== -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<!-- ====================== data source ======================== -->
<script type="text/javascript" src="data.json"></script>
<!-- ====================== element styling ======================== -->
<style>
body {
/* background-image: none; */
}
#summary {
font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif;
font-size: 1.4em;
font-variant: small-caps;
font-weight: 500;
text-align:center;
outline:none;
letter-spacing: 1.5px;
padding:10px 0px 0px 10px;
width:960px;
margin: 0 auto;
}
#content {
width:960px;
text-align:center;
margin: 0 auto;
}
#inputSliders {
font-family:"Palatino Linotype", "Book Antiqua", Palatino, serif;
text-align:justify;
outline:none;
padding:0px 0px 0px 0px;
width:960px;
margin: 0 auto;
}
.inputgroup {
border: 4px double cornflowerblue;
/* display: flex;
flex-wrap: nowrap; */
}
.slider {
width:164.8px;
float: left;
display: flex;
flex-direction: column;
flex-wrap: initial;
padding:10px;
height:100px;
/* display: -webkit-flex;
-webkit-flex-flow: row-reverse wrap; */
/* display: flex;
flex-wrap: initial; */
}
.slider2 {
width:234px;
float:left;
padding:14px 0px 1px 0px;
}
label {
float:left;
font-weight:bold;
text-align:center;
padding-bottom:20px;
}
input[type=range] {
float:none;
clear: both;
margin:10px 0px 0px 20px;
text-align:center;
width:130px;
}
input[type=range]::-ms-track {
background: transparent;
border-color: transparent;
color: transparent;
-webkit-appearance: none
}
input[type=range]::-ms-track {
-ms-appearance: none;
height: 3px;
background-color: #d5d5d5;
margin-right: 0;
margin-top: 5px;
margin-bottom: 5px;
border:0;
}
input[type=range]::-ms-thumb {
background-color: #FFF;
border: 3px solid rgb(150,150,150);
border-radius: 5px;
height: 10px;
width: 1px;
}
input[type=range]::-webkit-slider-runnable-track {
height: 5px;
background:#7c7c7c;
margin-top: -2px;
}
input[type=range]::-webkit-slider-thumb {
margin-top:-5px;
}
#inputSliders p {
padding-top:1px;
font-size: 1.3em;
text-align: center;
}
#ventilation {background-color:#f2f2f2}
#stockOptions {background-color:#e6e6e6}
#hoodDensity {background-color:#f2f2f2}
#uvalue {background-color:#e6e6e6}
#rvalue {background-color:#f2f2f2}
#hvacType {background-color:#e6e6e6}
#heatRecovery {background-color:#f2f2f2}
#ventilation {background-color:#f2f2f2}
#autoclosers {background-color:#e6e6e6}
#minimumflow {background-color:#f2f2f2}
#heatingsource {background-color:#e6e6e6}
#euidiv1 {background-color:#f2f2f2}
#euidiv2 {background-color:#e6e6e6}
#peakcooldiv {background-color:#f2f2f2}
#peakheatdiv {background-color:#e6e6e6}
</style>
</head>
<body>
<!-- ====================== DOM elements ======================== -->
<!-- summary figures bar -->
<div id="summary">
<div class="slider2" id="euidiv1">
<div id="eui1"></div>
<p style="margin-top:3px;">Guaranteed<br>Compensation</p>
</div>
<div class="slider2" id="euidiv2">
<div id="eui2"></div>
<p style="margin-top:3px;">Incentive<br>Compensation</p>
</div>
<div class="slider2" id="peakcooldiv">
<div id="peakcool"></div>
<p style="margin-top:3px;">Low-end<br>Value Estimate</p>
</div>
<div class="slider2" id="peakheatdiv">
<div id="peakheat"></div>
<p style="margin-top:3px;">High-end<br>Value Estimate</p>
</div>
</div>
<!-- stacked bar charts -->
<div id="content">
</div>
<!-- input sliders -->
<div id="inputSliders">
<form id="sliders" autocomplete="off">
<fieldset class="inputgroup">
<!-- cash salary -->
<div class="slider" id="ventilation">
<label>Cash Salary</label>
<input type="range" name="cashSal" id="cashSal" value="0" min="0" max="1" step = "1">
<p id="cashSaloutput">$90k</p>
</div>
<!-- equity salary -->
<div class="slider" id="stockOptions">
<label>Equity Salary</label>
<input type="range" name="options" id="options" value="6" min="3" max="12" step = "3">
<p id="optionsoutput">6k options*</p>
</div>
<!-- benefits -->
<div class="slider" id="hoodDensity">
<label>Benefits/Subsidies</label>
<input type="range" name="hoodD" id="hoodD" value="0.5" min="0.5" max="1.5" step = "1">
<p id="hoodoutput">0.5</p>
</div>
<!-- professional development -->
<div class="slider" id="uvalue">
<label>Professional development</label>
<input type="range" name="uval" id="uval" value="2" min="0" max="2" step = "1">
<p id="uvaloutput">$4k</p>
</div>
<!-- vacation -->
<div class="slider" id="rvalue">
<label>Weeks of Vacation</label>
<input type="range" name="rval" id="rval" value="0" min="0" max="1" step = "1">
<p id="rvaloutput">3</p>
</div>
<!-- cash bonus -->
<div class="slider" id="hvacType">
<label>Cash Bonus</label>
<input type="range" name="hvac" id="hvac" value="0" min="0" max="2" step = "1">
<p id="hvacoutput">0%</p>
</div>
<!-- equity bonus -->
<div class="slider" id="heatRecovery">
<label>Equity Bonus</label>
<input type="range" name="heatr" id="heatr" value="0.5" min="0.1" max="0.50" step = "0.2">
<p id="heatroutput">50%</p>
</div>
<!-- 401k match -->
<div class="slider" id="autoclosers">
<label>401k Match</label>
<input type="range" name="autoc" id="autoc" value="0" min="0" max="1" step = "1">
<p id="autocoutput">No</p>
</div>
<!-- personal development -->
<div class="slider" id="minimumflow">
<label>Personal L&E</label>
<input type="range" name="minflow" id="minflow" value="25" min="10" max="25" step = "15">
<p id="minflowoutput">$500</p>
</div>
<!-- health insurance -->
<div class="slider" id="heatingsource">
<label>Health Insurance</label>
<input type="range" name="hsource" id="hsource" value="0" min="0" max="1" step = "1">
<p id="hsourceoutput">Silver</p>
</div>
</fieldset>
</form>
</div>
<script>
// ====================== load data ========================
var dataObj = JSON.parse(allResults)
// ====================== get input values from sliders ========================
var CashSal = $("#cashSal").val().toString(); // annual fixed salary
var Options = $("#options").val().toString(); // ESOP
var HoodD = $("#hoodD").val().toString(); // Fume Hood Density
var uValue = $("#uval").val().toString(); //U-value
var rValue = $("#rval").val().toString(); //R-value
var HVAC = $("#hvac").val().toString(); // HVAC Type
var hRecovery = $("#heatr").val().toString(); // Heat Recovery
var AutoC = $("#autoc").val().toString(); // Sash AutoClosers
var MinFlow = $("#minflow").val().toString(); // Fume Hood Minimum Flow
var hSource = $("#hsource").val().toString(); // Hot Water Source
// ============== assign input types & values for slider positions ===============
uValueDict = {'0':'0', '1':'4', '2':'5'}
rValueDict = {'0':'3', '1':'20'}
hvacTypeDict = {'0':'30%', '1':'10%', '2':'0%'}
labVentDict = {'0':'$90k', '1':'$120k'}
autoClosDict = {'0':'No', '1':'Yes'}
hSourceDict = {'0':'silver', '1':'gold'}
// ====================== update inputs ========================
$("#cashSal").on("input", function(event) {
CashSal = $(this).val();
$("#cashSaloutput").text(labVentDict[Vent]);
updateEnergy();
});
$("#options").on("input", function(event) {
Options = $(this).val();
$("#optionsoutput").text(Options.toString() + 'k options (4-yr vesting)');
updateEnergy();
});
$("#hoodD").on("input", function(event) {
HoodD = $(this).val();
$("#hoodoutput").text(HoodD.toString());
updateEnergy();
});
$("#uval").on("input", function(event) {
uValue = $(this).val();
$("#uvaloutput").text('$' + uValueDict[uValue] + 'k');
updateEnergy();
});
$("#rval").on("input", function(event) {
rValue = $(this).val();
$("#rvaloutput").text(rValueDict[rValue]);
updateEnergy();
});
$("#hvac").on("input", function(event) {
HVAC = $(this).val();
$("#hvacoutput").text(hvacTypeDict[HVAC]);
updateEnergy();
});
$("#heatr").on("input", function(event) {
hRecovery = $(this).val();
$("#heatroutput").text((hRecovery*100).toString() + "%");
updateEnergy();
});
$("#autoc").on("input", function(event) {
AutoC = $(this).val();
$("#autocoutput").text(autoClosDict[AutoC]);
updateEnergy();
});
$("#minflow").on("input", function(event) {
MinFlow = $(this).val();
$("#minflowoutput").text(MinFlow.toString() + 'cfm');
updateEnergy();
});
$("#hsource").on("input", function(event) {
hSource = $(this).val();
$("#hsourceoutput").text(hSourceDict[hSource]);
updateEnergy();
});
// Function to update the charts.
updateEnergy = function(){
// Retrieve the energy use and peak load data from the json.
var hRoption = 1
if (hRecovery == 0.5) {
var hRoption = 0
}
var ventOption = 1
if (CashSal == 1) {
var ventOption = 1.33
}
if (HoodD == 0.5) {
AutoC = 0
}
var windowOption = Math.abs(uValue-2)
var inputList = [rValue, windowOption, HVAC, hRoption, HoodD, ventOption, AutoC, MinFlow, Options]
var jsonStr = inputList.join(',')
var rawData = dataObj[jsonStr][0]
var data = [rawData[2], rawData[3], rawData[1], rawData[0], rawData[4], rawData[5]]
var coolElectr = rawData[0] / 27
var heatFuel = rawData[1] / 0.7
if (hSource == 1){
var heatFuel = rawData[1] / 0.95
}
var siteEUIData = [rawData[2], rawData[3], heatFuel, coolElectr, rawData[4], rawData[5]]
var peakData = dataObj[jsonStr][1]
var floorArea = 1194
peakData = [peakData[0]/floorArea, peakData[1]/floorArea]
// Update the energy chart.
svg2.selectAll('.energyBar').remove();
stackIncrement = 0
for (i = 0; i < data.length; i++) {
svg2.append("rect")
.attr("x", margin.left + barSpacer)
.attr("y", svgheight- margin.bottom - yScale(maxEUI-data[i]) - yScale(maxEUI - stackIncrement))
.attr("width", 100)
.attr("height", yScale(maxEUI - data[i]))
.attr('fill', colors[i])
.attr("class", "energyBar")
.style("stroke", "#000")
.style("stroke-width", "0.05em");
stackIncrement += data[i]
}
// Update the energy chart.
svg4.selectAll('.energyBar').remove();
stackIncrement = 0
for (i = 0; i < siteEUIData.length; i++) {
svg4.append("rect")
.attr("x", margin.left + barSpacer)
.attr("y", svgheight- margin.bottom - yScale(maxEUI-siteEUIData[i]) - yScale(maxEUI - stackIncrement))
.attr("width", 100)
.attr("height", yScale(maxEUI - siteEUIData[i]))
.attr('fill', colors[i])
.attr("class", "energyBar")
.style("stroke", "#000")
.style("stroke-width", "0.05em");
stackIncrement += siteEUIData[i]
}
// Update the peak loads chart.
svg3.selectAll('.peakBar').remove();
for (i = 0; i < peakData.length; i++) {
svg3.append("rect")
.attr("x", peakMarginLeft + barSpacer + 100*i)
.attr("y", svgheight- margin.bottom - yPeakScale(maxPeak-peakData[i]))
.attr("width", 60)
.attr("height", yPeakScale(maxPeak - peakData[i]))
.attr('fill', peakColors[i])
.attr("class", "peakBar")
.style("stroke", "hsla(127, 100%, 7%, 0.88)")
.style("stroke-width", "0.15em");
}
// Update the metrics on the bottom.
d3.selectAll(".resultText").remove();
// Calculate the metrics.
var EUI1 = precisionRound(rawData.reduce(add, 0),1);
var EUI2 = precisionRound(siteEUIData.reduce(add, 0),1);
d3.select("#eui1").append("text")
.attr("class", "resultText")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '30px')
.style('font-family', 'sans-serif')
.text(EUI1.toString());
d3.select("#eui2").append("text")
.attr("class", "resultText")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '30px')
.style('font-family', 'sans-serif')
.text(EUI2.toString());
d3.select("#peakcool").append("text")
.attr("class", "resultText")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '30px')
.style('font-family', 'sans-serif')
.text(precisionRound(peakData[0],1).toString());
d3.select("#peakheat").append("text")
.attr("class", "resultText")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '30px')
.style('font-family', 'sans-serif')
.text(precisionRound(peakData[1],1).toString());
}
// Utility Functions
function add(a, b) {
return a + b;
}
function precisionRound(number, precision) {
var factor = Math.pow(10, precision);
return Math.round(number * factor) / factor;
}
// Properties of the Energy Chart
var maxEUI = 300
var colors = ["rgb(255,255,0)", "rgb(191,191,191)", "rgb(255,0,102)", "rgb(0,176,240)","rgb(166,216,110)","rgb(119,185,49)"]
var energyTypes = ["401k Match", "Equity", "Bonus", "Salary","Stipends","Development"]
// Pixel sizes of the Energy Chart
margin = {top: 20, right: 40, bottom: 30, left: 70};
svgwidth = 300
svgheight = 400
barSpacer = 35
width = svgwidth - margin.left - margin.right
height = svgheight - margin.top - margin.bottom
var x = d3.scaleBand()
.rangeRound([0, svgwidth])
.padding(0.1)
.align(0.1);
var yScale = d3.scaleLinear()
.domain([0, maxEUI])
.rangeRound([height, 0]);
// Layout the EUI charts.
buildEUIChar = function(axisText) {
var svg = d3.select("#content").append("svg")
.attr("width", svgwidth)
.attr("height", svgheight)
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(yScale).ticks(10, "s"))
.append("text")
.attr("x", 10)
.attr("y", yScale(yScale.ticks(10).pop()))
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '14px')
.text(axisText);
g.append("text")
.attr("x", 10)
.attr("y", 18)
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '11px')
.style('font-family', 'sans-serif')
.text("(Projected Value)");
// Add the legend.
spacerIncrement = 0
for (i = 0; i < energyTypes.length; i++) {
svg.append("rect")
.attr("x", svgwidth - 11)
.attr("y", margin.top + spacerIncrement + 120)
.attr("width", 10)
.attr("height", 10)
.attr('fill', colors[i])
.style("stroke", "#000")
.style("stroke-width", "0.05em");
svg.append("text")
.attr("x",svgwidth - 15)
.attr("y", margin.top + spacerIncrement + 120)
.attr("dy", "10px")
.attr("text-anchor", "end")
.attr("fill", "#000")
.style('font-family', 'sans-serif')
.style('font-size', '12px')
.text(energyTypes[i]);
spacerIncrement += 20
}
return svg
}
svg2 = buildEUIChar('Guaranteed Compensation');
svg4 = buildEUIChar('Incentive Compensation');
// Properties of the Peak Loads Chart
var maxPeak = 8
var peakColors = ["rgb(9, 122, 47)", "rgba(0, 175, 23, 0.53)"]
var peakTypes = ["Guaranteed", "Incentive"]
var peakMarginLeft = 70
// Layout the chart.
var svg3 = d3.select("#content").append("svg")
.attr("width", svgwidth)
.attr("height", svgheight)
g2 = svg3.append("g").attr("transform", "translate(" + peakMarginLeft + "," + margin.top + ")");
var yPeakScale = d3.scaleLinear()
.domain([0, maxPeak])
.rangeRound([height, 0]);
g2.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g2.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(yPeakScale).ticks(10, "s"))
.append("text")
.attr("x", 10)
.attr("y", yPeakScale(yPeakScale.ticks(10).pop()))
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '14px')
.text("Risk Profile");
g2.append("text")
.attr("x", 10)
.attr("y", 18)
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '11px')
.style('font-family', 'sans-serif')
.text("(Fixed vs. Variable)");
// ================= add legend to risk profile ====================
spacerIncrement = 0
for (i = 0; i < peakTypes.length; i++) {
svg3.append("rect")
.attr("x", svgwidth - 30)
.attr("y", margin.top + spacerIncrement)
.attr("width", 10)
.attr("height", 10)
.attr('fill', peakColors[i])
.style("stroke", "#000")
.style("stroke-width", "0.05em");
svg3.append("text")
.attr("x",svgwidth - 35)
.attr("y", margin.top + spacerIncrement)
.attr("dy", "10px")
.attr("text-anchor", "end")
.attr("fill", "#000")
.style('font-family', 'sans-serif')
.style('font-size', '12px')
.text(peakTypes[i]);
spacerIncrement += 20
}
updateEnergy()
d3.select(self.frameElement).style("height", 800 + "px");
</script>
</body>
https://d3js.org/d3.v4.min.js
https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js
https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js