<commit_before>var context = new (window.AudioContext || window.webkitAudioContext)();
var analyser = context.createAnalyser();

var buf = new Float32Array( 1024 );
var MIN_SAMPLES = 0; // To be initailzed when context is set
var mediaStreamSource = null;
var analyser = null;

var alphabet = "^\n abcdefghijklmnopqrstuvwxyz$";
var emoticons = ["^", "smile", "cry", "cool", "sad", "sleep", "sob", "uneasy", "kiss", "$"];
var start = '^';
var end = '$';

var supersonic = false;
var freqMin = 440;
var freqMax = 1760;

var range = freqMax - freqMin;
var processing = false;
var listening = false;

var message = "";
var emoji = "";
var capturing = false;
var finished_capturing = false;

function submit() {
  if(processing)
    return;
  var message = document.getElementById('message').value;
  if(message.length === 0)
    return;
  processing = true;
  document.getElementById('submit').disabled = true;
  process(message.toLowerCase());
}

function listen() {
  if(!document.getElementById('emoji_box').checked) {
    var message = document.getElementById('message');
    message.value = "";

    var listen_text = document.getElementById('listen').innerText;
    if(listen_text == "Cancel") {
      listening = false;
      processing = false;
      document.getElementById('message_listen').innerText = "Listen";
      document.getElementById('submit').disabled = false;
      message.placeholder = "Type Message";
    } else {
      listening = true;
      processing = true;
      document.getElementById('message_listen').innerText = "Cancel";
      document.getElementById('submit').disabled = true;
      message.placeholder = "Listening...";
      liveInput();
    }
  } else {
    if(listening) {
      listening = false;
      processing = false;
      document.getElementById('emoji_listen').innerText = "Listen";
    } else {
      listening = true;
      processing = true;
      document.getElementById('emoji_listen').innerText = "Cancel";
      liveInput();
    }
  }
}

window.onload = function() {
  document.getElementById("emoji_wrapper").style.display = "none";
}

document.getElementById('supersonic').onclick = function() {
  if(supersonic) {
    supersonic = false;
    freqMin = 440;
    freqMax = 1760;
  } else {
    supersonic = true;
    freqMin = 18500;
    freqMax = 19500;
  }
}

document.getElementById('emoji_box').onclick = function() {
  if(document.getElementById('emoji_box').checked) {
    document.getElementById("message_wrapper").style.display = "none";
    document.getElementById("emoji_wrapper").style.display = "block";
  }
  else {
    document.getElementById("message_wrapper").style.display = "block";
    document.getElementById("emoji_wrapper").style.display = "none";
  }
}

function selected(emoji) {
  processEmoji(emoji.name);
}

function stopListening() {
  listening = false;
  processing = false;
  document.getElementById('listen').innerText = "Listen";
  document.getElementById('submit').disabled = false;
  message.placeholder = "Type Message";
  message = "";
  capturing = false;
  finished_capturing = false;
}

function error() {
  alert('Stream generation failed.');
}

function getUserMedia(dictionary, callback) {
  try {
    navigator.getUserMedia =
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia;
      navigator.getUserMedia(dictionary, callback, error);
  } catch (e) {
      alert('getUserMedia threw exception :' + e);
  }
}

function gotStream(stream) {
  // Create an AudioNode from the stream.
  mediaStreamSource = context.createMediaStreamSource(stream);

  // Connect it to the destination.
  analyser = context.createAnalyser();
  analyser.fftSize = 2048;
  mediaStreamSource.connect(analyser);
  if(document.getElementById('emoji_box').checked) {
    updateEmoji();
  } else {
    updatePitch();
  }
}

function output() {
  var result = arguments.join("");
  var message = document.getElementById('message');
  message.value = result;
}

function liveInput() {
  getUserMedia(
    {
      "audio": {
        "mandatory": {
          "googEchoCancellation": "false",
          "googAutoGainControl": "false",
          "googNoiseSuppression": "false",
          "googHighpassFilter": "false"
        },
        "optional": []
      },
    }, gotStream);
}

function autoCorrelate(buf, sampleRate) {
  var SIZE = buf.length;
  var MAX_SAMPLES = Math.floor(SIZE/2);
  var best_offset = -1;
  var best_correlation = 0;
  var rms = 0;
  var foundGoodCorrelation = false;
  var correlations = new Array(MAX_SAMPLES);

  for(var i = 0; i < SIZE; i++) {
    var val = buf[i];
    rms += Math.pow(val, 2);
  }

  rms = Math.sqrt(rms/SIZE);
  if(rms < 0.01) {
    //Not enough signal
    return -1;
  }

  var lastCorrelation = 1;
  for(var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
    var correlation = 0;

    for(var i = 0; i < MAX_SAMPLES; i++) {
      correlation += Math.abs((buf[i]) - (buf[i + offset]));
    }
    correlation = 1 - (correlation/MAX_SAMPLES);
    correlations[offset] = correlation; // Store for later

    if((correlation > 0.9) && (correlation > lastCorrelation)) {
      foundGoodCorrelation = true;
      if(correlation > best_correlation) {
        best_correlation = correlation;
        best_offset = offset;
      }
    } else if (foundGoodCorrelation) {
      var shift = (correlations[best_offset+1] - correlations[best_offset-1])/correlations[best_offset];
      return sampleRate/(best_offset + (8 * shift));
    }
    lastCorrelation = correlation;
  }

  if(best_correlation > 0.01) {
    return sampleRate/best_offset;
  }
  return -1;
}

function updateEmoji() {
  var cycles = new Array;
  analyser.getFlotTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toEmoji(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      emoji = note;
    }
    console.log(note);
  }
  if(finished_capturing) {
    selectEmoji(emoji);
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190);
  }
}

function updatePitch() {
  var cycles = new Array;
  analyser.getFloatTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  // console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toChar(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      message += note;
    }
    console.log(note);
  } else {
    //console.log("ac is -1");
  }
  if(finished_capturing) {
    output("Received: \"", message, "\""   );
    stopListening();
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190)
  }
}

function selectEmoji(emoji) {
  console.log(emoji);
  // var selected_emoji = document.getElementsByName(emoji);
  // selected_emoji[0].src = "images/" + emoji + ".png";
}

function process(message) {
  var message = start + message + end;

  var i = 0;
  for(i; i < message.length; i++) {
    var tone;
    var char = message[i];
    var time = context.currentTime + 0.2*i;
    if(char === start) {
      tone = freqMin;
    }
    else if(char === end) {
      tone = freqMax;
    }
    else {
      tone = toFreq(char);
    }
    emit(tone, time);
  }
  setTimeout(function() {
    processing = false;
    document.getElementById('submit').disabled = false;
  }, 200 * message.length);
}

function processEmoji(emoji) {

  emit(freqMin, context.currentTime);
  emit(toEmojiFreq(emoji), context.currentTime + 0.2);
  emit(freqMax, context.currentTime + 0.4);

}

function toFreq(char) {
  var index = alphabet.indexOf(char);
  if(index === -1) {
    console.error('Invalid character: ', char);
    index = alphabet.length - 1;
  }
  var percent = index / alphabet.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toEmojiFreq(emoji) {
  var index = emoticons.indexOf(emoji);
  if(index === -1) {
    console.error("Invalid emoji: ", emoji);
    index = emoticons.length - 1;
  }
  var percent = index / emoticons.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toChar(freq, emoji) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(alphabet.length * percent);
  if(index == alphabet.length)
    return alphabet[index-1];
  return alphabet[index];
}

function toEoji(freq) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(emoticons.length * percent);
  if(index == emoticons.length)
    return emoticons[index-1];
  return emoticons[index];
}

function emit(tone, time) {
  console.log(tone + " " + time);
  // GainNode
  var gainNode = context.createGain();
  gainNode.gain.value = 0;
  gainNode.gain.setValueAtTime(0, time);
  gainNode.gain.linearRampToValueAtTime(1, time + 0.001);
  gainNode.gain.setValueAtTime(1, time + 0.2 - 0.001);
  gainNode.gain.linearRampToValueAtTime(0, time + 0.2);
  gainNode.connect(context.destination);

  // Oscillator
  var oscillator = context.createOscillator();
  oscillator.frequency.value = tone;
  oscillator.connect(gainNode);
  oscillator.start();
}

function restart() {
  window.location.reload();
}<commit_msg>Fixing how javascript works<commit_after>var context = new (window.AudioContext || window.webkitAudioContext)();
var analyser = context.createAnalyser();

var buf = new Float32Array( 1024 );
var MIN_SAMPLES = 0; // To be initailzed when context is set
var mediaStreamSource = null;
var analyser = null;

var alphabet = "^\n abcdefghijklmnopqrstuvwxyz$";
var emoticons = ["^", "smile", "cry", "cool", "sad", "sleep", "sob", "uneasy", "kiss", "$"];
var start = '^';
var end = '$';

var supersonic = false;
var freqMin = 440;
var freqMax = 1760;

var range = freqMax - freqMin;
var processing = false;
var listening = false;

var message = "";
var emoji = "";
var capturing = false;
var finished_capturing = false;

function submit() {
  if(processing)
    return;
  var message = document.getElementById('message').value;
  if(message.length === 0)
    return;
  processing = true;
  document.getElementById('submit').disabled = true;
  process(message.toLowerCase());
}

function listen() {
  if(!document.getElementById('emoji_box').checked) {
    var message = document.getElementById('message');
    message.value = "";

    var listen_text = document.getElementById('listen').innerText;
    if(listen_text == "Cancel") {
      listening = false;
      processing = false;
      document.getElementById('message_listen').innerText = "Listen";
      document.getElementById('submit').disabled = false;
      message.placeholder = "Type Message";
    } else {
      listening = true;
      processing = true;
      document.getElementById('message_listen').innerText = "Cancel";
      document.getElementById('submit').disabled = true;
      message.placeholder = "Listening...";
      liveInput();
    }
  } else {
    if(listening) {
      listening = false;
      processing = false;
      document.getElementById('emoji_listen').innerText = "Listen";
    } else {
      listening = true;
      processing = true;
      document.getElementById('emoji_listen').innerText = "Cancel";
      liveInput();
    }
  }
}

