Rooney Rule Research Study

Initial Round Count

1516

Second Round Count

1502

Final Round Count

1604

Men in Final Round

1234

Women in Final Round

370

Competition Rounds

29

Round 2 Counts

Selected 0

  • RooneyInfo: 0
  • RooneyNoInfo: 0
  • Control: 204
  • total: 204

Selected 1

  • RooneyInfo: 410
  • RooneyNoInfo: 410
  • Control: 232
  • total: 1054

Selected 2

  • RooneyInfo: 76
  • RooneyNoInfo: 75
  • Control: 59
  • total: 210

Selected 3

  • RooneyInfo: 14
  • RooneyNoInfo: 14
  • Control: 5
  • total: 34
Export Documents
Users are automatically created an InitialRound group, and selects SecondRound group. Export SecondRound group.
  • 'prolificID',
  • 'condition',
  • 'teamKey',
  • 'existing1',
  • 'existing2',
  • 'finalist1',
  • 'finalist2',
  • 'finalist3',
  • 'numWFinal', # results will be 0, 1, 2 or 3 - this is the number of Women selected for second stage
Users randomly shown a SecondRound group, and selects FinalRound group. Export of FinalRound group.
  • 'prolificID',
  • 'condition',
  • 'teamKey',
  • 'existing1',
  • 'existing2',
  • 'finalist1', # from SecondRound team
  • 'finalist2', # from SecondRound team
  • 'finalist3', # from SecondRound team
  • 'numWFinal', # results will be 0, 1, 2 or 3 - this is the number of Women selected for second stage
  • 'chosenPlayer',
  • 'chosenPlayerW', # was the chosen player a woman 'yes' or 'no' -- currently 0 or 1
All candidates are randomly paired up and scored using their second round MR_Round2, JLAP_Round2 and Trivia_Round2 Each row is the winner of the match ups.
  • 'competitionKey',
  • 'matchKey',
  • 'winning_group',
  • 'teamKey',
  • 'condition',
  • 'teamType',
  • 'MRScore',
  • 'JLAPScore',
  • 'TriviaScore',
  • 'OverallScore',
  • 'prolificID_stage2',
  • 'prolificID_stage3',
Export the IDs of all of the winning members.
  • 'team_id',
  • 'prolificID_stage2',
  • 'prolificID_stage3'

About

Multi step survey connected by django application. To see the data go to https://z373615.research-it.wharton.upenn.edu/admin/.

Tables

CandidateGroup

  • group_id : primary_key
  • created_by
  • timestamp
  • validate : used for SecondRound and FinalRound to signify users that had made a candidate selection and completed their survey
  • selected: keeps track of Qualtrics survey selecting CandidateGroup


First Round Candidates (Inherited CandidateGroup)

  • members : 10 Members through InitialRelationship object
  • existing: 2 Members throughInitialExistingRelationship object


Second Round Candidates (Inherited CandidateGroup)

  • initial_round : foreignkey to InitialRound
  • members : 10 Members through SecondRelationship object
  • existing: 2 Members throughSecondExistingRelationship object


Final Round Candidates (Inherited CandidateGroup)

  • second_round: foreignkey to SecondRound
  • members : 10 Members through FinalRelationship object
  • existing: 2 Members throughFinalExistingRelationship object


Member

  • name: from csv upload
  • timestamp
  • prolific_id: from csv upload, change column name to match prolific_id
  • age: from csv upload
  • gender: from csv upload
  • race: from csv upload
  • education: from csv upload
  • occupation: from csv upload
  • homestate: from csv upload
  • gamesExperience: from csv upload
  • JLAP_Round1: from csv upload
  • JLAP_Round2: from csv upload
  • JLAP_Overall: from csv upload
  • Trivia_Round1: from csv upload
  • Trivia_Round2: from csv upload
  • Trivia_Overall: from csv upload
  • MR_Round1: from csv upload
  • MR_Round2: from csv upload
  • MR_Overall: from csv upload
  • Round1_Overall: from csv upload
  • Round2_Overall: from csv upload
  • Overall: from csv upload
  • existing_selected: count of if Member has been selected as an exisiting member of a team. It will only increment on gender = Man
  • first_round_selected: count of if Member has been selected as first_round of a team.
  • second_round_selected: cound of if Member has been selected as second_round of a team.
  • final_round: count of if Member has been delectred as final_round of a team.


