var init = function() {
  //set up stage
}

container = document.getElementById("container");
maskElement = document.getElementById("mask");
wordElement = document.getElementById("word");
wordLength = 6;

var timeoutPromise = function(duration) {
  return new Promise(function(fulfill, reject) {
    window.setTimeout(fulfill, duration);
  });
};

var showFixationRectangle = function() {
  container.className = "fixation-rectangle";

  return timeoutPromise(1000);
};

var showMask = function() {
  var mask = '';
  for (var i=0; i<= wordLength; i++) {
    mask += nonLetterCharacters[Math.floor(Math.random() * nonLetterCharacters.length)];
  }
  maskElement.textContent = mask;

  container.className = "mask";

  return timeoutPromise(200);
};

var showWord = function(word, exposureDuration) {
  wordElement.textContent = word;
  container.className = "word";

  return timeoutPromise(exposureDuration);
};

var awaitResponse = function(real) {
  container.className = "prompt";

  var listener;
  var promise = new Promise(function(fulfill, reject) {
    window.setTimeout(function() { reject("timeout"); }, 5000);

    listener = function(event) {
      if (event.keyCode === 81) {
        real ? fulfill("real") : reject("real");
      }
      else if (event.keyCode === 80) {
        real ? reject("pseudo") : fulfill("pseudo");
      }
    };

    document.addEventListener("keydown", listener);
  });

  promise.then(
    function() { document.removeEventListener("keydown", listener); },
    function() { document.removeEventListener("keydown", listener); }
  );

  return promise;
};

var runTrial = function(word, exposureDuration) {
  return showFixationRectangle()
    .then(showMask)
    .then(function() { return showWord(word.text, exposureDuration); })
    .then(showMask)
    .then(function() { return awaitResponse(word.real); });
};

var runSeries = function(words) {
  var words = words.slice(0),
      log = [],
      exposureDuration = 1000,
      x = function x() {
        if (words.length > 0) {
          var nextWord = words.shift(),
              trialResult = {
                word: nextWord.text,
                real: nextWord.real,
                duration: exposureDuration
              };

          return runTrial(nextWord, exposureDuration).then(
            function(response) {
              trialResult.response = response;
              log.push(trialResult);

              exposureDuration = exposureDuration * 0.75;
              return x();
            },
            function(response) {
              trialResult.response = response;
              log.push(trialResult);

              exposureDuration = exposureDuration * 1.5;
              return x();
            }
          );
        }
        else {
          return log;
        }
      };

  return x();
};

var wordList = [
  {text: "farted", real: true},
  {text: "guffed", real: true},
  {text: "trumpe", real: false},
  {text: "parped", real: true},
  {text: "flufed", real: false}
];

runSeries(wordList).then(function(log) {
  console.log(log);
});

@@ -1043,32 +1043,64 @@
 fill, reject) %7B%0A
+    var startTime = Date.now();%0A
     window.setTi
@@ -1125,16 +1125,27 @@
  reject(
+%7Bresponse: 
 %22timeout
@@ -1145,16 +1145,17 @@
 timeout%22
+%7D
 ); %7D, 50
@@ -1203,35 +1203,182 @@
     
-if (event.keyCode === 81) %7B
+var resolution = %7B%0A        response: undefined,%0A        responseTime: Date.now() - startTime%0A      %7D;%0A%0A      if (event.keyCode === 81) %7B%0A        resolution.response = %22real%22;
 %0A   
@@ -1397,22 +1397,26 @@
 fulfill(
-%22
 re
-al%22
+solution
 ) : reje
@@ -1418,22 +1418,26 @@
  reject(
-%22
 re
-al%22
+solution
 );%0A     
@@ -1474,24 +1474,64 @@
 e === 80) %7B%0A
+        resolution.response = %22pseudo%22;%0A
         real
@@ -1540,24 +1540,26 @@
  reject(
-%22pseudo%22
+resolution
 ) : fulf
@@ -1562,24 +1562,26 @@
 fulfill(
-%22pseudo%22
+resolution
 );%0A     
@@ -2547,32 +2547,92 @@
 function(res
-ponse) %7B
+olution) %7B%0A              trialResult.response = resolution.response;
 %0A           
@@ -2650,34 +2650,53 @@
 ult.response
+Time
  = res
-pons
+olution.responseTim
 e;%0A         
@@ -2851,16 +2851,76 @@
 (res
-ponse) %7B
+olution) %7B%0A              trialResult.response = resolution.response;
 %0A   
@@ -2954,18 +2954,37 @@
 onse
+Time
  = res
-pons
+olution.responseTim
 e;%0A 

Include response times in result log