window.onload = function() {
  document.getElementById("emoji_wrapper").style.display = "none";
}

document.getElementById('supersonic').onclick = function() {
  if(supersonic) {
    supersonic = false;
    freqMin = 440;
    freqMax = 1760;
  } else {
    supersonic = true;
    freqMin = 18500;
    freqMax = 19500;
  }
}

document.getElementById('emoji_box').onclick = function() {
  if(document.getElementById('emoji_box').checked) {
    document.getElementById("message_wrapper").style.display = "none";
    document.getElementById("emoji_wrapper").style.display = "block";
  }
  else {
    document.getElementById("message_wrapper").style.display = "block";
    document.getElementById("emoji_wrapper").style.display = "none";
  }
}

function selected(emoji) {
  processEmoji(emoji.name);
}

function stopListening() {
  listening = false;
  processing = false;
  document.getElementById('listen').innerText = "Listen";
  document.getElementById('submit').disabled = false;
  message.placeholder = "Type Message";
  message = "";
  capturing = false;
  finished_capturing = false;
}

function error() {
  alert('Stream generation failed.');
}

function getUserMedia(dictionary, callback) {
  try {
    navigator.getUserMedia =
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia;
      navigator.getUserMedia(dictionary, callback, error);
  } catch (e) {
      alert('getUserMedia threw exception :' + e);
  }
}

function gotStream(stream) {
  // Create an AudioNode from the stream.
  mediaStreamSource = context.createMediaStreamSource(stream);

  // Connect it to the destination.
  analyser = context.createAnalyser();
  analyser.fftSize = 2048;
  mediaStreamSource.connect(analyser);
  if(document.getElementById('emoji_box').checked) {
    updateEmoji();
  } else {
    updatePitch();
  }
}

function output() {
  var result = arguments.join("");
  var message = document.getElementById('message');
  message.value = result;
}

function liveInput() {
  getUserMedia(
    {
      "audio": {
        "mandatory": {
          "googEchoCancellation": "false",
          "googAutoGainControl": "false",
          "googNoiseSuppression": "false",
          "googHighpassFilter": "false"
        },
        "optional": []
      },
    }, gotStream);
}

function autoCorrelate(buf, sampleRate) {
  var SIZE = buf.length;
  var MAX_SAMPLES = Math.floor(SIZE/2);
  var best_offset = -1;
  var best_correlation = 0;
  var rms = 0;
  var foundGoodCorrelation = false;
  var correlations = new Array(MAX_SAMPLES);

  for(var i = 0; i < SIZE; i++) {
    var val = buf[i];
    rms += Math.pow(val, 2);
  }

  rms = Math.sqrt(rms/SIZE);
  if(rms < 0.01) {
    //Not enough signal
    return -1;
  }

  var lastCorrelation = 1;
  for(var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
    var correlation = 0;

    for(var i = 0; i < MAX_SAMPLES; i++) {
      correlation += Math.abs((buf[i]) - (buf[i + offset]));
    }
    correlation = 1 - (correlation/MAX_SAMPLES);
    correlations[offset] = correlation; // Store for later

    if((correlation > 0.9) && (correlation > lastCorrelation)) {
      foundGoodCorrelation = true;
      if(correlation > best_correlation) {
        best_correlation = correlation;
        best_offset = offset;
      }
    } else if (foundGoodCorrelation) {
      var shift = (correlations[best_offset+1] - correlations[best_offset-1])/correlations[best_offset];
      return sampleRate/(best_offset + (8 * shift));
    }
    lastCorrelation = correlation;
  }

  if(best_correlation > 0.01) {
    return sampleRate/best_offset;
  }
  return -1;
}

function updateEmoji() {
  var cycles = new Array;
  analyser.getFloatTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toEmoji(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      emoji = note;
    }
    console.log(note);
  }
  if(finished_capturing) {
    selectEmoji(emoji);
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190);
  }
}

function updatePitch() {
  var cycles = new Array;
  analyser.getFloatTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  // console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toChar(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      message += note;
    }
    console.log(note);
  } else {
    //console.log("ac is -1");
  }
  if(finished_capturing) {
    output("Received: \"", message, "\""   );
    stopListening();
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190)
  }
}

function selectEmoji(emoji) {
  console.log(emoji);
  // var selected_emoji = document.getElementsByName(emoji);
  // selected_emoji[0].src = "images/" + emoji + ".png";
}

function process(message) {
  var message = start + message + end;

  var i = 0;
  for(i; i < message.length; i++) {
    var tone;
    var char = message[i];
    var time = context.currentTime + 0.2*i;
    if(char === start) {
      tone = freqMin;
    }
    else if(char === end) {
      tone = freqMax;
    }
    else {
      tone = toFreq(char);
    }
    emit(tone, time);
  }
  setTimeout(function() {
    processing = false;
    document.getElementById('submit').disabled = false;
  }, 200 * message.length);
}

function processEmoji(emoji) {

  emit(freqMin, context.currentTime);
  emit(toEmojiFreq(emoji), context.currentTime + 0.2);
  emit(freqMax, context.currentTime + 0.4);

}

function toFreq(char) {
  var index = alphabet.indexOf(char);
  if(index === -1) {
    console.error('Invalid character: ', char);
    index = alphabet.length - 1;
  }
  var percent = index / alphabet.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toEmojiFreq(emoji) {
  var index = emoticons.indexOf(emoji);
  if(index === -1) {
    console.error("Invalid emoji: ", emoji);
    index = emoticons.length - 1;
  }
  var percent = index / emoticons.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toChar(freq, emoji) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(alphabet.length * percent);
  if(index == alphabet.length)
    return alphabet[index-1];
  return alphabet[index];
}

function toEoji(freq) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(emoticons.length * percent);
  if(index == emoticons.length)
    return emoticons[index-1];
  return emoticons[index];
}

function emit(tone, time) {
  console.log(tone + " " + time);
  // GainNode
  var gainNode = context.createGain();
  gainNode.gain.value = 0;
  gainNode.gain.setValueAtTime(0, time);
  gainNode.gain.linearRampToValueAtTime(1, time + 0.001);
  gainNode.gain.setValueAtTime(1, time + 0.2 - 0.001);
  gainNode.gain.linearRampToValueAtTime(0, time + 0.2);
  gainNode.connect(context.destination);

  // Oscillator
  var oscillator = context.createOscillator();
  oscillator.frequency.value = tone;
  oscillator.connect(gainNode);
  oscillator.start();
}

function restart() {
  window.location.reload();
}<|endoftext|>


<commit_before>'use strict';

var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');

// Space between the side edge of the canvas and the paddle.
var EDGE_TO_PADDLE = 5;

/**
   The paddle at either side of the canvas.
   @constructor
   @param {boolean} isLeft - If true, construct the left paddle, otherwise
   construct the right one.
*/
function Paddle(isLeft) {
  this.x = isLeft ? EDGE_TO_PADDLE : canvas.width - EDGE_TO_PADDLE - this.WIDTH;
  this.y = (canvas.height - this.HEIGHT) / 2;
}

Paddle.prototype = {
  constructor: Paddle,
  WIDTH: 20,
  HEIGHT: 100,

  /**
     Move the paddle.
     @param {boolean} isUp - Whether to move up or down.
     @param {number} speed - The number of pixels to move.
  */
  move: function(isUp, speed) {
    if (isUp) {
      this.y = Math.max(0, this.y - speed);
    } else {
      this.y = Math.min(canvas.height - this.HEIGHT, this.y + speed);
    }
  },

  render: function() {
    context.fillRect(this.x, this.y, this.WIDTH, this.HEIGHT);
  },
};

/**
   Holds the paddle and score for each player.
   @constructor
   @param {boolean} isLeft - True if this is a human player on the left,
   otherwise, this is the computer player on the right.
*/
function Player(isLeft) {
  this.paddle = new Paddle(isLeft);
  this.speed = isLeft ? 50 : 1.5;
}

Player.prototype = {
  constructor: Player,

  render: function() {
    this.paddle.render();
  },

  move: function(isUp) {
    this.paddle.move(isUp, this.speed);
  },
}

/**
   @constructor
*/
function Ball() {
  this.speedX = this.randomSpeed();
  this.speedY = this.randomSpeed();
}

Ball.prototype = {
  constructor: Ball,
  x: canvas.width / 2,
  y: canvas.height / 2,
  RADIUS: 10,

  // Pixels per frame in both x and y dimensions.
  SPEED: 2,

  render: function() {
    context.beginPath();
    context.arc(this.x, this.y, this.RADIUS, 0, Math.PI * 2);
    context.fill();
  },

  /**
     @desc Decides on a random speed in the x or y dimension.
  */
  randomSpeed: function() {
    var speed = this.SPEED;
    return Math.random() < 0.5 ? -speed : speed;
  },

  move: function() {
    this.x += this.speedX;
    this.y += this.speedY;
  },

  /**
     @param rectangle {Object}
     @return True iff the Ball collides with the rectangle.
  */
  collides: function(rectangle) {
    return this.x - this.RADIUS < rectangle.x + rectangle.WIDTH
      && this.x + this.RADIUS > rectangle.x
      && this.y - this.RADIUS < rectangle.y + rectangle.HEIGHT
      && this.y + this.RADIUS > rectangle.y;
  },
};

var animate = window.requestAnimationFrame ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame ||
  window.oRequestAnimationFrame ||
  window.msRequestAnimationFrame ||
  function(callback) {
    window.setTimeout(callback, 1000 / 60);
  };

var human = new Player(true);
var computer = new Player(false);

var ball = new Ball();

computer.update = function() {
  this.move(ball.y <= this.paddle.y + this.paddle.HEIGHT / 2);
};

