<commit_before>// BufferedView draws the ChunkView and the labels, shows the loaders,
// and presents the splash screen for a YLCV.
//
// This view makes sure that the splash screen never appears for too short a time period,
// and provides a grace period for new content to load after old content is invalidated.
function BufferedView(config) {
  this._splashScreen = config.splashScreen;
  this._leftLoader = config.loader1;
  this._rightLoader = config.loader2;

  this._element = document.createElement('div');
  this._canvas = document.createElement('canvas');

  this._element.appendChild(this._splashScreen.element());

  var elements = [this._canvas, this._element, this._splashScreen.element()];
  makeElementsFillAndAbsolute(elements);

  this._width = 0;
  this._height = 0;

  this._context = null;
  this._pixelRatio = 0;
  this._crystalCallback = this._updatePixelRatio.bind(this, true);

  this._animate = false;
  this._state = BufferedView.STATE_SPLASH;
  this._splashStartTime = 0;
  this._timeout = null;

  this._chunkViewOffset = 0;
  this._chunkView = null;
  this._yLabels = null;

  this._currentCursorPosition = null;
  this._registerPointerEvents();
}

BufferedView.STATE_SPLASH = 0;
BufferedView.STATE_EPHEMERAL_SPLASH = 1;
BufferedView.STATE_CONTENT = 2;
BufferedView.STATE_EPHEMERAL_CONTENT = 3;

BufferedView.EPHEMERAL_CONTENT_TIME = 100;
BufferedView.EPHEMERAL_SPLASH_TIME = 300;

// element returns the root DOM element of the view.
BufferedView.prototype.element = function() {
  return this._element;
};

// context returns the 2D drawing context for the view's canvas.
// This may return null if the view is not visible.
BufferedView.prototype.context = function() {
  return this._context;
};

// layout updates the size of the BufferedView.
//
// You should manually call draw() after calling this.
BufferedView.prototype.layout = function(w, h) {
  this._width = Math.ceil(w);
  this._height = Math.ceil(h);

  this._element.style.width = this._width + 'px';
  this._element.style.height = this._height + 'px';

  this._updateCanvasSize();
  this._splashScreen.layout(this._width, this._height);
};

// getAnimate returns the animate flag, as described in setAnimate().
BufferedView.prototype.getAnimate = function() {
  return this._animate;
};

// setAnimate toggles the animate flag.
// If the animate flag is set, then the loaders and splash screen will animate.
// While the animate flag is set, the view listens for DPI changes.
BufferedView.prototype.setAnimate = function(flag) {
  if (flag === this._animate) {
    return;
  }
  this._animate = flag;
  if (flag) {
    window.crystal.addListener(this._crystalCallback);
    this._updatePixelRatio(false);
    if (this._state === BufferedView.STATE_SPLASH ||
        this._state === BufferedView.STATE_EPHEMERAL_SPLASH) {
      this._splashScreen.setAnimate(true);
    } else {
      this.draw();
    }
  } else {
    window.crystal.removeListener(this._crystalCallback);
    this._splashScreen.setAnimate(false);
    this._leftLoader.setAnimate(false);
    this._rightLoader.setAnimate(false);
  }
};

// getChunkView returns the current chunk view, or null if no chunk view is associated with this.
BufferedView.prototype.getChunkView = function() {
  return this._chunkView;
};

// setChunkView changes the ChunkView that this view uses to draw.
// You may pass null to indicate that there is no available ChunkView.
//
// You should manually call draw() after calling this.
//
// This may trigger a pointerMove() event on the new ChunkView, which may in
// turn trigger a draw(). To avoid this, you can postpone on() calls on the
// ChunkView until after setChunkView().
BufferedView.prototype.setChunkView = function(cv) {
  if (this._chunkView === cv) {
    return;
  }

  this._chunkView = cv;

  if (cv === null) {
    switch (this._state) {
    case BufferedView.STATE_SPLASH:
    case BufferedView.STATE_EPHEMERAL_CONTENT:
      break;
    case BufferedView.STATE_CONTENT:
      this._state = BufferedView.STATE_EPHEMERAL_CONTENT;
      this._timeout = setTimeout(this._showSplashScreen.bind(this),
        BufferedView.EPHEMERAL_CONTENT_TIME);
      break;
    case BufferedView.STATE_EPHEMERAL_SPLASH:
      this._state = BufferedView.STATE_SPLASH;
      clearTimeout(this._timeout);
      this._timeout = null;
      break;
    }
  } else {
    switch (this._state) {
    case BufferedView.STATE_CONTENT:
      if (this._currentCursorPosition !== null) {
        this._chunkView.pointerMove(this._currentCursorPosition);
      }
      break;
    case BufferedView.STATE_EPHEMERAL_SPLASH:
      break;
    case BufferedView.STATE_SPLASH:
      var splashTime = Math.max(0, new Date().getTime()-this._splashStartTime);
      if (splashTime < BufferedView.EPHEMERAL_SPLASH_TIME) {
        this._state = BufferedView.STATE_EPHEMERAL_SPLASH;
        this._timeout = setTimeout(this._showContent.bind(this),
          BufferedView.EPHEMERAL_SPLASH_TIME-splashTime);
      } else {
        this._showContent();
      }
      break;
    case BufferedView.STATE_EPHEMERAL_CONTENT:
      this._state = BufferedView.STATE_CONTENT;
      clearTimeout(this._timeout);
      this._timeout = null;
      break;
    }
  }
};

// getChunkViewOffset returns the scroll offset minus the leftmost label width.
BufferedView.prototype.getChunkViewOffset = function() {
  return this._chunkViewOffset;
};

// setChunkViewOffset changes the scroll offset.
//
// You should manually call draw() after calling this.
BufferedView.prototype.setChunkViewOffset = function(val) {
  this._chunkViewOffset = val;
};

// getYLabels returns the current y labels, used for drawing.
BufferedView.prototype.getYLabels = function() {
  return this._yLabels;
};

// setYLabels changes the current y labels.
//
// You should manually call draw() after calling this.
BufferedView.prototype.setYLabels = function(labels) {
  this._yLabels = labels;
};

// draw draws the ContentView and the labels and positions the loaders.
BufferedView.prototype.draw = function() {
  if (this._state !== BufferedView.STATE_CONTENT || this._context === null) {
    return;
  }
  // TODO: draw the y-axis labels, the content, the y-axis lines, and position the loaders.
};

BufferedView.prototype._updatePixelRatio = function(redraw) {
  var newRatio = Math.ceil(window.crystal.getRatio());
  if (this._pixelRatio === newRatio) {
    return;
  }

  this._pixelRatio = newRatio;
  this._updateCanvasSize();

  if (redraw) {
    this.draw();
  }
};

BufferedView.prototype._updateCanvasSize = function() {
  this._canvas.width = this._width * this._pixelRatio;
  this._canvas.height = this._height * this._pixelRatio;
  this._canvas.style.width = this._width + 'px';
  this._canvas.style.height = this._height + 'px';
  this._context = this._canvas.getContext('2d');
  this._context.scale(this._pixelRatio, this._pixelRatio);
};

BufferedView.prototype._showSplashScreen = function() {
  this._timeout = null;
  this._state = BufferedView.STATE_SPLASH;

  this._splashStartTime = new Date().getTime();

  this._element.removeChild(this._canvas);
  if (this._leftLoader.element().parentNode) {
    this._element.removeChild(this._leftLoader.element());
  }
  if (this._rightLoader.element().parentNode) {
    this._element.removeChild(this._rightLoader.element());
  }

  this._element.appendChild(this._splashScreen.element());
};

BufferedView.prototype._showContent = function() {
  this._timeout = null;
  this._state = BufferedView.STATE_CONTENT;

  this._element.removeChild(this._splashScreen.element());
  this._element.appendChild(this._canvas);

  this.draw();
};

BufferedView.prototype._registerPointerEvents = function() {
  this._element.addEventListener('mousemove', function(e) {
    var rect = this._element.getBoundingClientRect();
    this._currentCursorPosition = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };
    if (this._chunkView !== null) {
      this._chunkView.pointerMove(this._currentCursorPosition);
    }
  }.bind(this));

  this._element.addEventListener('mouseleave', function(e) {
    if (this._currentCursorPosition !== null) {
      this._currentCursorPosition = null;
      if (this._chunkView !== null) {
        this._chunkView.pointerLeave();
      }
    }
  }.bind(this));

  this._element.addEventListener('click', function(e) {
    if (this._chunkView !== null) {
      var rect = this._element.getBoundingClientRect();
      var pos = {
        x: e.clientX - rect.left,
        y: e.clientY - rect.top
      };
      this._chunkView.pointerClick(pos);
    }
  }.bind(this));
};

function makeElementsFillAndAbsolute(elements) {
  for (var i = 0, len = elements.length; i < len; ++i) {
    var s = elements[i].style;
    s.style.position = 'absolute';
    s.style.width = '100%';
    s.style.height = '100%';
    s.style.top = '0';
    s.style.left = '0';
  }
}
<commit_msg>YLCV: show splash screen when resized on ephemeral content<commit_after>// BufferedView draws the ChunkView and the labels, shows the loaders,
// and presents the splash screen for a YLCV.
//
// This view makes sure that the splash screen never appears for too short a time period,
// and provides a grace period for new content to load after old content is invalidated.
function BufferedView(config) {
  this._splashScreen = config.splashScreen;
  this._leftLoader = config.loader1;
  this._rightLoader = config.loader2;

  this._element = document.createElement('div');
  this._canvas = document.createElement('canvas');

  this._element.appendChild(this._splashScreen.element());

  var elements = [this._canvas, this._element, this._splashScreen.element()];
  makeElementsFillAndAbsolute(elements);

  this._width = 0;
  this._height = 0;

  this._context = null;
  this._pixelRatio = 0;
  this._crystalCallback = this._updatePixelRatio.bind(this, true);

  this._animate = false;
  this._state = BufferedView.STATE_SPLASH;
  this._splashStartTime = 0;
  this._timeout = null;

  this._chunkViewOffset = 0;
  this._chunkView = null;
  this._yLabels = null;

  this._currentCursorPosition = null;
  this._registerPointerEvents();
}

BufferedView.STATE_SPLASH = 0;
BufferedView.STATE_EPHEMERAL_SPLASH = 1;
BufferedView.STATE_CONTENT = 2;
BufferedView.STATE_EPHEMERAL_CONTENT = 3;

BufferedView.EPHEMERAL_CONTENT_TIME = 100;
BufferedView.EPHEMERAL_SPLASH_TIME = 300;

// element returns the root DOM element of the view.
BufferedView.prototype.element = function() {
  return this._element;
};

// context returns the 2D drawing context for the view's canvas.
// This may return null if the view is not visible.
BufferedView.prototype.context = function() {
  return this._context;
};

// layout updates the size of the BufferedView.
//
// You should manually call draw() after calling this.
BufferedView.prototype.layout = function(w, h) {
  w = Math.ceil(w);
  h = Math.ceil(h);

  if (this._width === w && this._height === h) {
    return;
  }

  this._width = Math.ceil(w);
  this._height = Math.ceil(h);

  this._element.style.width = this._width + 'px';
  this._element.style.height = this._height + 'px';

  this._updateCanvasSize();
  this._splashScreen.layout(this._width, this._height);

  if (this._state === BufferedView.STATE_EPHEMERAL_CONTENT) {
    clearTimeout(this._timeout);
    this._showSplashScreen();
  }
};

// getAnimate returns the animate flag, as described in setAnimate().
BufferedView.prototype.getAnimate = function() {
  return this._animate;
};

