Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add sustainable web design model #58

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"main": "src/index.js",
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"travis": "npm run lint && jest"
Expand Down
5 changes: 5 additions & 0 deletions src/constants/file-size.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const GIGABYTE = 1024 * 1024 * 1024;

module.exports = {
GIGABYTE,
};
3 changes: 3 additions & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const fileSize = require("./file-size");

module.exports = { fileSize };
5 changes: 5 additions & 0 deletions src/helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const formatNumber = (num) => parseFloat(num.toFixed(2));

module.exports = {
formatNumber,
};
66 changes: 66 additions & 0 deletions src/sustainable-web-design.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use strict";

/**
* Sustainable Web Design
*
* Newly update calculations and figures from
* https://sustainablewebdesign.org/calculating-digital-emissions/
*
*
*/
const { fileSize } = require("./constants");
const { formatNumber } = require("./helpers");

// Taken from: https://sustainablewebdesign.org/calculating-digital-emissions/#:~:text=TWh/EB%20or-,0.81%20kWH/GB,-Carbon%20factor%20(global
const KWH_PER_GB = 0.81;
drydenwilliams marked this conversation as resolved.
Show resolved Hide resolved
// Taken from: https://www.iea.org/reports/renewables-2021
const GLOBAL_INTENSITY = 440;
// Taken from: https://gitlab.com/wholegrain/carbon-api-2-0/-/blob/master/includes/carbonapi.php
const FIRST_TIME_VIEWING_PERCENTAGE = 0.25;
const RETURNING_VISITOR_PERCENTAGE = 0.75;
const PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD = 0.02;
// Taken from: https://sustainablewebdesign.org/calculating-digital-emissions/#:~:text=Consumer%20device%20energy%20%3D%20AE%20x%200.52
const END_USER_DEVICE_ENERGY = 0.52;

class SustainableWebDesign {
constructor(options) {
this.options = options;
}

energyPerVisit(bytes) {
const transferedBytesToGb = bytes / fileSize.GIGABYTE;

const newVisitorEnergy =
transferedBytesToGb * KWH_PER_GB * FIRST_TIME_VIEWING_PERCENTAGE;
const returningVisitorEnergy =
transferedBytesToGb *
KWH_PER_GB *
RETURNING_VISITOR_PERCENTAGE *
PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD;

return newVisitorEnergy + returningVisitorEnergy;
}

emissionsPerVisitInGrams(energyPerVisit, globalIntensity = GLOBAL_INTENSITY) {
return formatNumber(energyPerVisit * globalIntensity);
}

annualEnergyInKwh(energyPerVisit, monthlyVisitors = 1000) {
return energyPerVisit * monthlyVisitors * 12;
}

annualEmissionsInGrams(co2grams, monthlyVisitors = 1000) {
return co2grams * monthlyVisitors * 12;
}

annualSegmentEnergy(annualEnergy) {
return {
consumerDeviceEnergy: formatNumber(annualEnergy * END_USER_DEVICE_ENERGY),
networkEnergy: formatNumber(annualEnergy * 0.14),
dataCenterEnergy: formatNumber(annualEnergy * 0.15),
productionEnergy: formatNumber(annualEnergy * 0.19),
};
}
}

module.exports = SustainableWebDesign;
57 changes: 57 additions & 0 deletions src/sustainable-web-design.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const fs = require("fs");
const path = require("path");
const SustainableWebDesign = require("./sustainable-web-design");

describe("sustainable web design model", () => {
const swd = new SustainableWebDesign();
const averageWebsiteInBytes = 2257715.2;

describe("energyPerVisit", function () {
it("should return a number", () => {
expect(typeof swd.energyPerVisit(2257715.2)).toBe("number");
});

it("should calculate the correct energy", () => {
expect(swd.energyPerVisit(2257715.2)).toBe(0.0004513362121582032);
});
});

describe("emissionsPerVisitInGrams", function () {
it("should calculate the correct co2 per visit", () => {
const averageWebsiteInBytes = 2257715.2;
const energy = swd.energyPerVisit(averageWebsiteInBytes);
expect(swd.emissionsPerVisitInGrams(energy)).toEqual(0.2);
});

it("should accept a dynamic KwH value", () => {
const averageWebsiteInBytes = 2257715.2;
const energy = swd.energyPerVisit(averageWebsiteInBytes);
expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.11);
});
});

describe("annualEnergyInKwh", function () {
it("should calculate the correct energy in kWh", () => {
expect(swd.annualEnergyInKwh(averageWebsiteInBytes)).toBe(27092582400);
});
});

describe("annualEmissionsInGrams", function () {
it("should calculate the corrent energy in grams", () => {
expect(swd.annualEmissionsInGrams(averageWebsiteInBytes)).toBe(
27092582400
);
});
});

describe("annualSegmentEnergy", function () {
it("should return the correct values", () => {
expect(swd.annualSegmentEnergy(averageWebsiteInBytes)).toEqual({
consumerDeviceEnergy: 1174011.9,
dataCenterEnergy: 338657.28,
networkEnergy: 316080.13,
productionEnergy: 428965.89,
});
});
});
});
Loading