function render() {
  context.fillStyle = '#fff';
  human.render();
  computer.render();
  ball.render();
}

function step() {
  ball.move();
  if (ball.collides(human.paddle) || ball.collides(computer.paddle)) {
    ball.speedX = -ball.speedX;
  }
  if (ball.y - ball.RADIUS < 0 || ball.y + ball.RADIUS > canvas.height) {
    ball.speedY = -ball.speedY;
  }

  computer.update();

  canvas.width = canvas.width;
  render();
  animate(step);
}

function keydown(event) {
  switch (event.key) {
  case 'ArrowDown':
    human.move(false);
    break;
  case 'ArrowUp':
    human.move(true);
    break;
  }
}

window.onload = function() {
  window.addEventListener('keydown', keydown);
  animate(step);
};
<commit_msg>If the ball gets past a goal, reset it.<commit_after>'use strict';

var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');

// Space between the side edge of the canvas and the paddle.
var EDGE_TO_PADDLE = 5;

/**
   The paddle at either side of the canvas.
   @constructor
   @param {boolean} isLeft - If true, construct the left paddle, otherwise
   construct the right one.
*/
function Paddle(isLeft) {
  this.x = isLeft ? EDGE_TO_PADDLE : canvas.width - EDGE_TO_PADDLE - this.WIDTH;
  this.y = (canvas.height - this.HEIGHT) / 2;
}

Paddle.prototype = {
  constructor: Paddle,
  WIDTH: 20,
  HEIGHT: 100,

  /**
     Move the paddle.
     @param {boolean} isUp - Whether to move up or down.
     @param {number} speed - The number of pixels to move.
  */
  move: function(isUp, speed) {
    if (isUp) {
      this.y = Math.max(0, this.y - speed);
    } else {
      this.y = Math.min(canvas.height - this.HEIGHT, this.y + speed);
    }
  },

  render: function() {
    context.fillRect(this.x, this.y, this.WIDTH, this.HEIGHT);
  },
};

/**
   Holds the paddle and score for each player.
   @constructor
   @param {boolean} isLeft - True if this is a human player on the left,
   otherwise, this is the computer player on the right.
*/
function Player(isLeft) {
  this.paddle = new Paddle(isLeft);
  if (isLeft) {
    this.speed = 50;
    this.goal = this.GOAL_WIDTH;
  } else {
    this.speed = 1.5;
    this.goal = canvas.width - this.GOAL_WIDTH;
  }
}

Player.prototype = {
  constructor: Player,
  GOAL_WIDTH: EDGE_TO_PADDLE + Paddle.prototype.WIDTH,

  render: function() {
    this.paddle.render();
  },

  move: function(isUp) {
    this.paddle.move(isUp, this.speed);
  },
}

/**
   @constructor
*/
function Ball() {
  this.speedX = this.randomSpeed();
  this.speedY = this.randomSpeed();
}

Ball.prototype = {
  constructor: Ball,
  x: canvas.width / 2,
  y: canvas.height / 2,
  RADIUS: 10,

  // Pixels per frame in both x and y dimensions.
  SPEED: 2,

  render: function() {
    context.beginPath();
    context.arc(this.x, this.y, this.RADIUS, 0, Math.PI * 2);
    context.fill();
  },

  /**
     @desc Decides on a random speed in the x or y dimension.
  */
  randomSpeed: function() {
    var speed = this.SPEED;
    return Math.random() < 0.5 ? -speed : speed;
  },

  move: function() {
    this.x += this.speedX;
    this.y += this.speedY;
  },

  /**
     @param rectangle {Object}
     @return True iff the Ball collides with the rectangle.
  */
  collides: function(rectangle) {
    return this.x - this.RADIUS < rectangle.x + rectangle.WIDTH
      && this.x + this.RADIUS > rectangle.x
      && this.y - this.RADIUS < rectangle.y + rectangle.HEIGHT
      && this.y + this.RADIUS > rectangle.y;
  },
};

var animate = window.requestAnimationFrame ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame ||
  window.oRequestAnimationFrame ||
  window.msRequestAnimationFrame ||
  function(callback) {
    window.setTimeout(callback, 1000 / 60);
  };

var human = new Player(true);
var computer = new Player(false);

var ball = new Ball();

computer.update = function() {
  this.move(ball.y <= this.paddle.y + this.paddle.HEIGHT / 2);
};

function render() {
  context.fillStyle = '#fff';
  human.render();
  computer.render();
  ball.render();
}

function step() {
  ball.move();
  if (ball.collides(human.paddle) || ball.collides(computer.paddle)) {
    ball.speedX = -ball.speedX;
  } else if (ball.x < human.goal || ball.x > computer.goal) {
    ball = new Ball();
  }
  if (ball.y - ball.RADIUS < 0 || ball.y + ball.RADIUS > canvas.height) {
    ball.speedY = -ball.speedY;
  }

  computer.update();

  canvas.width = canvas.width;
  render();
  animate(step);
}

function keydown(event) {
  switch (event.key) {
  case 'ArrowDown':
    human.move(false);
    break;
  case 'ArrowUp':
    human.move(true);
    break;
  }
}