// setAnimate toggles the animate flag.
// If the animate flag is set, then the loaders and splash screen will animate.
// While the animate flag is set, the view listens for DPI changes.
BufferedView.prototype.setAnimate = function(flag) {
  if (flag === this._animate) {
    return;
  }
  this._animate = flag;
  if (flag) {
    window.crystal.addListener(this._crystalCallback);
    this._updatePixelRatio(false);
    if (this._state === BufferedView.STATE_SPLASH ||
        this._state === BufferedView.STATE_EPHEMERAL_SPLASH) {
      this._splashScreen.setAnimate(true);
    } else {
      this.draw();
    }
  } else {
    window.crystal.removeListener(this._crystalCallback);
    this._splashScreen.setAnimate(false);
    this._leftLoader.setAnimate(false);
    this._rightLoader.setAnimate(false);
  }
};

// getChunkView returns the current chunk view, or null if no chunk view is associated with this.
BufferedView.prototype.getChunkView = function() {
  return this._chunkView;
};

// setChunkView changes the ChunkView that this view uses to draw.
// You may pass null to indicate that there is no available ChunkView.
//
// You should manually call draw() after calling this.
//
// This may trigger a pointerMove() event on the new ChunkView, which may in
// turn trigger a draw(). To avoid this, you can postpone on() calls on the
// ChunkView until after setChunkView().
BufferedView.prototype.setChunkView = function(cv) {
  if (this._chunkView === cv) {
    return;
  }

  this._chunkView = cv;

  if (cv === null) {
    switch (this._state) {
    case BufferedView.STATE_SPLASH:
    case BufferedView.STATE_EPHEMERAL_CONTENT:
      break;
    case BufferedView.STATE_CONTENT:
      this._state = BufferedView.STATE_EPHEMERAL_CONTENT;
      this._timeout = setTimeout(this._showSplashScreen.bind(this),
        BufferedView.EPHEMERAL_CONTENT_TIME);
      break;
    case BufferedView.STATE_EPHEMERAL_SPLASH:
      this._state = BufferedView.STATE_SPLASH;
      clearTimeout(this._timeout);
      this._timeout = null;
      break;
    }
  } else {
    switch (this._state) {
    case BufferedView.STATE_CONTENT:
      if (this._currentCursorPosition !== null) {
        this._chunkView.pointerMove(this._currentCursorPosition);
      }
      break;
    case BufferedView.STATE_EPHEMERAL_SPLASH:
      break;
    case BufferedView.STATE_SPLASH:
      var splashTime = Math.max(0, new Date().getTime()-this._splashStartTime);
      if (splashTime < BufferedView.EPHEMERAL_SPLASH_TIME) {
        this._state = BufferedView.STATE_EPHEMERAL_SPLASH;
        this._timeout = setTimeout(this._showContent.bind(this),
          BufferedView.EPHEMERAL_SPLASH_TIME-splashTime);
      } else {
        this._showContent();
      }
      break;
    case BufferedView.STATE_EPHEMERAL_CONTENT:
      this._state = BufferedView.STATE_CONTENT;
      clearTimeout(this._timeout);
      this._timeout = null;
      break;
    }
  }
};

// getChunkViewOffset returns the scroll offset minus the leftmost label width.
BufferedView.prototype.getChunkViewOffset = function() {
  return this._chunkViewOffset;
};

// setChunkViewOffset changes the scroll offset.
//
// You should manually call draw() after calling this.
BufferedView.prototype.setChunkViewOffset = function(val) {
  this._chunkViewOffset = val;
};

// getYLabels returns the current y labels, used for drawing.
BufferedView.prototype.getYLabels = function() {
  return this._yLabels;
};

// setYLabels changes the current y labels.
//
// You should manually call draw() after calling this.
BufferedView.prototype.setYLabels = function(labels) {
  this._yLabels = labels;
};

// draw draws the ContentView and the labels and positions the loaders.
BufferedView.prototype.draw = function() {
  if (this._state !== BufferedView.STATE_CONTENT || this._context === null) {
    return;
  }
  // TODO: draw the y-axis labels, the content, the y-axis lines, and position the loaders.
};

BufferedView.prototype._updatePixelRatio = function(redraw) {
  var newRatio = Math.ceil(window.crystal.getRatio());
  if (this._pixelRatio === newRatio) {
    return;
  }

  this._pixelRatio = newRatio;
  this._updateCanvasSize();

  if (redraw) {
    this.draw();
  }
};

BufferedView.prototype._updateCanvasSize = function() {
  this._canvas.width = this._width * this._pixelRatio;
  this._canvas.height = this._height * this._pixelRatio;
  this._canvas.style.width = this._width + 'px';
  this._canvas.style.height = this._height + 'px';
  this._context = this._canvas.getContext('2d');
  this._context.scale(this._pixelRatio, this._pixelRatio);
};

BufferedView.prototype._showSplashScreen = function() {
  this._timeout = null;
  this._state = BufferedView.STATE_SPLASH;

  this._splashStartTime = new Date().getTime();

  this._element.removeChild(this._canvas);
  if (this._leftLoader.element().parentNode) {
    this._element.removeChild(this._leftLoader.element());
  }
  if (this._rightLoader.element().parentNode) {
    this._element.removeChild(this._rightLoader.element());
  }

  this._element.appendChild(this._splashScreen.element());
};

BufferedView.prototype._showContent = function() {
  this._timeout = null;
  this._state = BufferedView.STATE_CONTENT;

  this._element.removeChild(this._splashScreen.element());
  this._element.appendChild(this._canvas);

  this.draw();
};

BufferedView.prototype._registerPointerEvents = function() {
  this._element.addEventListener('mousemove', function(e) {
    var rect = this._element.getBoundingClientRect();
    this._currentCursorPosition = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };
    if (this._chunkView !== null) {
      this._chunkView.pointerMove(this._currentCursorPosition);
    }
  }.bind(this));

  this._element.addEventListener('mouseleave', function(e) {
    if (this._currentCursorPosition !== null) {
      this._currentCursorPosition = null;
      if (this._chunkView !== null) {
        this._chunkView.pointerLeave();
      }
    }
  }.bind(this));

  this._element.addEventListener('click', function(e) {
    if (this._chunkView !== null) {
      var rect = this._element.getBoundingClientRect();
      var pos = {
        x: e.clientX - rect.left,
        y: e.clientY - rect.top
      };
      this._chunkView.pointerClick(pos);
    }
  }.bind(this));
};

function makeElementsFillAndAbsolute(elements) {
  for (var i = 0, len = elements.length; i < len; ++i) {
    var s = elements[i].style;
    s.style.position = 'absolute';
    s.style.width = '100%';
    s.style.height = '100%';
    s.style.top = '0';
    s.style.left = '0';
  }
}
<|endoftext|>


<commit_before>/*
reference: http://users.nber.org/~rosenbla/econ311-04/syllabus/holtlaury.pdf
Holt, C. A., & Laury, S. K. (2002). Risk aversion and incentive effects. American economic review, 92(5), 1644-1655.
*/

/* ************************************ */
/* Define helper functions */
/* ************************************ */
function getDisplayElement() {
  $('

').appendTo('body')
  return $('

').appendTo('body')
}

function addID() {
  jsPsych.data.addDataToLastTrial({
    'exp_id': 'holt_laury'
  })
}

var getInstructFeedback = function() {
  return '

' + feedback_instruct_text +
    '

'
}

function fillArray(value, len) {
  if (len === 0) return [];
  var a = [value];
  while (a.length * 2 <= len) a = a.concat(a);
  if (a.length < len) a = a.concat(a.slice(0, len - a.length));
  return a;
}
/* ************************************ */
/* Define experimental variables */
/* ************************************ */
// generic task variables
var run_attention_checks = true
var attention_check_thresh = 0.65
var sumInstructTime = 0 //ms
var instructTimeThresh = 3 ///in seconds

/* ************************************ */
/* Set up jsPsych blocks */
/* ************************************ */
/* define static blocks */
var welcome_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  text: '

Welcome to the experiment. Press enter to begin.

',
  cont_key: [13],
  timing_post_trial: 0
};

var feedback_instruct_text =
  'Starting with instructions.  Press  Enter  to continue.'
var feedback_instruct_block = {
  type: 'poldrack-text',
  cont_key: [13],
  text: getInstructFeedback,
  timing_post_trial: 0,
  timing_response: 6000
};
/// This ensures that the subject does not read through the instructions too quickly.  If they do it too quickly, then we will go over the loop again.
var instruction_trials = []
var instructions_block = {
  type: 'poldrack-instructions',
  pages: [
    '

In this experiment you will be presented with a series of lottery choices. Your job is to indicate which option you would prefer for each of the ten paired lottery choices.

You should indicate your true preference because at the end of the experiment a random trial will be chosen and you will receive a bonus payment proportional to the option you selected.

',
  ],
  allow_keys: false,
  show_clickable_nav: true,
  timing_post_trial: 1000
};
instruction_trials.push(feedback_instruct_block)
instruction_trials.push(instructions_block)

var instruction_node = {
  timeline: instruction_trials,
  /* This function defines stopping criteria */
  loop_function: function(data) {
    for (i = 0; i < data.length; i++) {
      if ((data[i].trial_type == 'poldrack-instructions') && (data[i].rt != -1)) {
        rt = data[i].rt
        sumInstructTime = sumInstructTime + rt
      }
    }
    if (sumInstructTime <= instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Read through instructions too quickly.  Please take your time and make sure you understand the instructions.  Press enter to continue.'
      return true
    } else if (sumInstructTime > instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Done with instructions. Press enter to continue.'
      return false
    }
  }
}

var all_pages = [fillArray('', 10)]

var all_options = [
  [
    ["10% chance of $100, 90% chance of $80", "10% chance of $190, 90% chance of $5"],
    ["20% chance of $100, 80% chance of $80", "20% chance of $190, 80% chance of $5"],
    ["30% chance of $100, 70% chance of $80", "30% chance of $190, 70% chance of $5"],
    ["40% chance of $100, 60% chance of $80", "40% chance of $190, 60% chance of $5"],
    ["50% chance of $100, 50% chance of $80", "50% chance of $190, 50% chance of $5"],
    ["60% chance of $100, 40% chance of $80", "60% chance of $190, 40% chance of $5"],
    ["70% chance of $100, 30% chance of $80", "70% chance of $190, 30% chance of $5"],
    ["80% chance of $100, 20% chance of $80", "80% chance of $190, 20% chance of $5"],
    ["90% chance of $100, 10% chance of $80", "90% chance of $190, 10% chance of $5"],
    ["100% chance of $100, 0% chance of $80", "100% chance of $190, 0% chance of $5"]
  ]
]

//higher - more impulsiveness: 1 is safe, 2 is risky
var score_scale = {
  "10% chance of $100, 90% chance of $80": 1,
  "10% chance of $190, 90% chance of $5": 2,
  "20% chance of $100, 80% chance of $80": 1,
  "20% chance of $190, 80% chance of $5": 2,
  "30% chance of $100, 70% chance of $80": 1,
  "30% chance of $190, 70% chance of $5": 2,
  "40% chance of $100, 60% chance of $80": 1,
  "40% chance of $190, 60% chance of $5": 2,
  "50% chance of $100, 50% chance of $80": 1,
  "50% chance of $190, 50% chance of $5": 2,
  "60% chance of $100, 40% chance of $80": 1,
  "60% chance of $190, 40% chance of $5": 2,
  "70% chance of $100, 30% chance of $80": 1,
  "70% chance of $190, 30% chance of $5": 2,
  "80% chance of $100, 20% chance of $80": 1,
  "80% chance of $190, 20% chance of $5": 2,
  "90% chance of $100, 10% chance of $80": 1,
  "90% chance of $190, 10% chance of $5": 2,
  "100% chance of $100, 0% chance of $80": 1,
  "100% chance of $190, 0% chance of $5": 2
}

var survey_block = {
  type: "poldrack-survey-multi-choice",
  exp_id: "holt_laury",
  horizontal: true,
  preamble: '
Please indicate your preference between the two gambles.
',
  pages: all_pages,
  options: all_options,
  scale: score_scale,
  show_clickable_nav: true,
  allow_backward: true,
  required: [fillArray(true, 10)],
  reverse_score: [
    [false, false, false, false, false, false, false, false, false, false]
  ],
};

var end_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  text: '

Thanks for completing this task!

Press enter to continue.

',
  cont_key: [13]
};

