Skip to content

Commit 7b4eaf2

Browse files
author
DanielRyanSmith
committed
move calculateColor to utils file
1 parent ba63939 commit 7b4eaf2

File tree

4 files changed

+111
-77
lines changed

4 files changed

+111
-77
lines changed

webapp/components/interop-dashboard.js

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { InteropDataManager } from './interop-data-manager.js';
88
import { WPTFlags } from './wpt-flags.js';
9+
import { calculateColor } from './utils.js';
910
import '../node_modules/@polymer/paper-button/paper-button.js';
1011
import '../node_modules/@polymer/polymer/lib/elements/dom-if.js';
1112
import '../node_modules/@polymer/paper-icon-button/paper-icon-button.js';
@@ -768,58 +769,17 @@ class InteropDashboard extends WPTFlags(PolymerElement) {
768769
afterNextRender(this, this.addSortEvents);
769770
}
770771

771-
/**
772-
* Generates a font and background color based on a score from 0 to 100.
773-
* The colors are calculated on a gradient from red to green.
774-
*
775-
* @param {number} score - The score, ranging from 0 to 100.
776-
* @returns {[string, string]} An array containing the font color as an RGB
777-
* string and the background color as an RGBA string with 15% opacity.
778-
*/
779-
calculateColor(score) {
780-
const gradient = [
781-
// Red.
782-
{ scale: 0, color: [250, 0, 0] },
783-
// Orange.
784-
{ scale: 33.33, color: [250, 125, 0] },
785-
// Yellow.
786-
{ scale: 66.67, color: [220, 220, 0] },
787-
// Green.
788-
{ scale: 100, color: [0, 160, 0] },
789-
];
790-
791-
let color1, color2;
792-
for (let i = 1; i < gradient.length; i++) {
793-
if (score <= gradient[i].scale) {
794-
color1 = gradient[i - 1];
795-
color2 = gradient[i];
796-
break;
797-
}
798-
}
799-
const colorWeight = ((score - color1.scale) / (color2.scale - color1.scale));
800-
const color = [
801-
Math.round(color1.color[0] * (1 - colorWeight) + color2.color[0] * colorWeight),
802-
Math.round(color1.color[1] * (1 - colorWeight) + color2.color[1] * colorWeight),
803-
Math.round(color1.color[2] * (1 - colorWeight) + color2.color[2] * colorWeight),
804-
];
805-
806-
return [
807-
`rgb(${color[0]}, ${color[1]}, ${color[2]})`,
808-
`rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.15)`,
809-
];
810-
}
811-
812772
getSubtotalScoreStyle(section, isStable) {
813773
const interopIndex = this.dataManager.getYearProp('numBrowsers');
814774
const score = this.getNumericalSubtotalScore(interopIndex, section, isStable);
815-
const colors = this.calculateColor(score);
775+
const colors = calculateColor(score);
816776
return `color: color-mix(in lch, ${colors[0]} 70%, black); background-color: ${colors[1]}`;
817777
}
818778

819779
getScoreStyle(feature, isStable) {
820780
const interopIndex = this.dataManager.getYearProp('numBrowsers');
821781
const score = this.getNumericalBrowserScoreByFeature(interopIndex, feature, isStable);
822-
const colors = this.calculateColor(score);
782+
const colors = calculateColor(score);
823783
return `color: color-mix(in lch, ${colors[0]} 70%, black); background-color: ${colors[1]}`;
824784
}
825785

webapp/components/interop-summary.js

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* found in the LICENSE file.
55
*/
66