window.onload = function() {
  window.addEventListener('keydown', keydown);
  animate(step);
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Raymond Camden
 *
 * See the file LICENSE for copying permission.
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, $, window, JSHINT*/
define(function (require, exports, module) {
    "use strict";

    var AppInit                 = brackets.getModule("utils/AppInit"),
        CodeInspection          = brackets.getModule("language/CodeInspection"),
        FileSystem              = brackets.getModule("filesystem/FileSystem"),
        ProjectManager          = brackets.getModule("project/ProjectManager"),
        DocumentManager         = brackets.getModule("document/DocumentManager"),
        defaultConfig = {
            "options": {"undef": true},
            "globals": {}
        },
        config = defaultConfig;

    require("jshint/jshint");

    /**
     * @private
     * @type {string}
     */
    var _configFileName = ".jshintrc";

    function handleHinter(text, fullPath) {
        var resultJH = JSHINT(text, config.options, config.globals);

        if (!resultJH) {
            var errors = JSHINT.errors,
                result = { errors: [] },
                i,
                len;
            for (i = 0, len = errors.length; i < len; i++) {
                var messageOb = errors[i],
                    //default
                    type = CodeInspection.Type.ERROR;

                // encountered an issue when jshint returned a null err
                if (messageOb) {
                    var message;
                    if (messageOb.type !== undefined) {
                        // default is ERROR, override only if it differs
                        if (messageOb.type === "warning") {
                            type = CodeInspection.Type.WARNING;
                        }
                    }

                    message = messageOb.reason;
                    if (messageOb.code) {
                        message += " (" + messageOb.code + ")";
                    }

                    result.errors.push({
                        pos: {line: messageOb.line - 1, ch: messageOb.character},
                        message: message,
                        type: type
                    });
                }
            }
            return result;
        } else {
            return null;
        }

    }

    /**
     * Loads project-wide JSHint configuration.
     *
     * JSHint project file should be located at <Project Root>/.jshintrc. It
     * is loaded each time project is changed or the configuration file is
     * modified.
     *
     * @return Promise to return JSHint configuration object.
     *
     * @see JSHint option
     * reference.
     */
    function _loadProjectConfig() {

        var projectRootEntry = ProjectManager.getProjectRoot(),
            result = new $.Deferred(),
            file,
            config;

        file = FileSystem.getFileForPath(projectRootEntry.fullPath + _configFileName);
        file.read(function (err, content) {
            if (!err) {
                var cfg = {};
                try {
                    config = JSON.parse(content);
                } catch (e) {
                    console.error("JSHint: error parsing " + file.fullPath + ". Details: " + e);
                    result.reject(e);
                    return;
                }
                cfg.globals = config.globals || {};
                if (config.global) { delete config.globals; }
                cfg.options = config;
                result.resolve(cfg);
            } else {
                result.reject(err);
            }
        });
        return result.promise();
    }

    /**
     * Attempts to load project configuration file.
     */
    function tryLoadConfig() {
        /**
         * Makes sure JSHint is re-ran when the config is reloaded
         *
         * This is a workaround due to some loading issues in Sprint 31.
         * See bug for details: https://github.com/adobe/brackets/issues/5442
         */
        function _refreshCodeInspection() {
            CodeInspection.toggleEnabled();
            CodeInspection.toggleEnabled();
        }
        _loadProjectConfig()
            .done(function (newConfig) {
                config = newConfig;
            })
            .fail(function () {
                config = defaultConfig;
            })
            .always(function () {
                _refreshCodeInspection();
            });
    }

    AppInit.appReady(function () {

        CodeInspection.register("javascript", {
            name: "JSHint",
            scanFile: handleHinter
        });

        $(DocumentManager)
            .on("documentSaved.jshint documentRefreshed.jshint", function (e, document) {
                // if this project's JSHint config has been updated, reload
                if (document.file.fullPath ===
                            ProjectManager.getProjectRoot().fullPath + _configFileName) {
                    tryLoadConfig();
                }
            });

        $(ProjectManager)
            .on("projectOpen.jshint", function () {
                tryLoadConfig();
            });

        tryLoadConfig();

    });

});
<commit_msg>Remove javascript comments from .jshintrc before loading<commit_after>/*
 * Copyright (c) 2012 Raymond Camden
 *
 * See the file LICENSE for copying permission.
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, $, window, JSHINT*/
define(function (require, exports, module) {
    "use strict";

    var AppInit                 = brackets.getModule("utils/AppInit"),
        CodeInspection          = brackets.getModule("language/CodeInspection"),
        FileSystem              = brackets.getModule("filesystem/FileSystem"),
        ProjectManager          = brackets.getModule("project/ProjectManager"),
        DocumentManager         = brackets.getModule("document/DocumentManager"),
        defaultConfig = {
            "options": {"undef": true},
            "globals": {}
        },
        config = defaultConfig;

    require("jshint/jshint");

    /**
     * @private
     * @type {string}
     */
    var _configFileName = ".jshintrc";

    function handleHinter(text, fullPath) {
        var resultJH = JSHINT(text, config.options, config.globals);

        if (!resultJH) {
            var errors = JSHINT.errors,
                result = { errors: [] },
                i,
                len;
            for (i = 0, len = errors.length; i < len; i++) {
                var messageOb = errors[i],
                    //default
                    type = CodeInspection.Type.ERROR;

                // encountered an issue when jshint returned a null err
                if (messageOb) {
                    var message;
                    if (messageOb.type !== undefined) {
                        // default is ERROR, override only if it differs
                        if (messageOb.type === "warning") {
                            type = CodeInspection.Type.WARNING;
                        }
                    }

                    message = messageOb.reason;
                    if (messageOb.code) {
                        message += " (" + messageOb.code + ")";
                    }

                    result.errors.push({
                        pos: {line: messageOb.line - 1, ch: messageOb.character},
                        message: message,
                        type: type
                    });
                }
            }
            return result;
        } else {
            return null;
        }

    }

    /**
     * Loads project-wide JSHint configuration.
     *
     * JSHint project file should be located at <Project Root>/.jshintrc. It
     * is loaded each time project is changed or the configuration file is
     * modified.
     *
     * @return Promise to return JSHint configuration object.
     *
     * @see JSHint option
     * reference.
     */
    function _loadProjectConfig() {

        var projectRootEntry = ProjectManager.getProjectRoot(),
            result = new $.Deferred(),
            file,
            config;

        file = FileSystem.getFileForPath(projectRootEntry.fullPath + _configFileName);
        file.read(function (err, content) {
            if (!err) {
                var cfg = {};
                try {
                    config = JSON.parse(removeComments(content));
                } catch (e) {
                    console.error("JSHint: error parsing " + file.fullPath + ". Details: " + e);
                    result.reject(e);
                    return;
                }
                cfg.globals = config.globals || {};
                if (config.global) { delete config.globals; }
                cfg.options = config;
                result.resolve(cfg);
            } else {
                result.reject(err);
            }
        });
        return result.promise();
    }

    /**
     * Removes JavaScript comments from a string by replacing
     * everything between block comments and everything after
     * single-line comments in a non-greedy way.
     *
     * English version of the regex:
     *   match '/*'
     *   then match zero or more instances of any character (incl. \n)
     *   except for instances of '* /' (without a space, obv.)
     *   then match '* /' (again, without a space)
     *
     * @param {string} str a string with potential JavaScript comments.
     * @returns {string} a string without JavaScript comments.
     */
    function removeComments(str) {
        str = str || "";

        str = str.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//g, "");
        str = str.replace(/\/\/[^\n\r]*/g, ""); // Everything after '//'

        return str;
    }
    /**
     * Attempts to load project configuration file.
     */
    function tryLoadConfig() {
        /**
         * Makes sure JSHint is re-ran when the config is reloaded
         *
         * This is a workaround due to some loading issues in Sprint 31.
         * See bug for details: https://github.com/adobe/brackets/issues/5442
         */
        function _refreshCodeInspection() {
            CodeInspection.toggleEnabled();
            CodeInspection.toggleEnabled();
        }
        _loadProjectConfig()
            .done(function (newConfig) {
                config = newConfig;
            })
            .fail(function () {
                config = defaultConfig;
            })
            .always(function () {
                _refreshCodeInspection();
            });
    }

    AppInit.appReady(function () {

        CodeInspection.register("javascript", {
            name: "JSHint",
            scanFile: handleHinter
        });

        $(DocumentManager)
            .on("documentSaved.jshint documentRefreshed.jshint", function (e, document) {
                // if this project's JSHint config has been updated, reload
                if (document.file.fullPath ===
                            ProjectManager.getProjectRoot().fullPath + _configFileName) {
                    tryLoadConfig();
                }
            });

        $(ProjectManager)
            .on("projectOpen.jshint", function () {
                tryLoadConfig();
            });

        tryLoadConfig();

    });

});
<|endoftext|>


<commit_before>/*!
 * async-helpers <https://github.com/doowb/async-helpers>
 *
 * Copyright (c) 2015, Brian Woodward.
 * Licensed under the MIT License.
 */

'use strict';

var async = require('async');

module.exports = AsyncHelpers;

/**
 * Create a new instance of AsyncHelpers
 *
 * ```js
 * var asyncHelpers = new AsyncHelpers();
 * ```
 *
 * @return {Object} new AsyncHelpers instance
 * @api public
 */

function AsyncHelpers (options) {
  if (!(this instanceof AsyncHelpers)) {
    return new AsyncHelpers(options);
  }
  options = options || {};
  this.prefix = options.prefix || '__async_';
  this.helpers = {};
  this.stash = {};
  this.counter = 0;
  this.globalCounter = AsyncHelpers.globalCounter++;
};

/**
 * Keep track of instances created for generating globally
 * unique ids
 *
 * @type {Number}
 */

AsyncHelpers.globalCounter = 0;

/**
 * Add a helper to the cache.
 *
 * ```js
 * asyncHelpers.set('upper', function (str, done) {
 *   done(null, str.toUpperCase());
 * });
 * ```
 *
 * @param {String} `name` Name of the helper
 * @param {Function} `fn` Helper function
 * @return {Object} Returns `this` for chaining
 * @api public
 */

AsyncHelpers.prototype.set = function(name, fn) {
  this.helpers[name] = fn;
  return this;
};

/**
 * Get all helpers or a helper with the given name.
 *
 * ```js
 * var helpers = asyncHelpers.get();
 * var wrappedHelpers = helperAync.get({wrap: true});
 * ```
 *
 * @param  {String} `name` Optionally pass in a name of a helper to get.
 * @param  {Object} `options` Additional options to use.
 *   @option {Boolean} `wrap` Wrap the helper(s) with async processing capibilities
 * @return {Function|Object} Single helper function when `name` is provided, otherwise object of all helpers
 * @api public
 */

AsyncHelpers.prototype.get = function(name, options) {
  if (typeof name === 'object') {
    options = name;
    name = null;
  }
  options = options || {};
  if (options.wrap) {
    return this.wrap(name);
  }
  return name == null ? this.helpers : this.helpers[name];
};

function wrapper (name) {
  var self = this;
  return function () {
    var obj = {
      name: name,
      id: self.prefix + self.globalCounter + '_' + (self.counter++) + '__',
      fn: self.helpers[name],
      args: [].concat.apply([], arguments),
      argRefs: []
    };

    // store references to other async helpers
    obj.args.forEach(function (arg, i) {
      if (typeof arg === 'string' && arg.indexOf(self.prefix) === 0) {
        obj.argRefs.push({arg: arg, idx: i});
      }
    });

    self.stash[obj.id] = obj;
    return obj.id;
  };
}

/**
 * Wrap a helper with async handling capibilities.
 *
 * ```js
 * var wrappedHelper = asyncHelpers.wrap('upper');
 * var wrappedHelpers = asyncHelpers.wrap();
 * ```
 *
 * @param  {String} `name` Optionally pass the name of the helper to wrap
 * @return {Function|Object} Single wrapped helper function when `name` is provided, otherwise object of all wrapped helpers.
 * @api public
 */

AsyncHelpers.prototype.wrap = function(name) {
  var self = this;
  if (name) {
    return wrapper.call(this, name);
  }
  var keys = Object.keys(this.helpers);
  return keys.reduce(function (res, key) {
    res[key] = self.wrap(key);
    return res;
  }, {});
};

/**
 * Reset all the stashed helpers.
 *
 * ```js
 * asyncHelpers.reset();
 * ```
 *
 * @return {Object} Returns `this` to enable chaining
 * @api public
 */

AsyncHelpers.prototype.reset = function() {
  this.stash = {};
  this.counter = 0;
  return this;
};

/**
 * Resolve a stashed helper by the generated id.
 *
 * ```js
 * var upper = asyncHelpers.get('upper', {wrap: true});
 * var id = upper('doowb');
 * asyncHelpers.resolve(id, function (err, result) {
 *   console.log(result);
 *   //=> DOOWB
 * });
 * ```
 *
 * @param  {String} `key` ID generated when from executing a wrapped helper.
 * @param  {Function} `done` Callback function with the results of executing the async helper.
 * @api public
 */

AsyncHelpers.prototype.resolve = function(key, done) {
  var stashed = this.stash[key];
  if (!stashed) {
    return done(new Error('Unable to resolve ' + key + '. Not Found'));
  }

  if (typeof stashed.fn !== 'function') {
    return done(null, stashed.fn);
  }

  var self = this;
  async.series([
    function (next) {
      if (stashed.argRefs.length > 0) {
        async.each(stashed.argRefs, function (arg, nextArg) {
          self.resolve(arg.arg, function (err, value) {
            if (err) return nextArg(err);
            stashed.args[arg.idx] = value;
            nextArg();
          });
        }, next);
      } else {
        next();
      }
    },
    function (next) {
      var called = false;
      function cb(err, value) {
        if (!called) {
          called = true;
          next(err, value);
        }
      }

      var res = null;
      var args = [].concat.call([], stashed.args);
      if (stashed.fn.async) {
        args = args.concat(cb);
      }
      res = stashed.fn.apply(stashed.thisArg, args);
      if (!stashed.fn.async) {
        return cb(null, res);
      }
    }
  ], function (err, results) {
    // update the fn so if it's called again it'll just return the true reults
    stashed.fn = results[1];
    done(err, stashed.fn);
  });

};
<commit_msg>simplifying once callback in resolve<commit_after>/*!
 * async-helpers <https://github.com/doowb/async-helpers>
 *
 * Copyright (c) 2015, Brian Woodward.
 * Licensed under the MIT License.
 */

'use strict';

var async = require('async');

module.exports = AsyncHelpers;

/**
 * Create a new instance of AsyncHelpers
 *
 * ```js
 * var asyncHelpers = new AsyncHelpers();
 * ```
 *
 * @return {Object} new AsyncHelpers instance
 * @api public
 */

function AsyncHelpers (options) {
  if (!(this instanceof AsyncHelpers)) {
    return new AsyncHelpers(options);
  }
  options = options || {};
  this.prefix = options.prefix || '__async_';
  this.helpers = {};
  this.stash = {};
  this.counter = 0;
  this.globalCounter = AsyncHelpers.globalCounter++;
};

/**
 * Keep track of instances created for generating globally
 * unique ids
 *
 * @type {Number}
 */

AsyncHelpers.globalCounter = 0;

/**
 * Add a helper to the cache.
 *
 * ```js
 * asyncHelpers.set('upper', function (str, done) {
 *   done(null, str.toUpperCase());
 * });
 * ```
 *
 * @param {String} `name` Name of the helper
 * @param {Function} `fn` Helper function
 * @return {Object} Returns `this` for chaining
 * @api public
 */

AsyncHelpers.prototype.set = function(name, fn) {
  this.helpers[name] = fn;
  return this;
};

/**
 * Get all helpers or a helper with the given name.
 *
 * ```js
 * var helpers = asyncHelpers.get();
 * var wrappedHelpers = helperAync.get({wrap: true});
 * ```
 *
 * @param  {String} `name` Optionally pass in a name of a helper to get.
 * @param  {Object} `options` Additional options to use.
 *   @option {Boolean} `wrap` Wrap the helper(s) with async processing capibilities
 * @return {Function|Object} Single helper function when `name` is provided, otherwise object of all helpers
 * @api public
 */

AsyncHelpers.prototype.get = function(name, options) {
  if (typeof name === 'object') {
    options = name;
    name = null;
  }
  options = options || {};
  if (options.wrap) {
    return this.wrap(name);
  }
  return name == null ? this.helpers : this.helpers[name];
};

function wrapper (name) {
  var self = this;
  return function () {
    var obj = {
      name: name,
      id: self.prefix + self.globalCounter + '_' + (self.counter++) + '__',
      fn: self.helpers[name],
      args: [].concat.apply([], arguments),
      argRefs: []
    };

    // store references to other async helpers
    obj.args.forEach(function (arg, i) {
      if (typeof arg === 'string' && arg.indexOf(self.prefix) === 0) {
        obj.argRefs.push({arg: arg, idx: i});
      }
    });

    self.stash[obj.id] = obj;
    return obj.id;
  };
}

/**
 * Wrap a helper with async handling capibilities.
 *
 * ```js
 * var wrappedHelper = asyncHelpers.wrap('upper');
 * var wrappedHelpers = asyncHelpers.wrap();
 * ```
 *
 * @param  {String} `name` Optionally pass the name of the helper to wrap
 * @return {Function|Object} Single wrapped helper function when `name` is provided, otherwise object of all wrapped helpers.
 * @api public
 */

AsyncHelpers.prototype.wrap = function(name) {
  var self = this;
  if (name) {
    return wrapper.call(this, name);
  }
  var keys = Object.keys(this.helpers);
  return keys.reduce(function (res, key) {
    res[key] = self.wrap(key);
    return res;
  }, {});
};

/**
 * Reset all the stashed helpers.
 *
 * ```js
 * asyncHelpers.reset();
 * ```
 *
 * @return {Object} Returns `this` to enable chaining
 * @api public
 */

AsyncHelpers.prototype.reset = function() {
  this.stash = {};
  this.counter = 0;
  return this;
};

/**
 * Resolve a stashed helper by the generated id.
 *
 * ```js
 * var upper = asyncHelpers.get('upper', {wrap: true});
 * var id = upper('doowb');
 * asyncHelpers.resolve(id, function (err, result) {
 *   console.log(result);
 *   //=> DOOWB
 * });
 * ```
 *
 * @param  {String} `key` ID generated when from executing a wrapped helper.
 * @param  {Function} `done` Callback function with the results of executing the async helper.
 * @api public
 */

AsyncHelpers.prototype.resolve = function(key, done) {
  var stashed = this.stash[key];
  if (!stashed) {
    return done(new Error('Unable to resolve ' + key + '. Not Found'));
  }

  if (typeof stashed.fn !== 'function') {
    return done(null, stashed.fn);
  }

  var self = this;
  async.series([
    function (next) {
      if (stashed.argRefs.length > 0) {
        async.each(stashed.argRefs, function (arg, nextArg) {
          self.resolve(arg.arg, function (err, value) {
            if (err) return nextArg(err);
            stashed.args[arg.idx] = value;
            nextArg();
          });
        }, next);
      } else {
        next();
      }
    },
    function (next) {
      next = once(next);

      var res = null;
      var args = [].concat.call([], stashed.args);
      if (stashed.fn.async) {
        args = args.concat(next);
      }
      res = stashed.fn.apply(stashed.thisArg, args);
      if (!stashed.fn.async) {
        return next(null, res);
      }
    }
  ], function (err, results) {
    // update the fn so if it's called again it'll just return the true reults
    stashed.fn = results[1];
    done(err, stashed.fn);
  });

};

function once (fn) {
  return function () {
    if (fn.called) return fn.value;
    fn.called = true;
    fn.value = fn.apply(fn, arguments);
    return fn.value;
  };
}
<|endoftext|>


<commit_before>var http = require("http");

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , url = require('url')

var words = fs.readFileSync("brit-a-z.txt", {encoding:"utf-8"});
words = words.replace("'", "").replace("\r", "").split("\n");

app.listen(8765);

var games = {};

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
}