//Set up experiment
var holt_laury_experiment = []
holt_laury_experiment.push(welcome_block);
holt_laury_experiment.push(instruction_node);
holt_laury_experiment.push(survey_block);
holt_laury_experiment.push(end_block)<commit_msg>Reworded preamble to resolve issue 192.<commit_after>/*
reference: http://users.nber.org/~rosenbla/econ311-04/syllabus/holtlaury.pdf
Holt, C. A., & Laury, S. K. (2002). Risk aversion and incentive effects. American economic review, 92(5), 1644-1655.
*/

/* ************************************ */
/* Define helper functions */
/* ************************************ */
function getDisplayElement() {
  $('

').appendTo('body')
  return $('

').appendTo('body')
}

function addID() {
  jsPsych.data.addDataToLastTrial({
    'exp_id': 'holt_laury'
  })
}

var getInstructFeedback = function() {
  return '

' + feedback_instruct_text +
    '

'
}

function fillArray(value, len) {
  if (len === 0) return [];
  var a = [value];
  while (a.length * 2 <= len) a = a.concat(a);
  if (a.length < len) a = a.concat(a.slice(0, len - a.length));
  return a;
}
/* ************************************ */
/* Define experimental variables */
/* ************************************ */
// generic task variables
var run_attention_checks = true
var attention_check_thresh = 0.65
var sumInstructTime = 0 //ms
var instructTimeThresh = 3 ///in seconds

/* ************************************ */
/* Set up jsPsych blocks */
/* ************************************ */
/* define static blocks */
var welcome_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  text: '

Welcome to the experiment. Press enter to begin.

',
  cont_key: [13],
  timing_post_trial: 0
};

var feedback_instruct_text =
  'Starting with instructions.  Press  Enter  to continue.'
var feedback_instruct_block = {
  type: 'poldrack-text',
  cont_key: [13],
  text: getInstructFeedback,
  timing_post_trial: 0,
  timing_response: 6000
};
/// This ensures that the subject does not read through the instructions too quickly.  If they do it too quickly, then we will go over the loop again.
var instruction_trials = []
var instructions_block = {
  type: 'poldrack-instructions',
  pages: [
    '

In this experiment you will be presented with a series of lottery choices. Your job is to indicate which option you would prefer for each of the ten paired lottery choices.

You should indicate your true preference because at the end of the experiment a random trial will be chosen and you will receive a bonus payment proportional to the option you selected.

',
  ],
  allow_keys: false,
  show_clickable_nav: true,
  timing_post_trial: 1000
};
instruction_trials.push(feedback_instruct_block)
instruction_trials.push(instructions_block)

var instruction_node = {
  timeline: instruction_trials,
  /* This function defines stopping criteria */
  loop_function: function(data) {
    for (i = 0; i < data.length; i++) {
      if ((data[i].trial_type == 'poldrack-instructions') && (data[i].rt != -1)) {
        rt = data[i].rt
        sumInstructTime = sumInstructTime + rt
      }
    }
    if (sumInstructTime <= instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Read through instructions too quickly.  Please take your time and make sure you understand the instructions.  Press enter to continue.'
      return true
    } else if (sumInstructTime > instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Done with instructions. Press enter to continue.'
      return false
    }
  }
}

var all_pages = [fillArray('', 10)]

var all_options = [
  [
    ["10% chance of $100, 90% chance of $80", "10% chance of $190, 90% chance of $5"],
    ["20% chance of $100, 80% chance of $80", "20% chance of $190, 80% chance of $5"],
    ["30% chance of $100, 70% chance of $80", "30% chance of $190, 70% chance of $5"],
    ["40% chance of $100, 60% chance of $80", "40% chance of $190, 60% chance of $5"],
    ["50% chance of $100, 50% chance of $80", "50% chance of $190, 50% chance of $5"],
    ["60% chance of $100, 40% chance of $80", "60% chance of $190, 40% chance of $5"],
    ["70% chance of $100, 30% chance of $80", "70% chance of $190, 30% chance of $5"],
    ["80% chance of $100, 20% chance of $80", "80% chance of $190, 20% chance of $5"],
    ["90% chance of $100, 10% chance of $80", "90% chance of $190, 10% chance of $5"],
    ["100% chance of $100, 0% chance of $80", "100% chance of $190, 0% chance of $5"]
  ]
]

//higher - more impulsiveness: 1 is safe, 2 is risky
var score_scale = {
  "10% chance of $100, 90% chance of $80": 1,
  "10% chance of $190, 90% chance of $5": 2,
  "20% chance of $100, 80% chance of $80": 1,
  "20% chance of $190, 80% chance of $5": 2,
  "30% chance of $100, 70% chance of $80": 1,
  "30% chance of $190, 70% chance of $5": 2,
  "40% chance of $100, 60% chance of $80": 1,
  "40% chance of $190, 60% chance of $5": 2,
  "50% chance of $100, 50% chance of $80": 1,
  "50% chance of $190, 50% chance of $5": 2,
  "60% chance of $100, 40% chance of $80": 1,
  "60% chance of $190, 40% chance of $5": 2,
  "70% chance of $100, 30% chance of $80": 1,
  "70% chance of $190, 30% chance of $5": 2,
  "80% chance of $100, 20% chance of $80": 1,
  "80% chance of $190, 20% chance of $5": 2,
  "90% chance of $100, 10% chance of $80": 1,
  "90% chance of $190, 10% chance of $5": 2,
  "100% chance of $100, 0% chance of $80": 1,
  "100% chance of $190, 0% chance of $5": 2
}

var survey_block = {
  type: "poldrack-survey-multi-choice",
  exp_id: "holt_laury",
  horizontal: true,
  preamble: '
Please indicate your preference between each of the pairs of gambles.
',
  pages: all_pages,
  options: all_options,
  scale: score_scale,
  show_clickable_nav: true,
  allow_backward: true,
  required: [fillArray(true, 10)],
  reverse_score: [
    [false, false, false, false, false, false, false, false, false, false]
  ],
};

var end_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  text: '

Thanks for completing this task!

Press enter to continue.

',
  cont_key: [13]
};

//Set up experiment
var holt_laury_experiment = []
holt_laury_experiment.push(welcome_block);
holt_laury_experiment.push(instruction_node);
holt_laury_experiment.push(survey_block);
holt_laury_experiment.push(end_block)<|endoftext|>


<commit_before>/**
 * @file deepEqual.js
 * @author Vladimir Deminenko
 * @date 09.08.2017
 */

'use strict';

/**
 * compares two objects and their properties
 * @param {Object} obj1
 * @param {Object} obj2
 * @returns {boolean}
 */
function deepEqual(obj1, obj2) {
    let keys;
    let keys2;

    if (![typeof obj1, typeof obj2].includes('object')) {
        return obj1 === obj2 && obj1 !== undefined;
    }

    if (
        obj1 === null &&
        obj2 === null
    ) {
        return true;
    }

    // ПРАВИЛЬНОЕ использование try...catch
    // позволяет обойтись без многих проверок - сравни с deepEqual2()
    try {
        keys = Object.keys(obj1);
        keys2 = Object.keys(obj2);
    }
    catch (err) {
        return false;
    }

    if (keys.length !== keys2.length) {
        return false;
    }

    for (let i = 0; i < keys.length; i++) {
        let key = keys[i];

        if (typeof obj1[key] === 'object') {
            return deepEqual(obj1[key], obj2[key]);
        }

        if (obj1[key] !== obj2[key]) {
            return false;
        }
    }

    return true;
}

/**
 * compares two objects and their properties
 * @param {Object} obj1
 * @param {Object} obj2
 * @returns {boolean}
 */
function deepEqual2(obj1, obj2) {
    let keys1;
    let keys2;

    if (![typeof obj1, typeof obj2].includes('object')) {
        return obj1 === obj2 && obj1 !== undefined;
    }

    if (
        obj1 === null &&
        obj2 === null
    ) {
        return true;
    }

    if (
        typeof obj1 !== 'object' ||
        typeof obj2 !== 'object' ||
        (obj1 === null && obj2 !== null) ||
        (obj2 === null && obj1 !== null)
    ) {
        return false;
    }

    keys1 = Object.keys(obj1);
    keys2 = Object.keys(obj2);

    if (
        keys1 && keys1.length &&
        keys2 && keys2.length &&
        keys1.length !== keys2.length
    ) {
        return false;
    }

    for (let i = 0; i < keys1.length; i++) {
        let key = keys1[i];

        if (typeof obj1[key] === 'object') {
            return deepEqual(obj1[key], obj2[key]);
        }

        if (obj1[key] !== obj2[key]) {
            return false;
        }
    }

    return true;
}
<commit_msg>homework-03<commit_after>/**
 * @file deepEqual.js
 * @author Vladimir Deminenko
 * @date 09.08.2017
 */

'use strict';

/**
 * compares two objects and their properties
 * @param {Object} obj1
 * @param {Object} obj2
 * @returns {boolean}
 */
function deepEqual(obj1, obj2) {
    // сравнение примитивов
    if (![typeof obj1, typeof obj2].includes('object')) {
        return obj1 === obj2 && obj1 !== undefined;
    }

    if (
        obj1 === null &&
        obj2 === null
    ) {
        return true;
    }

    let keys;
    let keys2;

    // использование try...catch
    // позволяет обойтись без многих проверок - сравни с deepEqual2()
    try {
        keys = Object.keys(obj1);
        keys2 = Object.keys(obj2);
    }
    catch (err) {
        return false;
    }

    if (keys.length !== keys2.length) {
        return false;
    }

    for (let i = 0; i < keys.length; i++) {
        let key = keys[i];

        if (typeof obj1[key] === 'object') {
            return deepEqual(obj1[key], obj2[key]);
        }

        if (obj1[key] !== obj2[key]) {
            return false;
        }
    }

    return true;
}

/**
 * compares two objects and their properties
 * @param {Object} obj1
 * @param {Object} obj2
 * @returns {boolean}
 */
