var state;
var FEATURES = ["gpu", "provider", "region", "hours"];
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function selectAndCopyText(containerid) {
if (document.selection) {
// IE
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(containerid));
range.select();
document.execCommand("copy");
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(containerid));
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand("copy");
}
}
function findGetParameter(parameterName) {
var result = null,
tmp = [];
location.search
.substr(1)
.split("&")
.forEach(function (item) {
tmp = item.split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
});
return result;
}
function insertParam(kvp, key, value) {
key = encodeURI(key);
value = encodeURI(value);
var i = kvp.length;
var x;
while (i--) {
x = kvp[i].split("=");
if (x[0] == key) {
x[1] = value;
kvp[i] = x.join("=");
break;
}
}
if (i < 0) {
kvp[kvp.length] = [key, value].join("=");
}
return kvp;
}
function sc(id) {
$("html,body").animate(
{
scrollTop:
$("#" + id).offset().top - parseInt($("#" + id).height() / 1.2),
},
"slow"
);
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// FORM HANDLING
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
const setImports = (serveFrom, elType, attr) => {
const isDev = serveFrom === "dev";
$(elType).each((i, el) => {
let val = $(el).attr(attr);
if (val && val.indexOf("...") >= 0) {
$(el).attr(
attr,
isDev ? val.split("...")[1] : "/impact" + val.split("...")[1]
);
}
});
};
const getValues = () => {
const gpu = $("#compute-gpu option:selected").val();
const provider = $("#compute-provider option:selected").val();
const region =
provider !== "custom" ? $("#compute-region option:selected").val() : null;
const customImpact =
provider !== "custom"
? null
: parseFloat($("#compute-custom-impact").val());
const customOffset =
provider !== "custom"
? null
: parseFloat($("#compute-custom-offset").val());
const hours = parseFloat($("#compute-hours").val());
return {
gpu,
provider,
region,
hours,
customImpact,
customOffset,
};
};
const scrollToBottomResultCard = () => {
const cardOffset =
$("#result-card").offset().top +
$("#result-card").outerHeight() -
$(window).height() +
50;
$("html, body").animate(
{
scrollTop: cardOffset,
},
1000,
"easeInOutExpo"
);
return;
};
const growDivOnArrowClick = (clickId, growId) => {
$(clickId).click(function () {
if (!$(this).find(".arrow-icon").hasClass("open")) {
var h = 0;
$(growId)
.children()
.each((k, v) => {
h += $(v).innerHeight();
});
$(growId).height(h);
setTimeout(() => {
if (
$(window).height() > $("#result-card").outerHeight() + 150 &&
!isBottomVisible()
) {
scrollToBottomResultCard();
}
}, 500);
} else {
$(growId).height(0);
setTimeout(() => {
!isBottomVisible(50) && scrollToBottomResultCard();
}, 500);
}
$(this).find(".arrow-icon").toggleClass("open");
});
};
const growDivOnArrowClickLearn = (clickId, growId) => {
$(clickId).click(function () {
if (!$(this).find(".arrow-icon").hasClass("open")) {
var h = 0;
$(this)
.siblings(growId)
.children()
.each((k, v) => {
h += $(v).innerHeight();
});
$(this).siblings(growId).height(h);
} else {
$(this).siblings(growId).height(0);
}
$(this).find(".arrow-icon").toggleClass("open");
});
};
const check = (type, value) => {
$("#compute-hours").css("border", "");
switch (type) {
case "gpu":
// console.log(state.gpus, value);
return state.gpus.filter((v, k) => {
return v.name === value;
}).length;
case "hours":
return Number.isInteger(value) && value > 0 && value < 1e6;
case "provider":
return state.providers.filter((v, k) => {
return v.name === value;
}).length;
case "region":
return state.regions.filter((v, k) => {
return v.name === value;
}).length;
default:
return true;
}
};
const checkForm = () => {
const values = getValues();
const { gpu, provider, region, hours } = values;
let failed = false;
FEATURES.forEach((v, k) => {
if (!check(k, v)) {
fail(k);
failed = true;
}
});
if (failed) return null;
return values;
};
const twoDigits = (n) => Number(Number(n).toFixed(2));
const toDigits = (n, d) => Number(Number(n).toFixed(d));
const fillLatexTemplate = (
provName,
region,
hours,
gpu,
gpuPower,
emissions,
offsetPercents,
impact
) => {
provName
? $("#template-text-offset").show()
: $("#template-text-offset").hide();
$("#template-provider").text(provName || "a private infrastructure");
$("#template-region").text(region ? ` in region ${region}` : "");
$("#template-region-efficiency").text(impact);
$("#template-hours").text(hours);
$("#template-gpu").text(gpu);
$("#template-gpu-power").text(gpuPower);
$("#template-emissions").text(emissions);
$("#template-percentage-offset").text(offsetPercents);
};
const setDetails = (values) => {
// console.log({ values });
const { gpu, hours, provider, region, customImpact, customOffset } = values;
const energy = twoDigits((state.gpus[gpu].watt * hours) / 1000); // kWh
const impact = Number.isFinite(customImpact)
? customImpact
: twoDigits(state.providers[provider][region].impact / 1000); // kg/kwH
const co2 = twoDigits(energy * impact);
const offset = Number.isFinite(customOffset)
? twoDigits((co2 * customOffset) / 100)
: twoDigits((co2 * state.providers[provider][region].offsetRatio) / 100);
const offsetPercents = Number.isFinite(customOffset)
? twoDigits(customOffset)
: twoDigits(state.providers[provider][region].offsetRatio);
const provName = Number.isFinite(customOffset)
? ""
: state.providers[provider][region].providerName;
const minRegId = Number.isFinite(customOffset)
? ""
: state.providers[provider].__min.region;
const minReg = Number.isFinite(customOffset)
? ""
: state.providers[provider][minRegId];
console.log(
"Computation details:" +
Object.entries(values)
.map(([k, v]) => `\n • ${k}: ${v}`)
.join("")
);
fillLatexTemplate(
provName,
region,
hours,
gpu,
state.gpus[gpu].watt,
co2,
offsetPercents,
impact
);
fillComparisonTable(co2);
$("#comparison-result-co2").text(co2);
$("#offset-value").text(offset);
$("#details-counts").html(`
${state.gpus[gpu].watt}W x ${hours}h = ${energy} kWh x ${impact}
kg eq. CO2/kWh = ${co2} kg eq. CO2
`);
if (Number.isFinite(customOffset)) {
$("#details-min-region").html("");
$("#details-alternative").html("");
$("#details-alternative-content").show();
$("#compute-carbon-offset-title").html("Carbon offset");
} else {
$("#compute-carbon-offset-title").html("Carbon Already Offset by Provider");
if (region !== minRegId) {
const minco2 = twoDigits((energy * minReg.impact) / 1000);
$("#details-min-selected").hide();
$("#details-alternative").html(
`
Had this model been run in ${provName}'s ${minReg.regionName} region,
the carbon emitted would have been of ${minco2} kg eq. CO2
`
);
$("#details-alternative").show();
} else {
$("#details-min-selected").show();
$("#details-alternative").hide();
$("#details-min-region").html(
`
You have selected ${provName}'s cleanest region!
`
);
}
}
};
const scientificNotation = (n, d) => {
const exp = n.toExponential() + "";
let dec = exp.split(".")[1].split("e")[0];
dec = dec.slice(0, d);
const power = exp.split("e")[1];
let n_d = parseFloat(exp.split(".")[0] + "." + dec);
if (power === "+0") {
n_d = toDigits(n_d * 1, d);
} else if (power === "+1") {
n_d = toDigits(n_d * 10, d);
} else if (power === "+2") {
n_d = toDigits(n_d * 100, d);
} else if (power === "-1") {
n_d = toDigits(n_d * 0.1, d);
} else if (power === "-2") {
n_d = toDigits(n_d * 0.01, d);
} else {
n_d += ` x10${power.replace("+", "")}`;
}
return n_d;
};
const fillComparisonTable = (co2) => {
$("#emitted-value").text(co2);
// https://www.epa.gov/energy/greenhouse-gases-equivalencies-calculator-calculations-and-references
const DIGITS = 2;
// # Miles driven by the average passenger vehicle
// 3.98 x 10-4 metric tons CO2E/mile
const kgC02PerKm = (3.98 * 1e-4 * 1e3) / 1.609344;
const eqDriven = scientificNotation(co2 / kgC02PerKm, DIGITS);
// # Pounds of coal burned
// 9.05 x 10-4 metric tons CO2/pound of coal
const kgCoalBurnedPerKg = 9.05 * 1e-4 * 1e3 * 2.204623;
const eqCoal = scientificNotation(co2 / kgCoalBurnedPerKg, DIGITS);
// https://www.epa.gov/energy/greenhouse-gases-equivalencies-calculator-calculations-and-references#seedlings
// 0.060 metric ton CO2 per urban tree planted (sequestered)
const kgC02SequestratedBySeedling = 0.06 * 1e3;
const eqForest = scientificNotation(
co2 / kgC02SequestratedBySeedling,
DIGITS
);
$("#comparison-result-driven").html(eqDriven);
$("#comparison-result-coal").html(eqCoal);
$("#comparison-result-forest").html(eqForest);
};
const isBottomVisible = (_bottomOffset) => {
const bottomOffset = _bottomOffset || 0;
return (
$("#result-card").offset().top +
$("#result-card").outerHeight() +
bottomOffset <
$(window).scrollTop() + $(window).height()
);
};
const submitCompute = (_values) => {
$("#result-card").hide();
$("#comparison-row").hide();
$("#details-content").height(0);
$("#details-banner .arrow-icon").removeClass("open");
$(".spinner-border").show();
// const values = _values ? _values : checkForm();
const values = getValues();
if (!values) return;
setDetails(values);
state.current = values;
setTimeout(() => {
$(".spinner-border").hide();
$("#result-card").fadeIn();
$("#comparison-row").fadeIn();
$("#compute-carbon-emitted-title").height(
$("#compute-carbon-offset-title").height()
);
// console.log($(window).scrollTop() + $(window).height());
if ($(window).width() < 769 || !isBottomVisible()) {
scrollToBottomResultCard();
}
}, getRandomInt(500, 1500));
};
const setRegions = (provider) => {
if (provider === "custom") {
$("#compute-region-div").fadeOut(() => {
$(".custom-hidable").fadeIn();
});
} else {
if (!$("#compute-region-div").is(":visible")) {
$(".custom-hidable").fadeOut(() => {
$("#compute-region-div").fadeIn();
});
}
$("#compute-region").html("");
let regs = [];
for (const region in state.providers[provider]) {
if (
state.providers[provider].hasOwnProperty(region) &&
region !== "__min"
) {
let { regionName } = state.providers[provider][region];
if (!regionName) {
regionName = region;
}
regs.push({ region, regionName });
}
}
regs.sort((a, b) =>
a.regionName > b.regionName ? 1 : b.regionName > a.regionName ? -1 : 0
);
for (const reg of regs) {
const { regionName, region } = reg;
$("#compute-region").append(
``
);
}
}
};
const setInputs = () => {
for (const gpuName of Object.keys(state.gpus).sort()) {
const selected = gpuName === "Tesla V100" ? "selected" : "";
$("#compute-gpu").append(
``
);
}
let prov;
let i = 0;
for (const provider in state.providers) {
if (i == 0) prov = provider;
i++;
if (state.providers.hasOwnProperty(provider)) {
let providerName;
for (const region in state.providers[provider]) {
if (
state.providers[provider].hasOwnProperty(region) &&
region !== "__min"
) {
providerName = state.providers[provider][region]["providerName"];
break;
}
}
$("#compute-provider").append(
``
);
}
}
$("#compute-provider").append(
``
);
setRegions(prov);
};
(async function ($) {
"use strict"; // Start of use strict
// Smooth scrolling using jQuery easing
$('a.js-scroll-trigger[href*="#"]:not([href="#"])').click(function () {
if (
location.pathname.replace(/^\//, "") ==
this.pathname.replace(/^\//, "") &&
location.hostname == this.hostname
) {
var target = $(this.hash);
target = target.length ? target : $("[name=" + this.hash.slice(1) + "]");
if (target.length) {
$("html, body").animate(
{
scrollTop: target.offset().top - 70,
},
1000,
"easeInOutExpo"
);
let w = window.location.pathname;
if (w[w.length - 1] !== "/") w += "/";
window.history.pushState("", "", w + this.hash);
return false;
}
}
});
// Closes responsive menu when a scroll trigger link is clicked
$(".js-scroll-trigger").click(function () {
$(".navbar-collapse").collapse("hide");
});
// // Activate scrollspy to add active class to navbar items on scroll
// $('body').scrollspy({
// target: '#mainNav',
// offset: 100
// });
// $('[data-spy="scroll"]').on('activate.bs.scrollspy', function () {
// console.log(this);
// })
// lazy load resources as images and iframes
const observer = lozad();
observer.observe();
// Collapse Navbar
var navbarCollapse = function () {
if ($("#mainNav").offset().top > 100) {
$("#mainNav").addClass("navbar-shrink");
} else {
$("#mainNav").removeClass("navbar-shrink");
}
};
// Collapse now if page is not at top
navbarCollapse();
// Collapse the navbar when page is scrolled
$(window).scroll(navbarCollapse);
state = await getData();
$("#compute-loader").fadeOut(() => {
$("#compute-container").fadeIn();
});
setInputs();
setImports(serveFrom, "a", "href");
setImports(serveFrom, "img", "src");
// $('select').selectize();
$("#compute-provider").change((e) => {
const provider = $("#compute-provider option:selected").val();
setRegions(provider);
});
$("#compute-form").submit((e) => {
submitCompute();
return false;
});
$(".details-summary").each((i, el) => {
if (i % 2 == 0 || $(window).width() < 770) {
const arrowTemplate = `
`;
$(el).append($(arrowTemplate));
} else {
const arrowTemplate = `
`;
$(el).css("justify-content", "flex-end");
$(el).prepend($(arrowTemplate));
}
});
growDivOnArrowClickLearn(`.details-summary`, `.summary-content`);
growDivOnArrowClick("#details-banner", "#details-content");
// $("#details-featured-maps").click()
// const response = await fetch("https://api.co2signal.com/v1/latest?lon=6.8770394&lat=45.9162776", {
// credentials: "include",
// headers: {
// 'Content-Type': 'application/jsonp',
// 'auth-token': 'c5f38468eddd9edb'
// }
// })
// console.log({ response });
$("#copy-template-btn").click(() => {
selectAndCopyText("template-code");
$("#copy-template-feedback").fadeIn(() => {
setTimeout(() => {
$("#copy-template-feedback").fadeOut();
}, 1000);
});
});
// const response = await fetch("https://api.co2signal.com/v1/latest?lon=6.8770394&lat=45.9162776", {
// credentials: "include",
// headers: {
// 'Content-Type': 'application/jsonp',
// 'auth-token': 'c5f38468eddd9edb'
// }
// })
// console.log({ response });
})(jQuery); // End of use strict