function Game(name){
    this.name = name;
    this.inProgress = false;
    this.players = []
    this.nicks = []
}
Game.prototype = {
    name: null,
    join: function(socket){
        if(this.nicks.indexOf(socket.nick) == -1 && this.nicks.length < 2){
            this.players.forEach( function(player){
                socket.emit('setOpponent', player.nick);
            });

            socket.game = game;
            socket.score = 0;
            this.players.push(socket);
            this.nicks.push(socket.nick);

            if(this.nicks.length == 2){
                this.players.forEach( function(player){
                    player.emit('start');
                });
                this.inProgress = true;
            }

            return true;
        }
        return false;
    },
    hasNick: function(nick){
        return this.nicks.indexOf(nick) != -1;
    }
}

function validGameId(name){
    return /\w+/.test(name)
}

function nickAvailable(gameId, nick){
    if(games.hasOwnProperty(gameId)){
        if(games[gameId].hasNick(nick)){
            return false;
        }else{
            return true;
        }
    }else{
        return true;
    }
}

function handler (req, res) {
    if(/\/game\/.*/.test(req['url'])){
        var parsed = url.parse(req['url'].slice(5));
        var splits = parsed.path.split("/");
        if(splits.length == 2){
            var gameId = splits[0];
            var nick = splits[1];
            if(validGameId(gameId) && nickAvailable(gameId, nick)){
                fs.readFile(__dirname + "/game.html",
                function (err, data) {
                    if (err) {
                        res.writeHead(500);
                        res.end("Error loading");
                    }
                    res.writeHead(200);
                    res.end(data);
                });
            }
        }
    }else{
        if(req['url'] == "/"){
            req['url'] = "/index.html";
        }
        fs.readFile(__dirname + req['url'],
        function (err, data) {
            if (err) {
                res.writeHead(500);
                res.end("Error loading");
            }

            res.writeHead(200);
            res.end(data);
        });
    }
}

io.sockets.on('connection', function (socket) {
    socket.on('init', function (gameId, nick){
        socket.nick = nick;

        if(!games.hasOwnProperty(gameId)){
            games[gameId] = new Game(gameId);
        }
        var game = games[gameId];

        if (game.join(socket)){
            socket.emit('initResponse', {});
        }
    });

});
<commit_msg>fixed path splitting in game url handling<commit_after>var http = require("http");

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , url = require('url')

var words = fs.readFileSync("brit-a-z.txt", {encoding:"utf-8"});
words = words.replace("'", "").replace("\r", "").split("\n");

app.listen(8765);

var games = {};

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
}

function Game(name){
    this.name = name;
    this.inProgress = false;
    this.players = []
    this.nicks = []
}
Game.prototype = {
    name: null,
    join: function(socket){
        if(this.nicks.indexOf(socket.nick) == -1 && this.nicks.length < 2){
            this.players.forEach( function(player){
                socket.emit('setOpponent', player.nick);
            });

            socket.game = game;
            socket.score = 0;
            this.players.push(socket);
            this.nicks.push(socket.nick);

            if(this.nicks.length == 2){
                this.players.forEach( function(player){
                    player.emit('start');
                });
                this.inProgress = true;
            }

            return true;
        }
        return false;
    },
    hasNick: function(nick){
        return this.nicks.indexOf(nick) != -1;
    }
}

function validGameId(name){
    return /\w+/.test(name)
}

function nickAvailable(gameId, nick){
    if(games.hasOwnProperty(gameId)){
        if(games[gameId].hasNick(nick)){
            return false;
        }else{
            return true;
        }
    }else{
        return true;
    }
}

function handler (req, res) {
    if(/\/game\/.*/.test(req['url'])){
        var parsed = url.parse(req['url'].slice(5));
        var splits = parsed.path.split("/");
        if(splits.length == 3){
            var gameId = splits[1];
            var nick = splits[2];
            if(validGameId(gameId) && nickAvailable(gameId, nick)){
                fs.readFile(__dirname + "/game.html",
                function (err, data) {
                    if (err) {
                        res.writeHead(500);
                        res.end("Error loading");
                    }
                    res.writeHead(200);
                    res.end(data);
                });
            }else{
                res.writeHead(500);
                res.end("Bad game or nick");
            }
        }else{
            res.writeHead(500);
            res.end("Bad game url");
        }
    }else{
        if(req['url'] == "/"){
            req['url'] = "/index.html";
        }
        fs.readFile(__dirname + req['url'],
        function (err, data) {
            if (err) {
                res.writeHead(500);
                res.end("Error loading");
            }

            res.writeHead(200);
            res.end(data);
        });
    }
}