Endpoints

  • https://z373615.research-it.wharton.upenn.edu/app/validate-pool/ [POST] validates the SecondRound and FinalRound candidate group that the user completed their survey and it is a valid result. This field is not being used anywhere in code other than to indicate that the participant completed their survey.
  • https://z373615.research-it.wharton.upenn.edu/app/existing-teammates/ [GET] two existing Member with gender = Man and creates a team with zero candidates. I have gone through the with the approach we discussed that the application will go through all of the Member with gender = Man n times before moving to n+1. This API call return two objects for each existing Member and the pk for the round created (InitialRound) to be used later - saved to EmbeddedData.
  • https://z373615.research-it.wharton.upenn.edu/app/first-candidate-pool/ [GET] get 10 Member candidates - 3 with gender = Woman and 7 with gender = Man and added to the same candidate group (InitialRound). Returns 12 objects and for 2 of the existing teammates and the 10 candidates to be used later - saved to EmbeddedData.
  • https://z373615.research-it.wharton.upenn.edu/app/advance-first-candidate-pool/ [POST] a list of the 3 primary keys associated with the selected Members. There is custom JavaScript that disables the Next button until at least 3 users are selected and at least one of them is a woman. It can technically take more than 3 users and has no ceiling. This API call creates the next round SecondRound and keeps the two existing members. These 5 Members can now be tracked and served to other participants in the next survey who will select from them and create the FinalRound.
  • https://z373615.research-it.wharton.upenn.edu/get-second-candidate-pool/ [GET] a random SecondRound team (3 candidates and 2 existing Member) and saves members as EmbeddedData.
  • https://z373615.research-it.wharton.upenn.edu/advance-second-candidate-pool/ [POST] sends the primary key of the selected Member. This is similar to the advance-first-candidate-pool where we use JavaScript to check and save data and prevent user from moving forward. This call creates the FinalRound which has the one candidate selected and the two existing Members seen in get_first_candidate_pool view.


# filter group of women Member, randomized and limited to least selected
w_least_first_round = Member.objects.all().filter(gender='Woman').order_by('?').filter(first_round_selected__in=w_list)[:3]

# filter group of men Member, randomized, excluding existing, limited to least selected
m_least_first_round = Member.objects.all().filter(gender='Man').order_by('?').filter(first_round_selected__in=m_list).exclude(pk__in=list(instance.existing.all().values_list('pk', flat=True)))[:7]

Landing Page reference

'initial_round' : InitialRound.objects.all().count(),
'second_round': SecondRound.objects.all().count(),
'final_round': FinalRound.objects.all().count(),
'man_final_round': FinalRound.objects.all().filter(gender='Man').count(),
'woman_final_round': FinalRound.objects.all().filter(gender='Woman').count(),


Survey Set Up

Stage 2 Survey


Survey selects 2 existing Member from CSV upload and saves them to InitialRound. In same survey, separate API call, 10 Member - 7 gender = Man and 3 gender = Woman are selected, excluding the existing members, so they will not be selected for both existing member and candidate. This survey creates SecondRound and saves existing Members and selected Members to newly created round.

Set Web Service > Survey Flow

existing teammates

  • test
  • qualtrics_id
  • Authorization


Saves existing, first_round_pk data fields to embedded data
static/img/existing_teammates_web_service.png_

first candidate pool

  • test
  • qualtrics_id
  • first_round_pk
  • Authorization


Saves existing, first_round and first_round_pk data fields to embedded data
static/img/first_candidate_pool_web_service.png

advance first candidate pool

  • test
  • candidate_pks
  • qualtrics_id = first_round_pk
  • Authorization


static/img/advance_first_candidate_pool_web_service.png

validate pool

  • test
  • round_pk
  • validate
  • Authorization


static/img/first_round_validate_pool_web_service.png

Set Embedded Data > Survey Flow

  • candidate_pks: default to error and saved over once selected.
  • condition: random number 0 or 1 will determine if participant must select 1 woman in round 2.
  • type: Control / Info / NoInfo or random number 0 / 1 / 2 respectively.

z373615/z373615/static/img/stage_2_embedded_data.png

Custom JavaScript > Survey Builder

