From 64db679399d9e1afefb6404652daf18e3f75eae0 Mon Sep 17 00:00:00 2001 From: Jonah <47046556+jonahb55@users.noreply.github.com> Date: Fri, 17 Feb 2023 17:05:38 -0500 Subject: [PATCH 1/3] Improve performance of field list updates --- src/hub/Sidebar.ts | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/hub/Sidebar.ts b/src/hub/Sidebar.ts index b6784a7f..461d4533 100644 --- a/src/hub/Sidebar.ts +++ b/src/hub/Sidebar.ts @@ -255,7 +255,9 @@ export default class Sidebar { childSpan.style.setProperty("--indent", (indent + this.INDENT_SIZE_PX).toString() + "px"); childSpan.hidden = true; + let firstExpand = true; let setExpanded = (expanded: boolean) => { + // Update icon and span display childSpan.hidden = !expanded; closedIcon.style.display = expanded ? "none" : "initial"; openIcon.style.display = expanded ? "initial" : "none"; @@ -264,24 +266,28 @@ export default class Sidebar { } else { this.expandedFields.delete(fullTitle); } + + // Add children if first time + if (firstExpand) { + firstExpand = false; + let childKeys = Object.keys(field.children); + if (fullTitle == "/AdvantageKit") { + // Apply hidden and known keys + childKeys = childKeys + .filter((key) => !this.HIDDEN_KEYS.includes(key)) + .sort((a, b) => this.sortKeys(a, b, true)); + } else { + childKeys = childKeys.sort((a, b) => this.sortKeys(a, b)); + } + childKeys.forEach((key) => { + this.addFields(key, fullTitle + "/" + key, field.children[key], childSpan, indent + this.INDENT_SIZE_PX); + }); + } }; closedIcon.addEventListener("click", () => setExpanded(true)); openIcon.addEventListener("click", () => setExpanded(false)); if (this.expandedFields.has(fullTitle)) setExpanded(true); - - let childKeys = Object.keys(field.children); - if (fullTitle == "/AdvantageKit") { - // Apply hidden and known keys - childKeys = childKeys - .filter((key) => !this.HIDDEN_KEYS.includes(key)) - .sort((a, b) => this.sortKeys(a, b, true)); - } else { - childKeys = childKeys.sort((a, b) => this.sortKeys(a, b)); - } - childKeys.forEach((key) => { - this.addFields(key, fullTitle + "/" + key, field.children[key], childSpan, indent + this.INDENT_SIZE_PX); - }); } } From ac3720b9f80e8968b8450ed2d836bb5840bfa76e Mon Sep 17 00:00:00 2001 From: Jonah <47046556+jonahb55@users.noreply.github.com> Date: Fri, 17 Feb 2023 17:53:30 -0500 Subject: [PATCH 2/3] Add limits for extreme line graph values --- src/hub/tabControllers/LineGraphController.ts | 63 +++++++++++++++---- src/shared/log/LogField.ts | 2 + src/shared/util.ts | 5 ++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/hub/tabControllers/LineGraphController.ts b/src/hub/tabControllers/LineGraphController.ts index c4eb92a9..8266422a 100644 --- a/src/hub/tabControllers/LineGraphController.ts +++ b/src/hub/tabControllers/LineGraphController.ts @@ -1,11 +1,11 @@ import { AllColors } from "../../shared/Colors"; +import { LineGraphState } from "../../shared/HubState"; import LoggableType from "../../shared/log/LoggableType"; import { getLogValueText } from "../../shared/log/LogUtil"; import { LogValueSetAny, LogValueSetNumber } from "../../shared/log/LogValueSets"; import TabType from "../../shared/TabType"; import { convertWithPreset, UnitConversionPreset } from "../../shared/units"; -import { cleanFloat, scaleValue, shiftColor } from "../../shared/util"; -import { LineGraphState } from "../../shared/HubState"; +import { clampValue, cleanFloat, scaleValue, shiftColor } from "../../shared/util"; import ScrollSensor from "../ScrollSensor"; import { SelectionMode } from "../Selection"; import TabController from "../TabController"; @@ -13,6 +13,9 @@ import TabController from "../TabController"; export default class LineGraphController implements TabController { private MIN_ZOOM_TIME = 0.05; private ZOOM_BASE = 1.001; + private MIN_AXIS_RANGE = 1e-5; + private MAX_AXIS_RANGE = 1e9; + private MAX_VALUE = 1e9; private CONTENT: HTMLElement; private LEGEND_ITEM_TEMPLATE: HTMLElement; @@ -555,12 +558,38 @@ export default class LineGraphController implements TabController { if (lockedRange != null) { targetRange = lockedRange; } else if (valueRange != null && marginProportion != null) { - let margin = (valueRange[1] - valueRange[0]) * marginProportion; - targetRange = [valueRange[0] - margin, valueRange[1] + margin]; - if (targetRange[0] == targetRange[1]) { - targetRange[0]--; - targetRange[1]++; + // Apply extreme limits + let adjustedValueRange = [...valueRange]; + if (adjustedValueRange[0] > this.MAX_VALUE) { + adjustedValueRange[0] = this.MAX_VALUE; + } + if (adjustedValueRange[1] > this.MAX_VALUE) { + adjustedValueRange[1] = this.MAX_VALUE; + } + if (adjustedValueRange[0] < -this.MAX_VALUE) { + adjustedValueRange[0] = -this.MAX_VALUE; } + if (adjustedValueRange[1] < -this.MAX_VALUE) { + adjustedValueRange[1] = -this.MAX_VALUE; + } + if (adjustedValueRange[0] == adjustedValueRange[1]) { + adjustedValueRange[0]--; + adjustedValueRange[1]++; + } + if (adjustedValueRange[1] - adjustedValueRange[0] > this.MAX_AXIS_RANGE) { + if (adjustedValueRange[0] + this.MAX_AXIS_RANGE < this.MAX_VALUE) { + adjustedValueRange[1] = adjustedValueRange[0] + this.MAX_AXIS_RANGE; + } else { + adjustedValueRange[0] = adjustedValueRange[1] - this.MAX_AXIS_RANGE; + } + } + if (adjustedValueRange[1] - adjustedValueRange[0] < this.MIN_AXIS_RANGE) { + adjustedValueRange[1] = adjustedValueRange[0] + this.MIN_AXIS_RANGE; + } + + // Calculate target range with margin + let margin = (adjustedValueRange[1] - adjustedValueRange[0]) * marginProportion; + targetRange = [adjustedValueRange[0] - margin, adjustedValueRange[1] + margin]; } // How many steps? @@ -836,7 +865,11 @@ export default class LineGraphController implements TabController { context.moveTo( graphLeft + graphWidth, scaleValue( - convertWithPreset(data.values[data.values.length - 1], unitConversion), + clampValue( + convertWithPreset(data.values[data.values.length - 1], unitConversion), + -this.MAX_VALUE, + this.MAX_VALUE + ), [axis.min, axis.max], [graphTop + graphHeightOpen, graphTop] ) @@ -848,7 +881,11 @@ export default class LineGraphController implements TabController { let x = scaleValue(data.timestamps[i], this.timestampRange, [graphLeft, graphLeft + graphWidth]); // Render start of current data point - let convertedValue = convertWithPreset(data.values[i], unitConversion); + let convertedValue = clampValue( + convertWithPreset(data.values[i], unitConversion), + -this.MAX_VALUE, + this.MAX_VALUE + ); context.lineTo(x, scaleValue(convertedValue, [axis.min, axis.max], [graphTop + graphHeightOpen, graphTop])); // Find previous data point and vertical range @@ -857,7 +894,11 @@ export default class LineGraphController implements TabController { let vertRange = [convertedValue, convertedValue]; do { i--; - let convertedValue = convertWithPreset(data.values[i], unitConversion); + let convertedValue = clampValue( + convertWithPreset(data.values[i], unitConversion), + -this.MAX_VALUE, + this.MAX_VALUE + ); if (convertedValue < vertRange[0]) vertRange[0] = convertedValue; if (convertedValue > vertRange[1]) vertRange[1] = convertedValue; newX = Math.floor( @@ -875,7 +916,7 @@ export default class LineGraphController implements TabController { context.moveTo( x, scaleValue( - convertWithPreset(data.values[i], unitConversion), + clampValue(convertWithPreset(data.values[i], unitConversion), -this.MAX_VALUE, this.MAX_VALUE), [axis.min, axis.max], [graphTop + graphHeightOpen, graphTop] ) diff --git a/src/shared/log/LogField.ts b/src/shared/log/LogField.ts index 1af207d8..a0295dc4 100644 --- a/src/shared/log/LogField.ts +++ b/src/shared/log/LogField.ts @@ -107,6 +107,8 @@ export default class LogField { /** Inserts a new value at the correct index. */ private putData(timestamp: number, value: any) { + if (value === null) return; + // Check if the timestamp already exists if (this.data.timestamps.includes(timestamp)) { this.data.values[this.data.timestamps.indexOf(timestamp)] = value; diff --git a/src/shared/util.ts b/src/shared/util.ts index b5da3636..6ceab4ef 100644 --- a/src/shared/util.ts +++ b/src/shared/util.ts @@ -81,6 +81,11 @@ export function scaleValue(value: number, oldRange: [number, number], newRange: return ((value - oldRange[0]) / (oldRange[1] - oldRange[0])) * (newRange[1] - newRange[0]) + newRange[0]; } +/** Clamps a value to a range. */ +export function clampValue(value: number, min: number, max: number) { + return Math.min(Math.max(value, min), max); +} + /** * Applys a transform to a pixel value. * @param originPx The origin pixel in image coordinates. From ef75dd01d314f4303e1052489bcfc98f8e72308f Mon Sep 17 00:00:00 2001 From: Jonah <47046556+jonahb55@users.noreply.github.com> Date: Fri, 17 Feb 2023 20:05:27 -0500 Subject: [PATCH 3/3] Update for 2.2.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index dfad8447..e6d1342d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "advantagescope", - "version": "2.2.1", + "version": "2.2.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "advantagescope", - "version": "2.2.1", + "version": "2.2.2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index d520ba2a..f95dd0aa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "advantagescope", "productName": "AdvantageScope", - "version": "2.2.1", + "version": "2.2.2", "description": "Robot telemetry application for FRC", "author": { "name": "FRC 6328",