Browse Source

Allow cooling spikes + better display for midnight

- Today, when cooling from ~31*C to ~29*C, the spike algorithm wound up
  excluding all temperatures after a certain time.
  - The approach to allow larger spikes when cooling isn't perfect, but
    is working well enough for right now.
- The date/time text, `2022-05-15 00:00` winds up squishing the graphs,
  making them too short to see anything useful. Changing it to just
  `2022-05-15` so the date is still available, but it's not quite as
  tall.
Jason Tarka 3 years ago
parent
commit
7d18eb165e

+ 19 - 0
web-view/src/js/cleanData.test.ts

@@ -112,5 +112,24 @@ describe('Clean data', () => {
 			const actual = removeSpikes(input);
 			should(actual).deepEqual(expected);
 		});
+
+		it('Allows cooling spikes at night', () => {
+			// Test that it allows "spikes" when temperature drops, such
+			// as in the summer when the sun starts setting.
+
+			// Nothing should be removed from the list.
+			const input = [
+				{ time: 1, value: 32.6 },
+				{ time: 2, value: 32.3 },
+				{ time: 3, value: 32.1 },
+				{ time: 4, value: 29.54 }, // Large-ish spike
+				{ time: 5, value: 28.73 },
+				{ time: 6, value: 28.13 },
+				{ time: 7, value: 27.53 },
+			];
+
+			const actual = removeSpikes(input);
+			should(actual).deepEqual(input);
+		})
 	});
 });

+ 6 - 1
web-view/src/js/cleanData.ts

@@ -82,6 +82,8 @@ function average(nums:number[], decimalPlaces:number = 1):number {
 
 /**
  * Remove elements that are particularly "spiky" compared to the ones next to them.
+ * Since the main concern is about the device heating up from multiple retries, a
+ * cooling "spike" can be a lot larger before it gets excluded.
  *
  * @param data: The data to remove spikes from, where each object contains a
  *              data field specified in `dataField`.
@@ -89,6 +91,7 @@ function average(nums:number[], decimalPlaces:number = 1):number {
  *                   it's considered a spike. eg: a difference of 0.1 is 10x an
  *                   earlier diff of 0.01, but isn't a spike. A `minChange` of
  *                   2 would ignore this.
+*                    Double this value is used when cooling.
  * @param minDiffMultiple: The minimum multiplier of differences between sibling
  *                         elements before it's considered a spike. eg: The
  *                         previous diff was 1.5*C, current diff is 3.8*C, this
@@ -120,8 +123,10 @@ export function removeSpikes(
 			prevDiff = Math.abs(data[i + 1].value - data[i + 2].value);
 			thisDiff = Math.abs(data[i].value - data[i + 1].value);
 		}
+		const isCooling = i > 0 && data[i].value < data[i - 1].value;
+		const minChangeToUse = isCooling ? minChange * 2 : minChange;
 
-		const tooBig = (thisDiff - prevDiff) > minChange
+		const tooBig = (thisDiff - prevDiff) > minChangeToUse
 					&& (thisDiff / prevDiff) > minDiffMultiple;
 		if(tooBig) {
 			console.log(`Removing spike element ${formatTime(data[i].time)}: Value: ${data[i].value}; prevDiff: ${prevDiff}; thisDiff: ${thisDiff}`);

+ 2 - 2
web-view/src/js/utils.test.ts

@@ -15,10 +15,10 @@ describe('Utils', () => {
 				expected: '23:24' // Assumes EST timezone
 			}, {
 				input: new Date(2022, 1, 2, 0, 0),
-				expected: '2022-01-02 00:00'
+				expected: '2022-01-02'
 			}, {
 				input: new Date(2022, 10, 12, 0, 0),
-				expected: '2022-10-12 00:00'
+				expected: '2022-10-12'
 			},
 		].forEach(data => it(`Formats ${data.input} to ${data.expected}`, () => {
 			const actual = formatTime(data.input);

+ 1 - 1
web-view/src/js/utils.ts

@@ -11,7 +11,7 @@ export function formatTime(date:Date|number):string {
 
 	let time = `${pad(date.getHours())}:${pad(date.getMinutes())}`;
 	return time === '00:00'
-		? `${date.getFullYear()}-${pad(date.getMonth())}-${pad(date.getDate())} ${time}`
+		? `${date.getFullYear()}-${pad(date.getMonth())}-${pad(date.getDate())}`
 		: time;
 
 	function pad(num:number):string {