Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recreate Data Bias interactive #1185

Merged
merged 20 commits into from
Nov 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions LICENCE-THIRD-PARTY
Original file line number Diff line number Diff line change
Expand Up @@ -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
------------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions csfieldguide/interactives/content/en/interactives.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions csfieldguide/interactives/content/structure/interactives.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions csfieldguide/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/",
Expand Down
25 changes: 25 additions & 0 deletions csfieldguide/static/interactives/data-bias/README.md
Original file line number Diff line number Diff line change
@@ -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.
122 changes: 122 additions & 0 deletions csfieldguide/static/interactives/data-bias/css/data-bias.scss
Original file line number Diff line number Diff line change
@@ -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%;
}
}
186 changes: 186 additions & 0 deletions csfieldguide/static/interactives/data-bias/js/data-bias.js
Original file line number Diff line number Diff line change
@@ -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! <br><br>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. <br><br>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 = $("<div>").addClass('circle ' + colour);
$circle.css(getRandomPosition());
// so overlapping circles don't give away the hidden circles
// brings non hidden circles up 1 layer
if (colour !== startColour) {
$circle.css('z-index', 1);
}
$('#circles-area').append($circle);
$circle.click(function() {
// toggle glow around clicked circle
$circle.toggleClass('glow');
});
}


/**
* Loads the next stage which is either revealing the hidden circles or adjusting the background colour with the slider.
*/
function loadNextStage() {
if (firstStage) {
// add a sneaky extra circle in the off chance they find all of the hidden circles :P
createCircle(startColour);
courtneycb marked this conversation as resolved.
Show resolved Hide resolved
$('#circles-area').removeClass(startColour);
$('#circles-area').addClass('grey');
$('#instruction-text').html(MISSED_CIRCLES_TEXT);
firstStage = false;
} else {
$('#instruction-text').html(SLIDER_TEXT);
$('.circle').removeClass('glow');
$('#circles-area').removeClass('grey');
$('#circles-area').addClass(startColour);
$('#next-stage').addClass('d-none');
$('#start-again').removeClass('d-none');
$('#background-colour-slider-container').removeClass('d-none');
}
}


/**
* Resets the interactive and calls init() to return page to the 'page loaded' state.
*/
function restartInteractive() {
$('.circle').remove();
$('#background-colour-slider-container').addClass('d-none');
firstStage = true;
$('#instruction-text').html(START_TEXT);
bgColourSlider[0].noUiSlider.destroy();
init();
}


/**
* Returns a random colour from the COLOURS array.
*/
function getRandomColour() {
return COLOURS[Math.floor(Math.random() * COLOURS.length)];
}
9 changes: 9 additions & 0 deletions csfieldguide/static/interactives/data-bias/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "csfg-interactive-data-bias",
"version": "1.0.0",
"private": true,
"dependencies": {
"nouislider": "13.1.5",
"wnumb": "1.2.0"
}
}
Loading