From b640fd15c2596252c5d4b001e3edb631696ce653 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Wed, 30 Oct 2019 15:02:03 +1300 Subject: [PATCH 01/16] add initial layout for new data vis interactive --- LICENCE-THIRD-PARTY | 9 +++ .../interactives/content/en/interactives.yaml | 2 + .../content/structure/interactives.yaml | 4 ++ csfieldguide/package.json | 1 + .../interactives/data-visualisation/README.md | 27 +++++++++ .../js/data-visualisation.js | 0 .../data-visualisation/package.json | 8 +++ .../scss/data-visualisation.scss | 8 +++ .../interactives/data-visualisation.html | 56 +++++++++++++++++++ third-party-licences/data-visualization.txt | 10 ++++ 10 files changed, 125 insertions(+) create mode 100644 csfieldguide/static/interactives/data-visualisation/README.md create mode 100644 csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js create mode 100644 csfieldguide/static/interactives/data-visualisation/package.json create mode 100644 csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss create mode 100644 csfieldguide/templates/interactives/data-visualisation.html create mode 100644 third-party-licences/data-visualization.txt diff --git a/LICENCE-THIRD-PARTY b/LICENCE-THIRD-PARTY index c35283e64..8f2305230 100644 --- a/LICENCE-THIRD-PARTY +++ b/LICENCE-THIRD-PARTY @@ -183,6 +183,15 @@ licensed under MIT licence. third-party-licences/cytoscape-no-overlap.txt ============================================================================== +============================================================================== +Data Visualization +------------------------------------------------------------------------------ +https://github.com/ahallak/CISC374 +Copyright 2019 ahallak, sestrobel, joy-kitson, KMeyerUD. +licensed under MIT licence. +third-party-licences/data-visualization.txt +============================================================================== + ============================================================================== del ------------------------------------------------------------------------------ diff --git a/csfieldguide/interactives/content/en/interactives.yaml b/csfieldguide/interactives/content/en/interactives.yaml index b3ee91f6e..2ec2fbc7d 100644 --- a/csfieldguide/interactives/content/en/interactives.yaml +++ b/csfieldguide/interactives/content/en/interactives.yaml @@ -46,6 +46,8 @@ confused-buttons: name: Confused Buttons confusing-error: name: Confusing Error +data-visualisation: + name: Data Visualisation date-picker: name: Date Picker deceiver: diff --git a/csfieldguide/interactives/content/structure/interactives.yaml b/csfieldguide/interactives/content/structure/interactives.yaml index 1778c9124..e79076007 100644 --- a/csfieldguide/interactives/content/structure/interactives.yaml +++ b/csfieldguide/interactives/content/structure/interactives.yaml @@ -111,6 +111,10 @@ confusing-error: de: interactives/confusing-error.html es: interactives/confusing-error.html is_interactive: false +data-visualisation: + languages: + en: interactives/data-visualisation.html + is_interactive: true date-picker: languages: en: interactives/date-picker.html diff --git a/csfieldguide/package.json b/csfieldguide/package.json index adf4c76be..9132b0561 100644 --- a/csfieldguide/package.json +++ b/csfieldguide/package.json @@ -23,6 +23,7 @@ "csfg-interactive-city-trip": "file:./static/interactives/city-trip/", "csfg-interactive-cmy-mixer": "file:./static/interactives/cmy-mixer/", "csfg-interactive-colour-matcher": "file:./static/interactives/colour-matcher/", + "csfg-interactive-data-visualisation": "file:./static/interactives/data-visualisation/", "csfg-interactive-frequency-anaylsis": "file:./static/interactives/frequency-analysis/", "csfg-interactive-jpeg-compression": "file:./static/interactives/jpeg-compression/", "csfg-interactive-matrix-simplifier": "file:./static/interactives/matrix-simplifier/", diff --git a/csfieldguide/static/interactives/data-visualisation/README.md b/csfieldguide/static/interactives/data-visualisation/README.md new file mode 100644 index 000000000..ff895c44e --- /dev/null +++ b/csfieldguide/static/interactives/data-visualisation/README.md @@ -0,0 +1,27 @@ +# Data Visualisation interactive + +**Authors:** + +- Amjed Hallak +- sestrobel +- Joy Kitson +- KMeyerUD + +**Recreated by:** Alasdair Smith + +This game serves to teach students that visualisation can help one quickly identify trends in data, and that some visualisations are more helpful than others. + +## The Game + +The user is presented with a data set for a short period, then expected to enter the mode (most common value) of the data. +This process is repeated with different visualisation techniques, including: a grid, pie chard, bar chart and heat map. + +## Licences + +This interactive uses [Chart.js](https://www.chartjs.org/). +Its licence, and that of the original game, is listed in `LICENCE-THIRD-PARTY`, with a full copy available in the `third-party-licences` directory. + +## TODO + +- Add original authors to community contribs +- Remove this todo when other todos are todone diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js new file mode 100644 index 000000000..e69de29bb diff --git a/csfieldguide/static/interactives/data-visualisation/package.json b/csfieldguide/static/interactives/data-visualisation/package.json new file mode 100644 index 000000000..abc1ac3d8 --- /dev/null +++ b/csfieldguide/static/interactives/data-visualisation/package.json @@ -0,0 +1,8 @@ +{ + "name": "csfg-interactive-data-visualisation", + "version": "1.0.0", + "private": true, + "dependencies": { + "chart.js": "2.9.1" + } +} diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss new file mode 100644 index 000000000..d9a0a4bd6 --- /dev/null +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -0,0 +1,8 @@ +#interactive-data-visualisation { + border-top: 1px dashed #000000; + border-bottom: 1px dashed #000000; +} + +#data-vis-title { + font-size: 2rem; +} \ No newline at end of file diff --git a/csfieldguide/templates/interactives/data-visualisation.html b/csfieldguide/templates/interactives/data-visualisation.html new file mode 100644 index 000000000..537092601 --- /dev/null +++ b/csfieldguide/templates/interactives/data-visualisation.html @@ -0,0 +1,56 @@ +{% extends interactive_mode_template %} + +{% load i18n %} +{% load static %} + +{% block html %} +
+
{% trans 'Data Visualisation' %}
+
+
+ {% blocktrans %} + Find the mode (most common number) of the data below. + You will have a limited amount of time to view the data. + {% endblocktrans %} +
+ +
+
+ +
+ + +
+
+
+ + +
+
+ +
+
+
+ +
+
+{% endblock html %} + +{% block css %} + +{% endblock css %} + +{% block js %} + +{% endblock js %} diff --git a/third-party-licences/data-visualization.txt b/third-party-licences/data-visualization.txt new file mode 100644 index 000000000..856927d1c --- /dev/null +++ b/third-party-licences/data-visualization.txt @@ -0,0 +1,10 @@ + +MIT License + +Copyright (c) 2019 ahallak, sestrobel, joy-kitson, KMeyerUD + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 5480b0e41e8f050d37257ce450078da7b068a624 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Thu, 31 Oct 2019 13:42:11 +1300 Subject: [PATCH 02/16] add data set creation and initial pie & bar charts --- .../js/data-visualisation.js | 212 ++++++++++++++++++ .../scss/data-visualisation.scss | 6 +- .../interactives/data-visualisation.html | 15 +- 3 files changed, 227 insertions(+), 6 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index e69de29bb..76d4a8a4d 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -0,0 +1,212 @@ +// const = CAPS +// global = CamelCase (start upper) +// local = camelCase (start lower) + +const CHART = require('chart.js'); + +const MIN = 0; // Numbers for data +const MAX = 9; +const WAIT = 5000; // Time (milliseconds) to show the chart +const CHART_TYPES = { + GRID: gettext("Plain grid"), + MAP: gettext("Heatmap"), + BAR: gettext("Bar chart"), + PIE: gettext("Pie chart") +}; +const TITLES = { + BAR: gettext("Frequency of each number."), + PIE: gettext("Relative frequency of each number."), +}; +const COLOURS = [ + "#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850", + "#28a745","#2a3da0","#34fcfe","#fb8532","#a37533", +]; + +var NextChart; + +var NumDataPoints; // Number of values in the data + +var Solutions; // List of lists: [[type, correct answer]] +var Responses; // User's choices + +var DataSet; +var Frequencies; // Frequency of each value in DataSet + +$(document).ready(function() { + init(); + +}); + +/** + * Returns everything to the initial 'page loaded' state + */ +function init() { + NextChart = CHART_TYPES.GRID; + NumDataPoints = 20; + Solutions = []; + Responses = []; + DataSet = []; + Frequencies = {}; + + newDataSet(); + buildChart(); +} + +/** + * Creates the next chart to be displayed + * TODO Can this be done before 'start' is pressed but still be invisible to the user even if they inspect the page? + */ +function buildChart() { + $('#data-vis-barchart').addClass('d-none'); + $('#data-vis-piechart').addClass('d-none'); + $('#data-vis-table').addClass('d-none'); + var type = NextChart; + if (type == CHART_TYPES.BAR) { + buildBarChart(); + } else if (type == CHART_TYPES.PIE) { + buildPieChart(); + } + $('#data-vis-game').removeClass('d-none'); +} + +function buildBarChart() { + var valueLabels = []; + var dataPoints = []; + for (var i in Frequencies) { + valueLabels.push(i.toString()); + dataPoints.push(Frequencies[i]); + } + var canvas = $('#data-vis-barchart'); + new CHART.Chart(canvas, { + type: 'bar', + data: { + labels: valueLabels, + datasets: [{ + label: gettext("Occurences"), + backgroundColor: '#2a3da0', // Primary CSFG colour + data: dataPoints + }] + }, + options: { + responsive: false, + legend: { + display: false + }, + title: { + display: true, + text: TITLES.BAR + } + } + }); + $('#data-vis-barchart').removeClass('d-none'); +} + +function buildPieChart() { + var valueLabels = []; + var dataPoints = []; + var num = Object.keys(Frequencies).length; + for (var i in Frequencies) { + if (Frequencies[i]) { + valueLabels.push(i.toString()); + dataPoints.push(Frequencies[i]); + } + } + var canvas = $('#data-vis-piechart'); + new CHART.Chart(canvas, { + type: 'pie', + data: { + labels: valueLabels, + datasets: [{ + backgroundColor: COLOURS, + data: dataPoints + }] + }, + options: { + responsive: false, + legend: { + display: true, + position: 'right' + }, + title: { + display: true, + text: TITLES.PIE + } + } + }); + $('#data-vis-piechart').removeClass('d-none'); +} + +/** + * Prepares a new set of data for the next chart. + * Also sets the next solution appropriately. + */ +function newDataSet() { + fillDataSet(NumDataPoints); + var solution, frequencies = getFrequencies(); + Solutions.push([NextChart, solution]) + Frequencies = frequencies; +} + +/** + * Sets the 'DataSet' global to a list of the given number of random values. + */ +function fillDataSet(num) { + var newDataSet = []; + for (var i=0; i < num; i++) { + newDataSet.push(getRandomInteger(MIN, MAX)) + } + + DataSet = newDataSet; +} + +/** + * Returns two values: + * The mode (most common value) of the global DataSet, ensuring only one value is most common. + * The frequency of each value in the global DataSet. + * + * If two or more values share the mode (most common value), one of the mode values is chosen at random. + * A random datapoint that is not that value is replaced with that value, resulting in a singular mode value. + */ +function getFrequencies() { + // Get the mode(s) + // Based on parts of https://stackoverflow.com/questions/3783950/get-the-item-that-appears-the-most-times-in-an-array + var modes = []; + var frequencies = {}; + var max = 0; + var localDataSet = DataSet; // Store a copy locally for performance + for (var v in localDataSet) { + frequencies[localDataSet[v]] = (frequencies[localDataSet[v]] || 0) + 1; + if (frequencies[localDataSet[v]] == max) { // More than one current mode + modes.push(localDataSet[v]); + } else if (frequencies[localDataSet[v]] > max) { // New (singular) mode + modes = [localDataSet[v]]; + max = frequencies[localDataSet[v]]; + } + } + + // Deal with conflicts + var mode; + if (modes.length > 1) { + mode = modes[getRandomInteger(0, modes.length - 1)]; // Choose a random best mode + var randomValue = getRandomInteger(0, localDataSet.length); + while (localDataSet[randomValue] == mode) { // Find a random not-best-mode number + randomValue++; + } + frequencies[localDataSet[randomValue]]--; // Reduce the frequecy of that number + DataSet[randomValue] = mode; // Set best mode (actual DataSet) + frequencies[localDataSet[randomValue]]++; // Increase the frequency of best-mode + } else { + mode = modes[0]; + } + + // Set the dataset and return the frequencies + return mode, frequencies; +} + +/** + * Returns a random integer between min and max inclusive. + * From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random + */ +function getRandomInteger(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index d9a0a4bd6..26d1b2eab 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -5,4 +5,8 @@ #data-vis-title { font-size: 2rem; -} \ No newline at end of file +} + +canvas { + margin: auto; +} diff --git a/csfieldguide/templates/interactives/data-visualisation.html b/csfieldguide/templates/interactives/data-visualisation.html index 537092601..4db9c71b3 100644 --- a/csfieldguide/templates/interactives/data-visualisation.html +++ b/csfieldguide/templates/interactives/data-visualisation.html @@ -15,7 +15,7 @@ -
+
- +
@@ -46,8 +46,8 @@
-
- +
+
{% endblock html %} From 298e7e5cd0bb0c89feea5207ede04b431af2771a Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Thu, 31 Oct 2019 15:10:19 +1300 Subject: [PATCH 04/16] add grid and heatmap charts --- .../js/data-visualisation.js | 47 +++++++++++++++---- .../scss/data-visualisation.scss | 11 +++++ .../interactives/data-visualisation.html | 2 +- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 2acb19ef9..3749da92a 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -4,9 +4,10 @@ const CHART = require('chart.js'); -const MIN = 0; // Numbers for data +const MIN = 0; // Numbers for data const MAX = 9; -const WAIT = 5000; // Time (milliseconds) to show the chart +const WAIT = 5000; // Time (milliseconds) to show the chart +const BASE_DATA_POINTS = 16; const CHART_TYPES = { GRID: gettext("Plain grid"), MAP: gettext("Heatmap"), @@ -17,10 +18,14 @@ const TITLES = { BAR: gettext("Frequency of each number."), PIE: gettext("Relative frequency of each number (%)."), }; -const COLOURS = [ +const COLOURS = [ // Pie chart colours "#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850", "#28a745","#2a3da0","#34fcfe","#fb8532","#a37533", ]; +const HEATMAP = [ // Heatmap colours + "#0006bf", "#2500c3", "#5200c7", "#8200cb", "#b400cf", + "#d400bf","#d80092","#dc0063","#e00032","#e50000", +]; var NextChart; @@ -46,7 +51,7 @@ function init() { showStartScreen(); NextChart = CHART_TYPES.GRID; - NumDataPoints = 16; + NumDataPoints = BASE_DATA_POINTS; Solutions = []; Responses = []; DataSet = []; @@ -76,9 +81,11 @@ function runGuessCheck() { function buildChart() { $('#data-vis-barchart').addClass('d-none'); $('#data-vis-piechart').addClass('d-none'); - $('#data-vis-table').addClass('d-none'); + $('#data-vis-grid').addClass('d-none'); var type = NextChart; - if (type == CHART_TYPES.BAR) { + if (type == CHART_TYPES.GRID || type == CHART_TYPES.MAP) { + buildGridChart(); + } else if (type == CHART_TYPES.BAR) { buildBarChart(); } else if (type == CHART_TYPES.PIE) { buildPieChart(); @@ -86,6 +93,30 @@ function buildChart() { $('#data-vis-game').removeClass('d-none'); } +function buildGridChart() { + var numValues = DataSet.length; + + // We can afford to have fewer columns with a low number of values + var numColumns = numValues > (BASE_DATA_POINTS * 4) ? (BASE_DATA_POINTS / 2) : (BASE_DATA_POINTS / 4); + + var html = ""; + var i=0; + while (i < numValues) { + html += "\n"; + for (var x=0; x < numColumns; x++) { + if (NextChart == CHART_TYPES.MAP) { + html += "" + DataSet[i] + "\n"; + } else { + html += "" + DataSet[i] + "\n"; + } + i++; + } + html += "\n"; + } + + $('#data-vis-grid').html(html).removeClass('d-none'); +} + function buildBarChart() { var valueLabels = []; var dataPoints = []; @@ -115,7 +146,7 @@ function buildBarChart() { } } }); - $('#data-vis-barchart').removeClass('d-none'); + canvas.removeClass('d-none'); } function buildPieChart() { @@ -149,7 +180,7 @@ function buildPieChart() { } } }); - $('#data-vis-piechart').removeClass('d-none'); + canvas.removeClass('d-none'); } /** diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index 26d1b2eab..e0d4f5a95 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -10,3 +10,14 @@ canvas { margin: auto; } + +table, th, td { + margin: auto; + font-family: monospace; + text-align: center; + padding: 15px; + padding-left: 50px; + padding-right: 50px; + border: 1px solid #000; + border-collapse: collapse; +} diff --git a/csfieldguide/templates/interactives/data-visualisation.html b/csfieldguide/templates/interactives/data-visualisation.html index 38a6917f1..f8dafcf73 100644 --- a/csfieldguide/templates/interactives/data-visualisation.html +++ b/csfieldguide/templates/interactives/data-visualisation.html @@ -41,7 +41,7 @@
-
+
From 1eef532ca67460be8169e27753c5e659e3d39ab2 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Thu, 31 Oct 2019 15:34:00 +1300 Subject: [PATCH 05/16] finish logic for cycling of graph types --- .../js/data-visualisation.js | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 3749da92a..ab59c5c99 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -11,12 +11,12 @@ const BASE_DATA_POINTS = 16; const CHART_TYPES = { GRID: gettext("Plain grid"), MAP: gettext("Heatmap"), + PIE: gettext("Pie chart"), BAR: gettext("Bar chart"), - PIE: gettext("Pie chart") }; const TITLES = { - BAR: gettext("Frequency of each number."), PIE: gettext("Relative frequency of each number (%)."), + BAR: gettext("Frequency of each number."), }; const COLOURS = [ // Pie chart colours "#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850", @@ -37,11 +37,17 @@ var Responses; // User's choices var DataSet; var Frequencies; // Frequency of each value in DataSet +var BarChart; +var PieChart; + $(document).ready(function() { init(); $('#button-start').on('click', runStart); $('#button-submit').on('click', runGuessCheck); + $('#button-next').on('click', runNext); + $('#button-quit').on('click', runQuit); + $('#button-restart').on('click', init); }); /** @@ -75,6 +81,30 @@ function runGuessCheck() { showPerformanceScreen(); } +function runNext() { + getNextChart(); + showStartScreen(); + newDataSet(); +} + +function runQuit() { + //showResultsScreen(); + //populatePerformanceTable(); +} + +function getNextChart() { + if (NextChart == CHART_TYPES.GRID) { + NextChart = CHART_TYPES.MAP; + } else if (NextChart == CHART_TYPES.MAP) { + NextChart = CHART_TYPES.PIE; + } else if (NextChart == CHART_TYPES.PIE) { + NextChart = CHART_TYPES.BAR; + } else /*(NextChart == CHART_TYPES.BAR)*/ { + NumDataPoints = min(128, NumDataPoints * 2); // More data points for the next cycle + NextChart = CHART_TYPES.GRID; + } +} + /** * Creates the next chart to be displayed */ @@ -97,7 +127,7 @@ function buildGridChart() { var numValues = DataSet.length; // We can afford to have fewer columns with a low number of values - var numColumns = numValues > (BASE_DATA_POINTS * 4) ? (BASE_DATA_POINTS / 2) : (BASE_DATA_POINTS / 4); + var numColumns = numValues > (BASE_DATA_POINTS * 3) ? (BASE_DATA_POINTS / 2) : (BASE_DATA_POINTS / 4); var html = ""; var i=0; @@ -125,7 +155,10 @@ function buildBarChart() { dataPoints.push(Frequencies[i]); } var canvas = $('#data-vis-barchart'); - new CHART.Chart(canvas, { + if (BarChart) { + BarChart.destroy(); + } + BarChart = new CHART.Chart(canvas, { type: 'bar', data: { labels: valueLabels, @@ -159,7 +192,10 @@ function buildPieChart() { } } var canvas = $('#data-vis-piechart'); - new CHART.Chart(canvas, { + if (PieChart) { + PieChart.destroy(); + } + PieChart = new CHART.Chart(canvas, { type: 'pie', data: { labels: valueLabels, From 6f4f242086f86de3abf4f3158b06ae1b41255044 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Fri, 1 Nov 2019 10:50:34 +1300 Subject: [PATCH 06/16] add table of performance so far --- .../interactives/data-visualisation/README.md | 2 +- .../js/data-visualisation.js | 69 +++++++++++++------ .../scss/data-visualisation.scss | 4 +- .../interactives/data-visualisation.html | 8 ++- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/README.md b/csfieldguide/static/interactives/data-visualisation/README.md index ff895c44e..aeb731ce3 100644 --- a/csfieldguide/static/interactives/data-visualisation/README.md +++ b/csfieldguide/static/interactives/data-visualisation/README.md @@ -14,7 +14,7 @@ This game serves to teach students that visualisation can help one quickly ident ## The Game The user is presented with a data set for a short period, then expected to enter the mode (most common value) of the data. -This process is repeated with different visualisation techniques, including: a grid, pie chard, bar chart and heat map. +This process is repeated with different visualisation techniques, including: a grid, heatmap, pie chard and bar chart. ## Licences diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index ab59c5c99..00b5bd6c1 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -17,6 +17,7 @@ const CHART_TYPES = { const TITLES = { PIE: gettext("Relative frequency of each number (%)."), BAR: gettext("Frequency of each number."), + RESULTS: gettext("") }; const COLOURS = [ // Pie chart colours "#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850", @@ -27,7 +28,7 @@ const HEATMAP = [ // Heatmap colours "#d400bf","#d80092","#dc0063","#e00032","#e50000", ]; -var NextChart; +var CurrentChart; var NumDataPoints; // Number of values in the data @@ -39,6 +40,7 @@ var Frequencies; // Frequency of each value in DataSet var BarChart; var PieChart; +var ResultsChart; $(document).ready(function() { init(); @@ -56,7 +58,7 @@ $(document).ready(function() { function init() { showStartScreen(); - NextChart = CHART_TYPES.GRID; + CurrentChart = CHART_TYPES.GRID; NumDataPoints = BASE_DATA_POINTS; Solutions = []; Responses = []; @@ -78,6 +80,7 @@ function runGuessCheck() { if (Responses.length != Solutions.length) { // At this point the two should always be equal console.log("ERROR: Number of responses does not match number of solutions.") } + populatePerformanceTable(); showPerformanceScreen(); } @@ -88,20 +91,20 @@ function runNext() { } function runQuit() { + //buildResultsChart(); //showResultsScreen(); - //populatePerformanceTable(); } function getNextChart() { - if (NextChart == CHART_TYPES.GRID) { - NextChart = CHART_TYPES.MAP; - } else if (NextChart == CHART_TYPES.MAP) { - NextChart = CHART_TYPES.PIE; - } else if (NextChart == CHART_TYPES.PIE) { - NextChart = CHART_TYPES.BAR; - } else /*(NextChart == CHART_TYPES.BAR)*/ { - NumDataPoints = min(128, NumDataPoints * 2); // More data points for the next cycle - NextChart = CHART_TYPES.GRID; + if (CurrentChart == CHART_TYPES.GRID) { + CurrentChart = CHART_TYPES.MAP; + } else if (CurrentChart == CHART_TYPES.MAP) { + CurrentChart = CHART_TYPES.PIE; + } else if (CurrentChart == CHART_TYPES.PIE) { + CurrentChart = CHART_TYPES.BAR; + } else /*(CurrentChart == CHART_TYPES.BAR)*/ { + NumDataPoints = Math.min(128, NumDataPoints * 2); // More data points for the next cycle + CurrentChart = CHART_TYPES.GRID; } } @@ -112,7 +115,7 @@ function buildChart() { $('#data-vis-barchart').addClass('d-none'); $('#data-vis-piechart').addClass('d-none'); $('#data-vis-grid').addClass('d-none'); - var type = NextChart; + var type = CurrentChart; if (type == CHART_TYPES.GRID || type == CHART_TYPES.MAP) { buildGridChart(); } else if (type == CHART_TYPES.BAR) { @@ -134,7 +137,7 @@ function buildGridChart() { while (i < numValues) { html += "\n"; for (var x=0; x < numColumns; x++) { - if (NextChart == CHART_TYPES.MAP) { + if (CurrentChart == CHART_TYPES.MAP) { html += "" + DataSet[i] + "\n"; } else { html += "" + DataSet[i] + "\n"; @@ -219,14 +222,28 @@ function buildPieChart() { canvas.removeClass('d-none'); } +function populatePerformanceTable() { + var table = $('#data-vis-performance'); + var data = [last(Solutions), last(Responses)]; // [[type, solution], response] + console.log(data); + var newRow = "\n" + + "" + data[0][0] + "\n" + + "" + data[0][1] + "\n" + + "" + data[1] + "\n" + + "\n"; + table.append(newRow); +} + /** * Prepares a new set of data for the next chart. * Also sets the next solution appropriately. */ function newDataSet() { fillDataSet(NumDataPoints); - var solution, frequencies = getFrequencies(); - Solutions.push([NextChart, solution]) + var [solution, frequencies] = getFrequencies(); + console.log(solution); + console.log(frequencies); + Solutions.push([CurrentChart, solution]) Frequencies = frequencies; } @@ -243,9 +260,12 @@ function fillDataSet(num) { } /** - * Returns two values: + * Returns two values in a list: + * [ * The mode (most common value) of the global DataSet, ensuring only one value is most common. + * , * The frequency of each value in the global DataSet. + * ] * * If two or more values share the mode (most common value), one of the mode values is chosen at random. * A random datapoint that is not that value is replaced with that value, resulting in a singular mode value. @@ -282,8 +302,8 @@ function getFrequencies() { mode = modes[0]; } - // Set the dataset and return the frequencies - return mode, frequencies; + // Return the mode and frequencies + return [mode, frequencies]; } /** @@ -294,6 +314,13 @@ function getRandomInteger(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } +/** + * Returns the last item in array like the python expression: `array[-1]` + */ +function last(array) { + return array[array.length - 1]; +} + /** * Hides irrrelevant HTML divs, then reveals relevant ones. */ @@ -328,8 +355,6 @@ function showPerformanceScreen() { $('#data-vis-results-table').addClass('d-none'); $('#data-vis-next').removeClass('d-none'); - $('#data-vis-performance-table').removeClass('d-none'); + $('#data-vis-performance').removeClass('d-none'); $('#data-vis-results').removeClass('d-none'); - - //populatePerformanceTable(); } diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index e0d4f5a95..eea0d36d8 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -1,6 +1,6 @@ #interactive-data-visualisation { - border-top: 1px dashed #000000; - border-bottom: 1px dashed #000000; + border-top: 1px dashed #000; + border-bottom: 1px dashed #000; } #data-vis-title { diff --git a/csfieldguide/templates/interactives/data-visualisation.html b/csfieldguide/templates/interactives/data-visualisation.html index f8dafcf73..36380a53f 100644 --- a/csfieldguide/templates/interactives/data-visualisation.html +++ b/csfieldguide/templates/interactives/data-visualisation.html @@ -46,7 +46,13 @@
-
+ + + + + + +
{% trans 'Chart type' %}{% trans 'Mode (most common value) of data' %}{% trans 'Your answer' %}
From ef4d90e6b60f615f6067de9b552da1d381272237 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Fri, 1 Nov 2019 11:42:15 +1300 Subject: [PATCH 07/16] add results graph --- .../js/data-visualisation.js | 116 ++++++++++++++++-- .../scss/data-visualisation.scss | 5 - .../interactives/data-visualisation.html | 12 +- 3 files changed, 114 insertions(+), 19 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 00b5bd6c1..dc8281fb6 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -17,9 +17,9 @@ const CHART_TYPES = { const TITLES = { PIE: gettext("Relative frequency of each number (%)."), BAR: gettext("Frequency of each number."), - RESULTS: gettext("") + RESULTS: gettext("Your accuracy (%) when finding the mode of data with different visualisations.") }; -const COLOURS = [ // Pie chart colours +const COLOURS = [ // Pie chart colours "#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850", "#28a745","#2a3da0","#34fcfe","#fb8532","#a37533", ]; @@ -42,6 +42,8 @@ var BarChart; var PieChart; var ResultsChart; +var BaseTable; // For storing just the headings of the results table + $(document).ready(function() { init(); @@ -64,6 +66,11 @@ function init() { Responses = []; DataSet = []; Frequencies = {}; + if (BaseTable) { + $('#data-vis-performance').html(BaseTable); + } else { + BaseTable = $('#data-vis-performance').html(); + } newDataSet(); } @@ -91,8 +98,8 @@ function runNext() { } function runQuit() { - //buildResultsChart(); - //showResultsScreen(); + buildResultsChart(); + showResultsScreen(); } function getNextChart() { @@ -222,10 +229,50 @@ function buildPieChart() { canvas.removeClass('d-none'); } +function buildResultsChart() { + var valueLabels = [CHART_TYPES.GRID, CHART_TYPES.MAP, CHART_TYPES.PIE, CHART_TYPES.BAR]; + var dataPoints = getFinalResults(); + var canvas = $('#data-vis-results-chart'); + if (ResultsChart) { + ResultsChart.destroy(); + } + ResultsChart = new CHART.Chart(canvas, { + type: 'bar', + data: { + labels: valueLabels, + datasets: [{ + label: gettext("Success (%)"), + backgroundColor: '#2a3da0', // Primary CSFG colour + data: dataPoints + }] + }, + options: { + responsive: false, + legend: { + display: false + }, + scales: { + yAxes: [{ + display: true, + ticks: { + beginAtZero: true, + stepValue: 10, + max: 100 + } + }] + }, + title: { + display: true, + text: TITLES.RESULTS + } + } + }); + canvas.removeClass('d-none'); +} + function populatePerformanceTable() { var table = $('#data-vis-performance'); var data = [last(Solutions), last(Responses)]; // [[type, solution], response] - console.log(data); var newRow = "\n" + "" + data[0][0] + "\n" + "" + data[0][1] + "\n" @@ -234,6 +281,50 @@ function populatePerformanceTable() { table.append(newRow); } +/** + * Returns a list of four items: + * The percentage of correct answers for the mode of each data visualisation type + * + * [grid, heatmap, pie, bar] + */ +function getFinalResults() { + var localSolutions = Solutions; // List of [[type, solution]] + var localResponses = Responses; // List of [response] + var proportionGrid = [0, 0]; // [correct, out-of] + var proportionHeatmap = [0, 0]; + var proportionPie = [0, 0]; + var proportionBar = [0, 0]; + for (var i=0; i < localSolutions.length; i++) { + if (localSolutions[i][0] == CHART_TYPES.GRID) { + if (localSolutions[i][1] == localResponses[i]) { + proportionGrid[0]++; + } + proportionGrid[1]++; + } else if (localSolutions[i][0] == CHART_TYPES.MAP) { + if (localSolutions[i][1] == localResponses[i]) { + proportionHeatmap[0]++; + } + proportionHeatmap[1]++; + } else if (localSolutions[i][0] == CHART_TYPES.PIE) { + if (localSolutions[i][1] == localResponses[i]) { + proportionPie[0]++; + } + proportionPie[1]++; + } else if (localSolutions[i][0] == CHART_TYPES.BAR) { + if (localSolutions[i][1] == localResponses[i]) { + proportionBar[0]++; + } + proportionBar[1]++; + } + } + return [ + Math.round(proportionGrid[0] / proportionGrid[1] * 100), + Math.round(proportionHeatmap[0] / proportionHeatmap[1] * 100), + Math.round(proportionPie[0] / proportionPie[1] * 100), + Math.round(proportionBar[0] / proportionBar[1] * 100) + ]; +} + /** * Prepares a new set of data for the next chart. * Also sets the next solution appropriately. @@ -241,8 +332,6 @@ function populatePerformanceTable() { function newDataSet() { fillDataSet(NumDataPoints); var [solution, frequencies] = getFrequencies(); - console.log(solution); - console.log(frequencies); Solutions.push([CurrentChart, solution]) Frequencies = frequencies; } @@ -352,9 +441,20 @@ function showPerformanceScreen() { $('#data-vis-guesser').addClass('d-none'); $('#data-vis-restart').addClass('d-none'); $('#data-vis-game').addClass('d-none'); - $('#data-vis-results-table').addClass('d-none'); + $('#data-vis-results-chart').addClass('d-none'); $('#data-vis-next').removeClass('d-none'); $('#data-vis-performance').removeClass('d-none'); $('#data-vis-results').removeClass('d-none'); } + +/** + * Hides irrrelevant HTML divs, then reveals relevant ones. + */ +function showResultsScreen() { + $('#data-vis-next').addClass('d-none'); + $('#data-vis-performance').addClass('d-none'); + + $('#data-vis-restart').removeClass('d-none'); + $('#data-vis-results-chart').removeClass('d-none'); +} diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index eea0d36d8..0c52115df 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -1,8 +1,3 @@ -#interactive-data-visualisation { - border-top: 1px dashed #000; - border-bottom: 1px dashed #000; -} - #data-vis-title { font-size: 2rem; } diff --git a/csfieldguide/templates/interactives/data-visualisation.html b/csfieldguide/templates/interactives/data-visualisation.html index 36380a53f..b90f73585 100644 --- a/csfieldguide/templates/interactives/data-visualisation.html +++ b/csfieldguide/templates/interactives/data-visualisation.html @@ -4,7 +4,7 @@ {% load static %} {% block html %} -
+
{% trans 'Data Visualisation' %}
@@ -13,7 +13,7 @@ You will have a limited amount of time to view the data. {% endblocktrans %}
- +
@@ -33,11 +33,11 @@
-
+
-
+
@@ -46,14 +46,14 @@
- +
{% trans 'Chart type' %} {% trans 'Mode (most common value) of data' %} {% trans 'Your answer' %}
- +
{% endblock html %} From 76eef5a09a311683a9b5f8144c04bee2b8a90e0b Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Fri, 1 Nov 2019 11:47:50 +1300 Subject: [PATCH 08/16] Finish docstrings --- .../js/data-visualisation.js | 85 +++++++++++++------ 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index dc8281fb6..b92c100f2 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -75,12 +75,18 @@ function init() { newDataSet(); } +/** + * Shows the next data representation then, after some time, shows the guess checker + */ function runStart() { $('#button-start').addClass('d-none'); buildChart(); setTimeout(showGuessScreen, WAIT); } +/** + * Runs the guess-checking functionality, then shows the user their performance so far + */ function runGuessCheck() { var guess = $('#data-vis-selector').val(); Responses.push(guess); @@ -91,17 +97,27 @@ function runGuessCheck() { showPerformanceScreen(); } +/** + * Prepares the next chart type and dataset + */ function runNext() { getNextChart(); showStartScreen(); newDataSet(); } +/** + * Runs the quit functionality; shows the user their overall performace (results) + */ function runQuit() { buildResultsChart(); showResultsScreen(); } +/** + * Assigns the chart type that should be used next, in a circular fashion. + * If the loop has completed, doubles the amount of data to create, up to 128 points + */ function getNextChart() { if (CurrentChart == CHART_TYPES.GRID) { CurrentChart = CHART_TYPES.MAP; @@ -133,6 +149,10 @@ function buildChart() { $('#data-vis-game').removeClass('d-none'); } +/** + * Builds a grid of values in the data. + * If the representation should be a heatmap, also colours each grid square appropriately + */ function buildGridChart() { var numValues = DataSet.length; @@ -157,78 +177,87 @@ function buildGridChart() { $('#data-vis-grid').html(html).removeClass('d-none'); } -function buildBarChart() { +/** + * Builds a pie chart showing the relative frequency of each point in the data + */ +function buildPieChart() { var valueLabels = []; var dataPoints = []; for (var i in Frequencies) { - valueLabels.push(i.toString()); - dataPoints.push(Frequencies[i]); + if (Frequencies[i]) { + valueLabels.push(i.toString()); + dataPoints.push(Math.round(Frequencies[i] / DataSet.length * 100)); // Percentage of total + } } - var canvas = $('#data-vis-barchart'); - if (BarChart) { - BarChart.destroy(); + var canvas = $('#data-vis-piechart'); + if (PieChart) { + PieChart.destroy(); } - BarChart = new CHART.Chart(canvas, { - type: 'bar', + PieChart = new CHART.Chart(canvas, { + type: 'pie', data: { labels: valueLabels, datasets: [{ - label: gettext("Occurences"), - backgroundColor: '#2a3da0', // Primary CSFG colour + backgroundColor: COLOURS, data: dataPoints }] }, options: { responsive: false, legend: { - display: false + display: true, + position: 'right' }, title: { display: true, - text: TITLES.BAR + text: TITLES.PIE } } }); - canvas.removeClass('d-none'); + canvas.removeClass('d-none'); } -function buildPieChart() { +/** + * Builds a bar chart showing the number of times each value appears in the data + */ +function buildBarChart() { var valueLabels = []; var dataPoints = []; for (var i in Frequencies) { - if (Frequencies[i]) { - valueLabels.push(i.toString()); - dataPoints.push(Math.round(Frequencies[i] / DataSet.length * 100)); // Percentage of total - } + valueLabels.push(i.toString()); + dataPoints.push(Frequencies[i]); } - var canvas = $('#data-vis-piechart'); - if (PieChart) { - PieChart.destroy(); + var canvas = $('#data-vis-barchart'); + if (BarChart) { + BarChart.destroy(); } - PieChart = new CHART.Chart(canvas, { - type: 'pie', + BarChart = new CHART.Chart(canvas, { + type: 'bar', data: { labels: valueLabels, datasets: [{ - backgroundColor: COLOURS, + label: gettext("Occurences"), + backgroundColor: '#2a3da0', // Primary CSFG colour data: dataPoints }] }, options: { responsive: false, legend: { - display: true, - position: 'right' + display: false }, title: { display: true, - text: TITLES.PIE + text: TITLES.BAR } } }); - canvas.removeClass('d-none'); + canvas.removeClass('d-none'); } +/** + * Builds a bar chart showing the user's accuracy when finding the mode for each representation of data + */ function buildResultsChart() { var valueLabels = [CHART_TYPES.GRID, CHART_TYPES.MAP, CHART_TYPES.PIE, CHART_TYPES.BAR]; var dataPoints = getFinalResults(); From c9482ffb8278342a68130d01f265e8faa5a4f700 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Fri, 1 Nov 2019 12:44:28 +1300 Subject: [PATCH 09/16] add resizing of charts for small screens --- .../interactives/data-visualisation/README.md | 2 +- .../js/data-visualisation.js | 20 +++++++++++++------ .../scss/data-visualisation.scss | 12 +++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/README.md b/csfieldguide/static/interactives/data-visualisation/README.md index aeb731ce3..3969d8436 100644 --- a/csfieldguide/static/interactives/data-visualisation/README.md +++ b/csfieldguide/static/interactives/data-visualisation/README.md @@ -9,7 +9,7 @@ **Recreated by:** Alasdair Smith -This game serves to teach students that visualisation can help one quickly identify trends in data, and that some visualisations are more helpful than others. +This game serves to teach students that visualisation can help a user quickly identify trends in data, and that some visualisations are more helpful than others. ## The Game diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index b92c100f2..66c433f36 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -8,6 +8,7 @@ const MIN = 0; // Numbers for data const MAX = 9; const WAIT = 5000; // Time (milliseconds) to show the chart const BASE_DATA_POINTS = 16; +const MAX_DATA_POINTS = 256; const CHART_TYPES = { GRID: gettext("Plain grid"), MAP: gettext("Heatmap"), @@ -32,7 +33,7 @@ var CurrentChart; var NumDataPoints; // Number of values in the data -var Solutions; // List of lists: [[type, correct answer]] +var Solutions; // List of lists: [[type of representation, correct answer]] var Responses; // User's choices var DataSet; @@ -116,7 +117,7 @@ function runQuit() { /** * Assigns the chart type that should be used next, in a circular fashion. - * If the loop has completed, doubles the amount of data to create, up to 128 points + * If the loop has completed, doubles the amount of data to create, up to MAX_DATA_POINTS */ function getNextChart() { if (CurrentChart == CHART_TYPES.GRID) { @@ -126,7 +127,7 @@ function getNextChart() { } else if (CurrentChart == CHART_TYPES.PIE) { CurrentChart = CHART_TYPES.BAR; } else /*(CurrentChart == CHART_TYPES.BAR)*/ { - NumDataPoints = Math.min(128, NumDataPoints * 2); // More data points for the next cycle + NumDataPoints = Math.min(MAX_DATA_POINTS, NumDataPoints * 2); // More data points for the next cycle CurrentChart = CHART_TYPES.GRID; } } @@ -193,6 +194,8 @@ function buildPieChart() { if (PieChart) { PieChart.destroy(); } + canvas.attr('width', Math.min(600, 0.8 * $( window ).width())); // 600 is the value in the html + canvas.attr('height', canvas.attr('width') / 2); PieChart = new CHART.Chart(canvas, { type: 'pie', data: { @@ -204,6 +207,7 @@ function buildPieChart() { }, options: { responsive: false, + maintainAspectRatio: false, legend: { display: true, position: 'right' @@ -231,6 +235,8 @@ function buildBarChart() { if (BarChart) { BarChart.destroy(); } + canvas.attr('width', Math.min(800, 0.8 * $( window ).width())); // 800 is the value in the html + canvas.attr('height', canvas.attr('width') / 2); BarChart = new CHART.Chart(canvas, { type: 'bar', data: { @@ -265,6 +271,8 @@ function buildResultsChart() { if (ResultsChart) { ResultsChart.destroy(); } + canvas.attr('width', Math.min(800, 0.8 * $( window ).width())); // 800 is the value in the html + canvas.attr('height', canvas.attr('width') / 2); ResultsChart = new CHART.Chart(canvas, { type: 'bar', data: { @@ -380,9 +388,9 @@ function fillDataSet(num) { /** * Returns two values in a list: * [ - * The mode (most common value) of the global DataSet, ensuring only one value is most common. + * The mode (most common value) of the global DataSet - ensuring only one value is most common * , - * The frequency of each value in the global DataSet. + * The frequency of each value in the global DataSet * ] * * If two or more values share the mode (most common value), one of the mode values is chosen at random. @@ -433,7 +441,7 @@ function getRandomInteger(min, max) { } /** - * Returns the last item in array like the python expression: `array[-1]` + * Returns the last item in the array, like the python expression: `array[-1]` */ function last(array) { return array[array.length - 1]; diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index 0c52115df..4f450ed1c 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -1,3 +1,7 @@ +@import "node_modules/bootstrap/scss/functions"; +@import "node_modules/bootstrap/scss/variables"; +@import "node_modules/bootstrap/scss/mixins"; + #data-vis-title { font-size: 2rem; } @@ -16,3 +20,11 @@ table, th, td { border: 1px solid #000; border-collapse: collapse; } + +@include media-breakpoint-down(sm) { + table, th, td { + padding: 5px; + padding-left: 15px; + padding-right: 15px; + } +} From 9efca51c07e730f9febe4d7c2db845db644191a7 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Fri, 1 Nov 2019 12:53:51 +1300 Subject: [PATCH 10/16] minor fixes, add community contribs --- .../static/interactives/data-visualisation/README.md | 5 ----- .../data-visualisation/js/data-visualisation.js | 8 ++++---- .../data-visualisation/scss/data-visualisation.scss | 2 +- csfieldguide/templates/appendices/contributors.html | 4 ++++ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/README.md b/csfieldguide/static/interactives/data-visualisation/README.md index 3969d8436..87c50d7e9 100644 --- a/csfieldguide/static/interactives/data-visualisation/README.md +++ b/csfieldguide/static/interactives/data-visualisation/README.md @@ -20,8 +20,3 @@ This process is repeated with different visualisation techniques, including: a g This interactive uses [Chart.js](https://www.chartjs.org/). Its licence, and that of the original game, is listed in `LICENCE-THIRD-PARTY`, with a full copy available in the `third-party-licences` directory. - -## TODO - -- Add original authors to community contribs -- Remove this todo when other todos are todone diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 66c433f36..5a325120a 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -15,9 +15,9 @@ const CHART_TYPES = { PIE: gettext("Pie chart"), BAR: gettext("Bar chart"), }; -const TITLES = { +const TITLES = { // Bar/Pie chart titles PIE: gettext("Relative frequency of each number (%)."), - BAR: gettext("Frequency of each number."), + BAR: gettext("Occurences of each number."), RESULTS: gettext("Your accuracy (%) when finding the mode of data with different visualisations.") }; const COLOURS = [ // Pie chart colours @@ -29,7 +29,7 @@ const HEATMAP = [ // Heatmap colours "#d400bf","#d80092","#dc0063","#e00032","#e50000", ]; -var CurrentChart; +var CurrentChart; // Chart to be rendered var NumDataPoints; // Number of values in the data @@ -39,7 +39,7 @@ var Responses; // User's choices var DataSet; var Frequencies; // Frequency of each value in DataSet -var BarChart; +var BarChart; // Charts var PieChart; var ResultsChart; diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index 4f450ed1c..44f4e623d 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -21,7 +21,7 @@ table, th, td { border-collapse: collapse; } -@include media-breakpoint-down(sm) { +@include media-breakpoint-down(md) { table, th, td { padding: 5px; padding-left: 15px; diff --git a/csfieldguide/templates/appendices/contributors.html b/csfieldguide/templates/appendices/contributors.html index 7bd3e9fca..a643ce556 100644 --- a/csfieldguide/templates/appendices/contributors.html +++ b/csfieldguide/templates/appendices/contributors.html @@ -139,6 +139,10 @@

{% trans 'Comm
  • gmohler213 (Greg Mohler)
  • Rachel Muzzelo
  • aenkirch
  • +
  • Amjed Hallak
  • +
  • sestrobel
  • +
  • Joy Kitson
  • +
  • KMeyerUD
  • {% trans 'Note: If there is an error in the list, please contact Jack Morgan' %}

    From 5200fa3e23f5e1be735d88ab0d2c0f010a751dfc Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 4 Nov 2019 10:32:03 +1300 Subject: [PATCH 11/16] Add original game github link to README --- csfieldguide/static/interactives/data-visualisation/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/csfieldguide/static/interactives/data-visualisation/README.md b/csfieldguide/static/interactives/data-visualisation/README.md index 87c50d7e9..0f4bf50ba 100644 --- a/csfieldguide/static/interactives/data-visualisation/README.md +++ b/csfieldguide/static/interactives/data-visualisation/README.md @@ -7,6 +7,8 @@ - Joy Kitson - KMeyerUD +The original can be found [here](https://github.com/ahallak/CISC374). + **Recreated by:** Alasdair Smith This game serves to teach students that visualisation can help a user quickly identify trends in data, and that some visualisations are more helpful than others. From 3b030c6c1a62bf7b1990ed7471ba8580269c7f91 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Tue, 5 Nov 2019 11:53:11 +1300 Subject: [PATCH 12/16] changes from review --- .../static/interactives/data-visualisation/README.md | 2 +- .../data-visualisation/js/data-visualisation.js | 1 + csfieldguide/templates/appendices/contributors.html | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/README.md b/csfieldguide/static/interactives/data-visualisation/README.md index 0f4bf50ba..dd631625a 100644 --- a/csfieldguide/static/interactives/data-visualisation/README.md +++ b/csfieldguide/static/interactives/data-visualisation/README.md @@ -16,7 +16,7 @@ This game serves to teach students that visualisation can help a user quickly id ## The Game The user is presented with a data set for a short period, then expected to enter the mode (most common value) of the data. -This process is repeated with different visualisation techniques, including: a grid, heatmap, pie chard and bar chart. +This process is repeated with different visualisation techniques, including: a grid, heatmap, pie chart and bar chart. ## Licences diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 5a325120a..1f1bc1d57 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -1,3 +1,4 @@ +// For readability this is the variable name syntax used: // const = CAPS // global = CamelCase (start upper) // local = camelCase (start lower) diff --git a/csfieldguide/templates/appendices/contributors.html b/csfieldguide/templates/appendices/contributors.html index a643ce556..86c36432c 100644 --- a/csfieldguide/templates/appendices/contributors.html +++ b/csfieldguide/templates/appendices/contributors.html @@ -139,10 +139,10 @@

    {% trans 'Comm
  • gmohler213 (Greg Mohler)
  • Rachel Muzzelo
  • aenkirch
  • -
  • Amjed Hallak
  • -
  • sestrobel
  • -
  • Joy Kitson
  • -
  • KMeyerUD
  • +
  • ahallak (Amjed Hallak)
  • +
  • sestrobel
  • +
  • joy-kitson (Joy Kitson)
  • +
  • KMeyerUD
  • {% trans 'Note: If there is an error in the list, please contact Jack Morgan' %}

    From 1d3b6e4d0e8a557139acf7a753eecb1d43d05363 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Tue, 5 Nov 2019 12:41:09 +1300 Subject: [PATCH 13/16] fix aspect ratio and other improvements --- .../data-visualisation/js/data-visualisation.js | 7 +++---- .../data-visualisation/scss/data-visualisation.scss | 10 ++++++---- .../templates/interactives/data-visualisation.html | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 1f1bc1d57..41ca722f7 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -207,8 +207,7 @@ function buildPieChart() { }] }, options: { - responsive: false, - maintainAspectRatio: false, + responsive: true, legend: { display: true, position: 'right' @@ -249,7 +248,7 @@ function buildBarChart() { }] }, options: { - responsive: false, + responsive: true, legend: { display: false }, @@ -285,7 +284,7 @@ function buildResultsChart() { }] }, options: { - responsive: false, + responsive: true, legend: { display: false }, diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index 44f4e623d..0f7860856 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -2,10 +2,6 @@ @import "node_modules/bootstrap/scss/variables"; @import "node_modules/bootstrap/scss/mixins"; -#data-vis-title { - font-size: 2rem; -} - canvas { margin: auto; } @@ -21,6 +17,12 @@ table, th, td { border-collapse: collapse; } +#data-vis-results, #data-vis-game { + position: relative; + margin: auto; + max-width: 800px; +} + @include media-breakpoint-down(md) { table, th, td { padding: 5px; diff --git a/csfieldguide/templates/interactives/data-visualisation.html b/csfieldguide/templates/interactives/data-visualisation.html index b90f73585..351d8f867 100644 --- a/csfieldguide/templates/interactives/data-visualisation.html +++ b/csfieldguide/templates/interactives/data-visualisation.html @@ -5,7 +5,7 @@ {% block html %}
    -
    {% trans 'Data Visualisation' %}
    +

    {% trans 'Data Visualisation' %}

    {% blocktrans %} @@ -18,7 +18,7 @@
    - @@ -30,7 +30,7 @@ - +
    From 96664ba67cf798cffdc252a9ed0e098fc616dd32 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Wed, 6 Nov 2019 10:22:16 +1300 Subject: [PATCH 14/16] fix bug from merge --- csfieldguide/interactives/content/structure/interactives.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csfieldguide/interactives/content/structure/interactives.yaml b/csfieldguide/interactives/content/structure/interactives.yaml index 9a35a3e75..b84a97cd9 100644 --- a/csfieldguide/interactives/content/structure/interactives.yaml +++ b/csfieldguide/interactives/content/structure/interactives.yaml @@ -114,7 +114,7 @@ confusing-error: data-bias: languages: en: interactives/data-bias.html - is_interactive: true + is_interactive: true data-visualisation: languages: en: interactives/data-visualisation.html From e9f95a00f202e55af04b308c7ce38d68ba0988aa Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Wed, 6 Nov 2019 10:48:04 +1300 Subject: [PATCH 15/16] changes to follow style rules --- .../js/data-visualisation.js | 129 +++++++++--------- .../scss/data-visualisation.scss | 12 +- 2 files changed, 69 insertions(+), 72 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 41ca722f7..5f4041a82 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -1,8 +1,3 @@ -// For readability this is the variable name syntax used: -// const = CAPS -// global = CamelCase (start upper) -// local = camelCase (start lower) - const CHART = require('chart.js'); const MIN = 0; // Numbers for data @@ -30,21 +25,23 @@ const HEATMAP = [ // Heatmap colours "#d400bf","#d80092","#dc0063","#e00032","#e50000", ]; -var CurrentChart; // Chart to be rendered +var dataVis = {}; // https://google.github.io/styleguide/javascriptguide.xml#Naming + +dataVis.renderChart; // Chart to be rendered -var NumDataPoints; // Number of values in the data +dataVis.numberOfDataPoints; // Number of values in the data -var Solutions; // List of lists: [[type of representation, correct answer]] -var Responses; // User's choices +dataVis.typesAndSolutions; // List of lists: [[type of representation, correct answer]] +dataVis.userResponses; // User's choices -var DataSet; -var Frequencies; // Frequency of each value in DataSet +dataVis.currentDataSet; +dataVis.dataFrequencies; // Frequency of each value in dataVis.currentDataSet -var BarChart; // Charts -var PieChart; -var ResultsChart; +dataVis.chartBar; // Charts +dataVis.chartPie; +dataVis.chartResults; -var BaseTable; // For storing just the headings of the results table +dataVis.tableHeadings; // For storing just the headings of the results table $(document).ready(function() { init(); @@ -62,16 +59,16 @@ $(document).ready(function() { function init() { showStartScreen(); - CurrentChart = CHART_TYPES.GRID; - NumDataPoints = BASE_DATA_POINTS; - Solutions = []; - Responses = []; - DataSet = []; - Frequencies = {}; - if (BaseTable) { - $('#data-vis-performance').html(BaseTable); + dataVis.renderChart = CHART_TYPES.GRID; + dataVis.numberOfDataPoints = BASE_DATA_POINTS; + dataVis.typesAndSolutions = []; + dataVis.userResponses = []; + dataVis.currentDataSet = []; + dataVis.dataFrequencies = {}; + if (dataVis.tableHeadings) { + $('#data-vis-performance').html(dataVis.tableHeadings); } else { - BaseTable = $('#data-vis-performance').html(); + dataVis.tableHeadings = $('#data-vis-performance').html(); } newDataSet(); @@ -91,8 +88,8 @@ function runStart() { */ function runGuessCheck() { var guess = $('#data-vis-selector').val(); - Responses.push(guess); - if (Responses.length != Solutions.length) { // At this point the two should always be equal + dataVis.userResponses.push(guess); + if (dataVis.userResponses.length != dataVis.typesAndSolutions.length) { // At this point the two should always be equal console.log("ERROR: Number of responses does not match number of solutions.") } populatePerformanceTable(); @@ -121,15 +118,15 @@ function runQuit() { * If the loop has completed, doubles the amount of data to create, up to MAX_DATA_POINTS */ function getNextChart() { - if (CurrentChart == CHART_TYPES.GRID) { - CurrentChart = CHART_TYPES.MAP; - } else if (CurrentChart == CHART_TYPES.MAP) { - CurrentChart = CHART_TYPES.PIE; - } else if (CurrentChart == CHART_TYPES.PIE) { - CurrentChart = CHART_TYPES.BAR; - } else /*(CurrentChart == CHART_TYPES.BAR)*/ { - NumDataPoints = Math.min(MAX_DATA_POINTS, NumDataPoints * 2); // More data points for the next cycle - CurrentChart = CHART_TYPES.GRID; + if (dataVis.renderChart == CHART_TYPES.GRID) { + dataVis.renderChart = CHART_TYPES.MAP; + } else if (dataVis.renderChart == CHART_TYPES.MAP) { + dataVis.renderChart = CHART_TYPES.PIE; + } else if (dataVis.renderChart == CHART_TYPES.PIE) { + dataVis.renderChart = CHART_TYPES.BAR; + } else /*(dataVis.renderChart == CHART_TYPES.BAR)*/ { + dataVis.numberOfDataPoints = Math.min(MAX_DATA_POINTS, dataVis.numberOfDataPoints * 2); // More data points for the next cycle + dataVis.renderChart = CHART_TYPES.GRID; } } @@ -140,7 +137,7 @@ function buildChart() { $('#data-vis-barchart').addClass('d-none'); $('#data-vis-piechart').addClass('d-none'); $('#data-vis-grid').addClass('d-none'); - var type = CurrentChart; + var type = dataVis.renderChart; if (type == CHART_TYPES.GRID || type == CHART_TYPES.MAP) { buildGridChart(); } else if (type == CHART_TYPES.BAR) { @@ -156,7 +153,7 @@ function buildChart() { * If the representation should be a heatmap, also colours each grid square appropriately */ function buildGridChart() { - var numValues = DataSet.length; + var numValues = dataVis.currentDataSet.length; // We can afford to have fewer columns with a low number of values var numColumns = numValues > (BASE_DATA_POINTS * 3) ? (BASE_DATA_POINTS / 2) : (BASE_DATA_POINTS / 4); @@ -166,10 +163,10 @@ function buildGridChart() { while (i < numValues) { html += "\n"; for (var x=0; x < numColumns; x++) { - if (CurrentChart == CHART_TYPES.MAP) { - html += "" + DataSet[i] + "\n"; + if (dataVis.renderChart == CHART_TYPES.MAP) { + html += "" + dataVis.currentDataSet[i] + "\n"; } else { - html += "" + DataSet[i] + "\n"; + html += "" + dataVis.currentDataSet[i] + "\n"; } i++; } @@ -185,19 +182,19 @@ function buildGridChart() { function buildPieChart() { var valueLabels = []; var dataPoints = []; - for (var i in Frequencies) { - if (Frequencies[i]) { + for (var i in dataVis.dataFrequencies) { + if (dataVis.dataFrequencies[i]) { valueLabels.push(i.toString()); - dataPoints.push(Math.round(Frequencies[i] / DataSet.length * 100)); // Percentage of total + dataPoints.push(Math.round(dataVis.dataFrequencies[i] / dataVis.currentDataSet.length * 100)); // Percentage of total } } var canvas = $('#data-vis-piechart'); - if (PieChart) { - PieChart.destroy(); + if (dataVis.chartPie) { + dataVis.chartPie.destroy(); } canvas.attr('width', Math.min(600, 0.8 * $( window ).width())); // 600 is the value in the html canvas.attr('height', canvas.attr('width') / 2); - PieChart = new CHART.Chart(canvas, { + dataVis.chartPie = new CHART.Chart(canvas, { type: 'pie', data: { labels: valueLabels, @@ -227,17 +224,17 @@ function buildPieChart() { function buildBarChart() { var valueLabels = []; var dataPoints = []; - for (var i in Frequencies) { + for (var i in dataVis.dataFrequencies) { valueLabels.push(i.toString()); - dataPoints.push(Frequencies[i]); + dataPoints.push(dataVis.dataFrequencies[i]); } var canvas = $('#data-vis-barchart'); - if (BarChart) { - BarChart.destroy(); + if (dataVis.chartBar) { + dataVis.chartBar.destroy(); } canvas.attr('width', Math.min(800, 0.8 * $( window ).width())); // 800 is the value in the html canvas.attr('height', canvas.attr('width') / 2); - BarChart = new CHART.Chart(canvas, { + dataVis.chartBar = new CHART.Chart(canvas, { type: 'bar', data: { labels: valueLabels, @@ -268,12 +265,12 @@ function buildResultsChart() { var valueLabels = [CHART_TYPES.GRID, CHART_TYPES.MAP, CHART_TYPES.PIE, CHART_TYPES.BAR]; var dataPoints = getFinalResults(); var canvas = $('#data-vis-results-chart'); - if (ResultsChart) { - ResultsChart.destroy(); + if (dataVis.chartResults) { + dataVis.chartResults.destroy(); } canvas.attr('width', Math.min(800, 0.8 * $( window ).width())); // 800 is the value in the html canvas.attr('height', canvas.attr('width') / 2); - ResultsChart = new CHART.Chart(canvas, { + dataVis.chartResults = new CHART.Chart(canvas, { type: 'bar', data: { labels: valueLabels, @@ -309,7 +306,7 @@ function buildResultsChart() { function populatePerformanceTable() { var table = $('#data-vis-performance'); - var data = [last(Solutions), last(Responses)]; // [[type, solution], response] + var data = [last(dataVis.typesAndSolutions), last(dataVis.userResponses)]; // [[type, solution], response] var newRow = "\n" + "" + data[0][0] + "\n" + "" + data[0][1] + "\n" @@ -325,8 +322,8 @@ function populatePerformanceTable() { * [grid, heatmap, pie, bar] */ function getFinalResults() { - var localSolutions = Solutions; // List of [[type, solution]] - var localResponses = Responses; // List of [response] + var localSolutions = dataVis.typesAndSolutions; // List of [[type, solution]] + var localResponses = dataVis.userResponses; // List of [response] var proportionGrid = [0, 0]; // [correct, out-of] var proportionHeatmap = [0, 0]; var proportionPie = [0, 0]; @@ -367,14 +364,14 @@ function getFinalResults() { * Also sets the next solution appropriately. */ function newDataSet() { - fillDataSet(NumDataPoints); + fillDataSet(dataVis.numberOfDataPoints); var [solution, frequencies] = getFrequencies(); - Solutions.push([CurrentChart, solution]) - Frequencies = frequencies; + dataVis.typesAndSolutions.push([dataVis.renderChart, solution]) + dataVis.dataFrequencies = frequencies; } /** - * Sets the 'DataSet' global to a list of the given number of random values. + * Sets the 'dataVis.currentDataSet' global to a list of the given number of random values. */ function fillDataSet(num) { var newDataSet = []; @@ -382,15 +379,15 @@ function fillDataSet(num) { newDataSet.push(getRandomInteger(MIN, MAX)) } - DataSet = newDataSet; + dataVis.currentDataSet = newDataSet; } /** * Returns two values in a list: * [ - * The mode (most common value) of the global DataSet - ensuring only one value is most common + * The mode (most common value) of the global dataVis.currentDataSet - ensuring only one value is most common * , - * The frequency of each value in the global DataSet + * The frequency of each value in the global dataVis.currentDataSet * ] * * If two or more values share the mode (most common value), one of the mode values is chosen at random. @@ -402,7 +399,7 @@ function getFrequencies() { var modes = []; var frequencies = {}; var max = 0; - var localDataSet = DataSet; // Store a copy locally for performance + var localDataSet = dataVis.currentDataSet; // Store a copy locally for performance for (var v in localDataSet) { frequencies[localDataSet[v]] = (frequencies[localDataSet[v]] || 0) + 1; if (frequencies[localDataSet[v]] == max) { // More than one current mode @@ -422,7 +419,7 @@ function getFrequencies() { randomValue++; } frequencies[localDataSet[randomValue]]--; // Reduce the frequecy of that number - DataSet[randomValue] = mode; // Set best mode (actual DataSet) + dataVis.currentDataSet[randomValue] = mode; // Set best mode (actual dataVis.currentDataSet) frequencies[localDataSet[randomValue]]++; // Increase the frequency of best-mode } else { mode = modes[0]; diff --git a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss index 0f7860856..2e38258c8 100644 --- a/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss +++ b/csfieldguide/static/interactives/data-visualisation/scss/data-visualisation.scss @@ -10,9 +10,9 @@ table, th, td { margin: auto; font-family: monospace; text-align: center; - padding: 15px; - padding-left: 50px; - padding-right: 50px; + padding: 1rem; + padding-left: 3rem; + padding-right: 3rem; border: 1px solid #000; border-collapse: collapse; } @@ -25,8 +25,8 @@ table, th, td { @include media-breakpoint-down(md) { table, th, td { - padding: 5px; - padding-left: 15px; - padding-right: 15px; + padding: 0.3rem; + padding-left: 1rem; + padding-right: 1rem; } } From e3ffaedd66ef02c6ffae07ee18bc899289acf3d7 Mon Sep 17 00:00:00 2001 From: eAlasdair Date: Wed, 6 Nov 2019 10:50:08 +1300 Subject: [PATCH 16/16] minor fixes --- .../data-visualisation/js/data-visualisation.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js index 5f4041a82..192d1e2df 100644 --- a/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js +++ b/csfieldguide/static/interactives/data-visualisation/js/data-visualisation.js @@ -156,7 +156,7 @@ function buildGridChart() { var numValues = dataVis.currentDataSet.length; // We can afford to have fewer columns with a low number of values - var numColumns = numValues > (BASE_DATA_POINTS * 3) ? (BASE_DATA_POINTS / 2) : (BASE_DATA_POINTS / 4); + var numColumns = numValues > (65) ? (8) : (4); var html = ""; var i=0; @@ -323,8 +323,8 @@ function populatePerformanceTable() { */ function getFinalResults() { var localSolutions = dataVis.typesAndSolutions; // List of [[type, solution]] - var localResponses = dataVis.userResponses; // List of [response] - var proportionGrid = [0, 0]; // [correct, out-of] + var localResponses = dataVis.userResponses; // List of [response] + var proportionGrid = [0, 0]; // [correct, out-of] var proportionHeatmap = [0, 0]; var proportionPie = [0, 0]; var proportionBar = [0, 0]; @@ -399,7 +399,7 @@ function getFrequencies() { var modes = []; var frequencies = {}; var max = 0; - var localDataSet = dataVis.currentDataSet; // Store a copy locally for performance + var localDataSet = dataVis.currentDataSet; // Store a copy locally for performance for (var v in localDataSet) { frequencies[localDataSet[v]] = (frequencies[localDataSet[v]] || 0) + 1; if (frequencies[localDataSet[v]] == max) { // More than one current mode @@ -419,7 +419,7 @@ function getFrequencies() { randomValue++; } frequencies[localDataSet[randomValue]]--; // Reduce the frequecy of that number - dataVis.currentDataSet[randomValue] = mode; // Set best mode (actual dataVis.currentDataSet) + dataVis.currentDataSet[randomValue] = mode; // Set best mode (actual dataVis.currentDataSet) frequencies[localDataSet[randomValue]]++; // Increase the frequency of best-mode } else { mode = modes[0];