diff --git a/LICENCE-THIRD-PARTY b/LICENCE-THIRD-PARTY
index c35283e64..300edb7a7 100644
--- a/LICENCE-THIRD-PARTY
+++ b/LICENCE-THIRD-PARTY
@@ -183,6 +183,15 @@ licensed under MIT licence.
third-party-licences/cytoscape-no-overlap.txt
==============================================================================
+==============================================================================
+Bias in Big Data
+------------------------------------------------------------------------------
+https://github.com/NCC74656/Bias-In-Big-Data-Interactive
+Copyright 2019 Mark Henszey Wolgin
+licensed under MIT licence.
+third-party-licences/bias-in-big-data.txt
+==============================================================================
+
==============================================================================
del
------------------------------------------------------------------------------
diff --git a/csfieldguide/interactives/content/en/interactives.yaml b/csfieldguide/interactives/content/en/interactives.yaml
index b3ee91f6e..13bedddc2 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-bias:
+ name: Data Bias
date-picker:
name: Date Picker
deceiver:
diff --git a/csfieldguide/interactives/content/structure/interactives.yaml b/csfieldguide/interactives/content/structure/interactives.yaml
index 1778c9124..4e8805c8a 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-bias:
+ languages:
+ en: interactives/data-bias.html
+ is_interactive: true
date-picker:
languages:
en: interactives/date-picker.html
diff --git a/csfieldguide/package.json b/csfieldguide/package.json
index adf4c76be..b7b4f4318 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-bias": "file:./static/interactives/data-bias/",
"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-bias/README.md b/csfieldguide/static/interactives/data-bias/README.md
new file mode 100644
index 000000000..f6844f3aa
--- /dev/null
+++ b/csfieldguide/static/interactives/data-bias/README.md
@@ -0,0 +1,25 @@
+# Data Bias interactive
+
+**Created by:**
+
+- Sofia DiGirolamo
+- Minji Kong
+- Korey Mitchell
+- Mark Wolgin
+
+The original can be found [here](https://github.com/NCC74656/Bias-In-Big-Data-Interactive).
+
+**Rebuilt by:** Courtney Bracefield
+
+This interactive demonstrates how small changes in selection and perception can change the result of a study or competition.
+The user will learn how to better view data by altering their perspective.
+
+## The interactive
+
+The user is presented with a number of coloured circles placed on a coloured background and is asked to click the visible circles.
+Some circles are the same colour as the background and therefore near impossible to find.
+The interactive then reveals the hidden circles and allows the user to change the background colour via a slider.
+
+## Licences
+
+The licence of the original interactive can be found in `LICENCE-THIRD-PARTY` with a full copy available in the `third-party-licences` directory.
diff --git a/csfieldguide/static/interactives/data-bias/css/data-bias.scss b/csfieldguide/static/interactives/data-bias/css/data-bias.scss
new file mode 100644
index 000000000..474c9f6a3
--- /dev/null
+++ b/csfieldguide/static/interactives/data-bias/css/data-bias.scss
@@ -0,0 +1,122 @@
+@import "node_modules/nouislider/distribute/nouislider";
+@import "node_modules/bootstrap/scss/functions";
+@import "node_modules/bootstrap/scss/variables";
+@import "node_modules/bootstrap/scss/mixins";
+
+.circle {
+ border-radius: 50%;
+ width: 3.125rem;
+ height: 3.125rem;
+ position: absolute;
+}
+
+#circles-area {
+ position: relative;
+ border-radius: 1rem;
+}
+
+#data-bias-container {
+ padding: 4rem !important;
+}
+
+.noUi-pips {
+ padding-top: 0.3125rem;
+}
+
+.noUi-target {
+ border: none;
+ background: linear-gradient(
+ to right,
+ hsl(0,100%,50%),
+ hsl(60,100%,50%),
+ hsl(120,100%,50%),
+ hsl(180,100%,50%),
+ hsl(240,100%,50%),
+ hsl(300,100%,50%),
+ hsl(360,100%,50%)
+ );
+}
+
+.noUi-handle {
+ border: 0.125rem white solid;
+ height: 1.75rem !important;
+ width: 1.75rem !important;
+ border-radius: 50%;
+ top: -0.375rem !important;
+}
+
+.noUi-handle:before,
+.noUi-handle:after {
+ content: none;
+}
+
+.noUi-connect {
+ background: none;
+}
+
+.glow {
+ box-shadow: 0 0 1rem 0.5rem black;
+}
+
+.red {
+ background: red;
+}
+
+.lime {
+ background: lime;
+}
+
+.blue {
+ background: blue;
+}
+
+.yellow {
+ background: yellow;
+}
+
+.purple {
+ background: #9d03fc;
+}
+
+.darkorange {
+ background: darkorange;
+}
+
+.fuchsia {
+ background: fuchsia;
+}
+
+.deepskyblue {
+ background: deepskyblue;
+}
+
+.grey {
+ background: grey !important;
+}
+
+@include media-breakpoint-down(sm) {
+ #instruction-area,
+ #background-colour-slider-container {
+ padding: 0rem !important;
+ }
+
+ #data-bias-container {
+ padding: 1rem 3rem !important;
+ }
+
+ #instruction-text {
+ margin: 1rem 0rem;
+ }
+
+ .circle {
+ width: 2.5rem !important;
+ height: 2.5rem !important;
+ }
+}
+
+@include media-breakpoint-up(xl) {
+ #circles-area {
+ max-width: 60%;
+ max-height: 80%;
+ }
+}
diff --git a/csfieldguide/static/interactives/data-bias/js/data-bias.js b/csfieldguide/static/interactives/data-bias/js/data-bias.js
new file mode 100644
index 000000000..843bb5932
--- /dev/null
+++ b/csfieldguide/static/interactives/data-bias/js/data-bias.js
@@ -0,0 +1,186 @@
+const noUiSlider = require('nouislider');
+const wNumb = require('wnumb');
+
+const COLOURS = ['red', 'lime', 'blue', 'yellow', 'purple', 'darkorange', 'fuchsia', 'deepskyblue'];
+const START_TEXT = gettext("Click each dot that you see on the screen, then click 'Next stage' to reveal the answer!");
+const MISSED_CIRCLES_TEXT = gettext('You seem to have missed some dots!
Forced perspective like this can be used in data representation and cause bias in the overall results.');
+const SLIDER_TEXT = gettext('Click and drag the slider to change the background colour.
What do you notice is happening?')
+const SLIDER_MIN = 0;
+const SLIDER_MAX = 360;
+const PERENTAGE_BOUNDARY_UPPER = 85; // 85%
+const PERCENTAGE_ADJUSTMENT = 15; // 15%
+const PERENTAGE_BOUNDARY_LOWER = 5; // 5%
+const NUM_CIRCLES_TO_ADD = 8; // in addition to the 3 circles created that are the same colour as the background colour
+// below dictionary holds the 'H' value of the HSL colours.
+// these numbers correspond to the slider value of that colour, e.g blue is at value 240 on the slider.
+const SLIDER_COLOUR_VALUES = {
+ 'red': 0,
+ 'lime': 120,
+ 'blue': 240,
+ 'yellow': 60,
+ 'purple': 277,
+ 'darkorange': 33,
+ 'fuchsia': 300,
+ 'deepskyblue': 195
+}
+var firstStage = true;
+var bgColourSlider = $('#background-colour-slider');
+var sliderStartPos = 0;
+var startColour = 'red';
+
+
+$(document).ready(function() {
+ init();
+ $('#next-stage').click(loadNextStage);
+ $('#start-again').click(restartInteractive);
+});
+
+
+/**
+ * Returns everything to the inital 'page loaded' state.
+ */
+function init() {
+ // get random background colour to start
+ startColour = getRandomColour();
+ sliderStartPos = SLIDER_COLOUR_VALUES[startColour];
+ $('#circles-area').addClass(startColour);
+ // make sure we have at least 2 circles that are the same as the background colour
+ // a third circle is added later in loadNextStage to make sure the user NEVER finds all of the circles
+ createCircle(startColour);
+ createCircle(startColour);
+ // generate 8 more randomly coloured circles
+ for (i=0; i < NUM_CIRCLES_TO_ADD; i++) {
+ createCircle();
+ }
+ $('#next-stage').removeClass('d-none');
+ $('#start-again').addClass('d-none');
+ createSlider();
+ bgColourSlider[0].noUiSlider.on('update', updateSlider);
+}
+
+
+/**
+ * Creates slider that controls background colour.
+ */
+function createSlider() {
+ noUiSlider.create(bgColourSlider[0], {
+ start: sliderStartPos,
+ step: 1,
+ connect: "lower",
+ orientation: "horizontal",
+ range: {
+ 'min': SLIDER_MIN,
+ 'max': SLIDER_MAX
+ },
+ format: wNumb({
+ decimals: 0
+ })
+ });
+}
+
+
+/**
+ * Updates background colour when slider is moved.
+ */
+function updateSlider() {
+ var value = bgColourSlider[0].noUiSlider.get();
+ hslColour = 'hsl(' + value + ', 100%, 50%)';
+ $('#circles-area').css('background', hslColour);
+ $('.noUi-handle').css('background', hslColour);
+}
+
+
+/**
+ * Returns a random position in the form of {top: ..., left: ...} to randomly place circles.
+ */
+function getRandomPosition() {
+ var circlesAreaHeight = $('#circles-area').height();
+ var circlesAreaWidth = $('#circles-area').width();
+ var randHeight = Math.floor((Math.random() * circlesAreaHeight));
+ var randWidth = Math.floor((Math.random() * circlesAreaWidth));
+
+ // convert px to %
+ heightInPercentage = Math.floor((randHeight / circlesAreaHeight) * 100);
+ widthInPercentage = Math.floor((randWidth / circlesAreaWidth) * 100);
+
+ // reduces or increases percentage by 5% to prevent circles going outside of parent
+ if (heightInPercentage >= PERENTAGE_BOUNDARY_UPPER) {
+ heightInPercentage -= PERCENTAGE_ADJUSTMENT;
+ } else if (heightInPercentage <= PERENTAGE_BOUNDARY_LOWER) {
+ heightInPercentage += PERCENTAGE_ADJUSTMENT
+ }
+ if (widthInPercentage >= PERENTAGE_BOUNDARY_UPPER) {
+ widthInPercentage -= PERCENTAGE_ADJUSTMENT;
+ } else if (widthInPercentage <= PERENTAGE_BOUNDARY_LOWER) {
+ widthInPercentage += PERCENTAGE_ADJUSTMENT;
+ }
+
+ return {
+ top: heightInPercentage + '%',
+ left: widthInPercentage + '%'
+ };
+}
+
+
+/**
+ * Creates a circle div and adds it to the page.
+ */
+function createCircle(colour) {
+ var colour = colour || getRandomColour();
+ var $circle = $("
{% trans 'Note: If there is an error in the list, please contact Jack Morgan' %}
diff --git a/csfieldguide/templates/interactives/data-bias.html b/csfieldguide/templates/interactives/data-bias.html new file mode 100644 index 000000000..992a015da --- /dev/null +++ b/csfieldguide/templates/interactives/data-bias.html @@ -0,0 +1,29 @@ +{% extends interactive_mode_template %} + +{% load i18n %} +{% load static %} + +{% block html %} +