@tgwf/co2 0.7.0 → 0.8.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.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
  ## Unreleased
10
10
 
11
11
  - Include a new alternative, "Green Byte Model" with the figures after speaking to folks at the IEA and other places.
12
+
13
+ # [0.8.0] - 2021-11-28
14
+
15
+ ### Fixed
16
+
17
+ - Update further dependencies
18
+ - Fix embarassing order of magnitude typo in 1byte model (thanks @mstaschik!)
19
+
20
+ ## Added
21
+
22
+ - Read JSON blob also as gzipped #44 (thanks @soulgalore)
23
+
24
+ ### Changed
25
+
26
+ - The 1bye model will give different numbers now. It's mentioned in `#fixed` but it's worth repeating.
27
+
12
28
  ## [0.7.0] - 2021-11-28
13
29
 
14
30
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tgwf/co2",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Work out the co2 of your digital services",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/1byte.js CHANGED
@@ -9,16 +9,25 @@ const CO2_PER_KWH_IN_DC_GREY = 519;
9
9
 
10
10
  // The device usage figure combines figures for:
11
11
  // 1. the usage for devices (which is small proportion of the energy use)
12
- // 2. the *making* the device, which is comparitively high.
12
+ // 2. the *making* the device, which is comparatively high.
13
13
 
14
- const KWH_PER_BYTE_IN_DC = 0.00000000072;
14
+ const KWH_PER_BYTE_IN_DC = 7.2e-11;
15
15
 
16
16
  // this is probably best left as something users can define, or
17
17
  // a weighted average based on total usage.
18
+ // Using a simple mean for now, as while web traffic to end users might trend
19
+ // towards wifi and mobile,
20
+ // Web traffic between servers is likely wired networks
21
+
22
+ const FIXED_NETWORK_WIRED = 4.29e-10;
23
+ const FIXED_NETWORK_WIFI = 1.52e-10;
24
+ const FOUR_G_MOBILE = 8.84e-10;
25
+
18
26
  // Pull requests gratefully accepted
19
- const KWH_PER_BYTE_FOR_NETWORK = 0.00000000488;
27
+ const KWH_PER_BYTE_FOR_NETWORK =
28
+ (FIXED_NETWORK_WIRED + FIXED_NETWORK_WIFI + FOUR_G_MOBILE) / 3;
20
29
 