function deepEqual2(obj1, obj2) {
    // сравнение примитивов
    if (![typeof obj1, typeof obj2].includes('object')) {
        return obj1 === obj2 && obj1 !== undefined;
    }

    if (
        obj1 === null &&
        obj2 === null
    ) {
        return true;
    }

    if (
        typeof obj1 !== 'object' ||
        typeof obj2 !== 'object' ||
        (obj1 === null && obj2 !== null) ||
        (obj1 !== null && obj2 === null)
    ) {
        return false;
    }

    let keys = Object.keys(obj1);
    let keys2 = Object.keys(obj2);

    if (
        keys && keys.length &&
        keys2 && keys2.length &&
        keys.length !== keys2.length
    ) {
        return false;
    }

    for (let i = 0; i < keys.length; i++) {
        let key = keys[i];

        if (typeof obj1[key] === 'object') {
            return deepEqual(obj1[key], obj2[key]);
        }

        if (obj1[key] !== obj2[key]) {
            return false;
        }
    }

    return true;
}
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    "use strict";
    var utils = require("converters/all");
    var Hex = require("modules/multivalue/hex");
    var Utf8String = require("modules/multivalue/utf8string");
    var EventEmitter = require("modules/events/eventEmitter");
    var extend = require("extend");
    var utils = require("./utils");

    var logfunc = function() {
        var args = [this.name].concat(arguments);
        //console.log.apply(console, args);
    }

    describe("True Link Encrypted Channel", function() {

        describe("with builder", function() {
            before(function(done) {
                var transport = this.transport = utils.factory.createTransport();
                var aliceTlec = this.aliceTlec = utils.factory.createTlecBuilder();
                var bobTlec = this.bobTlec = utils.factory.createTlecBuilder();

                aliceTlec.on("networkPacket", transport.sendNetworkPacket, transport);
                bobTlec.on("networkPacket", transport.sendNetworkPacket, transport);

                aliceTlec.on("addrIn", transport.openAddr, transport);
                bobTlec.on("addrIn", transport.openAddr, transport);

                transport.on("networkPacket", aliceTlec.processNetworkPacket, aliceTlec);
                transport.on("networkPacket", bobTlec.processNetworkPacket, bobTlec);

                aliceTlec.on("offer", bobTlec.enterOffer, bobTlec);
                aliceTlec.on("auth", bobTlec.enterAuth, bobTlec);

                var results = [];
                var success = function() {
                    results.push(this);
                    if (results.length == 2) done();
                };

                aliceTlec.on("done", function(tlec) {
                    this.aliceTlec = tlec;
                    tlec.on("message", function(bytes) {
                        this.aliceHistory.push(bytes.as(Utf8String).value);
                    }, this);
                    success();
                }, this);
                this.sendMessageFromAlice = function(text) {
                    this.aliceHistory.push(text);
                    this.aliceTlec.sendMessage(new Utf8String(text));
                };

                bobTlec.on("done", function(tlec) {
                    this.bobTlec = tlec;
                    tlec.on("message", function(bytes) {
                        this.bobHistory.push(bytes.as(Utf8String).value);
                    }, this);
                    success();
                }, this);
                this.sendMessageFromBob = function(text) {
                    this.bobHistory.push(text);
                    this.bobTlec.sendMessage(new Utf8String(text));
                };

                aliceTlec.build();
                bobTlec.build();
                aliceTlec.generateOffer();
            });

            beforeEach(function() {
                this.aliceHistory = [];
                this.bobHistory = [];
            });

            it("can send messages", function() {
                this.sendMessageFromAlice("Hi, Bob.");
                this.sendMessageFromBob("Hi, Alice.");
                this.sendMessageFromAlice("How are you doing, Bob?");
                this.sendMessageFromBob("I'm sending messages to you over TLEC!!!");
                this.sendMessageFromAlice("Wow, and how is it?");
                this.sendMessageFromBob("It is awesome!!!");
                this.sendMessageFromAlice("Why?");
                this.sendMessageFromBob("Because our conversation now is more secured than ever");

                expect(this.aliceHistory).to.deep.equal(this.bobHistory);
                expect(this.aliceHistory).to.deep.equal([
                    "Hi, Bob.",
                    "Hi, Alice.",
                    "How are you doing, Bob?",
                    "I'm sending messages to you over TLEC!!!",
                    "Wow, and how is it?",
                    "It is awesome!!!",
                    "Why?",
                    "Because our conversation now is more secured than ever"
                ]);
            });

            it("can send long messages (16k)", function() {
                var message="-"
                while(message.length < 10000) {
                    message = message + "|" + message;
                }
                this.sendMessageFromAlice(message);
                expect(this.aliceHistory).to.deep.equal(this.bobHistory);
                expect(this.aliceHistory).to.deep.equal([message]);
            });
        });

        describe("tlec over tlec", function() {
            before(function(done) {
                var transport = this.transport = utils.factory.createTransport();
                var aliceTlec = this.aliceTlec = utils.factory.createTlecBuilder();
                var bobTlec = this.bobTlec = utils.factory.createTlecBuilder();

                aliceTlec.on("networkPacket", transport.sendNetworkPacket, transport);
                bobTlec.on("networkPacket", transport.sendNetworkPacket, transport);

                aliceTlec.on("addrIn", transport.openAddr, transport);
                bobTlec.on("addrIn", transport.openAddr, transport);

                transport.on("networkPacket", aliceTlec.processNetworkPacket, aliceTlec);
                transport.on("networkPacket", bobTlec.processNetworkPacket, bobTlec);

                aliceTlec.on("offer", bobTlec.enterOffer, bobTlec);
                aliceTlec.on("auth", bobTlec.enterAuth, bobTlec);

                var results = [];
                var success = function() {
                    results.push(this);
                    if (results.length == 2) done();
                };

                aliceTlec.on("done", function(tlec) {
                    console.log("alice building over", tlec);
                    var over = utils.factory.createOverTlecBuilder();

                    over.on("networkPacket", transport.sendNetworkPacket, transport);
                    over.on("addrIn", transport.openAddr, transport);
                    transport.on("networkPacket", over.processNetworkPacket, over);

                    aliceTlec.on("message", function(bytes) {
                        var msg = JSON.parse(bytes.as(Utf8String).value);
                        over.processMessage(msg);
                    });
                    over.on("message", function(msg) {
                        aliceTlec.sendMessage(new Utf8String(JSON.stringify(msg)));
                    });
                    over.on("done", function(tlec2) {
                        console.log("alice !!!!", tlec2);
                        this.aliceNewTlec = tlec2;
                        tlec2.on("message", function(bytes) {
                            this.aliceHistory.push(bytes.as(Utf8String).value);
                        }, this);
                        success();
                    }, this);
                    over.build(false);
                }, this);
                bobTlec.on("done", function(tlec) {
                    console.log("bob building over", tlec);
                    var over = utils.factory.createOverTlecBuilder();

                    over.on("networkPacket", transport.sendNetworkPacket, transport);
                    over.on("addrIn", transport.openAddr, transport);
                    transport.on("networkPacket", over.processNetworkPacket, over);

                    bobTlec.on("message", function(bytes) {
                        var msg = JSON.parse(bytes.as(Utf8String).value);
                        over.processMessage(msg);
                    });
                    over.on("message", function(msg) {
                        bobTlec.sendMessage(new Utf8String(JSON.stringify(msg)));
                    });
                    over.on("done", function(tlec2) {
                        console.log("bob !!!!", tlec2);
                        this.bobNewTlec = tlec2;
                        tlec2.on("message", function(bytes) {
                            this.bobHistory.push(bytes.as(Utf8String).value);
                        }, this);
                        success();
                    }, this);
                    over.build(true);
                }, this);

                this.sendMessageFromAlice = function(text) {
                    this.aliceHistory.push(text);
                    this.aliceNewTlec.sendMessage(new Utf8String(text));
                };
                this.sendMessageFromBob = function(text) {
                    this.bobHistory.push(text);
                    this.bobNewTlec.sendMessage(new Utf8String(text));
                };

                aliceTlec.build();
                bobTlec.build();
                aliceTlec.generateOffer();
            });

            beforeEach(function() {
                this.aliceHistory = [];
                this.bobHistory = [];
            });

            it("can send messages", function() {
                this.sendMessageFromAlice("Hi, Bob.");
                this.sendMessageFromBob("Hi, Alice.");
                this.sendMessageFromAlice("How are you doing, Bob?");
                this.sendMessageFromBob("I'm sending messages to you over TLEC!!!");
                this.sendMessageFromAlice("Wow, and how is it?");
                this.sendMessageFromBob("It is awesome!!!");
                this.sendMessageFromAlice("Why?");
                this.sendMessageFromBob("Because our conversation now is more secured than ever");

                expect(this.aliceHistory).to.deep.equal(this.bobHistory);
                expect(this.aliceHistory).to.deep.equal([
                    "Hi, Bob.",
                    "Hi, Alice.",
                    "How are you doing, Bob?",
                    "I'm sending messages to you over TLEC!!!",
                    "Wow, and how is it?",
                    "It is awesome!!!",
                    "Why?",
                    "Because our conversation now is more secured than ever"
                ]);
            });

        });

    });

});<commit_msg>slow test for many messages<commit_after>define(function(require, exports, module) {
    "use strict";
    var utils = require("converters/all");
    var Hex = require("modules/multivalue/hex");
    var Utf8String = require("modules/multivalue/utf8string");
    var EventEmitter = require("modules/events/eventEmitter");
    var extend = require("extend");
    var utils = require("./utils");

    var logfunc = function() {
        var args = [this.name].concat(arguments);
        //console.log.apply(console, args);
    }

    describe("True Link Encrypted Channel", function() {

        describe("with builder", function() {
            before(function(done) {
                var transport = this.transport = utils.factory.createTransport();
                var aliceTlec = this.aliceTlec = utils.factory.createTlecBuilder();
                var bobTlec = this.bobTlec = utils.factory.createTlecBuilder();

                aliceTlec.on("networkPacket", transport.sendNetworkPacket, transport);
                bobTlec.on("networkPacket", transport.sendNetworkPacket, transport);

                aliceTlec.on("addrIn", transport.openAddr, transport);
                bobTlec.on("addrIn", transport.openAddr, transport);

                transport.on("networkPacket", aliceTlec.processNetworkPacket, aliceTlec);
                transport.on("networkPacket", bobTlec.processNetworkPacket, bobTlec);

                aliceTlec.on("offer", bobTlec.enterOffer, bobTlec);
                aliceTlec.on("auth", bobTlec.enterAuth, bobTlec);

                var results = [];
                var success = function() {
                    results.push(this);
                    if (results.length == 2) done();
                };

                aliceTlec.on("done", function(tlec) {
                    this.aliceTlec = tlec;
                    tlec.on("message", function(bytes) {
                        this.aliceHistory.push(bytes.as(Utf8String).value);
                    }, this);
                    success();
                }, this);
                this.sendMessageFromAlice = function(text) {
                    this.aliceHistory.push(text);
                    this.aliceTlec.sendMessage(new Utf8String(text));
                };

                bobTlec.on("done", function(tlec) {
                    this.bobTlec = tlec;
                    tlec.on("message", function(bytes) {
                        this.bobHistory.push(bytes.as(Utf8String).value);
                    }, this);
                    success();
                }, this);
                this.sendMessageFromBob = function(text) {
                    this.bobHistory.push(text);
                    this.bobTlec.sendMessage(new Utf8String(text));
                };

                aliceTlec.build();
                bobTlec.build();
                aliceTlec.generateOffer();
            });

            beforeEach(function() {
                this.aliceHistory = [];
                this.bobHistory = [];
            });

            it("can send messages", function() {
                this.sendMessageFromAlice("Hi, Bob.");
                this.sendMessageFromBob("Hi, Alice.");
                this.sendMessageFromAlice("How are you doing, Bob?");
                this.sendMessageFromBob("I'm sending messages to you over TLEC!!!");
                this.sendMessageFromAlice("Wow, and how is it?");
                this.sendMessageFromBob("It is awesome!!!");
                this.sendMessageFromAlice("Why?");
                this.sendMessageFromBob("Because our conversation now is more secured than ever");

                expect(this.aliceHistory).to.deep.equal(this.bobHistory);
                expect(this.aliceHistory).to.deep.equal([
                    "Hi, Bob.",
                    "Hi, Alice.",
                    "How are you doing, Bob?",
                    "I'm sending messages to you over TLEC!!!",
                    "Wow, and how is it?",
                    "It is awesome!!!",
                    "Why?",
                    "Because our conversation now is more secured than ever"
                ]);
            });

            it("can send long messages (16k)", function() {
                var message="-"
                while(message.length < 10000) {
                    message = message + "|" + message;
                }
                this.sendMessageFromAlice(message);
                expect(this.aliceHistory).to.deep.equal(this.bobHistory);
                expect(this.aliceHistory).to.deep.equal([message]);
            });

            it("can send many messages (100)", function() {
                for(var i=0; i<100; i++) {
                    this.sendMessageFromAlice("message #" + i);
                }
                expect(this.aliceHistory).to.deep.equal(this.bobHistory);
            });
        });

        describe("tlec over tlec", function() {
            before(function(done) {
                var transport = this.transport = utils.factory.createTransport();
                var aliceTlec = this.aliceTlec = utils.factory.createTlecBuilder();
                var bobTlec = this.bobTlec = utils.factory.createTlecBuilder();

                aliceTlec.on("networkPacket", transport.sendNetworkPacket, transport);
                bobTlec.on("networkPacket", transport.sendNetworkPacket, transport);

                aliceTlec.on("addrIn", transport.openAddr, transport);
                bobTlec.on("addrIn", transport.openAddr, transport);

                transport.on("networkPacket", aliceTlec.processNetworkPacket, aliceTlec);
                transport.on("networkPacket", bobTlec.processNetworkPacket, bobTlec);

                aliceTlec.on("offer", bobTlec.enterOffer, bobTlec);
                aliceTlec.on("auth", bobTlec.enterAuth, bobTlec);

                var results = [];
                var success = function() {
                    results.push(this);
                    if (results.length == 2) done();
                };

                aliceTlec.on("done", function(tlec) {
                    console.log("alice building over", tlec);
                    var over = utils.factory.createOverTlecBuilder();

                    over.on("networkPacket", transport.sendNetworkPacket, transport);
                    over.on("addrIn", transport.openAddr, transport);
                    transport.on("networkPacket", over.processNetworkPacket, over);

                    aliceTlec.on("message", function(bytes) {
                        var msg = JSON.parse(bytes.as(Utf8String).value);
                        over.processMessage(msg);
                    });
                    over.on("message", function(msg) {
                        aliceTlec.sendMessage(new Utf8String(JSON.stringify(msg)));
                    });
                    over.on("done", function(tlec2) {
                        console.log("alice !!!!", tlec2);
                        this.aliceNewTlec = tlec2;
                        tlec2.on("message", function(bytes) {
                            this.aliceHistory.push(bytes.as(Utf8String).value);
                        }, this);
                        success();
                    }, this);
                    over.build(false);
                }, this);
                bobTlec.on("done", function(tlec) {
                    console.log("bob building over", tlec);
                    var over = utils.factory.createOverTlecBuilder();

                    over.on("networkPacket", transport.sendNetworkPacket, transport);
                    over.on("addrIn", transport.openAddr, transport);
                    transport.on("networkPacket", over.processNetworkPacket, over);

                    bobTlec.on("message", function(bytes) {
                        var msg = JSON.parse(bytes.as(Utf8String).value);
                        over.processMessage(msg);
                    });
                    over.on("message", function(msg) {
                        bobTlec.sendMessage(new Utf8String(JSON.stringify(msg)));
                    });
                    over.on("done", function(tlec2) {
                        console.log("bob !!!!", tlec2);
                        this.bobNewTlec = tlec2;
                        tlec2.on("message", function(bytes) {
                            this.bobHistory.push(bytes.as(Utf8String).value);
                        }, this);
                        success();
                    }, this);
                    over.build(true);
                }, this);

                this.sendMessageFromAlice = function(text) {
                    this.aliceHistory.push(text);
                    this.aliceNewTlec.sendMessage(new Utf8String(text));
                };
                this.sendMessageFromBob = function(text) {
                    this.bobHistory.push(text);
                    this.bobNewTlec.sendMessage(new Utf8String(text));
                };

                aliceTlec.build();
                bobTlec.build();
                aliceTlec.generateOffer();
            });

            beforeEach(function() {
                this.aliceHistory = [];
                this.bobHistory = [];
            });

            it("can send messages", function() {
                this.sendMessageFromAlice("Hi, Bob.");
                this.sendMessageFromBob("Hi, Alice.");
                this.sendMessageFromAlice("How are you doing, Bob?");
                this.sendMessageFromBob("I'm sending messages to you over TLEC!!!");
                this.sendMessageFromAlice("Wow, and how is it?");
                this.sendMessageFromBob("It is awesome!!!");
                this.sendMessageFromAlice("Why?");
                this.sendMessageFromBob("Because our conversation now is more secured than ever");

                expect(this.aliceHistory).to.deep.equal(this.bobHistory);
                expect(this.aliceHistory).to.deep.equal([
                    "Hi, Bob.",
                    "Hi, Alice.",
                    "How are you doing, Bob?",
                    "I'm sending messages to you over TLEC!!!",
                    "Wow, and how is it?",
                    "It is awesome!!!",
                    "Why?",
                    "Because our conversation now is more secured than ever"
                ]);
            });

        });

    });

});<|endoftext|>