7+
import { calculateColor } from './utils.js';
78
import { CountUp } from '../node_modules/countup.js/dist/countUp.js';
89
import '../node_modules/@polymer/polymer/lib/elements/dom-if.js';
910
import { html, PolymerElement } from '../node_modules/@polymer/polymer/polymer-element.js';
@@ -272,7 +273,7 @@ class InteropSummary extends PolymerElement {
272273
new CountUp(number, score, {
273274
startVal: curScore === '--' ? 0 : curScore
274275
}).start();
275-
const colors = this.calculateColor(score);
276+
const colors = calculateColor(score);
276277
number.style.color = `color-mix(in lch, ${colors[0]} 70%, black)`;
277278
number.style.backgroundColor = colors[1];
278279
}
@@ -336,38 +337,5 @@ class InteropSummary extends PolymerElement {
336337
getBrowserNameParts(browserInfo) {
337338
return [browserInfo.tableName, ...browserInfo.experimentalName.split(' ')];
338339
}
339-
340-
calculateColor(score) {
341-
const gradient = [
342-
// Red.
343-
{ scale: 0, color: [250, 0, 0] },
344-
// Orange.
345-
{ scale: 33.33, color: [250, 125, 0] },
346-
// Yellow.
347-
{ scale: 66.67, color: [220, 220, 0] },
348-
// Green.
349-
{ scale: 100, color: [0, 160, 0] },
350-
];
351-
352-
let color1, color2;
353-
for (let i = 1; i < gradient.length; i++) {
354-
if (score <= gradient[i].scale) {
355-
color1 = gradient[i - 1];
356-
color2 = gradient[i];
357-
break;
358-
}
359-
}
360-
const colorWeight = ((score - color1.scale) / (color2.scale - color1.scale));
361-
const color = [
362-
Math.round(color1.color[0] * (1 - colorWeight) + color2.color[0] * colorWeight),
363-
Math.round(color1.color[1] * (1 - colorWeight) + color2.color[1] * colorWeight),
364-
Math.round(color1.color[2] * (1 - colorWeight) + color2.color[2] * colorWeight),
365-
];
366-
367-
return [
368-
`rgb(${color[0]}, ${color[1]}, ${color[2]})`,
369-
`rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.15)`,
370-
];
371-
}
372340
}
373341
export { InteropSummary };
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<script src="https://unpkg.com/@webcomponents/[email protected]/webcomponents-loader.js"></script>
6+
<script src="https://unpkg.com/[email protected]/browser.js"></script>
7+
</head>
8+
9+
<body>
10+
<script type="module">
11+
import { calculateColor } from '../utils.js';
12+
13+
suite('calculateColor', () => {
14+
test('should return pure red for a score of 0', () => {
15+
const expected = ['rgb(250, 0, 0)', 'rgba(250, 0, 0, 0.15)'];
16+
assert.deepEqual(calculateColor(0), expected);
17+
});
18+
19+
test('should return pure green for a score of 100', () => {
20+
const expected = ['rgb(0, 160, 0)', 'rgba(0, 160, 0, 0.15)'];
21+
assert.deepEqual(calculateColor(100), expected);
22+
});
23+
24+
test('should return the exact color for a gradient stop (Orange)', () => {
25+
const expected = ['rgb(250, 125, 0)', 'rgba(250, 125, 0, 0.15)'];
26+
assert.deepEqual(calculateColor(33.33), expected);
27+
});
28+
29+
test('should return the exact color for a gradient stop (Yellow)', () => {
30+
const expected = ['rgb(220, 220, 0)', 'rgba(220, 220, 0, 0.15)'];
31+
assert.deepEqual(calculateColor(66.67), expected);
32+
});
33+
34+
test('should return a color halfway between red and orange', () => {
35+
// Midpoint score: (0 + 33.33) / 2 = 16.665
36+
// Red component: round(250 * 0.5 + 250 * 0.5) = 250
37+
// Green component: round(0 * 0.5 + 125 * 0.5) = 63
38+
// Blue component: round(0 * 0.5 + 0 * 0.5) = 0
39+
const expected = ['rgb(250, 63, 0)', 'rgba(250, 63, 0, 0.15)'];
40+
assert.deepEqual(calculateColor(16.665), expected);
41+
});
42+
43+
test('should return a color at an arbitrary point between orange and yellow', () => {
44+
// weight = (50 - 33.33) / (66.67 - 33.33) = 16.67 / 33.34 ≈ 0.5
45+
// Let w = 16.67 / 33.34
46+
// R = round(250 * (1-w) + 220 * w) = round(125.025 + 109.989) = 235
47+
// G = round(125 * (1-w) + 220 * w) = round(62.5125 + 109.989) = 173
48+
// B = round(0 * (1-w) + 0 * w) = 0
49+
const expected = ['rgb(235, 173, 0)', 'rgba(235, 173, 0, 0.15)'];
50+
assert.deepEqual(calculateColor(50), expected);
51+
});
52+
53+
test('should return a color halfway between yellow and green', () => {
54+
// Midpoint score: (66.67 + 100) / 2 = 83.335
55+
// R: round(220 * 0.5 + 0 * 0.5) = 110
56+
// G: round(220 * 0.5 + 160 * 0.5) = 190
57+
// B: round(0 * 0.5 + 0 * 0.5) = 0
58+
const expected = ['rgb(110, 190, 0)', 'rgba(110, 190, 0, 0.15)'];
59+
assert.deepEqual(calculateColor(83.335), expected);
60+
});
61+
});
62+
</script>
63+
</body>
64+
</html>

webapp/components/utils.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,46 @@ function timeTaken(millis) {
2020
return `${s} seconds`;
2121
}
2222

23+
/**
24+
* Generates a font and background color for percentages on the Interop
25+
* dashboardbased on a score from 0 to 100. The colors are calculated on a
26+
* gradient from red to green.
27+
*
28+
* @param {number} score - The score, ranging from 0 to 100.
29+
* @returns {[string, string]} An array containing the font color as an RGB
30+
* string and the background color as an RGBA string with 15% opacity.
31+
*/
32+
export function calculateColor(score) {
33+
const gradient = [
34+
// Red.
35+
{ scale: 0, color: [250, 0, 0] },
36+
// Orange.
37+
{ scale: 33.33, color: [250, 125, 0] },
38+
// Yellow.
39+
{ scale: 66.67, color: [220, 220, 0] },
40+
// Green.
41+
{ scale: 100, color: [0, 160, 0] },
42+
];
43+
44+
let color1, color2;
45+
for (let i = 1; i < gradient.length; i++) {
46+
if (score <= gradient[i].scale) {
47+
color1 = gradient[i - 1];
48+
color2 = gradient[i];
49+
break;
50+
}
51+
}
52+
const colorWeight = ((score - color1.scale) / (color2.scale - color1.scale));
53+
const color = [
54+
Math.round(color1.color[0] * (1 - colorWeight) + color2.color[0] * colorWeight),
55+
Math.round(color1.color[1] * (1 - colorWeight) + color2.color[1] * colorWeight),
56+
Math.round(color1.color[2] * (1 - colorWeight) + color2.color[2] * colorWeight),
57+
];
58+
59+
return [
60+
`rgb(${color[0]}, ${color[1]}, ${color[2]})`,
61+
`rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.15)`,
62+
];
63+
}
64+
2365
export { timeTaken };

0 commit comments

Comments
 (0)