Qualtrics.SurveyEngine.addOnReady(function()
{   let qid = 'QID395'
    let condition = Qualtrics.SurveyEngine.getEmbeddedData('condition');
    this.disableNextButton();
    let that = this;
    const count = 11;
    let selectSet = new Set ([]);
    let selectGender = {};
    let enable = false;
    let j = 1; // DOM Elements start at 1
    let m = 1; // member vars start at 0
    function createError(msg){
        let outer = document.getElementById(qid);
        let errEl = document.createElement('div');
        errEl.setAttribute('id', 'QR~'+qid+'~VALIDATION');
        errEl.setAttribute('class', 'ValidationError');
        errEl.setAttribute('role', 'alert');
        errEl.setAttribute('data-runtime-show','runtime.ErrorMsg');
        errEl.setAttribute('data-runtime-html','runtime.ErrorMsg');
        errEl.innerText = msg;
    }
    function hideError(){
        let errEl = document.getElementById('QR~'+qid+'~VALIDATION');
        errEl.style.display = 'none';
    }
    function updateError(msg){
        let errEl = document.getElementById('QR~'+qid+'~VALIDATION');
        errEl.style.display = 'block';
        errEl.innerText = msg;
    }
    function checkWoman(arr){
        let r = false;
        console.log(condition);
        if(condition != 0){
            /// if object has a woman in it
            if (Object.keys(arr).length == 3) {
                for(const s in arr) {
                    if (arr[s] === 'Woman'){
                        hideError();
                        r = true;
                    }
                }
            } else {
                let text = 'You must select 3 candidates total; one of which must be a woman.';
                updateError(text)
            }
        } else {
            if (Object.keys(arr).length == 3){
                hideError();
                r = true;
            } else {
                let text = 'You must select 3 candidates total.';
                updateError(text)
            }
        }
        return r
    }
    let msg = '';
    createError(msg)
    for (let i=1; i < count; i++){ 
        let qid = 'QID395'
        let idEl = qid+'-'+j+'-label';
        let El = document.getElementById(idEl);
        // ${e://Field/first_round.0.pk}
        El.setAttribute('data-ed',m)
        if(El){     
            El.parentElement.parentElement.previousElementSibling.addEventListener("click", function(e){
                let memberPk = ""; // member primary key value
                let memberEd = ""; // member embedded data field name
                debugger;
                memberPk = e.target.parentElement.nextSibling.nextSibling.nextSibling.nextSibling.childNodes[1].childNodes[1].childNodes[0].childNodes[3].childNodes[11].innerText;
                let gender = "";
                gender =e.target.parentElement.nextSibling.nextSibling.nextSibling.nextSibling.childNodes[1].childNodes[1].childNodes[0].childNodes[3].childNodes[2].textContent;
                // TOGGLE PKs
                if(selectSet.has(memberPk)){
                    selectSet.delete(memberPk)
                } else {
                    selectSet.add(memberPk)
                }
                // TOGGLE GENDER
                if(selectGender[memberPk]){
                    delete selectGender[memberPk];
                } else {
                    selectGender[memberPk] = gender;
                }
                gender = checkWoman(selectGender);
                let v = [...selectSet].join(', ');
                Qualtrics.SurveyEngine.setEmbeddedData('candidate_pks', v);
                if(gender){
                    that.enableNextButton();
                } else {
                    that.disableNextButton();
                }
            });
        }
        j++;
        m++;
    }
});


Stage 3 Survey

Survey selects SecondRound. This survey creates FinalRound and saves existing Members and selected Member to newly created FinalRound.

Set Web Service > Survey Flow

second candidate pool

  • test
  • qualtrics_id
  • Authorization


Saves existing, second_round_pk, condition and type data fields to embedded data
static/img/second_candidate_pool_web_service.png

advance second candidate pool

  • test
  • qualtrics_id
  • second_round_pk
  • candidate_pks
  • Authorization


static/img/advance_second_candidate_pool_web_service.png

validate pool

  • test
  • round_pk
  • validate
  • Authorization


static/img/second_round_validate_pool_web_service.png


Set Embedded Data > Survey Flow

  • candidate_pks: default to error and saved over once selected.

/z373615/static/img/stage_2_embedded_data.png


Custom JavaScript > Survey Builder