<commit_before>var spawn = require("child_process").spawn,
  path = require("path"),
  through = require('through');

var GulpEventStream = function(mode, specialOptionKeys) {
  return function(options) {
    if (options == null) {
      options = {};
    }
    var opt = {}; // Clone not to mess up the input objecz
    var allowedOptionKeys = ['galenPath', 'parallel', 'htmlreport', 'testngreport', 'jsonreport', 'properties'].concat(specialOptionKeys);
    Object.keys(options).forEach(function(key) {
      if (allowedOptionKeys.indexOf(key) < 0) {
        throw new Error("Unknown option '" + key + "'. Valid options are: " + allowedOptionKeys.join(", "));
      }
      opt[key] = options[key];
    });

    var galenPath = "/usr/local/bin/galen";
    if (opt.galenPath) {
      galenPath = opt.galenPath;
      delete opt.galenPath;
    }

    var properties = {};
    if (opt.properties) {
      properties = opt.properties;
      delete opt.properties;
    }

    return through(function(file) {
      if (!opt.parallel) {
        // Prevent paralell execution
        this.pause();
      }

      var args = [mode, file.path];
      Object.keys(opt).forEach(function(key) {
        if (opt[key]) {
          args.push("--" + key + "=" + opt[key]);
        }
      });
      Object.keys(properties).forEach(function(key) {
        if (properties[key]) {
          args.push("-D" + key + "=" + properties[key]);
        }
      });

      spawn(galenPath, args, {
        "stdio": "inherit"
      }).on("close", function(code) {
        if (code === 0) {
          return this.emit('data', file);
        } else {
          throw new Error("Test '" + file.path + "' failed!");
        }
      }).on("error", function(err) {
        throw new Error("Could not start galen. Galen ('" + galenPath + "') not found?");
      });
    });
  };
};

module.exports = {
  check: GulpEventStream('check', ['url', 'javascript', 'size', 'include', 'exclude']),
  test: GulpEventStream('test', ['parallel-tests', 'recursive', 'filter', 'groups', 'excluded-groups'])
};
<commit_msg>Fixed bugs in stream handling<commit_after>var spawn = require("child_process").spawn,
  path = require("path"),
  through = require('through');

var GulpEventStream = function(mode, specialOptionKeys) {
  return function(options) {
    if (typeof(options) === 'undefined') {
      options = {};
    }
    var opt = {}; // Clone not to mess up the input objecz
    var allowedOptionKeys = ['galenPath', 'parallel', 'htmlreport', 'testngreport', 'jsonreport', 'properties'].concat(specialOptionKeys);
    Object.keys(options).forEach(function(key) {
      if (allowedOptionKeys.indexOf(key) < 0) {
        throw new Error("Unknown option '" + key + "'. Valid options are: " + allowedOptionKeys.join(", "));
      }
      opt[key] = options[key];
    });

    var galenPath = "/usr/local/bin/galen";
    if (opt.galenPath) {
      galenPath = opt.galenPath;
      delete opt.galenPath;
    }

    var properties = {};
    if (opt.properties) {
      properties = opt.properties;
      delete opt.properties;
    }

    return through(function(file) {

      var stream = this;

      if (!opt.parallel) {
        // Prevent paralell execution
        stream.pause();
      }

      var args = [mode, file.path];
      Object.keys(opt).forEach(function(key) {
        if (opt[key]) {
          args.push("--" + key + "=" + opt[key]);
        }
      });
      Object.keys(properties).forEach(function(key) {
        if (properties[key]) {
          args.push("-D" + key + "=" + properties[key]);
        }
      });

      spawn(galenPath, args, {
        "stdio": "inherit"
      }).on("close", function(code) {
        if (code === 0) {
          stream.emit('data', file);
          stream.resume();
        } else {
          stream.emit('error', new Error("Test '" + file.path + "' failed!"));
        }
      }).on("error", function(err) {
        stream.emit('error',  new Error("Could not start galen. Galen ('" + galenPath + "') not found?"));
      });
    });
  };
};

module.exports = {
  check: GulpEventStream('check', ['url', 'javascript', 'size', 'include', 'exclude']),
  test: GulpEventStream('test', ['parallel-tests', 'recursive', 'filter', 'groups', 'excluded-groups'])
};
<|endoftext|>


<commit_before>
var _selector_chart_box_all = "section div[name=chart-box]";

function renderCharts () {
  renderChartBoxes();
  renderChartContents();
}

function renderChartBoxes () {
  removeChartBoxes();

  initializePartnersForCharts();
  var source_list = [gauge_data, partner_data];

  $.each(source_list, function (source_index, source) {
    $.each(source, function (index, label_data) {
      var _id_col = index % 2 == 0 ? "#chart-col-left" : "#chart-col-right";
      $(_id_col).append(createChartBox(label_data, source_index));
    });
  });
}

function renderChartContents () {
  _chart_set = {};

  var _suffix = $("#content-title-desc").text();
  $.each(gauge_data, function (index, label_data) {
    createChartContent(label_data.id + "-chart", label_data, _suffix);
  });

  var _profile = extractEnvPartProfile();
  _suffix = _profile.env_name || _profile.region_name;
  $.each(partner_data, function (index, label_data) {
    createPartnerChartContent(label_data.id + "-chart", label_data, _suffix);
  });
}

function createChartContent (_div_id, _label, _suffix) {
  var _setting = $.extend(true, {}, _chart_setting);
  _setting.graphs[0].title = _label.name;
  _setting.graphs[0].valueField = "value";
  _setting.graphs[0].balloonText = "[[value]] " + (_label.unit || "");
  _setting.titles[0].id = _label.id + "-title";
  _setting.titles[0].text = _label.name + " - " + _suffix;
  _setting.valueAxes[0].title = _label.unit || "Rate";
  _setting.legend.valueText = _setting.graphs[0].balloonText;
  _setting.legend.valueWidth = 100;
  _setting.dataProvider = [];

  $("#" + _div_id).replaceWith($("<div/>", { class: "chart", style: "height:400px;", id: _div_id }));
  _chart_set[_label.id] = AmCharts.makeChart(_div_id, _setting);
  _chart_set[_label.id].addListener("zoomed", syncZoom);
}

