//*************************************************************************************//
//*************************************************************************************//
// //
// RESPONDER FOR THE PBS SEXISM QUIZ //
// ---------------------------------------- //
// //
// instructions for use: //
// //
// 1. create a robot respondent to answer the quiz on your behalf. //
// - var r1 = new respondent(name, gender, age, american, education, salary); //
// //
// 2. set the respondent off doing the quiz, passing in the respondent object. //
// - do_quiz(r1); //
// //
//*************************************************************************************//
//*************************************************************************************//
// each time a quiz is submitted or restarted, the browser reloads and the script is read.
// memento is called at the bottom of the script, and it reads a note left by the last function
// called before reload, if there was one. memento then calls the next appropriate function,
// according to the status indicated by the note.
function memento() {
var fname;
var status;
var read_me;
var respondent = {};
var note_to_self = {};
// see if there is a \'read me\' note in session storage, which will tell us who we are and what we
// are supposed to be doing. if there is no note, then it means that we have just started the quiz.
if (sessionStorage.read_me !== null) {
read_me = sessionStorage.getItem(\'read_me\');
note_to_self = JSON.parse(read_me);
fname = note_to_self.fname;
status = note_to_self.status;
} else {
status = \'ready to start\';
}
// if the \'read me\' note gives us a \'ready to start\' status, then we are just starting the quiz. output
// instructions to the user on how to make a respondent and start them off doing the quiz.
if (status == \'ready to start\') {
console.log(\'ready: \');
console.log(\'create a respondent, like this: r1 = new respondent(fname, gender, age, american, education, salary);\');
console.log(\'then set them off doing the quiz, like this: do_quiz(r1);\');
console.log(\'you can harvest the results once they are done.\');
// if status is \'ready for next pass\', then we have just done one pass of the quiz and are ready for the next.
// wake the respondent up and set them going on the next pass. the respondent will do 6 x 12 = 72 passes of the
// quiz in total (12 questions, 6 options for each).
} else if (status == \'ready for next pass\') {
respondent = cryogenic_suspension(fname, \'wake\');
do_quiz(respondent);
// if the status in the note is \'ready to process results\', then we have done a pass of the quiz and submitted it, and
// now we are looking at the results. wke up our respondet and get them to write down the results and put them in their
// jacket pocket.
} else if (status == \'ready to process results\') {
respondent = cryogenic_suspension(fname, \'wake\');
process_results(respondent);
// if the status in the note reads \'ready to output results\', then we have done all 72 passes of the quiz and we want
// to output them to the console in a rough and ready kind of csv format. wake our respondent up and get the results
//out of his or her jacket pocket.
} else if (status == \'ready to output results\') {
respondent = cryogenic_suspension(fname, \'wake\');
do_debrief(respondent);
// if the status in the note reads \'done\', then there is nothing else for our respondent to do. He or she is asleep now, and
// we won\'t wake them. They deserve the rest. put their name in a list of respondents currently in sessionStorage so we can
// get in touch with them if we need to, remove the \'read me\' note so we\'re ready to start afresh with a new respondent, and
// call memento again to display the welcome message.
} else if (status == \'done\') {
sessionStorage.setItem(\'retired_respondents\', fname);
sessionStorage.removeItem(\'read_me\');
memento();
}
}
// constructor for respondent objects. respondent objects hold the personal details
// of the \'respondent\' answering the quiz, and also the results of their questionnaire
// responses. each respondent will give all possible answers to each (non personal)
// question on the quiz, while holding all the other answers at a constant middle value.
// each respondent will therefore recieve 6 x 12 = 72 result sets.
function respondent(fname, gender, age, american, education, salary) {
this.fname = fname;
this.gender = gender;
this.age = age;
this.american = american;
this.education = education;
this.salary = salary;
this.current_pass = 1;
this.current_focus_question = 1;
this.response_variation_value = 0;
this.codebook = get_codebook();
this.quiz_info = {\'status\': false};
this.result_set = [];
}
// make a codebook of the quiz questions and response levels.
function get_codebook() {
var codebook = {}; // codebook of questions and response levels.
var lev = []; // array of levels for each question.
var q_key; // serves as the question in the codebook and provedes the key for the arrays of response levels.
//there are 17 questions
for (var q = 1; q <= 17; q++) {
// q_key serves as a record of the question, and the key for the question arrays which are inside
// it in the codebook object
q_key = jQuery(\'#q\' + q + \'>.question_text\').text();
//get the number of options for the question in... um... question.
q_children = jQuery(\'#q\' + q + \'>ul\').children(\'li\').length;
//put the answers into the array lev
for (var a = 0; a < q_children; a++) {
lev[a] = jQuery(\'label[for="a\' + q + \'_\' + a + \'"]\').text();
}
codebook[q_key] = lev.slice();
lev = [];
}
return codebook;
}
// make the quiz responses. pass in the respondent and add the results for each pass of the
// quiz to the respondent object variables.
function do_quiz(respondent) {
// get the current focus question and response variation value for the respondent.
var current_focus_question = respondent.current_focus_question;
var response_variation_value = respondent.response_variation_value;
// answer each of the sexism questions. answer \'2\' (slightly agree) for each question (this is as
// close to a neutral response we can get), except the current focus question, which will be answered
// according to what pass we are currently on.
for (var question = 1; question <= 12; question++) {
var response = (question == current_focus_question) ? response_variation_value : 2;
jQuery(\'input[name=a\' + question + \'][value=\' + response + \']\').prop("checked",true);
}
// answer the questions about our respondent\'s personal details.
jQuery(\'input[name=a13][value="\' + respondent.gender +\'"]\').prop("checked",true);
jQuery(\'input[name=a14][value="\' + respondent.age +\'"]\').prop("checked",true);
jQuery(\'input[name=a15][value="\' + respondent.american +\'"]\').prop("checked",true);
jQuery(\'input[name=a16][value="\' + respondent.education +\'"]\').prop("checked",true);
jQuery(\'input[name=a17][value="\' + respondent.salary +\'"]\').prop("checked",true);
//submit the quiz to get the results.
do_submission(respondent);
}
// submit the form after writing a note-to-self to remind us what we are doing when we wake up
// from the page load.
function do_submission(respondent) {
// write a little note-to-self so that we know who we are and what we\'re supposed to be doing when
// we wake up after browser reload. Then submit.
var fname = respondent.fname;
write_note_to_self(fname, \'ready to process results\');
// store the respondent away so he/she doesn\'t get vaporized when the the results page gets
//loaded.
r = cryogenic_suspension(respondent, \'sleep\');
// submit once the responcence is safely in their chamber, or let us know if something goes wrong.
if (r === true) jQuery("#submit-quiz").submit(); else console.log("Cryo-pod malfunction.");
}
// once the quiz has been submitted, the results need to be processed. process_results() scrapes the scores
// from the screen and puts them in the responents jacket pocket (the inner one) for safe keeping until all the
// passes are done, when they can be output to the console.
function process_results(respondent) {
var hos = jQuery(\'#highcharts-0 svg g g:first-child text tspan\').html(); // the location of the result for hostile sexism in the html.
var ben = jQuery(\'#highcharts-2 svg g g:first-child text tspan\').html(); // the location of the result for benevolent sexism in the html.
var foc = respondent.current_focus_question; // the question the respondent is currently recursing over with all the possible permutations.
var val = respondent.response_variation_value; // the current option permutation we are getting results for.
var pass = respondent.current_pass; // current pass of the quiz. 72 passes will be made in total.
//load up an array of the results
var result = {
\'pass\': pass,
\'foc\': foc,
\'val\': val,
\'hos\': hos,
\'ben\': ben
};
// put this result with the others in the respondent\'s jacket pocket.
if (respondent.result_set === undefined) respondent.result_set = [result]; else respondent.result_set.push(result);
// if we don\'t already have it, get the results definitions and average scores for the populace (i think), and put them in our
// respondent\'s jacket pocket.
if (respondent.quiz_info.status === false) respondent.quiz_info = quiz_info(respondent);
// along with the results, our respondent is also keeping a note of which question and option they have to do next. level
//it up. level_up() also calls write_note_to_self() in order to update the status.
respondent = level_up(respondent);
// put the respondent into a deep, deep, frozen sleep.
r = cryogenic_suspension(respondent, \'sleep\');
// reset the quiz if the cryogenic suspension goes ok, or let us know if there\'s a problem. then reset the quiz so our respondent
// can do another pass, or output the results if he or she has done all 72 passes.
if (r === true) reset_quiz(); else console.log(\'Uhm... there was a bit of an issue with cryogenisis...\');
}
function quiz_info(respondent) {
//info from results page
var hos_def = jQuery(\'.results-description:eq(0) > p\').text(); // definition of hostile sexismm
var ben_def = jQuery(\'.results-description:eq(1) > p\').text(); // defiinition of benevolent sexism
var hos_male = jQuery(\'#highcharts-0 > svg > g.highcharts-data-labels > g:nth-child(2) > text > tspan\').text(); // average scores (for populace, i guess)
var hos_fem = jQuery(\'#highcharts-0 > svg > g.highcharts-data-labels > g:nth-child(3) > text > tspan\').text(); // average scores (for populace, i guess)
var ben_male = jQuery(\'#highcharts-2 > svg > g.highcharts-data-labels > g:nth-child(2) > text > tspan\').text(); // average scores (for populace, i guess)
var ben_fem = jQuery(\'#highcharts-2 > svg > g.highcharts-data-labels > g:nth-child(3) > text > tspan\').text(); // average scores (for populace, i guess)
var quiz_info = {\'status\': true, \'hos_def\': hos_def, \'ben_def\': ben_def, \'hos_male\': hos_male, \'hos_fem\': hos_fem, \'ben_male\': ben_male, \'ben_fem\': ben_fem};
return quiz_info;
}
// do another pass of the quiz. resets the form and goes back to the beginning.
function reset_quiz() {
window.location.assign(\'http://www.pbs.org/newshour/data/quiz/ambivalent-sexism?clear=true\');
}
function do_debrief(respondent) {
var fname = respondent.fname;
//output the result set.
output_result_set(respondent);
// output the codebook;
output_codebook(respondent);
//output the definitions of terms and population averages from the results page.
output_quiz_info(respondent);
// write our little \'read me\' note to update the respondent\'s status to indicate a job well done.
write_note_to_self(fname, \'done\');
//retire our respondent
r = cryogenic_suspension(fname, \'sleep\');
console.log(\'mission accomplished!\');
}
// ok! all passes of the quiz have been completed and it\'s time to harvest the results. print to
// the console in a ramshackle kind of csv format that can be tidied up fairly easily, afterwards.
function output_result_set(respondent) {
var fname = respondent.fname;
var gen = respondent.gender;
var age = respondent.age;
var american = respondent.american;
var edu = respondent.education;
var sal = respondent.salary;
var res = respondent.result_set;
/// csv header
var w = window.open();
w.document.writeln(\'<h2>Result Set</h2><br>\');
w.document.writeln(\'name,gender,age,american,education,salary,pass,question,value,hostile,benevolent\');
w.document.writeln(\'<br>\');
for (var i = 0; i < res.length; i++) {
// csv values. go through all the result slips in the respondent\'s tweed jacket pocket. The
// tweed is either being worn ironically or not, depending on the personal details provided
// for our respondent.
w.document.writeln(fname + \',\' + gen + \',\' + age + \',\' + american + \',\' + edu + \',\' + \'"\' + sal + \'"\'+ \',\' + respondent.result_set[i].pass + \',\' + respondent.result_set[i].foc + \',\' + respondent.result_set[i].val + \',\' + respondent.result_set[i].hos + \',\' + respondent.result_set[i].ben);
w.document.writeln(\'<br>\');
}
}
// output the codebook as a list of questions and response levels, in a separate browser window.
// this can be copied and pasted from the browser window and saved as a text file.
function output_codebook(respondent) {
var sorted_keys = Object.keys(respondent.codebook).sort();
var w = window.open();
w.document.writeln(\'<h2>Codebook</h2><br>\');
for (var q = 0; q < 17; q++) {
var lev = respondent.codebook[Object.keys(respondent.codebook)[q]].length;
w.document.writeln(\'<ul style="list-style:none;"><li>\' + Object.keys(respondent.codebook)[q] + \'<ul style="list-style:none;">\');
for (var a = 0; a < lev; a++) {
w.document.writeln(\'<li> [\' + a + \'] \' + respondent.codebook[Object.keys(respondent.codebook)[q]][a] + \'</li>\');
}
w.document.writeln(\'</ul></li><br>\');
w.document.writeln(\'</ul>\');
}
}
// output the quiz info in a separate browser window. this can be copied and pasted from the browser window and saved as a text file.
function output_quiz_info(respondent) {
var hos_def = respondent.quiz_info.hos_def;
var ben_def = respondent.quiz_info.ben_def;
var hos_male = respondent.quiz_info.hos_male;
var hos_fem = respondent.quiz_info.hos_fem;
var ben_male = respondent.quiz_info.ben_male;
var ben_fem = respondent.quiz_info.ben_fem;
var w = window.open();
w.document.writeln(\'<h2>Quiz Info</h2><br>\');
w.document.writeln(\'<p><b>Definitions</b></p>\');
w.document.writeln(\'<p>\' + hos_def + \'</p>\');
w.document.writeln(\'<p>\' + ben_def + \'</p>\');
w.document.writeln(\'<p><b>Population averages</b></p>\');
w.document.writeln(\'<p>Hostile sexism average - male: \' + hos_male + \'</p>\');
w.document.writeln(\'<p>Hostile sexism average - female: \' + hos_fem + \'</p>\');
w.document.writeln(\'<p>Benevolent sexism average - male: \' + ben_male + \'</p>\');
w.document.writeln(\'<p>Benevolent sexism average - female: \' + ben_fem + \'</p>\');
}
// we\'ve finished a pass of the quiz, so lets write an entry in our journal to remind us where we\'re at -
// we\'ll have been to sleep by the next time we need to know!
function level_up(respondent) {
var current_focus_question = respondent.current_focus_question;
var response_variation_value = respondent.response_variation_value;
var pass = respondent.current_pass;
//if we haven\'t iterated though all the possible responses to the current question...
if (response_variation_value < 5) {
// set our reminder to the next response.
response_variation_value++;
pass++;
write_note_to_self(respondent.fname, \'ready for next pass\');
// if we have made all possible responses to the current question but we haven\'t gone through all the questions, yet...
} else if (current_focus_question < 12) {
//set our reminder to start the next question.
response_variation_value = 0;
current_focus_question++;
pass++;
write_note_to_self(respondent.fname, \'ready for next pass\');
// if we\'ve done all responses to all questions...
} else {
// set our reminder to indicate such state of affairs.
write_note_to_self(respondent.fname, \'ready to output results\');
}
// put the reminder in our respondent\'s inside jacket pocket. next to their heart.
respondent.current_focus_question = current_focus_question;
respondent.response_variation_value = response_variation_value;
respondent.current_pass = pass;
return respondent;
}
// write a little note-to-self to remind us who we are and what we\'re supposed to be doing
// when we wake up... am i right, guys? eh? am i right?
function write_note_to_self(respondent_fname, status) {
// pack an array with the name of the respondent (by which they are awoken from thier slumber)
// and their status along the production line of this quiz.
var note_to_self = {
\'fname\': respondent_fname,
\'status\': status
};
//sessionStorage only accepts strings, so turn the array into a json string.
var read_me = JSON.stringify(note_to_self);
// put the note somewhere our respondent will see it.
sessionStorage.setItem(\'read_me\', read_me);
return true;
}
//cryogenically suspend our respondent so that he doesn\'t get vaporized by the page-load
//pay-load.
function cryogenic_suspension(respondent, mode) {
// if we\'re in sleep mode, put the respondent in a frozen sleep to evade the memory apocolypse that
// is a browser reload.
if (mode == \'sleep\') {
suspended_respondent = JSON.stringify(respondent);
sessionStorage.setItem(respondent.fname, suspended_respondent);
return true;
// if we are in wake mode, then the angel of death has passed over and we can thaw out our
//respondent and set them about their task once more.
} else if (mode == \'wake\') {
fetched_respondent = sessionStorage.getItem(respondent);
awoken_respondent = JSON.parse(fetched_respondent);
return awoken_respondent;
}
}
function stereotyped_respondent(description) {
var r;
if (description == \'male student\') r = new respondent(\'stuart\', \'male\', \'18-34\', \'no response\', \'high school or less\', \'< $30,000\');
if (description == \'female student\') r = new respondent(\'sally\', \'female\', \'18-34\', \'no response\', \'high school or less\', \'< $30,000\');
if (description == \'male professional\') r = new respondent(\'patrick\', \'male\', \'35-50\', \'no response\', \'bachelors degree or more\', \'$30,000 - $74,999\');
if (description == \'male professional\') r = new respondent(\'polly\', \'female\', \'35-50\', \'no response\', \'bachelors degree or more\', \'$30,000 - $74,999\');
if (description == \'Hugh Hefner\') r = new respondent(\'Hugh\', \'male\', \'88+\', \'no response\', \'bachelors degree or more\', \'> $75,000\');
if (description == \'Queen Elizabeth\') r = new respondent(\'Lizzy\', \'female\', \'88+\', \'no response\', \'high school or less\', \'> $75,000\');
return r;
}
function context_page() {
// open the context page on pbs website.
var w = window.open(\'http://www.pbs.org/newshour/rundown/are-you-sexist-take-this-quiz/\');
}
// clip out variable definitions, average scores, and other information from the quiz, to give us some background
// information. put this in our respondent\'s jacket pocket.
// | | | | | | | | | | | | | | | | | | |
// v v v v v v v v v v v v v v v v v v v
// -------------------> start the ball rolling <----------------------------- <--
// |
//--> -------------- read me ---------------------------------------------- <--
memento();
//--> ---------------------------- // memento boots the whole thing up <--
// //each time a new page is loaded
// | <--
///////////////////////////////------------------------------------------
// ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
// | | | | | | | | | | | | | | | | | | |