io.sockets.on('connection', function (socket) {
    socket.on('init', function (gameId, nick){
        socket.nick = nick;

        if(!games.hasOwnProperty(gameId)){
            games[gameId] = new Game(gameId);
        }
        var game = games[gameId];

        if (game.join(socket)){
            socket.emit('initResponse', {});
        }
    });

});
<|endoftext|>


<commit_before>var constants = require('constants')
var hypercore = require('hypercore')
var sublevel = require('subleveldown')
var fs = require('fs')
var mkdirp = require('mkdirp')
var bulk = require('bulk-write-stream')
var path = require('path')
var deltas = require('delta-list')
var from = require('from2')
var through = require('through2')
var pump = require('pump')
var pumpify = require('pumpify')
var octal = require('octal')
var util = require('util')
var events = require('events')
var storage
var rabin
if (process.browser) rabin = through
else rabin = require('rabin')
if (process.browser) storage = require('./lib/browser-storage')
else storage = require('./lib/storage')
var messages = require('./lib/messages')

var DMODE = octal(755)
var FMODE = octal(644)

module.exports = Hyperdrive

function Hyperdrive (db) {
  if (!(this instanceof Hyperdrive)) return new Hyperdrive(db)
  var self = this

  this.db = db
  this.drives = sublevel(db, 'drives', {valueEncoding: 'binary'})
  this.core = hypercore(db, {
    storage: function (feed) {
      return storage(self, feed)
    }
  })
}

// Hyperdrive.prototype.list = function () {
//   return this.drives.createKeyStream()
// }

Hyperdrive.prototype.createPeerStream = function () {
  return this.core.createPeerStream()
}

Hyperdrive.prototype.get = function (id, folder) {
  if (!folder || !id) throw new Error('id and folder required')
  return new Archive(this, folder, id)
}

Hyperdrive.prototype.add = function (folder) {
  if (!folder) throw new Error('folder required')
  return new Archive(this, folder, null)
}

function Progress () {
  this.bytesInitial = 0
  this.bytesRead = 0
  this.bytesTotal = 0
  events.EventEmitter.call(this)
}

util.inherits(Progress, events.EventEmitter)

Progress.prototype.end = function (err) {
  if (!err) return this.emit('end')
  if (this.listeners('error').length) this.emit('error', err)
  return
}

function Archive (drive, folder, id) {
  events.EventEmitter.call(this)

  var self = this

  this.id = id
  this.directory = folder
  this.core = drive.core
  this.entries = 0
  this.metadata = {type: 'hyperdrive'}
  this.stats = {
    bytesRead: 0,
    bytesDownloaded: 0,
    filesRead: 0,
    filesDownloaded: 0
  }

  this._first = true

  if (!id) {
    this.feed = this.core.add({filename: null})
  } else {
    this.feed = this.core.get(id)
    this.feed.get(0, onmetadata)
  }

  this.feed.on('put', function (block, data) {
    self.stats.bytesDownloaded += data.length
    self.emit('download', data, block)
  })

  this.feed.ready(function (err) {
    if (err) return
    self.entries = self.feed.blocks - 1
    self.emit('ready')
  })

  function onmetadata (err, json) {
    if (err) self.emit('error', err)

    var doc

    try {
      doc = JSON.parse(json.toString())
    } catch (err) {
      // do nothing
    }

    if (!doc || doc.type !== 'hyperdrive') {
      self.emit('error', new Error('feed is not a hyperdrive'))
    } else {
      self.metadata = doc
      self.emit('metadata')
    }
  }
}

util.inherits(Archive, events.EventEmitter)

Archive.prototype.close = function (cb) {
  this.feed.close(cb)
}

Archive.prototype.ready = function (cb) {
  this.feed.ready(cb)
}

Archive.prototype.download = function (i, cb) {
  if (!cb) cb = noop

  var ptr = 0
  var self = this
  var stats = new Progress()
  var offset = 0

  if (typeof i === 'number') this.entry(i, onentry)
  else onentry(null, i)

  return stats

  function onentry (err, entry) {
    if (err) return cb(err)

    var feed = self._getFeed(entry)
    var dest = join(self.directory, entry.name)

    if (!feed) return createEmtpyEntry()

    function createEmtpyEntry () {
      var dir = dest
      if (entry.type === 'file') dir = path.dirname(dest)
      mkdirp(dir, function (err) {
        if (err) return cb(err)
        if (entry.type !== 'file') return cb(null)
        fs.open(dest, 'a', function (err) {
          if (err) return cb(err)
          return cb(null)
        })
      })
    }

    feed.on('put', kick)
    feed.open(kick)
    stats.bytesTotal = entry.size

    if (feed._storage) onstorage(feed._storage)
    else feed.on('_storage', onstorage)

    function onstorage (storage) {
      if (!storage._bytesWritten) return
      storage._bytesWritten(function (_, bytes) {
        if (bytes) {
          stats.bytesInitial = bytes - offset
          stats.bytesRead = bytes
          stats.emit('ready')
        }
      })
    }

    function kick (block, data) {
      if (!feed.blocks) return

      if (data && this === feed && entry.link && block < feed.blocks - entry.link.index.length) {
        stats.bytesRead += data.length
        offset += data.length
      }
      for (; ptr < feed.blocks; ptr++) {
        if (!feed.has(ptr)) return
      }

      if (process.browser) return done()

      fs.stat(dest, function (_, st) {
        feed.removeListener('put', kick)

        // the size check probably isn't nessary here...
        if (st && st.size === entry.size) return done(null)

        // duplicate - just copy it in
        mkdirp(path.dirname(dest), function () {
          pump(self.createFileStream(entry), fs.createWriteStream(dest), done)
        })
      })
    }

    function done (err) {
      if (!err) self.stats.filesDownloaded++
      stats.bytesRead = stats.bytesTotal
      stats.end(err)
      cb(err)
    }
  }
}

Archive.prototype.select = function (i, cb) {
  if (!cb) cb = noop

  var self = this

  if (typeof i === 'number') this.entry(i, onentry)
  else onentry(null, i)

  function onentry (err, entry) {
    if (err) return cb(err)
    if (!entry || !entry.link) return cb(null, null)
    cb(null, self._getFeed(entry))
  }
}

Archive.prototype.deselect = function (i, cb) {
  throw new Error('not yet implemented')
}

Archive.prototype.entry = function (i, cb) {
  this.feed.get(i + 1, function (err, data) {
    if (err) return cb(err)
    if (!data) return cb(null, null)
    cb(null, messages.Entry.decode(data))
  })
}

Archive.prototype.finalize = function (cb) {
  if (!cb) cb = noop
  var self = this
  this.feed.finalize(function (err) {
    if (err) return cb(err)
    self.id = self.feed.id
    self.entries = self.feed.blocks - 1
    cb()
  })
}

Archive.prototype.createEntryStream = function (opts) {
  if (!opts) opts = {}
  var start = opts.start || 0
  var limit = opts.limit || Infinity
  var self = this
  return from.obj(read)

  function read (size, cb) {
    if (limit-- === 0) return cb(null, null)
    self.entry(start++, cb)
  }
}

Archive.prototype._getFeed = function (entry) {
  if (!entry.link) return null

  var self = this
  var done = false
  var contentBlocks = entry.link.blocks - entry.link.index.length
  var feed = this.core.get(entry.link.id, {
    filename: join(this.directory, entry.name),
    index: deltas.unpack(entry.link.index),
    contentBlocks: contentBlocks
  })

  var ptr = 0

  feed.on('put', function (block, data) {
    self.emit('file-download', entry, data, block)
    kick()
  })

  feed.open(function (err) {
    if (err) return
    kick()
    for (var i = 0; i < entry.link.index.length; i++) {
      if (!feed.has(i + contentBlocks)) feed.want.push({block: i + contentBlocks, callback: noop, critical: true})
    }
  })

  return feed

  function kick () {
    if (done || !feed.blocks) return
    for (; ptr < feed.blocks; ptr++) {
      if (!feed.has(ptr)) return
    }
    done = true
    self.emit('file-downloaded', entry)
  }
}

Archive.prototype.createFileCursor = function (i, opts) {
  throw new Error('not yet implemented')
}

Archive.prototype.createFileStream = function (i, opts) { // TODO: expose random access stuff
  if (!opts) opts = {}
  var start = opts.start || 0
  var limit = opts.limit || Infinity
  var self = this
  var feed = null
  return from.obj(read)

  function read (size, cb) {
    if (feed) {
      if (limit-- === 0) return cb(null, null)
      feed.get(start++, cb)
      return
    }

    if (typeof i === 'number') self.entry(i, onentry)
    else onentry(null, i)

    function onentry (err, entry) {
      if (err) return cb(err)
      if (!entry.link) return cb(null, null)
      feed = self._getFeed(entry)
      limit = Math.min(limit, entry.link.blocks - entry.link.index.length)
      read(0, cb)
    }
  }
}