function createPartnerChartContent (_div_id, _label, _suffix) {
  var _setting = $.extend(true, {}, _chart_setting);
  _setting.titles[0].id = _label.id + "-title";
  _setting.titles[0].text = _label.name + " - " + _suffix;
  _setting.valueAxes[0].title = _label.unit || "Rate";
  _setting.legend.valueText = "[[value]]";
  _setting.legend.valueWidth = 65;
  _setting.dataProvider = [];

  _setting.graphs = [];
  var _graphs_setting = _chart_setting.graphs[0];
  $.each(partner_profile, function (index, profile) {
    var _color = undefined;
    var _graphs = $.extend(true, {}, _graphs_setting);
    _graphs.id = "p" + index;
    _graphs.title = profile.name;
    _graphs.valueField = "value" + index;
    _graphs.balloonText = profile.name + ": [[value" + index +  "]] " + (_label.unit || "");
    _graphs.bulletBorderColor = _color;
    _graphs.bulletColor = _color;
    _graphs.lineColor = _color;
    _setting.graphs.push(_graphs);
  })

  $("#" + _div_id).replaceWith($("<div/>", { class: "chart", style: "height:400px;", id: _div_id }));
  _chart_set[_label.id] = AmCharts.makeChart(_div_id, _setting);
  _chart_set[_label.id].addListener("zoomed", syncZoom);
}

function syncZoom(event) {
  zoomAllChartContent(event.startIndex, event.endIndex);
}

function zoomAllChartContent(_start, _end) {
  $.each(_chart_set, function (index, _chart_id) {
    _chart_id.zoomToIndexes(_start, _end);
  });
}

function updateCharts (_data_set) {
  updateChartContents(_data_set);
}

function updateChartContents (_data_set) {
  $.each(gauge_data.concat(partner_data), function (index, label_data) {
    updateChartContentWithData(label_data.id, _data_set[label_data.id]);
  });
}

function updateChartContentWithData (_id, _data) {
  var _start = _chart_set[_id].startIndex;
  var _end = _chart_set[_id].endIndex;
  var _length = _chart_set[_id].dataProvider.length;
  if (!(_start && _end) || (_length == _end - _start + 1)) {
    var _archive_data = _chart_set[_id].dataProvider;
    _chart_set[_id].dataProvider = _data;
    _chart_set[_id].validateData();
    _archive_data.length = 0;
  }
}

function showChartBoxes () {
  $(_selector_chart_box_all).show();
}

function hideChartBoxes () {
  $(_selector_chart_box_all).hide();
}

function removeChartBoxes () {
  $.each(_chart_set, function (index, _chart_id) {
    _chart_id.clear();
  });
  _chart_set.length = 0;
  $(_selector_chart_box_all).remove();
}

function createChartBox (_data, _striped_header) {
  var _div = $("<div/>", { class: "box box-solid", id: _data.id + "-box", name: "chart-box" });

  var _header = $("<div/>", { class: "box-header", style: "border-radius: 3px 3px 0 0 / 3px 3px;" });
  if (_striped_header) {
    _header.addClass(_data.color);
    _header.addClass("chart-box-header-striped");
    _header.addClass("chart-box-header-active");
  }
  else {
    _header.addClass(_data.color + "-gradient");
  }

  _header.append($("<i/>", { class: _data.icon }));
  _header.append($("<h3/>", { class: "box-title", text: _data.name + " Graph" }));

  var _body = $("<div/>", { class: "box-body border-radius-none" });
  _body.append($("<div/>", { class: "chart", style: "height:400px;", id: _data.id + "-chart" }));

  _div.append(_header);
  _div.append(_body);

  return _div;
}

var _chart_set = {};

var _chart_font_size = 14;
var _chart_bullet_color = "#000000";

var _chart_setting =
{
  "type": "serial",
  "addClassNames": true,
  "classNamePrefix": "amcharts",
  "pathToImages": "amcharts/images/",
  "categoryField": "date",
  "dataDateFormat": "YYYY-MM-DD HH:NN:SS",
  "fontSize": _chart_font_size,
  "fontFamily": "'Source Sans Pro','Helvetica Neue',Helvetica,Arial,sans-serif",
  "theme": "light",
  "categoryAxis": {
    "minPeriod": "ss",
    "parseDates": true
  },
  "chartCursor": {
    "categoryBalloonDateFormat": "JJ:NN:SS"
  },
  "trendLines": [],
  "graphs": [
    {
      "animationPlayed": true,
      "balloonText": undefined,
      "bullet": "round",
      "bulletBorderAlpha": 1,
      "bulletBorderColor": _chart_bullet_color,
      "bulletBorderThickness": 1,
      "bulletColor": _chart_bullet_color,
      "bulletSize": 1,
      "classNameField": "bulletClass",
      "id": "g2",
      "lineColor": _chart_bullet_color,
      "lineThickness": 1,
      "showBalloon": true,
      "title": undefined,
      "type": "line",
      "valueField": undefined,
    },
  ],
  "guides": [],
  "valueAxes": [
    {
      "id": "ValueAxis",
      "title": undefined,
      "fontSize": _chart_font_size,
      "minimum": 0,
    }
  ],
  "allLabels": [],
  "balloon": {},
  "legend": {
    "useGraphSettings": true,
    "valueWidth": undefined,
    "valueText": undefined,
  },
  "titles": [
    {
      "id": undefined,
      "size": _chart_font_size + 3,
      "text": undefined,
    }
  ],
  "dataProvider": undefined,
};
<commit_msg>Bring back gradient colors for lines but commented<commit_after>
var _selector_chart_box_all = "section div[name=chart-box]";

function renderCharts () {
  renderChartBoxes();
  renderChartContents();
}

function renderChartBoxes () {
  removeChartBoxes();

  initializePartnersForCharts();
  var source_list = [gauge_data, partner_data];

  $.each(source_list, function (source_index, source) {
    $.each(source, function (index, label_data) {
      var _id_col = index % 2 == 0 ? "#chart-col-left" : "#chart-col-right";
      $(_id_col).append(createChartBox(label_data, source_index));
    });
  });
}

function renderChartContents () {
  _chart_set = {};

  var _suffix = $("#content-title-desc").text();
  $.each(gauge_data, function (index, label_data) {
    createChartContent(label_data.id + "-chart", label_data, _suffix);
  });

  var _profile = extractEnvPartProfile();
  _suffix = _profile.env_name || _profile.region_name;
  $.each(partner_data, function (index, label_data) {
    createPartnerChartContent(label_data.id + "-chart", label_data, _suffix);
  });
}

function createChartContent (_div_id, _label, _suffix) {
  var _setting = $.extend(true, {}, _chart_setting);
  _setting.graphs[0].title = _label.name;
  _setting.graphs[0].valueField = "value";
  _setting.graphs[0].balloonText = "[[value]] " + (_label.unit || "");
  _setting.titles[0].id = _label.id + "-title";
  _setting.titles[0].text = _label.name + " - " + _suffix;
  _setting.valueAxes[0].title = _label.unit || "Rate";
  _setting.legend.valueText = _setting.graphs[0].balloonText;
  _setting.legend.valueWidth = 100;
  _setting.dataProvider = [];

  $("#" + _div_id).replaceWith($("<div/>", { class: "chart", style: "height:400px;", id: _div_id }));
  _chart_set[_label.id] = AmCharts.makeChart(_div_id, _setting);
  _chart_set[_label.id].addListener("zoomed", syncZoom);
}

function createPartnerChartContent (_div_id, _label, _suffix) {
  var _color_setting = $("#" + _label.id + "-box .box-header").css("background-color");
  var _color_percent = partner_limit > 1 ? 0.5 / (partner_limit - 1) : 0;

  var _setting = $.extend(true, {}, _chart_setting);
  _setting.titles[0].id = _label.id + "-title";
  _setting.titles[0].text = _label.name + " - " + _suffix;
  _setting.valueAxes[0].title = _label.unit || "Rate";
  _setting.legend.valueText = "[[value]]";
  _setting.legend.valueWidth = 65;
  _setting.dataProvider = [];

  _setting.graphs = [];
  var _graphs_setting = _chart_setting.graphs[0];
  $.each(partner_profile, function (index, profile) {
    var _color = undefined;
    // var _color = shadeRGBColor(_color_setting, index * _color_percent);
    var _graphs = $.extend(true, {}, _graphs_setting);
    _graphs.id = "p" + index;
    _graphs.title = profile.name;
    _graphs.valueField = "value" + index;
    _graphs.balloonText = profile.name + ": [[value" + index +  "]] " + (_label.unit || "");
    _graphs.bulletBorderColor = _color;
    _graphs.bulletColor = _color;
    _graphs.lineColor = _color;
    _setting.graphs.push(_graphs);
  })

  $("#" + _div_id).replaceWith($("<div/>", { class: "chart", style: "height:400px;", id: _div_id }));
  _chart_set[_label.id] = AmCharts.makeChart(_div_id, _setting);
  _chart_set[_label.id].addListener("zoomed", syncZoom);
}

function syncZoom(event) {
  zoomAllChartContent(event.startIndex, event.endIndex);
}

function zoomAllChartContent(_start, _end) {
  $.each(_chart_set, function (index, _chart_id) {
    _chart_id.zoomToIndexes(_start, _end);
  });
}

function updateCharts (_data_set) {
  updateChartContents(_data_set);
}

function updateChartContents (_data_set) {
  $.each(gauge_data.concat(partner_data), function (index, label_data) {
    updateChartContentWithData(label_data.id, _data_set[label_data.id]);
  });
}

function updateChartContentWithData (_id, _data) {
  var _start = _chart_set[_id].startIndex;
  var _end = _chart_set[_id].endIndex;
  var _length = _chart_set[_id].dataProvider.length;
  if (!(_start && _end) || (_length == _end - _start + 1)) {
    var _archive_data = _chart_set[_id].dataProvider;
    _chart_set[_id].dataProvider = _data;
    _chart_set[_id].validateData();
    _archive_data.length = 0;
  }
}

function showChartBoxes () {
  $(_selector_chart_box_all).show();
}

function hideChartBoxes () {
  $(_selector_chart_box_all).hide();
}

function removeChartBoxes () {
  $.each(_chart_set, function (index, _chart_id) {
    _chart_id.clear();
  });
  _chart_set.length = 0;
  $(_selector_chart_box_all).remove();
}

function createChartBox (_data, _striped_header) {
  var _div = $("<div/>", { class: "box box-solid", id: _data.id + "-box", name: "chart-box" });

  var _header = $("<div/>", { class: "box-header", style: "border-radius: 3px 3px 0 0 / 3px 3px;" });
  if (_striped_header) {
    _header.addClass(_data.color);
    _header.addClass("chart-box-header-striped");
    _header.addClass("chart-box-header-active");
  }
  else {
    _header.addClass(_data.color + "-gradient");
  }

  _header.append($("<i/>", { class: _data.icon }));
  _header.append($("<h3/>", { class: "box-title", text: _data.name + " Graph" }));

  var _body = $("<div/>", { class: "box-body border-radius-none" });
  _body.append($("<div/>", { class: "chart", style: "height:400px;", id: _data.id + "-chart" }));

  _div.append(_header);
  _div.append(_body);

  return _div;
}

var _chart_set = {};

var _chart_font_size = 14;
var _chart_bullet_color = "#000000";

