From 99da72cf4ff980cdcc69a881eeb65d60b529befc Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Sat, 7 Jan 2017 11:11:57 +1300 Subject: [PATCH] Ability to control smoothing settings per-graphline --- app/css/main.css | 10 +-- app/js/graph_config.js | 9 ++- app/js/graph_config_dialog.js | 143 +++++++++++++++++++++++++++------- 3 files changed, 125 insertions(+), 37 deletions(-) diff --git a/app/css/main.css b/app/css/main.css index a2c1bad..2d4a144 100644 --- a/app/css/main.css +++ b/app/css/main.css @@ -163,12 +163,6 @@ html.has-log .log-graph-config { .config-graph dd { margin-top:0.5em; } -.config-graph-field { - margin:0.5em 0; -} -.config-graph-field select { - margin-right:4px; -} .config-graph h4, .config-graph .remove-single-graph-button { display:inline-block; @@ -177,6 +171,10 @@ html.has-log .log-graph-config { .config-graph h4 button { margin-left:0.5em; } +.config-graph .table > tbody > tr > td, +.config-graph .table > thead:first-child > tr:first-child > th { + border: none; +} #graphCanvas { position:absolute; diff --git a/app/js/graph_config.js b/app/js/graph_config.js index 3fdd428..2184d0f 100644 --- a/app/js/graph_config.js +++ b/app/js/graph_config.js @@ -73,8 +73,15 @@ function GraphConfig(graphConfig) { colorIndex++; } - if (field.smoothing === undefined) { + if (field.smoothing === undefined || field.smoothing == "default") { field.smoothing = GraphConfig.getDefaultSmoothingForField(flightLog, field.name); + } else { + let + smoothing = parseInt(field.smoothing, 10); + + if (!isNaN(smoothing)) { + field.smoothing = smoothing; + } } return field; diff --git a/app/js/graph_config_dialog.js b/app/js/graph_config_dialog.js index 58f2151..7c231b0 100644 --- a/app/js/graph_config_dialog.js +++ b/app/js/graph_config_dialog.js @@ -8,6 +8,23 @@ const {Presets} = require("./presets.js"), PresetPicker = require("./preset_picker.js"); +function formatTinyInterval(nanos) { + let + millis = Math.floor(nanos / 1000); + + nanos = nanos % 1000; + + if (millis > 0) { + if (nanos == 0) { + return millis + "ms"; + } else { + return (millis + nanos / 1000).toFixed(1) + "ms"; + } + } else { + return nanos + "ns"; + } +} + /** * * @param {HTMLElement} dialog - Root dialog element to attach to @@ -15,9 +32,22 @@ const * @constructor */ function GraphConfigurationDialog(dialog, graphPresets) { + const + // Some fields it doesn't make sense to graph + BLACKLISTED_FIELDS = {time:true, loopIteration:true}, + + SUGGESTED_SMOOTHING_INTERVALS = [ + 500, 1000, 1500, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 15000, 20000, 30000, 40000, 50000 + ], + + SMOOTHING_OPTIONS = SUGGESTED_SMOOTHING_INTERVALS.map(interval => ({ + name: formatTinyInterval(interval), + value: interval + })), + + that = this; + var - // Some fields it doesn't make sense to graph - BLACKLISTED_FIELDS = {time:true, loopIteration:true}, offeredFieldNames = [], exampleGraphs = [], @@ -41,17 +71,14 @@ function GraphConfigurationDialog(dialog, graphPresets) { } - function renderFieldOption(fieldName, selectedName) { - var - option = $("") - .text(FlightLogFieldPresenter.fieldNameToFriendly(fieldName)) - .attr("value", fieldName); - - if (fieldName == selectedName) { - option.attr("selected", "selected"); - } - - return option; + function renderOptionElem(value, displayName) { + var + result = document.createElement("option"); + + result.innerText = displayName; + result.value = value; + + return result; } /** @@ -60,19 +87,46 @@ function GraphConfigurationDialog(dialog, graphPresets) { */ function renderField(field) { let - elem = $( - '
  • ' - + '' - + '' - + '
  • ' - ), - select = $('select', elem), + elem = $(` + + + + + + + + + + + + `), + fieldNameSelect = $('.graph-field-name', elem), + smoothingSelect = $('.graph-field-smoothing', elem), + selectedFieldName = field ? field.name : false; - - for (let fieldName of offeredFieldNames) { - select.append(renderFieldOption(fieldName, selectedFieldName)); - } - + + fieldNameSelect.append(offeredFieldNames.map(name => renderOptionElem(name, FlightLogFieldPresenter.fieldNameToFriendly(name)))); + fieldNameSelect.val(selectedFieldName); + + let + defaultSmoothingMessage = "Default"; + + if (selectedFieldName) { + let + defaultSmoothing = GraphConfig.getDefaultSmoothingForField(that.flightLog, selectedFieldName); + + defaultSmoothingMessage += " (" + (defaultSmoothing ? formatTinyInterval(defaultSmoothing) : "none") + ")"; + } + + smoothingSelect.append(renderOptionElem("default", defaultSmoothingMessage)); + smoothingSelect.append(renderOptionElem("0", "None")); + + smoothingSelect.append(SMOOTHING_OPTIONS.map(suggestion => renderOptionElem(suggestion.value, suggestion.name))); + + smoothingSelect.val(field.smoothing === undefined ? "default" : field.smoothing); + return elem; } @@ -96,7 +150,23 @@ function GraphConfigurationDialog(dialog, graphPresets) {
    -
      + + + + + + + + + + +
      + Field name + + Smoothing + +   +
      @@ -105,7 +175,7 @@ function GraphConfigurationDialog(dialog, graphPresets) { `), - fieldList = $(".config-graph-field-list", graphElem), + fieldList = $(".config-graph-field-list tbody", graphElem), graphNameField = $("input", graphElem); graphNameField @@ -130,14 +200,25 @@ function GraphConfigurationDialog(dialog, graphPresets) { .append(graph.fields.map(renderField)) // Catch field dropdown changes - .on("change", "select", function(e) { + .on("change", ".graph-field-name", function(e) { let fieldIndex = $(this).parents('.config-graph-field').index(); updateActivePreset(preset => preset.graphs[graphIndex].fields[fieldIndex].name = $(e.target).val()); }) - - // Remove field button + .on("change", ".graph-field-smoothing", function(e) { + let + fieldIndex = $(this).parents('.config-graph-field').index(), + newVal = $(e.target).val(); + + if (!isNaN(parseInt(newVal, 10))) { + newVal = parseInt(newVal, 10); + } + + updateActivePreset(preset => preset.graphs[graphIndex].fields[fieldIndex].smoothing = newVal); + }) + + // Remove field button .on('click', 'button', function(e) { let fieldIndex = $(this).parents('.config-graph-field').index(); @@ -248,6 +329,8 @@ function GraphConfigurationDialog(dialog, graphPresets) { // We'll restore this backup if the user cancels the dialog graphPresetsBackup = graphPresets.clone(); + this.flightLog = flightLog; + populateExampleGraphs(flightLog, exampleGraphsMenu); buildOfferedFieldNamesList(flightLog, graphPresets.getActivePreset().graphs);