Archive.prototype.append = function (entry, opts, cb) {
  if (typeof opts === 'function') return this.append(entry, null, opts)
  if (typeof entry === 'string') entry = {name: entry, type: 'file'}
  if (!entry.name) throw new Error('entry.name is required')
  if (!entry.type && entry.mode) entry.type = modeToType(entry.mode)
  if (entry.type && !entry.mode) entry.mode = entry.type === 'directory' ? DMODE : FMODE
  if (!opts) opts = {}

  var self = this

  if (entry.type !== 'file') {
    append(null, cb)
    return null
  }

  if (opts.filename === true) opts.filename = entry.name

  var size = 0
  var stats = opts.stats
  var feed = this.core.add({filename: opts.filename && path.resolve(this.directory, opts.filename)})
  var stream = pumpify(rabin(), bulk(write, end))

  if (cb) {
    stream.on('error', cb)
    stream.on('finish', forward)
  }

  return stream

  function forward () {
    cb(null, entry)
  }

  function append (link, cb) {
    if (link) self.stats.filesRead++
    entry.size = size
    entry.link = link
    if (self._first) {
      // first block is gonna be a human readable metadata block
      // this makes updating the protocol easier in the future
      self.feed.append(JSON.stringify(self.metadata))
      self._first = false
    }
    self.feed.append(messages.Entry.encode(entry), done)

    function done (err) {
      if (err) return cb(err)
      self.entries++
      cb(null)
    }
  }

  function write (buffers, cb) {
    for (var i = 0; i < buffers.length; i++) {
      size += buffers[i].length
      if (stats) stats.bytesRead += buffers[i].length
      self.stats.bytesRead += buffers[i].length
    }
    feed.append(buffers, cb)
  }

  function end (cb) {
    feed.finalize(function (err) {
      if (err) return cb(err)
      if (!feed.id) return append(null, cb)

      var link = {
        id: feed.id,
        blocks: feed.blocks,
        index: deltas.pack(feed._storage._index)
      }

      append(link, cb)
    })
  }
}

Archive.prototype.appendFile = function (filename, name, cb) {
  if (typeof name === 'function') return this.appendFile(filename, null, name)
  if (!cb) cb = noop
  if (!name) name = filename

  var self = this
  var stats = new Progress()

  fs.lstat(filename, function (err, st) {
    if (err) return done(err)

    var opts = {filename: filename, stats: stats}
    var ws = self.append({
      name: name,
      mode: st.mode,
      size: 0,
      link: null
    }, opts, done)

    stats.bytesTotal = st.size
    stats.emit('ready')

    if (ws) {
      var readStream = fs.createReadStream(path.resolve(self.directory, filename))
      pump(readStream, ws)
    }
  })

  return stats

  function done (err) {
    stats.end(err)
    cb(err)
  }
}

function noop () {}

function modeToType (mode) { // from tar-stream
  switch (mode & constants.S_IFMT) {
    case constants.S_IFBLK: return 'block-device'
    case constants.S_IFCHR: return 'character-device'
    case constants.S_IFDIR: return 'directory'
    case constants.S_IFIFO: return 'fifo'
    case constants.S_IFLNK: return 'symlink'
  }

  return 'file'
}

function join (a, b) {
  return path.join(a, path.resolve('/', b))
}
<commit_msg>move fn down; close fs.open; typo fix<commit_after>var constants = require('constants')
var hypercore = require('hypercore')
var sublevel = require('subleveldown')
var fs = require('fs')
var mkdirp = require('mkdirp')
var bulk = require('bulk-write-stream')
var path = require('path')
var deltas = require('delta-list')
var from = require('from2')
var through = require('through2')
var pump = require('pump')
var pumpify = require('pumpify')
var octal = require('octal')
var util = require('util')
var events = require('events')
var storage
var rabin
if (process.browser) rabin = through
else rabin = require('rabin')
if (process.browser) storage = require('./lib/browser-storage')
else storage = require('./lib/storage')
var messages = require('./lib/messages')

var DMODE = octal(755)
var FMODE = octal(644)

module.exports = Hyperdrive

function Hyperdrive (db) {
  if (!(this instanceof Hyperdrive)) return new Hyperdrive(db)
  var self = this

  this.db = db
  this.drives = sublevel(db, 'drives', {valueEncoding: 'binary'})
  this.core = hypercore(db, {
    storage: function (feed) {
      return storage(self, feed)
    }
  })
}

// Hyperdrive.prototype.list = function () {
//   return this.drives.createKeyStream()
// }

Hyperdrive.prototype.createPeerStream = function () {
  return this.core.createPeerStream()
}

Hyperdrive.prototype.get = function (id, folder) {
  if (!folder || !id) throw new Error('id and folder required')
  return new Archive(this, folder, id)
}

Hyperdrive.prototype.add = function (folder) {
  if (!folder) throw new Error('folder required')
  return new Archive(this, folder, null)
}

function Progress () {
  this.bytesInitial = 0
  this.bytesRead = 0
  this.bytesTotal = 0
  events.EventEmitter.call(this)
}

util.inherits(Progress, events.EventEmitter)

Progress.prototype.end = function (err) {
  if (!err) return this.emit('end')
  if (this.listeners('error').length) this.emit('error', err)
  return
}

function Archive (drive, folder, id) {
  events.EventEmitter.call(this)

  var self = this

  this.id = id
  this.directory = folder
  this.core = drive.core
  this.entries = 0
  this.metadata = {type: 'hyperdrive'}
  this.stats = {
    bytesRead: 0,
    bytesDownloaded: 0,
    filesRead: 0,
    filesDownloaded: 0
  }

  this._first = true

  if (!id) {
    this.feed = this.core.add({filename: null})
  } else {
    this.feed = this.core.get(id)
    this.feed.get(0, onmetadata)
  }

  this.feed.on('put', function (block, data) {
    self.stats.bytesDownloaded += data.length
    self.emit('download', data, block)
  })

  this.feed.ready(function (err) {
    if (err) return
    self.entries = self.feed.blocks - 1
    self.emit('ready')
  })

  function onmetadata (err, json) {
    if (err) self.emit('error', err)

    var doc

    try {
      doc = JSON.parse(json.toString())
    } catch (err) {
      // do nothing
    }

    if (!doc || doc.type !== 'hyperdrive') {
      self.emit('error', new Error('feed is not a hyperdrive'))
    } else {
      self.metadata = doc
      self.emit('metadata')
    }
  }
}

util.inherits(Archive, events.EventEmitter)

Archive.prototype.close = function (cb) {
  this.feed.close(cb)
}

Archive.prototype.ready = function (cb) {
  this.feed.ready(cb)
}

Archive.prototype.download = function (i, cb) {
  if (!cb) cb = noop

  var ptr = 0
  var self = this
  var stats = new Progress()
  var offset = 0

  if (typeof i === 'number') this.entry(i, onentry)
  else onentry(null, i)

  return stats

  function onentry (err, entry) {
    if (err) return cb(err)

    var feed = self._getFeed(entry)
    var dest = join(self.directory, entry.name)

    if (!feed) return createEmptyEntry()

    feed.on('put', kick)
    feed.open(kick)
    stats.bytesTotal = entry.size

    if (feed._storage) onstorage(feed._storage)
    else feed.on('_storage', onstorage)

    function onstorage (storage) {
      if (!storage._bytesWritten) return
      storage._bytesWritten(function (_, bytes) {
        if (bytes) {
          stats.bytesInitial = bytes - offset
          stats.bytesRead = bytes
          stats.emit('ready')
        }
      })
    }

    function kick (block, data) {
      if (!feed.blocks) return

      if (data && this === feed && entry.link && block < feed.blocks - entry.link.index.length) {
        stats.bytesRead += data.length
        offset += data.length
      }
      for (; ptr < feed.blocks; ptr++) {
        if (!feed.has(ptr)) return
      }

      if (process.browser) return done()

      fs.stat(dest, function (_, st) {
        feed.removeListener('put', kick)

        // the size check probably isn't nessary here...
        if (st && st.size === entry.size) return done(null)

        // duplicate - just copy it in
        mkdirp(path.dirname(dest), function () {
          pump(self.createFileStream(entry), fs.createWriteStream(dest), done)
        })
      })
    }

    function done (err) {
      if (!err) self.stats.filesDownloaded++
      stats.bytesRead = stats.bytesTotal
      stats.end(err)
      cb(err)
    }

    function createEmptyEntry () {
      var dir = dest
      if (entry.type === 'file') dir = path.dirname(dest)
      mkdirp(dir, function (err) {
        if (err) return cb(err)
        if (entry.type !== 'file') return cb(null)
        fs.open(dest, 'a', function (err, fd) {
          if (err) return cb(err)
          fs.close(fd, cb)
        })
      })
    }
  }
}

Archive.prototype.select = function (i, cb) {
  if (!cb) cb = noop

  var self = this

  if (typeof i === 'number') this.entry(i, onentry)
  else onentry(null, i)

  function onentry (err, entry) {
    if (err) return cb(err)
    if (!entry || !entry.link) return cb(null, null)
    cb(null, self._getFeed(entry))
  }
}

Archive.prototype.deselect = function (i, cb) {
  throw new Error('not yet implemented')
}

Archive.prototype.entry = function (i, cb) {
  this.feed.get(i + 1, function (err, data) {
    if (err) return cb(err)
    if (!data) return cb(null, null)
    cb(null, messages.Entry.decode(data))
  })
}

Archive.prototype.finalize = function (cb) {
  if (!cb) cb = noop
  var self = this
  this.feed.finalize(function (err) {
    if (err) return cb(err)
    self.id = self.feed.id
    self.entries = self.feed.blocks - 1
    cb()
  })
}

Archive.prototype.createEntryStream = function (opts) {
  if (!opts) opts = {}
  var start = opts.start || 0
  var limit = opts.limit || Infinity
  var self = this
  return from.obj(read)

  function read (size, cb) {
    if (limit-- === 0) return cb(null, null)
    self.entry(start++, cb)
  }
}

Archive.prototype._getFeed = function (entry) {
  if (!entry.link) return null

  var self = this
  var done = false
  var contentBlocks = entry.link.blocks - entry.link.index.length
  var feed = this.core.get(entry.link.id, {
    filename: join(this.directory, entry.name),
    index: deltas.unpack(entry.link.index),
    contentBlocks: contentBlocks
  })

  var ptr = 0

  feed.on('put', function (block, data) {
    self.emit('file-download', entry, data, block)
    kick()
  })

  feed.open(function (err) {
    if (err) return
    kick()
    for (var i = 0; i < entry.link.index.length; i++) {
      if (!feed.has(i + contentBlocks)) feed.want.push({block: i + contentBlocks, callback: noop, critical: true})
    }
  })

  return feed

  function kick () {
    if (done || !feed.blocks) return
    for (; ptr < feed.blocks; ptr++) {
      if (!feed.has(ptr)) return
    }
    done = true
    self.emit('file-downloaded', entry)
  }
}