var _chart_setting =
{
  "type": "serial",
  "addClassNames": true,
  "classNamePrefix": "amcharts",
  "pathToImages": "amcharts/images/",
  "categoryField": "date",
  "dataDateFormat": "YYYY-MM-DD HH:NN:SS",
  "fontSize": _chart_font_size,
  "fontFamily": "'Source Sans Pro','Helvetica Neue',Helvetica,Arial,sans-serif",
  "theme": "light",
  "categoryAxis": {
    "minPeriod": "ss",
    "parseDates": true
  },
  "chartCursor": {
    "categoryBalloonDateFormat": "JJ:NN:SS"
  },
  "trendLines": [],
  "graphs": [
    {
      "animationPlayed": true,
      "balloonText": undefined,
      "bullet": "round",
      "bulletBorderAlpha": 1,
      "bulletBorderColor": _chart_bullet_color,
      "bulletBorderThickness": 1,
      "bulletColor": _chart_bullet_color,
      "bulletSize": 1,
      "classNameField": "bulletClass",
      "id": "g2",
      "lineColor": _chart_bullet_color,
      "lineThickness": 1,
      "showBalloon": true,
      "title": undefined,
      "type": "line",
      "valueField": undefined,
    },
  ],
  "guides": [],
  "valueAxes": [
    {
      "id": "ValueAxis",
      "title": undefined,
      "fontSize": _chart_font_size,
      "minimum": 0,
    }
  ],
  "allLabels": [],
  "balloon": {},
  "legend": {
    "useGraphSettings": true,
    "valueWidth": undefined,
    "valueText": undefined,
  },
  "titles": [
    {
      "id": undefined,
      "size": _chart_font_size + 3,
      "text": undefined,
    }
  ],
  "dataProvider": undefined,
};
<|endoftext|>


<commit_before>
// greet :: String -> String
function greet(who){
    return "Hello, "+who+" :)";
}

// power :: Integer -> Integer -> Integer
function power(base, exponent){
    if(exponent == 0){
	return 1;
    }else if(exponent % 2 == 0){
	var p = power(base, exponent/2)
	return p*p;
    }else{
	return base * power(base,exponent-1);
    }
}

// findSolution :: Integer -> String
function findSolution(target){
    function find(start, history){
	if (start == target){
	    return history;
	}else if (start > target){
	    return null;
	}else{
	    return find(start*3, "(" + history + " * 3)") ||
		find(start+5, "(" + history + " + 5)");
	}
    }
    return find(1, "1");
}

// Min :: Integer -> Integer -> Integer
function Min(a,b){
    if(a < b){
	return a ;
    }else{
	return b ;
    }
}

// isEven :: Integer -> Bool
function isEven(n){
    if(n == 0){
	return true;
    }else if(n == 1){
	return false;
    }else{
	return isEven(n-2);
    }
}

// countBs :: String -> Integer
function countBs(s){
    return countChar(s,"B");
}

// countChar :: String -> Char -> Integer
function countChar(s,target){
    var result = 0 ;
    for(i = 0; i < s.length; i++){
	if(s.charAt(i) == target){
	    result++ ;
	}
    }
    return result ;
}

// Objects and Arrays

// The Lycanthrope's Journal

function phi(table){
    return (table[3]*table[0] - table[2]*table[1])/
	Math.sqrt((table[2] + table[3])*
		  (table[0] + table[1])*
		  (table[1] + table[3])*
		  (table[0] + table[2]));
}

function hasEvent(event, entry){
    return entry.events.indexOf(event) != -1;
}

function tableFor(event, journal){
    var table = [0, 0, 0, 0];
    for (var i=0; i < journal.length; i++){
	var entry = journal[i];
	if(hasEvent(event, entry) && entry.squirrel){
	    table[3] += 1;
	}else if (hasEvent(event, entry)){
	    table[1] += 1;
	}else if (entry.squirrel){
	    table[2] += 1;
	}else{
	    table[0] += 1;
	}
    }
    return table;
}

function gatherCorrelations(journal){
    var phis = {};
    journal.forEach(function(entry){
	entry.events.forEach(function(event){
	    if(!(event in phis)){
		phis[event] = phi(tableFor(event, journal));
	    }
	});
    });
    return phis;
}

function range(a,b){
    var result = [];
    var step = arguments[2];
    if(step == null){
	step = 1;
    }
    for(var i=a; ((i-b)*(step/Math.abs(step)) <= 0) ; i += step){
	result.push(i);
    }
    return result ;
}

function sum(ls){
    var result = 0;
    for(var i = 0; i < ls.length; i++){
	result += ls[i];
    }
    return result;
}

function reverseArray(arr){
    var result = [] ;
    for(var i=0; i < arr.length; i++){
	result.unshift(arr[i]);
    }
    return result;
}

function reverseArrayInPlace(arr){
    var l = arr.length ;
    for(var i=0; i < l/2 ;i++){
	var a = arr[i];
	var b = arr[l-1-i];
	arr[i] = b;
	arr[l-i-1] = a;
    }
}

function arrayToList(arr){
    if(arr.length == 0){
	return null;
    }else{
	return {
	    value : arr.shift(),
	    rest: arrayToList(arr)
	};
    }
}

function prepend(el, list){
    return {
	value: el,
	rest: list
    };
}

function nth(n, list){
    if(!list){
	return undefined;
    }else if(n == 0){
	return list.value;
    }else{
	return nth(n-1, list.rest);
    }
}

function listToArray(list){
    var result = [];
    var i = 0;
    while(nth(i,list)){
	result.push(nth(i,list));
	i = i+1;
    }
    return result;
}

// Higher Order Functions

function forEach(arr, action){
    for(var i = 0 ; i < arr.length ; i++){
	action(arr[i]);
    }
}

function filter(arr, test){
    var passed = [];
    arr.forEach(function(el){
	if(test(el)){
	    passed.push(el);
	}
    });
    return passed;
}

function map(arr, transform){
    var result = [];
    arr.forEach(function(el){
	result.push(transform(el));
    });
    return result;
}

function reduce(arr, combine, start){
    var current = start;
    arr.forEach(function(el){
	current = combine(current, el);
    });
    return current;
}

function average(arr){
    function plus(a, b){return a+b}
    return arr.reduce(plus) / arr.length;
}

function male(p){return p.sex == "m"}

function female(p){return p.sex == "f"}

function age(p){return p.died - p.born}

/*

var byName = {};
ancestry.forEach(function(person) {
  byName[person.name] = person;
});

*/

function ageDiffMother(p){
  if((p.mother == null) || (byName[p.mother] == undefined)){
    return null;
  }else{
    return (p.born - byName[p.mother].born);
  }
}

/*

console.log(average(ancestry.map(ageDiffMother).filter(function(diff){return diff})));

var byCentury = {};
var ancestry = JSON.parse(ANCESTRY_FILE);

ancestry.forEach(function(p){
  if(century(p) in byCentury){
     byCentury[century(p)].push(age(p));
  }else{
    byCentury[century(p)] = [age(p)] ;
  }
});
for(var item in byCentury){
  console.log(item + " : " + average(byCentury[item]));
}

*/

function every(arr, action){
  function and(a, b){
    return a && b ;
  }
  return arr.map(action).reduce(and);
}

function some(arr, action){
  function or(a, b){
    return a || b ;
  }
  return arr.map(action).reduce(or);
}

// Object Oriented Programming

function Rabbit(type){
    this.type = type ;
}

Rabbit.prototype.speak = function(line){
    return "The " + this.type + " rabbit says " + line ;
} ;

Rabbit.prototype.toString = function(){
  return "This is a " + this.type + " Rabbit!"
};

// Table Cells Representation

function TextCell(text){
    this.text = text.split("\n");
}

TextCell.prototype.minHeight = function(){
    return this.text.length;
}

TextCell.prototype.minWidth = function(){
    return this.text.reduce(function(width, line){
	return Math.max(width, line.length);
    }, 0)
}

function repeat(string, times){
    var result = "";
	for(var i = 0; i < times; i++){
	    result += string;
	}
    return result;
}

TextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(line + repeat(" ", width - line.length));
    }
    return result;
}

function UnderlinedCell(inner){
    this.inner = inner;
}

UnderlinedCell.prototype.minHeight = function(){
    return this.inner.minHeight() + 1;
}

UnderlinedCell.prototype.minWidth = function(){
    return this.inner.minWidth();
}

UnderlinedCell.prototype.draw = function(width, height){
    return this.inner.draw(width, height - 1)
	.concat([repeat("-", width)])
}

function RTextCell(text){
    TextCell.call(this, text);
}

RTextCell.prototype = Object.create(TextCell.prototype);

RTextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(repeat(" ", width - line.length) + line);
    }
    return result;
}

// Methods for calculating the minimum heights and widths for the
// rows and columns of table to be drawn out of above table cells

function rowHeights(rows){
    return rows.map(function(row){
	return row.reduce(function(current, cell){
	    return Math.max(current, cell.minHeight());
	}, 0);
    });
}

function colWidths(rows){
    return rows[0].map(function(_, i){
	return rows.reduce(function(current, row){
	    return Math.max(current, row[i].minWidth());
	}, 0);
    });
}

// Draw table method for drawing the tables out of array of arrays of table cells

function drawTable(rows){
    var heights = rowHeights(rows);
    var widths = colWidths(rows);

    function drawLine(blocks, lineNo){
	return blocks.map(function(block){
	    return block[lineNo];
	}).join("\t");
    }

    function drawRow(row, rowNum){
	var blocks = row.map(function(cell, colNum){
	    return cell.draw(widths[colNum], heights[rowNum]);
	});

	return blocks[0].map(function(_, lineNo){
	    return drawLine(blocks, lineNo);
	}).join("\n");
    }

    return rows.map(drawRow).join("\n");

}

function dataConvert(data){
    var keys = Object.keys(data[0]);
    var keysTable = keys.map(function(key){
	return new UnderlinedCell(new TextCell(key.toString()));
    });
    var dataTable =  data.map(function(entry){
	var row = [];
	keys.forEach(function(key){
	    var el = entry[key];
	    if (typeof el == "number"){
		row.push(new RTextCell(el.toString()));
	    }else{
		row.push(new TextCell(el.toString()));
	    }
	});
	return row;
    });
    dataTable.unshift(keysTable);
    return dataTable;
}

// Vector Representation

function Vector(x, y){
    this.x = x;
    this.y = y;
}

Vector.prototype.plus = function(that){
    return new Vector(this.x + that.x, this.y + that.y);
}

Vector.prototype.minus = function(that){
    return new Vector(this.x - that.x, this.y - that.y);
}

Object.defineProperty(Vector.prototype, "length", {
    get: function(){
	return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
    }
});

// Stretched Cell Representation

function StretchCell(inner, width, height){
    this.inner = inner;
    this.width = width;
    this.height = height;
}

StretchCell.prototype.minHeight = function(){
    return Math.max(this.height, this.inner.minHeight());
}

StretchCell.prototype.minWidth = function(){
    return Math.max(this.width, this.inner.minWidth());
}

StretchCell.prototype.draw = function(width, height){
    return this.inner.draw(Math.max(this.minWidth(), width),
			   Math.max(this.minHeight(), height));
}

// Bugs & Error Handling

function loop(a, b){
    if(!isNaN(a) && !isNaN(b) && a < b) return range(a, b);
    throw new Error("Not a valid pair of input!");
}

// Regular Expressions

function findDate(s){
    var dateTime = /(\d{1,2})-(\d{1,2})-(\d{1,4})/ ;
    var match = dateTime.exec(s);
    return new Date(Number(match[3]),
		    Number(match[2])-1,
		    Number(match[1]));
}

var stock = "1 lemon , 2 cabbages , and 101 eggs ";
function minusOne ( match , amount , unit ) {
    amount = Number ( amount ) - 1;
    if ( amount == 1)
	unit = unit . slice (0 , unit . length - 1) ;
    else if ( amount == 0){
	amount = " no ";
	unit = unit + "s";
    }
    return amount + " " + unit ;
}