Qualtrics.SurveyEngine.addOnReady(function()
{   
    let qid = 'QID5';
    this.disableNextButton();
    let that = this;
    const count = 4;
    let selectSet = new Set ([]);
    let selectGender = {};
    let enable = false;
    let j = 1; // DOM Elements start at 1
    let m = 1; // member vars start at 0
    function createError(msg){
        let outer = document.getElementById(qid);
        let errEl = document.createElement('div');
        errEl.setAttribute('id', 'QR~'+qid+'~VALIDATION');
        errEl.setAttribute('class', 'ValidationError');
        errEl.setAttribute('role', 'alert');
        errEl.setAttribute('data-runtime-show','runtime.ErrorMsg');
        errEl.setAttribute('data-runtime-html','runtime.ErrorMsg');
        errEl.innerText = msg;
    }
    function hideError(){
        let errEl = document.getElementById('QR~'+qid+'~VALIDATION');
        errEl.style.display = 'none';
    }
    function updateError(msg){
        let errEl = document.getElementById('QR~'+qid+'~VALIDATION');
        errEl.style.display = 'block';
        errEl.innerText = msg;
    }
    function checkWoman(arr){
        /// if object has a woman in it
        if (Object.keys(arr).length = 1) {
            hideError();
            for(const s in arr) {
                if (arr[s]){
                    r = true;
                } else {
                    let text = 'You must select 1 candidates total.';
                    updateError(text)
                }
            }
        }
        return r
    }
    let msg = '';
    createError(msg)
    // for (let i=1; i < count; i++){ 
    //  let qid = 'QID4'
    //  let idEl = qid+'-'+j+'-label';
    //  let El = document.getElementById(idEl);
    //  // ${e://Field/first_round.0.pk}
    //  El.setAttribute('data-ed',m)
    //  if(El){     
    //    El.parentElement.parentElement.addEventListener("click", function(e){
    //          let memberPk = ""; // member primary key value
    //          let memberEd = ""; // member embedded data field name
    //          let El = document.getElementById(idEl);
    //          if (e.target.tagName === 'DIV' ){

    //          }
    //          memberPk = e.target.parentElement.childNodes[1].childNodes[1].childNodes[0].childNodes[0].childNodes[4].textContent;
    //          let gender = "";
    //          gender = e.target.parentElement.nextSibling.nextSibling.nextSibling.nextSibling.childNodes[1].childNodes[1].childNodes[0].childNodes[5].innerText;
    //          // TOGGLE PKs
    //          if(selectSet.has(memberPk)){
    //              selectSet.delete(memberPk)
    //          } else {
    //              selectSet.add(memberPk)
    //          }
    //            // TOGGLE GENDER
    //          if(selectGender[memberPk]){
    //              delete selectGender[memberPk];
    //          } else {
    //              selectGender[memberPk] = gender;
    //          }
    //          gender = checkWoman(selectGender);
    //          let v = [...selectSet].join(', ');
    //          Qualtrics.SurveyEngine.setEmbeddedData('candidate_pks', v);
    //          if(gender){
    //              that.enableNextButton();
    //          } else {
    //              that.disableNextButton();
    //          }
    //    });
    //  }
    //  j++;
    //  m++;
    // }
});
Qualtrics.SurveyEngine.addOnload(function()
{
jQuery("#"+this.questionId+" div.Items h2").html("Candidates for finalists");
jQuery("#"+this.questionId+" span.LabelWrapper").css("text-align", "left");

});

Qualtrics.SurveyEngine.addOnReady(function()
{   
    let qid = 'QID475';
    let that = this;
    const count = 4;
    let selectSet = new Set ([]);
    let selectGender = {};
    let enable = false;
    let j = 1; // DOM Elements start at 1
    let m = 1; // member vars start at 0
    function createError(msg){
        let outer = document.getElementById(qid);
        let errEl = document.createElement('div');
        errEl.setAttribute('id', 'QR~'+qid+'~VALIDATION');
        errEl.setAttribute('class', 'ValidationError');
        errEl.setAttribute('role', 'alert');
        errEl.setAttribute('data-runtime-show','runtime.ErrorMsg');
        errEl.setAttribute('data-runtime-html','runtime.ErrorMsg');
        errEl.innerText = msg;
    }
    function hideError(){
        let errEl = document.getElementById('QR~'+qid+'~VALIDATION');
        errEl.style.display = 'none';
    }
    function updateError(msg){
        let errEl = document.getElementById('QR~'+qid+'~VALIDATION');
        errEl.style.display = 'block';
        errEl.innerText = msg;
    }
    function checkWoman(arr){
        /// if object has a woman in it
        r = true;
        if (Object.keys(arr).length = 1) {
            hideError();
            for(const s in arr) {
                if (arr[s]){
                    r = true;
                } else {
                    let text = 'You must select 1 candidates total.';
                    updateError(text)
                }
            }
        }
        return r
    }
    let msg = '';
    createError(msg)
    let text = 'You must select 1 candidates total.';
    updateError(text)

});

Qualtrics.SurveyEngine.addOnload(function ()
{
    this.disableNextButton();
    this.questionclick = function(event,element)
    {
        if (element.type == 'radio')
        {
            var v = element.parentElement.parentElement.childNodes[1].childNodes[1].childNodes[0].childNodes[0].childNodes[4].textContent
            Qualtrics.SurveyEngine.setEmbeddedData('candidate_pks', v);
            console.log(v)
            var e = Qualtrics.SurveyEngine.getEmbeddedData('candidate_pks');
            console.log(e)
            this.enableNextButton();
        }
    }
});