21
- const KWH_PER_BYTE_FOR_DEVICES = 0.00000000013;
30
+ const KWH_PER_BYTE_FOR_DEVICES = 1.3e-10;
22
31
  module.exports = {
23
32
  KWH_PER_BYTE_IN_DC,
24
33
  KWH_PER_BYTE_FOR_NETWORK,
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ const oneByte = require("./1byte");
4
+
5
+ describe("onebyte", function () {
6
+ describe("perByte", function () {
7
+ it.only("returns a simple average of the different networks", function () {
8
+ // we limit this to 12 figures with toFixed(12), because
9
+ // we have a recurring 333333 afterwards
10
+ // 4.88e-10 is the same as 0.000000000488
11
+ const expected_val = (0.000000000488).toFixed(12);
12
+
13
+ expect(oneByte.KWH_PER_BYTE_FOR_NETWORK.toFixed(12)).toBe(expected_val);
14
+ });
15
+ });
16
+ });
package/src/co2.test.js CHANGED
@@ -8,13 +8,13 @@ const pagexray = require("pagexray");
8
8
 
9
9
  describe("co2", function () {
10
10
  let har, co2;
11
- const TGWF_GREY_VALUE = 2.0484539712;
12
- const TGWF_GREEN_VALUE = 0.54704300112;
13
- const TGWF_MIXED_VALUE = 1.6706517455999996;
11
+ const TGWF_GREY_VALUE = 0.20497;
12
+ const TGWF_GREEN_VALUE = 0.54704;
13
+ const TGWF_MIXED_VALUE = 0.16718;
14
14
 
15
15
  const MILLION = 1000000;
16
- const MILLION_GREY = 2.9064;
17
- const MILLION_GREEN = 2.318;
16
+ const MILLION_GREY = 0.29081;
17
+ const MILLION_GREEN = 0.23196;
18
18
 
19
19
  beforeEach(function () {
20
20
  co2 = new CO2();
@@ -28,12 +28,18 @@ describe("co2", function () {
28
28
 
29
29
  describe("perByte", function () {
30
30
  it("returns a CO2 number for data transfer using 'grey' power", function () {
31
- expect(co2.perByte(MILLION)).toBe(MILLION_GREY);
31
+ expect(co2.perByte(MILLION).toPrecision(5)).toBe(
32
+ MILLION_GREY.toPrecision(5)
33
+ );
32
34
  });
33
35
 
34
36
  it("returns a lower CO2 number for data transfer from domains using entirely 'green' power", function () {
35
- expect(co2.perByte(MILLION, false)).toBe(MILLION_GREY);
36
- expect(co2.perByte(MILLION, true)).toBe(MILLION_GREEN);
37
+ expect(co2.perByte(MILLION, false).toPrecision(5)).toBe(
38
+ MILLION_GREY.toPrecision(5)
39
+ );
40
+ expect(co2.perByte(MILLION, true).toPrecision(5)).toBe(
41
+ MILLION_GREEN.toPrecision(5)
42
+ );
37
43
  });
38
44
  });
39
45
 
@@ -42,7 +48,9 @@ describe("co2", function () {
42
48
  const pages = pagexray.convert(har);
43
49
  const pageXrayRun = pages[0];
44
50
 
45
- expect(co2.perPage(pageXrayRun)).toBe(TGWF_GREY_VALUE);
51
+ expect(co2.perPage(pageXrayRun).toPrecision(5)).toBe(
52
+ TGWF_GREY_VALUE.toPrecision(5)
53
+ );
46
54
  });
47
55
  it("returns lower CO2 for page served from green site", function () {
48
56
  const pages = pagexray.convert(har);
@@ -75,7 +83,9 @@ describe("co2", function () {
75
83
  "fonts.gstatic.com",
76
84
  "api.thegreenwebfoundation.org",
77
85
  ];
78
- expect(co2.perPage(pageXrayRun, green)).toBe(TGWF_MIXED_VALUE);
86
+ expect(co2.perPage(pageXrayRun, green).toPrecision(5)).toBe(
87
+ TGWF_MIXED_VALUE.toPrecision(5)
88
+ );
79
89
  });
80
90
  });
81
91
  describe("perDomain", function () {
@@ -3,11 +3,31 @@
3
3
  const log = require("debug")("tgwf:hostingCache");
4
4
  const path = require("path");
5
5
  const fs = require("fs");
6
+ const zlib = require("zlib");
6
7
  const { promisify } = require("util");
7
8
  const readFile = promisify(fs.readFile);
9
+ const gunzip = promisify(zlib.gunzip);
10
+
11
+ async function streamToString(stream) {
12
+ return new Promise((resolve, reject) => {
13
+ const chunks = [];
14
+ stream.on("error", reject);
15
+ stream.on("data", (chunk) => chunks.push(chunk));
16
+ stream.on("end", () => resolve(Buffer.concat(chunks)));
17
+ });
18
+ }
19
+
20
+ async function getGzippedFileAsJson(jsonPath) {
21
+ const readStream = fs.createReadStream(jsonPath);
22
+ const text = await streamToString(readStream);
23
+ const unzipped = await gunzip(text);
24
+ return unzipped.toString();
25
+ }
8
26
 
9
27
  async function loadJSON(jsonPath) {
10
- const jsonBuffer = await readFile(jsonPath);
28
+ const jsonBuffer = jsonPath.endsWith(".gz")
29
+ ? await getGzippedFileAsJson(jsonPath)
30
+ : await readFile(jsonPath);
11
31
  return JSON.parse(jsonBuffer);
12
32
  }
13
33
 
@@ -11,7 +11,13 @@ describe("hostingJSON", function () {
11
11
  "fixtures",
12
12
  "url2green.test.json"
13
13
  );
14
-
14
+ const jsonPathGz = path.resolve(
15
+ __dirname,
16
+ "..",
17
+ "data",
18
+ "fixtures",
19
+ "url2green.test.json.gz"
20
+ );
15
21
  describe("checking a single domain with #check", function () {
16
22
  test("against the list of domains as JSON", async function () {
17
23
  const db = await hosting.loadJSON(jsonPath);
@@ -19,6 +25,13 @@ describe("hostingJSON", function () {
19
25
  expect(res).toEqual(true);
20
26
  });
21
27
  });
28
+ describe("checking a single domain with #check", function () {
29
+ test("against the list of domains as JSON loaded from a gzipped JSON", async function () {
30
+ const db = await hosting.loadJSON(jsonPathGz);
31
+ const res = await hosting.check("google.com", db);
32
+ expect(res).toEqual(true);
33
+ });
34
+ });
22
35
  describe("implicitly checking multiple domains with #check", function () {
23
36
  test("against the list of domains as JSON", async function () {
24
37
  const db = await hosting.loadJSON(jsonPath);