Why does Javascript output NaN un-predictably? [HARD!] | XM Community
Skip to main content

Hello,
First time post here.
I just ran 1000 instances of an academic survey on Qualtrics. Respondents guess how other people answered some questions, and get a higher bonus the more accurate they are.
Here's how it works. Let's call the respondent John.
1) When John starts the survey, a web service in service flow calls a php script on an external server to receive other respondents' answers from a static SQL database and store as embedded data.
2) When John enters his guesses of others' answers, javascript stores his guesses in embedded data.
3) After John enters all guesses, another javascript retrieves his answers and other respondents' answers from embedded data. Then it calculates his bonus.
This works 99% of the time. But 1% of respondents get NaN as their bonus. I never get this bug, even when I enter the exact same guesses as John. But John told me he saw NaN, and indeed, that's what my data from Qualtrics says.
The php script ran successfully: the embedded data it retrieved are correctly present in the Qualtrics data. The bug must emerged either in storing the answers or in calculating the bonus.
Code below. Any ideas?
--- BEGIN ANSWER STORAGE JAVASCRIPT ---
var qinfo = Qualtrics.SurveyEngine.QuestionInfo;
var keys = Object.keys(qinfo);

// store x
var qid_x = keys[2];
var instance_x = Qualtrics.SurveyEngine.QuestionData.getInstance(qid_x);
var this_answer = instance_x.getChoiceRecodeValue(instance_x.getSelectedChoices()[0]);
Qualtrics.SurveyEngine.setEmbeddedData("answer_x_"+qid_x, this_answer);

// store y if not missing
if (keys.length > 3) {
  var qid_y = keysy3]
  for (var i=1; i < 4; i++) {
    istr = i.toString();
    var this_answer = document.getElementById("QR~"+qid_y+"~"+istr).value;
    Qualtrics.SurveyEngine.setEmbeddedData("answer_y"+istr+"_"+qid_x, this_answer);
  }
}
--- END ANSWER STORAGE JAVASCRIPT ---
--- BEGIN CALCULATE BONUS JAVASCRIPT ---
Qualtrics.SurveyEngine.addOnload(function()
{
var treatment = Qualtrics.SurveyEngine.getEmbeddedData("treatment");
var bonus_ed = "bonus_2";
var report_ed = "report_2";
var qid = "QID335";
var num_items = 30;
var start_item = 36;
calculate_bonus(treatment, qid, start_item, num_items, bonus_ed, report_ed);
});
function calculate_bonus(treatment, qid, start_item, num_items, bonus_ed, report_ed) {
  // get data
  var items = t];
  var answers_x = <];
  var answers_y_1 = <];
  var answers_y_2 = ]];
  var answers_y_3 = ];
  for (var i=0; i < num_items; i++) {
    var i_n = start_item + i;
    var istr = (i+1).toString();
    items.push(Qualtrics.SurveyEngine.getEmbeddedData("use"+i_n.toString()));
    var a_x = Qualtrics.SurveyEngine.getEmbeddedData("answer_x_"+istr+"_"+qid);
    answers_x.push(a_x);
    var a_y1 = Qualtrics.SurveyEngine.getEmbeddedData("answer_y1_"+istr+"_"+qid);
    answers_y_1.push(a_y1);
    var a_y2 = Qualtrics.SurveyEngine.getEmbeddedData("answer_y2_"+istr+"_"+qid);
    answers_y_2.push(a_y2);
    var a_y3 = Qualtrics.SurveyEngine.getEmbeddedData("answer_y3_"+istr+"_"+qid);
    answers_y_3.push(a_y3);
calculate_bonus_gc(items, answers_y_1, answers_y_2, answers_y_3, bonus_ed, report_ed, start_item, num_items)
  }

function calculate_bonus_gc(items, answers1, answers2, answers3, bonus_ed, report_ed, start_item, num_items) {

  // get shares for items in SQL query
  var item_list_str = "'"+items.join("','")+"'";
  var shares1 = Qualtrics.SurveyEngine.getEmbeddedData("share1").split(",").slice(start_item-1,start_item+num_items-1);
  var shares2 = Qualtrics.SurveyEngine.getEmbeddedData("share2").split(",").slice(start_item-1,start_item+num_items-1)
  var shares3 = Qualtrics.SurveyEngine.getEmbeddedData("share3").split(",").slice(start_item-1,start_item+num_items-1)

  // calculate scores
  var score = 0;
  for (var i=0; i < items.length; i++) {
    var dev1 = Math.abs(parseInt(answers1 i]) - parseInt(shares1;i]));
    var dev2 = Math.abs(parseInt(answers2ti]) - parseInt(shares21i]));
    var dev3 = Math.abs(parseInt(answers3=i]) - parseInt(shares3wi]));
    var this_score = (300 - (dev1 + dev2 + dev3)) / 300
    score += this_score;
  }

  // set amount
  var multiplier = 4;
  var bonus = Math.round(score * multiplier);
  var max = multiplier * items.length;

  // report
  var report = "Based on your answers to the questions about other participants' beliefs, your total bonus for this round is " + bonus.toString() + " cents, out of a possible " + max.toString() + " cents.";

  // set ed
  Qualtrics.SurveyEngine.setEmbeddedData(bonus_ed, bonus);
  Qualtrics.SurveyEngine.setEmbeddedData(report_ed, report);
}
--- END CALCULATE BONUS JAVASCRIPT ---

I haven't gone through your entire code because it's too long. However, it's possible that you are getting this error due to using

parseInt
. While
parseInt
will convert "0.24" to 0, it will give you NaN in the case of ".24".
Try changing that to
Math.round(Number(x))


Leave a Reply