Archive.prototype.createFileCursor = function (i, opts) {
  throw new Error('not yet implemented')
}

Archive.prototype.createFileStream = function (i, opts) { // TODO: expose random access stuff
  if (!opts) opts = {}
  var start = opts.start || 0
  var limit = opts.limit || Infinity
  var self = this
  var feed = null
  return from.obj(read)

  function read (size, cb) {
    if (feed) {
      if (limit-- === 0) return cb(null, null)
      feed.get(start++, cb)
      return
    }

    if (typeof i === 'number') self.entry(i, onentry)
    else onentry(null, i)

    function onentry (err, entry) {
      if (err) return cb(err)
      if (!entry.link) return cb(null, null)
      feed = self._getFeed(entry)
      limit = Math.min(limit, entry.link.blocks - entry.link.index.length)
      read(0, cb)
    }
  }
}

Archive.prototype.append = function (entry, opts, cb) {
  if (typeof opts === 'function') return this.append(entry, null, opts)
  if (typeof entry === 'string') entry = {name: entry, type: 'file'}
  if (!entry.name) throw new Error('entry.name is required')
  if (!entry.type && entry.mode) entry.type = modeToType(entry.mode)
  if (entry.type && !entry.mode) entry.mode = entry.type === 'directory' ? DMODE : FMODE
  if (!opts) opts = {}

  var self = this

  if (entry.type !== 'file') {
    append(null, cb)
    return null
  }

  if (opts.filename === true) opts.filename = entry.name

  var size = 0
  var stats = opts.stats
  var feed = this.core.add({filename: opts.filename && path.resolve(this.directory, opts.filename)})
  var stream = pumpify(rabin(), bulk(write, end))

  if (cb) {
    stream.on('error', cb)
    stream.on('finish', forward)
  }

  return stream

  function forward () {
    cb(null, entry)
  }

  function append (link, cb) {
    if (link) self.stats.filesRead++
    entry.size = size
    entry.link = link
    if (self._first) {
      // first block is gonna be a human readable metadata block
      // this makes updating the protocol easier in the future
      self.feed.append(JSON.stringify(self.metadata))
      self._first = false
    }
    self.feed.append(messages.Entry.encode(entry), done)

    function done (err) {
      if (err) return cb(err)
      self.entries++
      cb(null)
    }
  }

  function write (buffers, cb) {
    for (var i = 0; i < buffers.length; i++) {
      size += buffers[i].length
      if (stats) stats.bytesRead += buffers[i].length
      self.stats.bytesRead += buffers[i].length
    }
    feed.append(buffers, cb)
  }

  function end (cb) {
    feed.finalize(function (err) {
      if (err) return cb(err)
      if (!feed.id) return append(null, cb)

      var link = {
        id: feed.id,
        blocks: feed.blocks,
        index: deltas.pack(feed._storage._index)
      }

      append(link, cb)
    })
  }
}

Archive.prototype.appendFile = function (filename, name, cb) {
  if (typeof name === 'function') return this.appendFile(filename, null, name)
  if (!cb) cb = noop
  if (!name) name = filename

  var self = this
  var stats = new Progress()

  fs.lstat(filename, function (err, st) {
    if (err) return done(err)

    var opts = {filename: filename, stats: stats}
    var ws = self.append({
      name: name,
      mode: st.mode,
      size: 0,
      link: null
    }, opts, done)

    stats.bytesTotal = st.size
    stats.emit('ready')

    if (ws) {
      var readStream = fs.createReadStream(path.resolve(self.directory, filename))
      pump(readStream, ws)
    }
  })

  return stats

  function done (err) {
    stats.end(err)
    cb(err)
  }
}

function noop () {}

function modeToType (mode) { // from tar-stream
  switch (mode & constants.S_IFMT) {
    case constants.S_IFBLK: return 'block-device'
    case constants.S_IFCHR: return 'character-device'
    case constants.S_IFDIR: return 'directory'
    case constants.S_IFIFO: return 'fifo'
    case constants.S_IFLNK: return 'symlink'
  }

  return 'file'
}

function join (a, b) {
  return path.join(a, path.resolve('/', b))
}
<|endoftext|>


<commit_before>$(function() {

    $(document).on("click",'.mute',function(){
        $(".sounds").each(function(index,audio){
             audio.volume=0;
        })

        $('.mute').addClass('unmute').removeClass('mute').html('unmute');
    });

    $(document).on('click','.unmute',function(){
        $(".sounds").each(function(index,audio){
            audio.volume=1;
        })

        $('.unmute').addClass('mute').removeClass('unmute').html('mute');
    });

    $(document).on('click','.tryAgain',function(){
       duckhunt.retry();
    });

    $(document).on('click','.doit',function(){
        var LCwaves = parseInt($("#LCwaves").attr("value"));
        var LCducks = parseInt($("#LCducks").attr("value"));
        var LCbullets = parseInt($("#LCbullets").attr("value"));
        var LCwavetime = parseInt($("#LCwavetime").attr("value"));
        var LCdif = parseInt($("#LCdif").attr("value"));

        duckhunt.clearField();

        duckhunt.loadLevel({
            id: 0,
            title: 'Custom Level',
            waves: LCwaves,
            ducks: LCducks,
            pointsPerDuck: 100,
            speed: LCdif,
            bullets: LCbullets,
            time: LCwavetime
        })
    });

    $(document).ready(function(){
        //mute the sounds for debuging
        //$('.mute').trigger('click');
        duckhunt.init();
        duckhunt.loadLevel(levels[0]);
    });

});

function addCommas(nStr)
{
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

<commit_msg>Use val function in level creator logic<commit_after>$(function() {

    $(document).on("click",'.mute',function(){
        $(".sounds").each(function(index,audio){
             audio.volume=0;
        })

        $('.mute').addClass('unmute').removeClass('mute').html('unmute');
    });

    $(document).on('click','.unmute',function(){
        $(".sounds").each(function(index,audio){
            audio.volume=1;
        })

        $('.unmute').addClass('mute').removeClass('unmute').html('mute');
    });

    $(document).on('click','.tryAgain',function(){
       duckhunt.retry();
    });

    $(document).on('click','.doit',function(){
        var LCwaves = parseInt($("#LCwaves").val());
        var LCducks = parseInt($("#LCducks").val());
        var LCbullets = parseInt($("#LCbullets").val());
        var LCwavetime = parseInt($("#LCwavetime").val());
        var LCdif = parseInt($("#LCdif").val());

        duckhunt.clearField();

        duckhunt.loadLevel({
            id: 0,
            title: 'Custom Level',
            waves: LCwaves,
            ducks: LCducks,
            pointsPerDuck: 100,
            speed: LCdif,
            bullets: LCbullets,
            time: LCwavetime
        })
    });

    $(document).ready(function(){
        //mute the sounds for debuging
        //$('.mute').trigger('click');
        duckhunt.init();
        duckhunt.loadLevel(levels[0]);
    });

});

function addCommas(nStr)
{
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

<|endoftext|>


<commit_before>/*
    This script starts a web server and waits for incoming http requests. Requests should have the form:
    http://myserver:port/VIN[?refresh]

    VIN is your vehicle identification number
        for example WBAXXXXXXXV123456

    ?refresh is an optional parameter.
        If set, fresh data is download from the BMW servers. If left out, a cached copy
        from stored JSON files is returned instead
 */

var http = require("http");
var url = require('url');
var fs = require('fs');

const g_serverListenPort = 8777;

var vehicle = require('./vehicle.js');

function writeResponse(res, _vin)
{
    fs.readFile('result_' + _vin + '.json', 'utf8', function(_err, _data)
    {
        if(_err)
        {
            res.writeHead(404, {'Content-Type': 'text/plain'});
            res.end("Failed to open file " + _vin + ": " + _err);
        }
        else
        {
            res.writeHead(200, {'Content-Type': 'application/json; charset=utf-8'});
            res.end(_data);
        }
    })
}

http.createServer(function (req, res)
{
    var requestUrl = url.parse(req.url);
    var path = requestUrl.pathname;
    var search = requestUrl.search;

    var vin = path.substring(1);

    if(search === '?refresh')
    {
        console.log("Requesting new data from BMW ConnectedDrive API server");

        vehicle.writeAllVehiclesData(function()
        {
            writeResponse(res, vin);
        }, function(err)
        {
            res.writeHead(500, {'Content-Type': 'text/plain'});
            res.end('Request Error: ' + err);
        });
    }
    else
    {
        console.log("Returning cached version of data for VIN " + vin);
        writeResponse(res, vin);
    }
}).listen(g_serverListenPort);
<commit_msg>remove caching functionality<commit_after>/*
    This script starts a web server and waits for incoming http requests. Requests should have the form:
    http://myserver:port/VIN[?refresh]

    VIN is your vehicle identification number
        for example WBAXXXXXXXV123456

    ?refresh is an optional parameter.
        If set, fresh data is download from the BMW servers. If left out, a cached copy
        from stored JSON files is returned instead
 */

var http = require("http");
var url = require('url');
var fs = require('fs');

const g_serverListenPort = 8777;

var vehicle = require('./vehicle.js');

http.createServer(function (req, res)
{
    var requestUrl = url.parse(req.url);
    var path = requestUrl.pathname;
    var search = requestUrl.search;

    var vin = path.substring(1);

	vehicle.requestVehicles(function(_vin, _data)
    {
		res.writeHead(200, {'Content-Type': 'application/json; charset=utf-8'});
		res.end(JSON.stringify(_data));
	}, function(_success)
	{
	}, function(err)
	{
		console.log("Error: " + err);
		res.writeHead(500, {'Content-Type': 'text/plain'});
		res.end('Request Error: ' + err);
	});
}).listen(g_serverListenPort);
<|endoftext|>