function stripComments(code){
    return code.replace(/\/\/.*|\/\*[^]*?\*\//g, "")
}

// RegExp Exercises

/* First Question Answers

/ca(r|t)/ , /pr?op/ , /ferr(et|y|ari)/ , /.ious/ , /\s(\.|\,|\;|\:)/ ,

/\w{7,}/ , /[^e]/

*/

function removeSingleQuotes(s){
    var regExp = /(\'\s|\s\')/g ;
    return s.replace(regExp, '"');
}

<commit_msg>Added the parseINI function<commit_after>
// greet :: String -> String
function greet(who){
    return "Hello, "+who+" :)";
}

// power :: Integer -> Integer -> Integer
function power(base, exponent){
    if(exponent == 0){
	return 1;
    }else if(exponent % 2 == 0){
	var p = power(base, exponent/2)
	return p*p;
    }else{
	return base * power(base,exponent-1);
    }
}

// findSolution :: Integer -> String
function findSolution(target){
    function find(start, history){
	if (start == target){
	    return history;
	}else if (start > target){
	    return null;
	}else{
	    return find(start*3, "(" + history + " * 3)") ||
		find(start+5, "(" + history + " + 5)");
	}
    }
    return find(1, "1");
}

// Min :: Integer -> Integer -> Integer
function Min(a,b){
    if(a < b){
	return a ;
    }else{
	return b ;
    }
}

// isEven :: Integer -> Bool
function isEven(n){
    if(n == 0){
	return true;
    }else if(n == 1){
	return false;
    }else{
	return isEven(n-2);
    }
}

// countBs :: String -> Integer
function countBs(s){
    return countChar(s,"B");
}

// countChar :: String -> Char -> Integer
function countChar(s,target){
    var result = 0 ;
    for(i = 0; i < s.length; i++){
	if(s.charAt(i) == target){
	    result++ ;
	}
    }
    return result ;
}

// Objects and Arrays

// The Lycanthrope's Journal

function phi(table){
    return (table[3]*table[0] - table[2]*table[1])/
	Math.sqrt((table[2] + table[3])*
		  (table[0] + table[1])*
		  (table[1] + table[3])*
		  (table[0] + table[2]));
}

function hasEvent(event, entry){
    return entry.events.indexOf(event) != -1;
}

function tableFor(event, journal){
    var table = [0, 0, 0, 0];
    for (var i=0; i < journal.length; i++){
	var entry = journal[i];
	if(hasEvent(event, entry) && entry.squirrel){
	    table[3] += 1;
	}else if (hasEvent(event, entry)){
	    table[1] += 1;
	}else if (entry.squirrel){
	    table[2] += 1;
	}else{
	    table[0] += 1;
	}
    }
    return table;
}

function gatherCorrelations(journal){
    var phis = {};
    journal.forEach(function(entry){
	entry.events.forEach(function(event){
	    if(!(event in phis)){
		phis[event] = phi(tableFor(event, journal));
	    }
	});
    });
    return phis;
}

function range(a,b){
    var result = [];
    var step = arguments[2];
    if(step == null){
	step = 1;
    }
    for(var i=a; ((i-b)*(step/Math.abs(step)) <= 0) ; i += step){
	result.push(i);
    }
    return result ;
}

function sum(ls){
    var result = 0;
    for(var i = 0; i < ls.length; i++){
	result += ls[i];
    }
    return result;
}

function reverseArray(arr){
    var result = [] ;
    for(var i=0; i < arr.length; i++){
	result.unshift(arr[i]);
    }
    return result;
}

function reverseArrayInPlace(arr){
    var l = arr.length ;
    for(var i=0; i < l/2 ;i++){
	var a = arr[i];
	var b = arr[l-1-i];
	arr[i] = b;
	arr[l-i-1] = a;
    }
}

function arrayToList(arr){
    if(arr.length == 0){
	return null;
    }else{
	return {
	    value : arr.shift(),
	    rest: arrayToList(arr)
	};
    }
}

function prepend(el, list){
    return {
	value: el,
	rest: list
    };
}

function nth(n, list){
    if(!list){
	return undefined;
    }else if(n == 0){
	return list.value;
    }else{
	return nth(n-1, list.rest);
    }
}

function listToArray(list){
    var result = [];
    var i = 0;
    while(nth(i,list)){
	result.push(nth(i,list));
	i = i+1;
    }
    return result;
}

// Higher Order Functions

function forEach(arr, action){
    for(var i = 0 ; i < arr.length ; i++){
	action(arr[i]);
    }
}

function filter(arr, test){
    var passed = [];
    arr.forEach(function(el){
	if(test(el)){
	    passed.push(el);
	}
    });
    return passed;
}

function map(arr, transform){
    var result = [];
    arr.forEach(function(el){
	result.push(transform(el));
    });
    return result;
}

function reduce(arr, combine, start){
    var current = start;
    arr.forEach(function(el){
	current = combine(current, el);
    });
    return current;
}

function average(arr){
    function plus(a, b){return a+b}
    return arr.reduce(plus) / arr.length;
}

function male(p){return p.sex == "m"}

function female(p){return p.sex == "f"}

function age(p){return p.died - p.born}

/*

var byName = {};
ancestry.forEach(function(person) {
  byName[person.name] = person;
});

*/

function ageDiffMother(p){
  if((p.mother == null) || (byName[p.mother] == undefined)){
    return null;
  }else{
    return (p.born - byName[p.mother].born);
  }
}

/*

console.log(average(ancestry.map(ageDiffMother).filter(function(diff){return diff})));

var byCentury = {};
var ancestry = JSON.parse(ANCESTRY_FILE);

ancestry.forEach(function(p){
  if(century(p) in byCentury){
     byCentury[century(p)].push(age(p));
  }else{
    byCentury[century(p)] = [age(p)] ;
  }
});
for(var item in byCentury){
  console.log(item + " : " + average(byCentury[item]));
}

*/

function every(arr, action){
  function and(a, b){
    return a && b ;
  }
  return arr.map(action).reduce(and);
}

function some(arr, action){
  function or(a, b){
    return a || b ;
  }
  return arr.map(action).reduce(or);
}

// Object Oriented Programming

function Rabbit(type){
    this.type = type ;
}

Rabbit.prototype.speak = function(line){
    return "The " + this.type + " rabbit says " + line ;
} ;

Rabbit.prototype.toString = function(){
  return "This is a " + this.type + " Rabbit!"
};

// Table Cells Representation

function TextCell(text){
    this.text = text.split("\n");
}

TextCell.prototype.minHeight = function(){
    return this.text.length;
}

TextCell.prototype.minWidth = function(){
    return this.text.reduce(function(width, line){
	return Math.max(width, line.length);
    }, 0)
}

function repeat(string, times){
    var result = "";
	for(var i = 0; i < times; i++){
	    result += string;
	}
    return result;
}

TextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(line + repeat(" ", width - line.length));
    }
    return result;
}

function UnderlinedCell(inner){
    this.inner = inner;
}

UnderlinedCell.prototype.minHeight = function(){
    return this.inner.minHeight() + 1;
}

UnderlinedCell.prototype.minWidth = function(){
    return this.inner.minWidth();
}

UnderlinedCell.prototype.draw = function(width, height){
    return this.inner.draw(width, height - 1)
	.concat([repeat("-", width)])
}

function RTextCell(text){
    TextCell.call(this, text);
}

RTextCell.prototype = Object.create(TextCell.prototype);

RTextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(repeat(" ", width - line.length) + line);
    }
    return result;
}

// Methods for calculating the minimum heights and widths for the
// rows and columns of table to be drawn out of above table cells

function rowHeights(rows){
    return rows.map(function(row){
	return row.reduce(function(current, cell){
	    return Math.max(current, cell.minHeight());
	}, 0);
    });
}

function colWidths(rows){
    return rows[0].map(function(_, i){
	return rows.reduce(function(current, row){
	    return Math.max(current, row[i].minWidth());
	}, 0);
    });
}

// Draw table method for drawing the tables out of array of arrays of table cells

function drawTable(rows){
    var heights = rowHeights(rows);
    var widths = colWidths(rows);

    function drawLine(blocks, lineNo){
	return blocks.map(function(block){
	    return block[lineNo];
	}).join("\t");
    }

    function drawRow(row, rowNum){
	var blocks = row.map(function(cell, colNum){
	    return cell.draw(widths[colNum], heights[rowNum]);
	});

	return blocks[0].map(function(_, lineNo){
	    return drawLine(blocks, lineNo);
	}).join("\n");
    }

    return rows.map(drawRow).join("\n");

}

function dataConvert(data){
    var keys = Object.keys(data[0]);
    var keysTable = keys.map(function(key){
	return new UnderlinedCell(new TextCell(key.toString()));
    });
    var dataTable =  data.map(function(entry){
	var row = [];
	keys.forEach(function(key){
	    var el = entry[key];
	    if (typeof el == "number"){
		row.push(new RTextCell(el.toString()));
	    }else{
		row.push(new TextCell(el.toString()));
	    }
	});
	return row;
    });
    dataTable.unshift(keysTable);
    return dataTable;
}

// Vector Representation

function Vector(x, y){
    this.x = x;
    this.y = y;
}

Vector.prototype.plus = function(that){
    return new Vector(this.x + that.x, this.y + that.y);
}

Vector.prototype.minus = function(that){
    return new Vector(this.x - that.x, this.y - that.y);
}

Object.defineProperty(Vector.prototype, "length", {
    get: function(){
	return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
    }
});

// Stretched Cell Representation

function StretchCell(inner, width, height){
    this.inner = inner;
    this.width = width;
    this.height = height;
}

StretchCell.prototype.minHeight = function(){
    return Math.max(this.height, this.inner.minHeight());
}

StretchCell.prototype.minWidth = function(){
    return Math.max(this.width, this.inner.minWidth());
}

StretchCell.prototype.draw = function(width, height){
    return this.inner.draw(Math.max(this.minWidth(), width),
			   Math.max(this.minHeight(), height));
}

// Bugs & Error Handling

function loop(a, b){
    if(!isNaN(a) && !isNaN(b) && a < b) return range(a, b);
    throw new Error("Not a valid pair of input!");
}

// Regular Expressions

function findDate(s){
    var dateTime = /(\d{1,2})-(\d{1,2})-(\d{1,4})/ ;
    var match = dateTime.exec(s);
    return new Date(Number(match[3]),
		    Number(match[2])-1,
		    Number(match[1]));
}

var stock = "1 lemon , 2 cabbages , and 101 eggs ";
function minusOne ( match , amount , unit ) {
    amount = Number ( amount ) - 1;
    if ( amount == 1)
	unit = unit . slice (0 , unit . length - 1) ;
    else if ( amount == 0){
	amount = " no ";
	unit = unit + "s";
    }
    return amount + " " + unit ;
}

function stripComments(code){
    return code.replace(/\/\/.*|\/\*[^]*?\*\//g, "")
}

// RegExp Exercises

/* First Question Answers

/ca(r|t)/ , /pr?op/ , /ferr(et|y|ari)/ , /.ious/ , /\s(\.|\,|\;|\:)/ ,

/\w{7,}/ , /[^e]/

*/

function removeSingleQuotes(s){
    var regExp = /(\'\s|\s\')/g ;
    return s.replace(regExp, '"');
}

// Programming Language : Egg

function parseINI(s){
    var currentSection = {name: null, fields: []};
    var categories = [currentSection];

    s.split(/\r?\n/).forEach(function(line){
	var match;
	if(/^\s*(;.*)?$/.test(line)){
	    return;
	}else if(match = line.match(/^\[(.*)\]$/)){
	    currentSection = {name: match[1], fields: []};
	    categories.push(currentSection);
	}else if(match = line.match(/^(\w+)=(.*)$/)){
	    currentSection.fields.push({name: match[1],
					value: match[2]});
	}else{
	    throw new Error("Line '" + line + "' is invalid.");
	}
    });

    return categories;
}

<|endoftext|>