<commit_before>var eventQueue = [];
var svg;
var element;
var drawingArea;
var width;
var height;
var volume = 0.6;
var ULTIMATE_DREAM_KILLER = false;  // https://github.com/debugger22/github-audio/pull/19
var orgRepoFilterNames = [];

var scale_factor = 6,
    note_overlap = 2,
    note_timeout = 300,
    current_notes = 0,
    max_life = 20000;

var svg_background_color_online = 'rgb(78, 79, 140)',
    svg_background_color_offline = '#E91E63',
    svg_text_color = '#FFFFFF',
    newuser_box_color = 'rgb(41, 128, 185)',
    push_color = 'rgb(155, 89, 182)',
    issue_color = 'rgb(46, 204, 113)',
    pull_request_color = 'rgb(46, 204, 113)',
    comment_color = 'rgb(46, 204, 113)',
    create_color = '#0288D1',
    watch_color = 'rgb(46, 204, 113)',
    fork_color = '#0288D1',
    edit_color = '#fff',
    total_sounds = 51;

var celesta = [],
    clav = [],
    swells = [],
    all_loaded = false;

var socket = new WebSocket("ws://localhost:1337/ws");

socket.addEventListener("message", function (data) {
  var json = JSON.parse(data.data);

  $('.online-users-count').html(json.connectedUsers);

  if(json.connectedUsers == null) {
      json.forEach(function (event) {
          if (!isEventInQueue(event)) {
              // Filter out events only specified by the user
              if (orgRepoFilterNames != []) {
                  // Don't consider pushes to github.io repos when org filter is on
                  if (new RegExp(orgRepoFilterNames.join("|")).test(event.repoName)
                      && event.repoName.indexOf('github.io') == -1) {
                      eventQueue.push(event);
                  }
              } else {
                  eventQueue.push(event);
              }
          }
      });
      // Don't let the eventQueue grow more than 1000
      if (eventQueue.length > 1000) eventQueue = eventQueue.slice(0, 1000);
  }
});

socket.onopen = function(e){
    if(svg != null){
      $('svg').css('background-color', svg_background_color_online);
      $('header').css('background-color', svg_background_color_online);
      $('.offline-text').css('visibility', 'hidden');
      $('.events-remaining-text').css('visibility', 'visible');
      $('.events-remaining-value').css('visibility', 'visible');
      $('.online-users-div').css('visibility', 'visible');
    }
};

socket.onclose = function(e){
    if(svg != null){
      $('svg').css('background-color', svg_background_color_offline);
      $('header').css('background-color', svg_background_color_offline);
      $('.offline-text').css('visibility', 'visible');
      $('.events-remaining-text').css('visibility', 'visible');
      $('.events-remaining-value').css('visibility', 'visible');
    }
};

socket.onerror = function(e){
    if(svg != null){
      $('svg').css('background-color', svg_background_color_offline);
      $('header').css('background-color', svg_background_color_offline);
      $('.offline-text').css('visibility', 'visible');
      $('.events-remaining-text').css('visibility', 'visible');
      $('.events-remaining-value').css('visibility', 'visible');
    }
};

/**
* This function checks whether an event is already in the queue
*/
function isEventInQueue(event){
  for(var i=0; i<eventQueue.length; i++){
    if(eventQueue[i].id == event.id)
      return true;
  }
  return false;
}

/**
 * This function adds a filter for events that we don't want to hear.
 *
 * To extend this function, simply add return true for events that should be filtered.
 */
function shouldEventBeIgnored(event){
  // This adds an easter egg to only play closed PRs
  if (!!ULTIMATE_DREAM_KILLER)
    return (event.type !== "PullRequestEvent" || event.action !== "closed");

  return false;
}

$(function(){
  element = document.documentElement;
  drawingArea = document.getElementsByTagName('#area')[0];
  width  = window.innerWidth || element.clientWidth || drawingArea.clientWidth;
  height = (window.innerHeight - $('header').height()) || (element.clientHeight - $('header').height()) || (drawingArea.clientHeight - $('header').height());
  $('svg').css('background-color', svg_background_color_online);
  $('header').css('background-color', svg_background_color_online);
  $('svg text').css('color', svg_text_color);
  $('#volumeSlider').slider({
    'max': 100,
    'min': 0,
    'value': volume*100,
    'slide' : function(event, ui){
      volume = ui.value/100.0;
      Howler.volume(volume);
    },
    'change' : function(event, ui){
      volume = ui.value/100.0;
      Howler.volume(volume);
    }
  });

  // Main drawing area
  svg = d3.select("#area").append("svg");
  svg.attr({width: width, height: height});
  svg.style('background-color', svg_background_color_online);

  // For window resizes
  var update_window = function() {
      width = window.innerWidth || element.clientWidth || drawingArea.clientWidth;
      height = (window.innerHeight  - $('header').height())|| (element.clientHeight - $('header').height()) || (drawingArea.clientHeight - $('header').height());
      svg.attr("width", width).attr("height", height);
  };
  window.onresize = update_window;
  update_window();

  var loaded_sounds = 0;
  var sound_load = function(r) {
      loaded_sounds += 1;
      if (loaded_sounds == total_sounds) {
          all_loaded = true;
          setTimeout(playFromQueueExchange1, Math.floor(Math.random() * 1000));
          // Starting the second exchange makes music a bad experience
          // setTimeout(playFromQueueExchange2, Math.floor(Math.random() * 2000));
      }
  };

  // Load sounds
  for (var i = 1; i <= 24; i++) {
      if (i > 9) {
          fn = 'c0' + i;
      } else {
          fn = 'c00' + i;
      }
      celesta.push(new Howl({
          src : ['https://d1fz9d31zqor6x.cloudfront.net/sounds/celesta/' + fn + '.ogg',
                  'https://d1fz9d31zqor6x.cloudfront.net/sounds/celesta/' + fn + '.mp3'],
          volume : 0.7,
          onload : sound_load(),
          buffer: true
      }));
      clav.push(new Howl({
          src : ['https://d1fz9d31zqor6x.cloudfront.net/sounds/clav/' + fn + '.ogg',
                  'https://d1fz9d31zqor6x.cloudfront.net/sounds/clav/' + fn + '.mp3'],
          volume : 0.4,
          onload : sound_load(),
          buffer: true
      }))
  }

  for (var i = 1; i <= 3; i++) {
      swells.push(new Howl({
          src : ['https://d1fz9d31zqor6x.cloudfront.net/sounds/swells/swell' + i + '.ogg',
                  'https://d1fz9d31zqor6x.cloudfront.net/sounds/swells/swell' + i + '.mp3'],
          volume : 1,
          onload : sound_load(),
          buffer: true
      }));
  }

  Howler.volume(volume);

  // Make header and footer visible
  $('body').css('visibility', 'visible');

  $('#org-repo-filter-name').on('input', function() {
    orgRepoFilterNames = $('#org-repo-filter-name').val().split(' ');
    eventQueue = [];
  });

});

/**
* Randomly selects a swell sound and plays it
*/
function playRandomSwell() {
    var index = Math.round(Math.random() * (swells.length - 1));
    swells[index].play();
}

/**
* Plays a sound(celesta and clav) based on passed parameters
*/
function playSound(size, type) {
    var max_pitch = 100.0;
    var log_used = 1.0715307808111486871978099;
    var pitch = 100 - Math.min(max_pitch, Math.log(size + log_used) / Math.log(log_used));
    var index = Math.floor(pitch / 100.0 * Object.keys(celesta).length);
    var fuzz = Math.floor(Math.random() * 4) - 2;
    index += fuzz;
    index = Math.min(Object.keys(celesta).length - 1, index);
    index = Math.max(1, index);
    if (current_notes < note_overlap) {
        current_notes++;
        if (type == 'IssuesEvent' || type == 'IssueCommentEvent') {
            clav[index].play();
        } else if(type == 'PushEvent') {
            celesta[index].play();
        }else{
          playRandomSwell();
        }
        setTimeout(function() {
            current_notes--;
        }, note_timeout);
    }
}

// Following are the n numbers of event consumers
// consuming n events each per second with a random delay between them

function playFromQueueExchange1(){
  var event = eventQueue.shift();
  if(event != null && event.message != null && !shouldEventBeIgnored(event) && svg != null){
    playSound(event.message.length*1.1, event.type);
    if(!document.hidden)
      drawEvent(event, svg);
  }
  setTimeout(playFromQueueExchange1, Math.floor(Math.random() * 1000) + 500);
  $('.events-remaining-value').html(eventQueue.length);
}

function playFromQueueExchange2(){
  var event = eventQueue.shift();
  if(event != null && event.message != null && !shouldEventBeIgnored(event) && svg != null){
    playSound(event.message.length, event.type);
    if(!document.hidden)
      drawEvent(event, svg);
  }
  setTimeout(playFromQueueExchange2, Math.floor(Math.random() * 800) + 500);
  $('.events-remaining-value').html(eventQueue.length);
}

// This method capitalizes the string in place
String.prototype.capitalize=function(all){
    if(all){
      return this.split(' ').map(function(e){
        return e.capitalize().join(' ');
      });
    }else{
         return this.charAt(0).toUpperCase() + this.slice(1);
    }
};

function drawEvent(data, svg_area) {
    var starting_opacity = 1;
    var opacity = 1 / (100 / data.message.length);
    if (opacity > 0.5) {
        opacity = 0.5;
    }
    var size = data.message.length;
    var label_text;
    var ring_radius = 80;
    var ring_anim_duration = 3000;
    svg_text_color = '#FFFFFF';
    switch(data.type){
      case "PushEvent":
        label_text = data.actorName.capitalize() + " pushed to " + data.repoName;
        edit_color = '#B2DFDB';
      break;
      case "PullRequestEvent":
        label_text = data.actorName.capitalize() + " " +
          data.action + " " + " a PR for " + data.repoName;
          edit_color = '#C6FF00';
          ring_anim_duration = 10000;
          ring_radius = 600;
      break;
      case "IssuesEvent":
        label_text = data.actorName.capitalize() + " " +
          data.action + " an issue in " + data.repoName;
          edit_color = '#FFEB3B';
      break;
      case "IssueCommentEvent":
        label_text = data.actorName.capitalize() + " commented in " + data.repoName;
        edit_color = '#FF5722';
      break;
      case "ForkEvent":
        label_text = data.actorName.capitalize() + " forked " + data.repoName;
        edit_color = '#0288D1';
        break;
      case "CreateEvent":
        label_text = data.actorName.capitalize() + " created " + data.repoName;
        edit_color = '#0288D1';
      break;
      case "WatchEvent":
        label_text = data.actorName.capitalize() + " watched " + data.repoName;
        edit_color = '#B2DFDB';
      break;
    }
    var csize = size;
    var no_label = false;
    var type = data.type;

    var circle_id = 'd' + ((Math.random() * 100000) | 0);
    var abs_size = Math.abs(size);
    size = Math.max(Math.sqrt(abs_size) * scale_factor, 3);

    Math.seedrandom(data.message)
    var x = Math.random() * (width - size) + size;
    var y = Math.random() * (height - size) + size;

    var circle_group = svg_area.append('g')
        .attr('transform', 'translate(' + x + ', ' + y + ')')
        .attr('fill', edit_color)
        .style('opacity', starting_opacity)

    var ring = circle_group.append('circle');
    ring.attr({r: size, stroke: 'none'});
    ring.transition()
        .attr('r', size + ring_radius)
        .style('opacity', 0)
        .ease(Math.sqrt)
        .duration(ring_anim_duration)
        .remove();

    var circle_container = circle_group.append('a');
    circle_container.attr('xlink:href', data.eventURL);
    circle_container.attr('target', '_blank');
    circle_container.attr('fill', svg_text_color);

    var circle = circle_container.append('circle');
    circle.classed(type, true);
    circle.attr('r', size)
      .attr('fill', edit_color)
      .transition()
      .duration(max_life)
      .style('opacity', 0)
      .remove();

    circle_container.on('mouseover', function() {
      circle_container.append('text')
          .text(label_text)
          .classed('label', true)
          .attr('text-anchor', 'middle')
          .attr('font-size', '0.8em')
          .transition()
          .delay(1000)
          .style('opacity', 0)
          .duration(2000)
          .each(function() { no_label = true; })
          .remove();
    });

    var text = circle_container.append('text')
        .text(label_text)
        .classed('article-label', true)
        .attr('text-anchor', 'middle')
        .attr('font-size', '0.8em')
        .transition()
        .delay(2000)
        .style('opacity', 0)
        .duration(5000)
        .each(function() { no_label = true; })
        .remove();

  // Remove HTML of decayed events
  // Keep it less than 50
  if($('#area svg g').length > 50){
    $('#area svg g:lt(10)').remove();
  }
}
<commit_msg>Fixed race condition to show counters<commit_after>var eventQueue = [];
var svg;
var element;
var drawingArea;
var width;
var height;
var volume = 0.6;
var ULTIMATE_DREAM_KILLER = false;  // https://github.com/debugger22/github-audio/pull/19
var orgRepoFilterNames = [];

var scale_factor = 6,
    note_overlap = 2,
    note_timeout = 300,
    current_notes = 0,
    max_life = 20000;

var svg_background_color_online = 'rgb(78, 79, 140)',
    svg_background_color_offline = '#E91E63',
    svg_text_color = '#FFFFFF',
    newuser_box_color = 'rgb(41, 128, 185)',
    push_color = 'rgb(155, 89, 182)',
    issue_color = 'rgb(46, 204, 113)',
    pull_request_color = 'rgb(46, 204, 113)',
    comment_color = 'rgb(46, 204, 113)',
    create_color = '#0288D1',
    watch_color = 'rgb(46, 204, 113)',
    fork_color = '#0288D1',
    edit_color = '#fff',
    total_sounds = 51;

var celesta = [],
    clav = [],
    swells = [],
    all_loaded = false;

var socket = new WebSocket("ws://localhost:1337/ws");

socket.addEventListener("message", function (data) {
  var json = JSON.parse(data.data);

  $('.online-users-count').html(json.connectedUsers);

  if(json.connectedUsers == null) {
      json.forEach(function (event) {
          if (!isEventInQueue(event)) {
              // Filter out events only specified by the user
              if (orgRepoFilterNames != []) {
                  // Don't consider pushes to github.io repos when org filter is on
                  if (new RegExp(orgRepoFilterNames.join("|")).test(event.repoName)
                      && event.repoName.indexOf('github.io') == -1) {
                      eventQueue.push(event);
                  }
              } else {
                  eventQueue.push(event);
              }
          }
      });
  }
      // Don't let the eventQueue grow more than 1000
      if (eventQueue.length > 1000) eventQueue = eventQueue.slice(0, 1000);
});

socket.onopen = function(e){
    $('svg').css('background-color', svg_background_color_online);
    $('header').css('background-color', svg_background_color_online);
    $('.offline-text').css('visibility', 'hidden');
    $('.events-remaining-text').css('visibility', 'visible');
    $('.events-remaining-value').css('visibility', 'visible');
    $('.online-users-div').css('visibility', 'visible');
};

socket.onclose = function(e){
    $('svg').css('background-color', svg_background_color_offline);
    $('header').css('background-color', svg_background_color_offline);
    $('.offline-text').css('visibility', 'visible');
    $('.events-remaining-text').css('visibility', 'visible');
    $('.events-remaining-value').css('visibility', 'visible');
};

socket.onerror = function(e){
    $('svg').css('background-color', svg_background_color_offline);
    $('header').css('background-color', svg_background_color_offline);
    $('.offline-text').css('visibility', 'visible');
    $('.events-remaining-text').css('visibility', 'visible');
    $('.events-remaining-value').css('visibility', 'visible');
};

/**
* This function checks whether an event is already in the queue
*/
function isEventInQueue(event){
  for(var i=0; i<eventQueue.length; i++){
    if(eventQueue[i].id == event.id)
      return true;
  }
  return false;
}

/**
 * This function adds a filter for events that we don't want to hear.
 *
 * To extend this function, simply add return true for events that should be filtered.
 */
function shouldEventBeIgnored(event){
  // This adds an easter egg to only play closed PRs
  if (!!ULTIMATE_DREAM_KILLER)
    return (event.type !== "PullRequestEvent" || event.action !== "closed");

  return false;
}

$(function(){
  element = document.documentElement;
  drawingArea = document.getElementsByTagName('#area')[0];
  width  = window.innerWidth || element.clientWidth || drawingArea.clientWidth;
  height = (window.innerHeight - $('header').height()) || (element.clientHeight - $('header').height()) || (drawingArea.clientHeight - $('header').height());
  $('svg').css('background-color', svg_background_color_online);
  $('header').css('background-color', svg_background_color_online);
  $('svg text').css('color', svg_text_color);
  $('#volumeSlider').slider({
    'max': 100,
    'min': 0,
    'value': volume*100,
    'slide' : function(event, ui){
      volume = ui.value/100.0;
      Howler.volume(volume);
    },
    'change' : function(event, ui){
      volume = ui.value/100.0;
      Howler.volume(volume);
    }
  });

  // Main drawing area
  svg = d3.select("#area").append("svg");
  svg.attr({width: width, height: height});
  svg.style('background-color', svg_background_color_online);

  // For window resizes
  var update_window = function() {
      width = window.innerWidth || element.clientWidth || drawingArea.clientWidth;
      height = (window.innerHeight  - $('header').height())|| (element.clientHeight - $('header').height()) || (drawingArea.clientHeight - $('header').height());
      svg.attr("width", width).attr("height", height);
  };
  window.onresize = update_window;
  update_window();

  var loaded_sounds = 0;
  var sound_load = function(r) {
      loaded_sounds += 1;
      if (loaded_sounds == total_sounds) {
          all_loaded = true;
          setTimeout(playFromQueueExchange1, Math.floor(Math.random() * 1000));
          // Starting the second exchange makes music a bad experience
          // setTimeout(playFromQueueExchange2, Math.floor(Math.random() * 2000));
      }
  };

  // Load sounds
  for (var i = 1; i <= 24; i++) {
      if (i > 9) {
          fn = 'c0' + i;
      } else {
          fn = 'c00' + i;
      }
      celesta.push(new Howl({
          src : ['https://d1fz9d31zqor6x.cloudfront.net/sounds/celesta/' + fn + '.ogg',
                  'https://d1fz9d31zqor6x.cloudfront.net/sounds/celesta/' + fn + '.mp3'],
          volume : 0.7,
          onload : sound_load(),
          buffer: true
      }));
      clav.push(new Howl({
          src : ['https://d1fz9d31zqor6x.cloudfront.net/sounds/clav/' + fn + '.ogg',
                  'https://d1fz9d31zqor6x.cloudfront.net/sounds/clav/' + fn + '.mp3'],
          volume : 0.4,
          onload : sound_load(),
          buffer: true
      }))
  }

  for (var i = 1; i <= 3; i++) {
      swells.push(new Howl({
          src : ['https://d1fz9d31zqor6x.cloudfront.net/sounds/swells/swell' + i + '.ogg',
                  'https://d1fz9d31zqor6x.cloudfront.net/sounds/swells/swell' + i + '.mp3'],
          volume : 1,
          onload : sound_load(),
          buffer: true
      }));
  }

  Howler.volume(volume);

  // Make header and footer visible
  $('body').css('visibility', 'visible');

  $('#org-repo-filter-name').on('input', function() {
    orgRepoFilterNames = $('#org-repo-filter-name').val().split(' ');
    eventQueue = [];
  });

});

/**
* Randomly selects a swell sound and plays it
*/
function playRandomSwell() {
    var index = Math.round(Math.random() * (swells.length - 1));
    swells[index].play();
}

/**
* Plays a sound(celesta and clav) based on passed parameters
*/
function playSound(size, type) {
    var max_pitch = 100.0;
    var log_used = 1.0715307808111486871978099;
    var pitch = 100 - Math.min(max_pitch, Math.log(size + log_used) / Math.log(log_used));
    var index = Math.floor(pitch / 100.0 * Object.keys(celesta).length);
    var fuzz = Math.floor(Math.random() * 4) - 2;
    index += fuzz;
    index = Math.min(Object.keys(celesta).length - 1, index);
    index = Math.max(1, index);
    if (current_notes < note_overlap) {
        current_notes++;
        if (type == 'IssuesEvent' || type == 'IssueCommentEvent') {
            clav[index].play();
        } else if(type == 'PushEvent') {
            celesta[index].play();
        }else{
          playRandomSwell();
        }
        setTimeout(function() {
            current_notes--;
        }, note_timeout);
    }
}

// Following are the n numbers of event consumers
// consuming n events each per second with a random delay between them

function playFromQueueExchange1(){
  var event = eventQueue.shift();
  if(event != null && event.message != null && !shouldEventBeIgnored(event) && svg != null){
    playSound(event.message.length*1.1, event.type);
    if(!document.hidden)
      drawEvent(event, svg);
  }
  setTimeout(playFromQueueExchange1, Math.floor(Math.random() * 1000) + 500);
  $('.events-remaining-value').html(eventQueue.length);
}

function playFromQueueExchange2(){
  var event = eventQueue.shift();
  if(event != null && event.message != null && !shouldEventBeIgnored(event) && svg != null){
    playSound(event.message.length, event.type);
    if(!document.hidden)
      drawEvent(event, svg);
  }
  setTimeout(playFromQueueExchange2, Math.floor(Math.random() * 800) + 500);
  $('.events-remaining-value').html(eventQueue.length);
}

// This method capitalizes the string in place
String.prototype.capitalize=function(all){
    if(all){
      return this.split(' ').map(function(e){
        return e.capitalize().join(' ');
      });
    }else{
         return this.charAt(0).toUpperCase() + this.slice(1);
    }
};

function drawEvent(data, svg_area) {
    var starting_opacity = 1;
    var opacity = 1 / (100 / data.message.length);
    if (opacity > 0.5) {
        opacity = 0.5;
    }
    var size = data.message.length;
    var label_text;
    var ring_radius = 80;
    var ring_anim_duration = 3000;
    svg_text_color = '#FFFFFF';
    switch(data.type){
      case "PushEvent":
        label_text = data.actorName.capitalize() + " pushed to " + data.repoName;
        edit_color = '#B2DFDB';
      break;
      case "PullRequestEvent":
        label_text = data.actorName.capitalize() + " " +
          data.action + " " + " a PR for " + data.repoName;
          edit_color = '#C6FF00';
          ring_anim_duration = 10000;
          ring_radius = 600;
      break;
      case "IssuesEvent":
        label_text = data.actorName.capitalize() + " " +
          data.action + " an issue in " + data.repoName;
          edit_color = '#FFEB3B';
      break;
      case "IssueCommentEvent":
        label_text = data.actorName.capitalize() + " commented in " + data.repoName;
        edit_color = '#FF5722';
      break;
      case "ForkEvent":
        label_text = data.actorName.capitalize() + " forked " + data.repoName;
        edit_color = '#0288D1';
        break;
      case "CreateEvent":
        label_text = data.actorName.capitalize() + " created " + data.repoName;
        edit_color = '#0288D1';
      break;
      case "WatchEvent":
        label_text = data.actorName.capitalize() + " watched " + data.repoName;
        edit_color = '#B2DFDB';
      break;
    }
    var csize = size;
    var no_label = false;
    var type = data.type;

    var circle_id = 'd' + ((Math.random() * 100000) | 0);
    var abs_size = Math.abs(size);
    size = Math.max(Math.sqrt(abs_size) * scale_factor, 3);

    Math.seedrandom(data.message)
    var x = Math.random() * (width - size) + size;
    var y = Math.random() * (height - size) + size;

    var circle_group = svg_area.append('g')
        .attr('transform', 'translate(' + x + ', ' + y + ')')
        .attr('fill', edit_color)
        .style('opacity', starting_opacity)

    var ring = circle_group.append('circle');
    ring.attr({r: size, stroke: 'none'});
    ring.transition()
        .attr('r', size + ring_radius)
        .style('opacity', 0)
        .ease(Math.sqrt)
        .duration(ring_anim_duration)
        .remove();

    var circle_container = circle_group.append('a');
    circle_container.attr('xlink:href', data.eventURL);
    circle_container.attr('target', '_blank');
    circle_container.attr('fill', svg_text_color);

    var circle = circle_container.append('circle');
    circle.classed(type, true);
    circle.attr('r', size)
      .attr('fill', edit_color)
      .transition()
      .duration(max_life)
      .style('opacity', 0)
      .remove();

    circle_container.on('mouseover', function() {
      circle_container.append('text')
          .text(label_text)
          .classed('label', true)
          .attr('text-anchor', 'middle')
          .attr('font-size', '0.8em')
          .transition()
          .delay(1000)
          .style('opacity', 0)
          .duration(2000)
          .each(function() { no_label = true; })
          .remove();
    });

    var text = circle_container.append('text')
        .text(label_text)
        .classed('article-label', true)
        .attr('text-anchor', 'middle')
        .attr('font-size', '0.8em')
        .transition()
        .delay(2000)
        .style('opacity', 0)
        .duration(5000)
        .each(function() { no_label = true; })
        .remove();

  // Remove HTML of decayed events
  // Keep it less than 50
  if($('#area svg g').length > 50){
    $('#area svg g:lt(10)').remove();
  }
}
<|endoftext|>


<commit_before>
// debugger

//Three.js rendering:
var camera, scene, renderer;
var effect, controls;
var element, container;
var cube, time;

var particleSystem, particles,
particleSystemHeight = 500,
particleCount = 2000;

var clock = new THREE.Clock();

var KEYDOWN = false;
var WHICHKEY = undefined;
var trixelData = undefined;

/*
var request = new XMLHttpRequest();
request.open('GET', 'http://api.trixel.io/trixels/26', true);

request.onload = function() {
  if (this.status >= 200 && this.status < 400) {
    // Success!
    trixelData = JSON.parse(this.response);

    console.log('trixel data', trixelData);

  } else {
    console.error('json load error');

  }
};

request.onerror = function() {
  console.error('json request error');
};

request.send();
*/

//web socket stuff

var socket = io();

function socketSend(message){

  socket.emit('message', message);

}

socket.on('message', function(message){

  console.log(message);

  if(message.event == 'keydown'){

    handleKey(message.key);
  }

  if(message.event == 'chat'){

    console.log('chat:', message.body);
    $console.text(message.body);

  }

});

//speach recognition controls:

var $console = $('.console');

var show = function(term) {

  var url = 'http://api.flickr.com/services/rest/?tags='+term;
  console.log($.getJSON(url));
}

var greeting = function(term) {

  console.log('say:', term);
  $console.text(term);

  //socketSend({event: 'chat', body: term});

}

var test = function() {

  console.log('blah');
  $console.text('blah');

  //socketSend({event: 'chat', body: term});

}

var commands = {

  'test': test,

  // By defining a part of the following command as optional, annyang will respond to both:
  // "say hello to my little friend" as well as "say hello friend"
  'say *term': greeting
};

// Add our commands to annyang
annyang.addCommands(commands);

annyang.debug();

annyang.addCallback('resultMatch', function (e) {
  console.log('resultMatch:', e);
});

// Start listening. You can call this here, or attach this call to an event, button, etc.
annyang.start();

//start three.js stuff
//init();
//animate();

//fullscreen();

//socket-based remote keyboard control

var camera_y, camera_x;

function handleKey(WHICHKEY){

  //console.log(keyevent);

  switch(WHICHKEY){

    case 87: //w key

      //console.log('forward');
      camera_y = camera.position.y - 10;
      break;

    case 83: //s key

      //console.log('back');
      camera_y = camera.position.y + 10;
      break;

    case 65: //a key

      //console.log('left');
      camera_x = camera.position.x - 10;
      break;

    case 68: //d key

      //console.log('right');
      camera_x = camera.position.x + 10;
      break;
  }
}

window.onkeydown = function(e) {

  KEYDOWN = true;

  WHICHKEY = e.keyCode ? e.keyCode : e.which;
}

function doKeyDOWN() {

  // debugger
  var key = WHICHKEY ? WHICHKEY : WHICHKEY;

  var keyevent = {'event': 'keydown', 'key': key};

  handleKey(WHICHKEY);

  socketSend(keyevent);
}

window.onkeyup = function(e) {

  KEYDOWN = false;
}

function init() {

  //set up camera stuff:
  var errorCallback = function(e) {
    console.log('Reeeejected!', e);
  };

  navigator.getUserMedia  = navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia;

  function gotSources(sourceInfos) {

    console.log(sourceInfos);

    var sourceId;

    //the back facing camera on nexus 5 is the 4th source:
    if(sourceInfos[4]){

      sourceId = sourceInfos[4].id;
    }

    //set the constraints for this preference
    var constraints = {
      audio: false,
      video: {
        optional: [{sourceId: sourceId}]
      }
    }

    //video containers for left and right eye
    var video1 = document.querySelector('video.left');
    var video2 = document.querySelector('video.right');

    //set the video source for both eyes to the same video stream:
    if (navigator.getUserMedia) {
      navigator.getUserMedia(constraints, function(stream) {
        video1.src = window.URL.createObjectURL(stream);
        video2.src = window.URL.createObjectURL(stream);

        annyang.start();

      }, errorCallback);
    }
  }

  if (typeof MediaStreamTrack === 'undefined'){
    alert('This browser does not support MediaStreamTrack.');
  } else {
    MediaStreamTrack.getSources(gotSources);
  }

  // make the three.js background transparent:
  renderer = new THREE.WebGLRenderer({ alpha: true });
  renderer.setClearColor( 0x000000, 0 );

  // create the three container:
  element = renderer.domElement;
  container = document.getElementById('example');
  container.appendChild(element);

  //stereo render effect:
  effect = new THREE.StereoEffect(renderer);
  scene = new THREE.Scene();

  // add saved trixel viewer
  Trixelworld = new THREE.Object3D();
  //scene.add( Trixelworld );

  buildTrixelDisplay(Trixelworld,scene);

  //set up the camera:
  camera = new THREE.PerspectiveCamera(90, 1, 0.001, 700);
  camera.position.set(0, 10, 100);
  scene.add(camera);

  camera_y = camera.position.y;
  camera_x = camera.position.x;

  controls = new THREE.OrbitControls(camera, element);
  controls.rotateUp(Math.PI / 4);
  controls.target.set(
    camera.position.x + 0.1,
    camera.position.y,
    camera.position.z
  );
  controls.noZoom = true;
  controls.noPan = true;

  //if mobile device, user device orientation controls:
  if(window.DeviceOrientationEvent){

    //console.log('orientation');

    controls = new THREE.DeviceOrientationControls(camera, true);
    controls.connect();
    controls.update();

    //element.addEventListener('click', fullscreen, false);
  }

  var full_button = document.getElementById('fullscreen');
  full_button.addEventListener('click', fullscreen, false);

  //add light to the scene (this is red light)
  var light = new THREE.HemisphereLight(0xff0000, 0x000000, 1);
  scene.add(light);

  //add an object to the scene
  cube = new THREE.Mesh( new THREE.DodecahedronGeometry( 100 ), new THREE.MeshBasicMaterial( { color: 0xff00ff, wireframe: true } ));
  cube.position.x = 300;
  cube.position.y = 70;
  cube.position.z = 50;
  scene.add( cube );

  /*
  // create the particle variables
  particles = new THREE.Geometry();

  pMaterial = new THREE.PointCloudMaterial({
    color: 0xFF0000,
    size: 3,

    fog: true,
    blending: THREE.AdditiveBlending,
    transparent: true
  });

  // now create the individual particles
  for (var p = 0; p < particleCount; p++) {

    // create a particle with random
    // position values, -250 -> 250
    var pX = Math.random() * particleSystemHeight * 2 - particleSystemHeight,
        pY = Math.random() * particleSystemHeight * 2 - particleSystemHeight,
        pZ = Math.random() * particleSystemHeight * 2 - particleSystemHeight,
        particle = new THREE.Vector3(pX, pY, pZ);

        particle.velocity = new THREE.Vector3(
          0,              // x
          -Math.random() / 3, // y: random vel
          0);             // z

    // add it to the geometry
    particles.vertices.push(particle);
  }

  // create the particle system
  particleSystem = new THREE.PointCloud(
      particles,
      pMaterial);

  particleSystem.sortParticles = true;

  // add it to the scene
  scene.add(particleSystem);
  */

  //var text = new THREE.Mesh( new THREE.TextGeometry("Testing", {size: 20, height: 30}), new THREE.MeshNormalMaterial() );
  //scene.add( text );

  window.addEventListener('resize', resize, false);
  setTimeout(resize, 1);
}

function resize() {
  var width = container.offsetWidth;
  var height = container.offsetHeight;

  camera.aspect = width / height;
  camera.updateProjectionMatrix();

  renderer.setSize(width, height);
  effect.setSize(width, height);
}

function update(dt) {
  resize();

  camera.updateProjectionMatrix();

  controls.update(dt);
}

function render(dt) {

  time = clock.getElapsedTime();

  cube.rotation.x += 0.02;
  cube.rotation.y += 0.02;
  cube.rotation.z += 0.02;
  cube.position.y  = 100 + 20 * Math.sin(time * 3);

  //particleSystem.rotation.y += 0.01;
  if (KEYDOWN) {
    doKeyDOWN();
  };
  //update camera
  camera.position.y = camera_y;
  camera.position.x = camera_x;
  camera.updateProjectionMatrix();

  // simple billboard method
  Trixelworld.quaternion.copy( camera.quaternion );

  /*
  var pCount = particleCount;
  while (pCount--) {

    // get the particle
    var particle =
      particles.vertices[pCount];

    // check if we need to reset
    if (particle.y < -1 * particleSystemHeight ) {
      particle.y = particleSystemHeight;
      particle.velocity.y = 0;
    }

    // update the velocity with
    // a splat of randomniz
    particle.velocity.y -= Math.random() * .05;

    // and the position
    particle.add(particle.velocity);
  }

  // flag to the particle system
  // that we've changed its vertices.
  particleSystem.
    geometry.
    __dirtyVertices = true;
  */

  effect.render(scene, camera);
}

function animate(t) {
  requestAnimationFrame(animate);

  var dt = clock.getDelta();

  update(dt);
  render(dt);
}

function fullscreen() {
  if (document.body.requestFullscreen) {
    document.body.requestFullscreen();
  } else if (document.body.msRequestFullscreen) {
    document.body.msRequestFullscreen();
  } else if (document.body.mozRequestFullScreen) {
    document.body.mozRequestFullScreen();
  } else if (document.body.webkitRequestFullscreen) {
    document.body.webkitRequestFullscreen();
  }

  //annyang.start();

}<commit_msg>voice test<commit_after>
// debugger

//Three.js rendering:
var camera, scene, renderer;
var effect, controls;
var element, container;
var cube, time;

var particleSystem, particles,
particleSystemHeight = 500,
particleCount = 2000;

var clock = new THREE.Clock();

var KEYDOWN = false;
var WHICHKEY = undefined;
var trixelData = undefined;

/*
var request = new XMLHttpRequest();
request.open('GET', 'http://api.trixel.io/trixels/26', true);

request.onload = function() {
  if (this.status >= 200 && this.status < 400) {
    // Success!
    trixelData = JSON.parse(this.response);

    console.log('trixel data', trixelData);

  } else {
    console.error('json load error');

  }
};

request.onerror = function() {
  console.error('json request error');
};

request.send();
*/

//web socket stuff

var socket = io();

function socketSend(message){

  socket.emit('message', message);

}

socket.on('message', function(message){

  console.log(message);

  if(message.event == 'keydown'){

    handleKey(message.key);
  }

  if(message.event == 'chat'){

    console.log('chat:', message.body);
    $console.text(message.body);

  }

});

//speach recognition controls:

var $console = $('.console');

var show = function(term) {

  var url = 'http://api.flickr.com/services/rest/?tags='+term;
  console.log($.getJSON(url));
}

var greeting = function(term) {

  console.log('say:', term);
  $console.text(term);

  socketSend({event: 'chat', body: term});

}

var test = function() {

  console.log('blah');
  $console.text('blah');

  socketSend({event: 'chat', body: 'blah'});

}

var commands = {

  'test': test,

  // By defining a part of the following command as optional, annyang will respond to both:
  // "say hello to my little friend" as well as "say hello friend"
  'say *term': greeting
};

// Add our commands to annyang
annyang.addCommands(commands);

annyang.debug();

annyang.addCallback('resultMatch', function (e) {
  console.log('resultMatch:', e);
});

// Start listening. You can call this here, or attach this call to an event, button, etc.
annyang.start();

//start three.js stuff
//init();
//animate();

//fullscreen();

//socket-based remote keyboard control

var camera_y, camera_x;

function handleKey(WHICHKEY){

  //console.log(keyevent);

  switch(WHICHKEY){

    case 87: //w key

      //console.log('forward');
      camera_y = camera.position.y - 10;
      break;

    case 83: //s key

      //console.log('back');
      camera_y = camera.position.y + 10;
      break;

    case 65: //a key

      //console.log('left');
      camera_x = camera.position.x - 10;
      break;

    case 68: //d key

      //console.log('right');
      camera_x = camera.position.x + 10;
      break;
  }
}

window.onkeydown = function(e) {

  KEYDOWN = true;

  WHICHKEY = e.keyCode ? e.keyCode : e.which;
}

function doKeyDOWN() {

  // debugger
  var key = WHICHKEY ? WHICHKEY : WHICHKEY;

  var keyevent = {'event': 'keydown', 'key': key};

  handleKey(WHICHKEY);

  socketSend(keyevent);
}

window.onkeyup = function(e) {

  KEYDOWN = false;
}

function init() {

  //set up camera stuff:
  var errorCallback = function(e) {
    console.log('Reeeejected!', e);
  };

  navigator.getUserMedia  = navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia;

  function gotSources(sourceInfos) {

    console.log(sourceInfos);

    var sourceId;

    //the back facing camera on nexus 5 is the 4th source:
    if(sourceInfos[4]){

      sourceId = sourceInfos[4].id;
    }

    //set the constraints for this preference
    var constraints = {
      audio: false,
      video: {
        optional: [{sourceId: sourceId}]
      }
    }

    //video containers for left and right eye
    var video1 = document.querySelector('video.left');
    var video2 = document.querySelector('video.right');

    //set the video source for both eyes to the same video stream:
    if (navigator.getUserMedia) {
      navigator.getUserMedia(constraints, function(stream) {
        video1.src = window.URL.createObjectURL(stream);
        video2.src = window.URL.createObjectURL(stream);

        annyang.start();

      }, errorCallback);
    }
  }

  if (typeof MediaStreamTrack === 'undefined'){
    alert('This browser does not support MediaStreamTrack.');
  } else {
    MediaStreamTrack.getSources(gotSources);
  }

  // make the three.js background transparent:
  renderer = new THREE.WebGLRenderer({ alpha: true });
  renderer.setClearColor( 0x000000, 0 );

  // create the three container:
  element = renderer.domElement;
  container = document.getElementById('example');
  container.appendChild(element);

  //stereo render effect:
  effect = new THREE.StereoEffect(renderer);
  scene = new THREE.Scene();

  // add saved trixel viewer
  Trixelworld = new THREE.Object3D();
  //scene.add( Trixelworld );

  buildTrixelDisplay(Trixelworld,scene);

  //set up the camera:
  camera = new THREE.PerspectiveCamera(90, 1, 0.001, 700);
  camera.position.set(0, 10, 100);
  scene.add(camera);

  camera_y = camera.position.y;
  camera_x = camera.position.x;

  controls = new THREE.OrbitControls(camera, element);
  controls.rotateUp(Math.PI / 4);
  controls.target.set(
    camera.position.x + 0.1,
    camera.position.y,
    camera.position.z
  );
  controls.noZoom = true;
  controls.noPan = true;

  //if mobile device, user device orientation controls:
  if(window.DeviceOrientationEvent){

    //console.log('orientation');

    controls = new THREE.DeviceOrientationControls(camera, true);
    controls.connect();
    controls.update();

    //element.addEventListener('click', fullscreen, false);
  }

  var full_button = document.getElementById('fullscreen');
  full_button.addEventListener('click', fullscreen, false);

  //add light to the scene (this is red light)
  var light = new THREE.HemisphereLight(0xff0000, 0x000000, 1);
  scene.add(light);

  //add an object to the scene
  cube = new THREE.Mesh( new THREE.DodecahedronGeometry( 100 ), new THREE.MeshBasicMaterial( { color: 0xff00ff, wireframe: true } ));
  cube.position.x = 300;
  cube.position.y = 70;
  cube.position.z = 50;
  scene.add( cube );

  /*
  // create the particle variables
  particles = new THREE.Geometry();

  pMaterial = new THREE.PointCloudMaterial({
    color: 0xFF0000,
    size: 3,

    fog: true,
    blending: THREE.AdditiveBlending,
    transparent: true
  });

  // now create the individual particles
  for (var p = 0; p < particleCount; p++) {

    // create a particle with random
    // position values, -250 -> 250
    var pX = Math.random() * particleSystemHeight * 2 - particleSystemHeight,
        pY = Math.random() * particleSystemHeight * 2 - particleSystemHeight,
        pZ = Math.random() * particleSystemHeight * 2 - particleSystemHeight,
        particle = new THREE.Vector3(pX, pY, pZ);

        particle.velocity = new THREE.Vector3(
          0,              // x
          -Math.random() / 3, // y: random vel
          0);             // z

    // add it to the geometry
    particles.vertices.push(particle);
  }

  // create the particle system
  particleSystem = new THREE.PointCloud(
      particles,
      pMaterial);

  particleSystem.sortParticles = true;

  // add it to the scene
  scene.add(particleSystem);
  */

  //var text = new THREE.Mesh( new THREE.TextGeometry("Testing", {size: 20, height: 30}), new THREE.MeshNormalMaterial() );
  //scene.add( text );

  window.addEventListener('resize', resize, false);
  setTimeout(resize, 1);
}

function resize() {
  var width = container.offsetWidth;
  var height = container.offsetHeight;

  camera.aspect = width / height;
  camera.updateProjectionMatrix();

  renderer.setSize(width, height);
  effect.setSize(width, height);
}

function update(dt) {
  resize();

  camera.updateProjectionMatrix();

  controls.update(dt);
}

function render(dt) {

  time = clock.getElapsedTime();

  cube.rotation.x += 0.02;
  cube.rotation.y += 0.02;
  cube.rotation.z += 0.02;
  cube.position.y  = 100 + 20 * Math.sin(time * 3);

  //particleSystem.rotation.y += 0.01;
  if (KEYDOWN) {
    doKeyDOWN();
  };
  //update camera
  camera.position.y = camera_y;
  camera.position.x = camera_x;
  camera.updateProjectionMatrix();

  // simple billboard method
  Trixelworld.quaternion.copy( camera.quaternion );

  /*
  var pCount = particleCount;
  while (pCount--) {

    // get the particle
    var particle =
      particles.vertices[pCount];

    // check if we need to reset
    if (particle.y < -1 * particleSystemHeight ) {
      particle.y = particleSystemHeight;
      particle.velocity.y = 0;
    }

    // update the velocity with
    // a splat of randomniz
    particle.velocity.y -= Math.random() * .05;

    // and the position
    particle.add(particle.velocity);
  }

  // flag to the particle system
  // that we've changed its vertices.
  particleSystem.
    geometry.
    __dirtyVertices = true;
  */

  effect.render(scene, camera);
}

function animate(t) {
  requestAnimationFrame(animate);

  var dt = clock.getDelta();

  update(dt);
  render(dt);
}

function fullscreen() {
  if (document.body.requestFullscreen) {
    document.body.requestFullscreen();
  } else if (document.body.msRequestFullscreen) {
    document.body.msRequestFullscreen();
  } else if (document.body.mozRequestFullScreen) {
    document.body.mozRequestFullScreen();
  } else if (document.body.webkitRequestFullscreen) {
    document.body.webkitRequestFullscreen();
  }

  //annyang.start();

}<|endoftext|>


<commit_before>/* global require */

/**
 * Main bootstrap file.
 */

"use strict";

require.config({
  paths: {
    'jquery':               'vendor/jquery',
    'foundation':           'vendor/foundation/foundation',
    'foundation-joyride':   'vendor/foundation/foundation.joyride',
    'foundation-cookie':    'vendor/foundation/foundation.cookie',
    'foundation-dropdown':  'vendor/foundation/foundation.dropdown',
    'foundation-reveal':    'vendor/foundation/foundation.reveal',
    'angular':              'vendor/angular.min',
    'angular-cookies':      'vendor/angular-cookies.min',
    'angular-route':        'vendor/angular-route.min',
    'angular-animate':      'vendor/angular-animate.min'
  },
  shim: {
    'angular':              { exports: 'angular' },
    'foundation':           { exports: 'Foundation' },
    'angular-cookies':      ['angular'],
    'angular-route':        ['angular'],
    'angular-animate':      ['angular'],
    'foundation-cookie':    ['foundation'],
    'foundation-joyride':   ['foundation', 'foundation-cookie'],
    'foundation-dropdown':  ['foundation'],
    'foundation-reveal':    ['foundation']
  },
  priority: ['angular']
});

require(['jquery', 'angular', 'controllers/App'], function ($, angular, appController) {
  appController();
  angular.bootstrap(document, ['tomatar']);
});
<commit_msg>Remove unneeded dependency<commit_after>/* global require */

/**
 * Main bootstrap file.
 */

"use strict";

require.config({
  paths: {
    'jquery':               'vendor/jquery',
    'foundation':           'vendor/foundation/foundation',
    'foundation-joyride':   'vendor/foundation/foundation.joyride',
    'foundation-cookie':    'vendor/foundation/foundation.cookie',
    'foundation-dropdown':  'vendor/foundation/foundation.dropdown',
    'foundation-reveal':    'vendor/foundation/foundation.reveal',
    'angular':              'vendor/angular.min',
    'angular-cookies':      'vendor/angular-cookies.min',
    'angular-route':        'vendor/angular-route.min',
    'angular-animate':      'vendor/angular-animate.min'
  },
  shim: {
    'angular':              { exports: 'angular' },
    'foundation':           { exports: 'Foundation' },
    'angular-cookies':      ['angular'],
    'angular-route':        ['angular'],
    'angular-animate':      ['angular'],
    'foundation-cookie':    ['foundation'],
    'foundation-joyride':   ['foundation', 'foundation-cookie'],
    'foundation-dropdown':  ['foundation'],
    'foundation-reveal':    ['foundation']
  },
  priority: ['angular']
});

require(['angular', 'controllers/App'], function (angular, appController) {
  appController();
  angular.bootstrap(document, ['tomatar']);
});
<|endoftext|>


<commit_before>(function($) {
  var ood=angular.module('ood', ['ngRoute']), scaleOptions;

  scaleOptions=new Array(33).join().replace(/./g, function(m, i) {
    return '<option value="'+(i+1)+'">'+(i+1)+'</option>';
  });

  $(document).on('focus', 'select.scale', function() {
    if (this.childNodes.length===1) {
      $(this).append(scaleOptions);
    }
  });

  ood.config(function($routeProvider) {
    router($routeProvider)
      .when('/status', {templateUrl:'/.oodmin/view/status'})
      .when('/config', {templateUrl: '/.oodmin/view/config'})
      .when('/app/:appName', {templateUrl:'/.oodmin/view/app'})
      .otherwise({redirectTo:'/status'});
  });

  ood.factory('api', function($http, $route, $rootScope) {
    function api(cmd, params, cb) {
      if (typeof params==='function') {
        cb=params;
        params=null;
      }
      $http({
        method:'POST',
        url:'/.oodmin/api/'+cmd,
        data:params,
        headers:{'x-csrf':$rootScope.csrf}
      }).then(function(res) {
        if (res.data.error) {
          alert(res.data.error);
          $route.reload();
        } else if (typeof cb==='function') {
          cb(res.data);
        }
      }, function(res) {
        alert('error');
        $route.reload();
      });
    }

    api.logout=function() {
      api('logout');
      $route.reload();
    };

    return api;
  });

  ood.controller('AppCtrl', function($scope, api) {
    $scope.logout=api.logout;
  });

  ood.controller('StatusCtrl', function($scope, $routeParams, $timeout, api) {
    $scope.appName=$routeParams.appName;
    $scope.status={};
    $scope.app={};

    $scope.uptime=uptimeHuman;

    $scope.restart=function(appName) {
      api('restart', {app:appName});
    };

    $scope.scale=function(appName, app) {
      var scale=app.scale, diff=app.workers.length-scale,
        q='Do you really want to kill '+diff+' worker'+(diff>1 ? 's' : '')+'?';
      app.scale='';
      if (diff>0 && !confirm(q)) {
        return;
      }
      api('scale', {app:appName, instances:scale});
    };

    (function refresh() {
      if (!$scope.loggedIn) {
        return;
      }
      api('status', function(data) {
        $scope.status=data.status;
        $scope.timeout=[
          $timeout($scope.$apply.bind($scope), 1000),
          $timeout($scope.$apply.bind($scope), 2000),
          $timeout(refresh, 2950)
        ];
      });
    })();

    $scope.$on('$destroy', function(){
      $scope.timeout.forEach($timeout.cancel);
    });
  });

  ood.controller('ConfigCtrl', function($scope, $routeParams, api) {
    $scope.config={};

    $scope.refresh=function() {
      api(
        'config',
        {get:$routeParams.appName ? 'app:'+$routeParams.appName : ''},
        function(res) {
          $scope.config=res.value;
        }
      );
    };

    $scope.refresh();
  });

  ood.filter('cpu', function() {
    return function(p) {
      return (typeof p!=='number' || p===-1) ? 'N/A' : p.toFixed(1)+'%';
    };
  });

  ood.filter('ram', function() {
    return function(b) {
      return (typeof b!=='number' || b===-1) ? 'N/A' : (b/1048576).toFixed(2)+' MB';
    };
  });

  ood.filter('teselecta', function($sce) {
    return function(d) {
      return $sce.trustAsHtml(teselecta(d));
    };
  });

  function init($q, $http, $rootScope) {
    var deffered=$q.defer();
    $http.get('/.oodmin/api/init').then(function(res) {
      $rootScope.loggedIn=res.data.loggedIn;
      $rootScope.csrf=res.data.csrf;
      deffered[$rootScope.loggedIn ? 'resolve' : 'reject']();
    });
    return deffered.promise;
  }

  function router($routeProvider) {
    return angular.extend({}, $routeProvider, {
      when: function(path, route) {
        route.resolve=angular.extend({init:init}, route.resolve);
        $routeProvider.when(path, route);
        return this;
      }
    })
  }

  function uptimeHuman(time) {
    var ms=Date.now()-time, s=Math.floor(ms/1000), m, h, d;
    m=Math.floor(s/60);
    s=s % 60;
    h=Math.floor(m/60);
    m=m % 60;
    d=Math.floor(h/24);
    h=h % 24;
    s=s<10 ? '0'+s : s;
    m=m<10 ? '0'+m : m;
    h=h<10 ? '0'+h : h;
    return d+'d '+h+':'+m+':'+s;
  }

})(jQuery);
<commit_msg>fixed uptime display issue<commit_after>(function($) {
  var ood=angular.module('ood', ['ngRoute']), scaleOptions;

  scaleOptions=new Array(33).join().replace(/./g, function(m, i) {
    return '<option value="'+(i+1)+'">'+(i+1)+'</option>';
  });

  $(document).on('focus', 'select.scale', function() {
    if (this.childNodes.length===1) {
      $(this).append(scaleOptions);
    }
  });

  ood.config(function($routeProvider) {
    router($routeProvider)
      .when('/status', {templateUrl:'/.oodmin/view/status'})
      .when('/config', {templateUrl: '/.oodmin/view/config'})
      .when('/app/:appName', {templateUrl:'/.oodmin/view/app'})
      .otherwise({redirectTo:'/status'});
  });

  ood.factory('api', function($http, $route, $rootScope) {
    function api(cmd, params, cb) {
      if (typeof params==='function') {
        cb=params;
        params=null;
      }
      $http({
        method:'POST',
        url:'/.oodmin/api/'+cmd,
        data:params,
        headers:{'x-csrf':$rootScope.csrf}
      }).then(function(res) {
        if (res.data.error) {
          alert(res.data.error);
          $route.reload();
        } else if (typeof cb==='function') {
          cb(res.data);
        }
      }, function(res) {
        alert('error');
        $route.reload();
      });
    }

    api.logout=function() {
      api('logout');
      $route.reload();
    };

    return api;
  });

  ood.controller('AppCtrl', function($scope, api) {
    $scope.logout=api.logout;
  });

  ood.controller('StatusCtrl', function($scope, $routeParams, $timeout, api) {
    $scope.appName=$routeParams.appName;
    $scope.status={};
    $scope.app={};

    $scope.uptime=uptimeHuman;

    $scope.restart=function(appName) {
      api('restart', {app:appName});
    };

    $scope.scale=function(appName, app) {
      var scale=app.scale, diff=app.workers.length-scale,
        q='Do you really want to kill '+diff+' worker'+(diff>1 ? 's' : '')+'?';
      app.scale='';
      if (diff>0 && !confirm(q)) {
        return;
      }
      api('scale', {app:appName, instances:scale});
    };

    (function refresh() {
      if (!$scope.loggedIn) {
        return;
      }
      api('status', function(data) {
        $scope.status=data.status;
        $scope.timeout=[
          $timeout($scope.$apply.bind($scope), 1000),
          $timeout($scope.$apply.bind($scope), 2000),
          $timeout(refresh, 2950)
        ];
      });
    })();

    $scope.$on('$destroy', function(){
      $scope.timeout.forEach($timeout.cancel);
    });
  });

  ood.controller('ConfigCtrl', function($scope, $routeParams, api) {
    $scope.config={};

    $scope.refresh=function() {
      api(
        'config',
        {get:$routeParams.appName ? 'app:'+$routeParams.appName : ''},
        function(res) {
          $scope.config=res.value;
        }
      );
    };

    $scope.refresh();
  });

  ood.filter('cpu', function() {
    return function(p) {
      return (typeof p!=='number' || p===-1) ? 'N/A' : p.toFixed(1)+'%';
    };
  });

  ood.filter('ram', function() {
    return function(b) {
      return (typeof b!=='number' || b===-1) ? 'N/A' : (b/1048576).toFixed(2)+' MB';
    };
  });

  ood.filter('teselecta', function($sce) {
    return function(d) {
      return $sce.trustAsHtml(teselecta(d));
    };
  });

  function init($q, $http, $rootScope) {
    var deffered=$q.defer();
    $http.get('/.oodmin/api/init').then(function(res) {
      $rootScope.loggedIn=res.data.loggedIn;
      $rootScope.csrf=res.data.csrf;
      deffered[$rootScope.loggedIn ? 'resolve' : 'reject']();
    });
    return deffered.promise;
  }

  function router($routeProvider) {
    return angular.extend({}, $routeProvider, {
      when: function(path, route) {
        route.resolve=angular.extend({init:init}, route.resolve);
        $routeProvider.when(path, route);
        return this;
      }
    })
  }

  function uptimeHuman(time) {
    var ms=Date.now()-time, s=Math.floor(ms/1000), m, h, d;
    if (isNaN(ms)) {
      return '';
    }
    m=Math.floor(s/60);
    s=s % 60;
    h=Math.floor(m/60);
    m=m % 60;
    d=Math.floor(h/24);
    h=h % 24;
    s=s<10 ? '0'+s : s;
    m=m<10 ? '0'+m : m;
    h=h<10 ? '0'+h : h;
    return d+'d '+h+':'+m+':'+s;
  }

})(jQuery);
<|endoftext|>


<commit_before>$(main);

function main() {
    $.getJSON('./data.json', function(providers) {
        var $e = $('.latencies');

        createControls($e);
        createChart($e, providers);
        createLegend($e, providers);
    });

    function createControls($p) {
        var $e = $('<div>', {'class': 'controls'}).appendTo($p);

        createTypes($e);
        createRanges($e);
        createCategories($e);
    }

    function createTypes($p) {
        $controls($p, 'types', 'type', {
            'ping': function() {
                console.log('should show ping now');
            },
            'http': function() {
                console.log('should show http now');
            },
            'https': function() {
                console.log('should show https now');
            }
        });
    }

    function createRanges($p) {
        $controls($p, 'ranges', 'range', {
            '1 day': function() {
                console.log('change to 1 day view');
            },
            '7 days': function() {
                console.log('change to 7 days view');
            },
            '30 days': function() {
                console.log('change to 30 days view');
            }
        });
    }

    function createCategories($p) {
        $controls($p, 'categories', 'category', {
            'latency': function() {
                console.log('change to latency view');
            },
            'uptime': function() {
                console.log('change to uptime view');
            }
        });
    }

    function $controls($p, containerClass, itemClass, controls) {
        var $e = $('<div>', {'class': 'controlsContainer ' + containerClass}).appendTo($p);

        for(var control in controls) $control($e, itemClass, control, controls[control]);

        $('.control', $e).first().addClass('selected');
    }

    function $control($p, type, name, handler) {
        var $e = $('<a>', {'class': 'control ' + type, href: '#'}).text(name).on('click', function(e) {
            e.preventDefault();

            $e.siblings().removeClass('selected');
            $e.addClass('selected');

            handler(e);
        }).appendTo($p);
    }

    function createChart($p, providers) {
        var $c = $('<canvas>', {'class': 'chart'}).attr({width: 750, height: 400}).appendTo($p);
        var ctx = $c[0].getContext('2d');
        var data = getData(providers);
        var options = {
            datasetFill: false
        };

        new Chart(ctx).Line(data, options);
    }

    function createLegend($p, providers) {
        var providerNames = getProviderNames(providers).sort();
        var $table = $('<table>', {'class': 'legend'}).appendTo($p);
        var $header = $('<tr>').appendTo($table);

        $('<th>', {'class': 'colorLegend'}).appendTo($header);
        $('<th>', {'class': 'cdn'}).text('CDN').appendTo($header);
        $('<th>', {'class': 'category'}).text('Latency').appendTo($header);

        providerNames.map(function(name) {
            var $row = $('<tr>').appendTo($table);
            var lowerName = name.toLowerCase();

            $('<td>', {'class': 'color ' + lowerName}).css('background-color', getColor(lowerName)).appendTo($row);
            $('<td>', {'class': 'name ' + lowerName}).text(name).appendTo($row);
            $('<td>', {'class': 'value ' + lowerName}).appendTo($row);
        });
    }

    function getData(providers) {
        return {
            labels: getLabels(providers),
            datasets: getDatasets(providers)
        };
    }

    function getProviderNames(providers) {
        return unique(providers.map(prop('name')).map(getProviderName));
    }

    function getLabels(providers) {
        return providers[0].data.map(prop('x'));
    }

    function getDatasets(providers) {
        var pointColor = '#222';

        return providers.map(function(provider) {
            return {
                strokeColor: getColor(getProviderName(provider.name)),
                pointColor: pointColor,
                pointStrokeColor: pointColor,
                data: provider.data.map(prop('y'))
            };
        });
    }

    function getProviderName(fullname) {
        return fullname.split(' ')[0];
    }

    function getColor(name) {
        if(!name) return console.warn('getColor is missing name parameter');

        name = name.toLowerCase();
        var colors = {
            jsdelivr: '#b00',
            yandex: 'green',
            microsoft: 'blue',
            cdnjs: '#c64012',
            google: '#333',
            'jquery(mt)': 'red'
        };

        if(name in colors) return colors[name];

        console.warn('Failed to get a color for ', name);
    }

    function unique(arr) {
        var ret = {};

        arr.forEach(function(v) {
            ret[v] = true;
        });

        return Object.keys(ret);
    }

    function prop(name) {
        return function(v) {
            return v[name];
        };
    }
}
<commit_msg>Add TODOs<commit_after>$(main);

function main() {
    // TODO: load json based on control status (types, ranges, categories)
    // TODO: figure out how to deal with this (file for each permutation?)
    $.getJSON('./data.json', function(providers) {
        var $e = $('.latencies');

        createControls($e);
        createChart($e, providers);
        createLegend($e, providers);
    });

    function createControls($p) {
        var $e = $('<div>', {'class': 'controls'}).appendTo($p);

        createTypes($e);
        createRanges($e);
        createCategories($e);
    }

    function createTypes($p) {
        $controls($p, 'types', 'type', {
            'ping': function() {
                console.log('should show ping now');
            },
            'http': function() {
                console.log('should show http now');
            },
            'https': function() {
                console.log('should show https now');
            }
        });
    }

    function createRanges($p) {
        $controls($p, 'ranges', 'range', {
            '1 day': function() {
                console.log('change to 1 day view');
            },
            '7 days': function() {
                console.log('change to 7 days view');
            },
            '30 days': function() {
                console.log('change to 30 days view');
            }
        });
    }

    function createCategories($p) {
        $controls($p, 'categories', 'category', {
            'latency': function() {
                console.log('change to latency view');
            },
            'uptime': function() {
                console.log('change to uptime view');
            }
        });
    }

    function $controls($p, containerClass, itemClass, controls) {
        var $e = $('<div>', {'class': 'controlsContainer ' + containerClass}).appendTo($p);

        for(var control in controls) $control($e, itemClass, control, controls[control]);

        $('.control', $e).first().addClass('selected');
    }

    function $control($p, type, name, handler) {
        var $e = $('<a>', {'class': 'control ' + type, href: '#'}).text(name).on('click', function(e) {
            e.preventDefault();

            $e.siblings().removeClass('selected');
            $e.addClass('selected');

            handler(e);
        }).appendTo($p);
    }

    function createChart($p, providers) {
        var $c = $('<canvas>', {'class': 'chart'}).attr({width: 750, height: 400}).appendTo($p);
        var ctx = $c[0].getContext('2d');
        var data = getData(providers);
        var options = {
            datasetFill: false
        };

        new Chart(ctx).Line(data, options);
    }

    function createLegend($p, providers) {
        var providerNames = getProviderNames(providers).sort();
        var $table = $('<table>', {'class': 'legend'}).appendTo($p);
        var $header = $('<tr>').appendTo($table);

        $('<th>', {'class': 'colorLegend'}).appendTo($header);
        $('<th>', {'class': 'cdn'}).text('CDN').appendTo($header);
        $('<th>', {'class': 'category'}).text('Latency').appendTo($header);

        providerNames.map(function(name) {
            var $row = $('<tr>').appendTo($table);
            var lowerName = name.toLowerCase();

            $('<td>', {'class': 'color ' + lowerName}).css('background-color', getColor(lowerName)).appendTo($row);
            $('<td>', {'class': 'name ' + lowerName}).text(name).appendTo($row);
            $('<td>', {'class': 'value ' + lowerName}).appendTo($row);
        });
    }

    function getData(providers) {
        return {
            labels: getLabels(providers),
            datasets: getDatasets(providers)
        };
    }

    function getProviderNames(providers) {
        return unique(providers.map(prop('name')).map(getProviderName));
    }

    function getLabels(providers) {
        return providers[0].data.map(prop('x'));
    }

    function getDatasets(providers) {
        var pointColor = '#222';

        return providers.map(function(provider) {
            return {
                strokeColor: getColor(getProviderName(provider.name)),
                pointColor: pointColor,
                pointStrokeColor: pointColor,
                data: provider.data.map(prop('y'))
            };
        });
    }

    function getProviderName(fullname) {
        return fullname.split(' ')[0];
    }

    function getColor(name) {
        if(!name) return console.warn('getColor is missing name parameter');

        name = name.toLowerCase();
        var colors = {
            jsdelivr: '#b00',
            yandex: 'green',
            microsoft: 'blue',
            cdnjs: '#c64012',
            google: '#333',
            'jquery(mt)': 'red'
        };

        if(name in colors) return colors[name];

        console.warn('Failed to get a color for ', name);
    }

    function unique(arr) {
        var ret = {};

        arr.forEach(function(v) {
            ret[v] = true;
        });

        return Object.keys(ret);
    }

    function prop(name) {
        return function(v) {
            return v[name];
        };
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Sam Wilson <tecywiz121@gmail.com>
 *
 * This file is part of SketchWith.Us.
 *
 * SketchWith.Us is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SketchWith.Us is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with SketchWith.Us.  If not, see <http://www.gnu.org/licenses/>.
 */
(function(global) {
    'use strict';

    var DrawingArea = function DrawingArea(canvas) {
        this._canvas = canvas;
        this._ctx = canvas.getContext('2d');

        this._enabled = false;

        var that = this;
        canvas.addEventListener('mouseup',
            function(evt) { return that._onmouseup(evt); });
        canvas.addEventListener('mousedown',
            function(evt) { return that._onmousedown(evt); });
        canvas.addEventListener('mousemove',
            function(evt) { that._onmousemove(evt); });
    };

    DrawingArea.prototype._getMouseCoords = function _getMouseCoords(evt) {
        var mouseX, mouseY;
        if (typeof(evt.offsetX) !== 'undefined') {
            mouseX = evt.offsetX;
            mouseY = evt.offsetY;
        } else if (typeof(evt.layerX) !== 'undefined') {
            mouseX = evt.layerX;
            mouseY = evt.layerY;
        }
        return [mouseX, mouseY];
    };

    DrawingArea.prototype._onmousedown = function _onmousedown(evt) {
        if (!this._enabled) { return; }
        var point = this._getMouseCoords(evt);
        this._path = [point];

        // TODO: Start a timer to report partial strokes
    };

    DrawingArea.prototype._onmouseup = function _onmouseup(evt) {
        if (!this._enabled) { return; }
        var point = this._getMouseCoords(evt);
        this._drawPoint(point[0], point[1]);

        if (this.onstroke) {
            this.onstroke(this._path);
        }
    };

    DrawingArea.prototype._onmousemove = function _onmousemove(evt) {
        if (!this._enabled) { return; }
        if (evt.buttons !== 1) {
            return;
        }

        var point = this._getMouseCoords(evt);
        this._drawPoint(point[0], point[1]);
    };

    DrawingArea.prototype._drawPoint = function _drawPoint(mouseX, mouseY) {
        var lastMouse = this._path[this._path.length - 1];
        this._ctx.beginPath();
        this._ctx.moveTo(lastMouse[0], lastMouse[1]);
        this._ctx.lineTo(mouseX, mouseY);
        this._ctx.stroke();
        this._path.push([mouseX, mouseY]);
    };

    DrawingArea.prototype.start = function start() { this._enabled = true; };
    DrawingArea.prototype.stop = function stop() { this._enabled = false; };

    DrawingArea.prototype.clear = function clear() {
        this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
        this._path = [];
    };

    var SketchTableLog = function SketchTableLog(target) {
        this._el = $(target);
        this._scroll = this._el.parent('.tab-content');
    };

    SketchTableLog.prototype.chat = function chat(username, msg) {
        var $user = $('').text(username),
            $msg = $('').text(msg),
            $div = $('
').append($user, $msg);

        this._write($div);
    };

    SketchTableLog.prototype.control = function control(msg) {
        var $msg = $('').text(msg),
            $div = $('
').append($msg);
        this._write($div);
    };

    SketchTableLog.prototype._write = function _write(element) {
        this._el.append(element);

        if (this._el.is('.active')) {
            this._scroll.animate({ scrollTop: this._el.height() }, 'slow');
        }
    };

    var PlayerList = function PlayerList(chatLog, target) {
        this._el = $(target);
        this._chat = chatLog;
        this._players = {};
    };

    PlayerList.prototype.joined = function joined(player) {
        this._chat.control(player + ' has joined the table');

        if (!(player in this._players)) {
            var $li = $('
').text(player);

            this._players[player] = $li;
            this._el.append($li);
        }
    };

    PlayerList.prototype.departed = function departed(player, disconnected) {
        if (disconnected) {
            this._chat.control(player + ' has disconnected');
        } else {
            this._chat.control(player + ' has left the table');
        }

        var $li = this._players[player];
        delete this._players[player];
        $li.remove();
    };

    PlayerList.prototype.clear = function clear() {
        var x = this._players;
        this._players = {};
        for (var key in x) {
            x[key].remove();
        }
    };

    var SketchTable = function SketchTable(target) {
        this._root = $(target);
        this._guess_form = this._root.find('.guess-form');
        this._draw_controls = this._root.find('.draw-controls');
        this._draw_word = this._draw_controls.find('.canvas-word');
        this._btn_guess = this._guess_form.find('.canvas-guess');
        this._btn_skip = this._guess_form.find('.canvas-skip');
        this._btn_pass = this._draw_controls.find('.canvas-pass');

        /* Set up skip/pass buttons */
        var that = this;
        this._btn_pass.click(function(evt) { return that._onpass(evt); });
        this._btn_guess.click(function(evt) { return that._onguess(evt); });
        this._btn_skip.click(function(evt) { return that._onskip(evt); });

        /* Initialize the drawing area */
        this._drawing = new DrawingArea(this._root.find('.the-canvas').get(0));
        this._drawing.onstroke = function(path) { console.log(path); };

        /* Initialize the chat log */
        this._chat = new SketchTableLog(this._root.find('.chat-log'));

        /* Initialize the players list */
        this._players = new PlayerList(this._chat,
                                        this._root.find('.player-list'));
    };

    SketchTable.prototype._onpass = function _onpass(evt) {
        this.pass();
        return false;
    };

    SketchTable.prototype._onguess = function _onguess(evt) {
        console.log(evt);
        return false;
    };

    SketchTable.prototype._onskip = function _onskip(evt) {
        console.log(evt);
        return false;
    };

    SketchTable.prototype._log = function _log() {
        return console.log.apply(console, arguments);
    };

    SketchTable.prototype._send = function _send(obj) {
        this._log('Sending:', obj);
        this._socket.send(JSON.stringify(obj));
    };

    SketchTable.prototype._onopen = function _onopen(evt) {
        this._log('Connecting');
        this._players.clear();

        /* Restablish State */
        if (typeof(this._player_name) !== 'undefined') {
            this._chat.control('Registering as ' + this._player_name);
            this._send({verb: 'CONNECT', player_name: this._player_name});
        }

        if (typeof(this._table) !== 'undefined') {
            this.join(this._table);
        }
    };

    SketchTable.prototype._onmessage = function _onmessage(evt) {
        var that = this;
        if (typeof(evt.data) === 'string') {
            this._processMessage(evt.data);
        } else {
            var f = new FileReader();
            f.addEventListener('loadend',
                function() { that._processMessage(f.result); });
            f.readAsText(evt.data);
        }
    };

    SketchTable.prototype._processMessage = function _processMessage(text) {
        try {
            var obj = JSON.parse(text);
            this._log(obj);
        } catch (e) {
            this._log('Error while parsing JSON:', e);
            this._log(text);
            return;
        }

        switch (obj.verb.toUpperCase()) {
        case 'KEEPALIVE':
            break;
        case 'JOINED':
            this._players.joined(obj.player_name);
            break;
        case 'DEPARTED':
            this._players.departed(obj.player_name, obj.disconnected);
            break;
        case 'PASSED':
            this._passed(obj.player_name, obj.word);
            break;
        }
    };

    SketchTable.prototype.login = function login(to, player_name) {
        this._url = to;
        this._player_name = player_name;

        var ws = new ReconnectingWebSocket(this._url);

        var that = this;
        ws.onopen = function(evt) { that._onopen(evt); };
        ws.onmessage = function(evt) { that._onmessage(evt); };

        this._socket = ws;
    };

    SketchTable.prototype.join = function join(table) {
        this._table = table;

        if (this._socket.readyState === WebSocket.OPEN) {
            this._chat.control('Joining table ' + table);
            this._send({verb: 'JOIN', table: table});
        }
    };

    SketchTable.prototype.leave = function leave() {
        delete this._table;
        this._send({verb: 'LEAVE'});
        this._players.clear();
    };

    SketchTable.prototype.pass = function pass() {
        this._send({verb: 'PASS'});
    };

    SketchTable.prototype._passed = function _passed(player_name, word) {
        // Print the active player in the log
        var possessive = player_name + "'s";
        if (player_name.slice(-1) === 's') {
            possessive = _player_name + "'";
        }
        this._chat.control('It is ' + possessive + ' turn');

        // Clear the drawing area
        this._drawing.clear();

        if (this._player_name === player_name && typeof(word) !== 'undefined') {
            // If we're the active player, enable drawing.
            this._drawing.start();

            this._draw_word.text(word);

            this._guess_form.hide();
            this._draw_controls.show();
        } else {
            // If we're not the active player, disable everything.
            this._drawing.stop();

            this._draw_controls.hide();
            this._guess_form.show();
        }
    };

    global.SketchTable = SketchTable;
}(this));

$(function() {
    'use strict';

    var $modal = $('#login-modal'),
        $btn = $('#login-button'),
        $name = $('#login-form-name'),
        $table = $('#login-form-table');

    var game = new SketchTable('.sketch-row');

    $btn.click(function(e) {
        var name = $name.val(),
            table = $table.val();

        var good = true;

        /* Check for valid inputs */
        if (name.length > 0) {
            $name.parent('.form-group').removeClass('has-error');
        } else {
            $name.parent('.form-group').addClass('has-error');
            good = false;
        }

        if (table.length > 0) {
            $table.parent('.form-group').removeClass('has-error');
        } else {
            $table.parent('.form-group').addClass('has-error');
            good = false;
        }

        if (!good) {
            return false;
        }
        $modal.modal('hide');

        /* Get the WebSocket path */
        var loc = window.location, new_uri;
        if (loc.protocol === 'https') {
            new_uri = 'wss';
        } else {
            new_uri = 'ws';
        }

        new_uri += '://' + loc.host + '/game';

        /* Perform the login and join */
        game.login(new_uri, name);
        game.join(table);
        return false;
    });

    $modal.modal({
        backdrop: 'static',
        keyboard: false});

});
<commit_msg>Fix drawing when canvas not at 100%<commit_after>/*
 * Copyright 2014 Sam Wilson <tecywiz121@gmail.com>
 *
 * This file is part of SketchWith.Us.
 *
 * SketchWith.Us is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SketchWith.Us is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with SketchWith.Us.  If not, see <http://www.gnu.org/licenses/>.
 */
(function(global) {
    'use strict';

    var DrawingArea = function DrawingArea(canvas) {
        this._canvas = canvas;
        this._ctx = canvas.getContext('2d');

        this._enabled = false;

        var that = this;
        canvas.addEventListener('mouseup',
            function(evt) { return that._onmouseup(evt); });
        canvas.addEventListener('mousedown',
            function(evt) { return that._onmousedown(evt); });
        canvas.addEventListener('mousemove',
            function(evt) { that._onmousemove(evt); });
    };

    DrawingArea.prototype._getMouseCoords = function _getMouseCoords(evt) {
        var mouseX, mouseY;
        if (typeof(evt.offsetX) !== 'undefined') {
            mouseX = evt.offsetX;
            mouseY = evt.offsetY;
        } else if (typeof(evt.layerX) !== 'undefined') {
            mouseX = evt.layerX;
            mouseY = evt.layerY;
        }

        var $canvas = $(this._canvas);
        var realW = $canvas.width(),
            realH = $canvas.height(),
            attrW = $canvas.attr('width'),
            attrH = $canvas.attr('height');

        var xRatio = attrW / realW,
            yRatio = attrH / realH;

        return [mouseX * xRatio, mouseY * yRatio];
    };

    DrawingArea.prototype._onmousedown = function _onmousedown(evt) {
        if (!this._enabled) { return; }
        var point = this._getMouseCoords(evt);
        this._path = [point];

        // TODO: Start a timer to report partial strokes
    };

    DrawingArea.prototype._onmouseup = function _onmouseup(evt) {
        if (!this._enabled) { return; }
        var point = this._getMouseCoords(evt);
        this._drawPoint(point[0], point[1]);

        if (this.onstroke) {
            this.onstroke(this._path);
        }
    };

    DrawingArea.prototype._onmousemove = function _onmousemove(evt) {
        if (!this._enabled) { return; }
        if (evt.buttons !== 1) {
            return;
        }

        var point = this._getMouseCoords(evt);
        this._drawPoint(point[0], point[1]);
    };

    DrawingArea.prototype._drawPoint = function _drawPoint(mouseX, mouseY) {
        var lastMouse = this._path[this._path.length - 1];
        this._ctx.beginPath();
        this._ctx.moveTo(lastMouse[0], lastMouse[1]);
        this._ctx.lineTo(mouseX, mouseY);
        this._ctx.stroke();
        this._path.push([mouseX, mouseY]);
    };

    DrawingArea.prototype.start = function start() { this._enabled = true; };
    DrawingArea.prototype.stop = function stop() { this._enabled = false; };

    DrawingArea.prototype.clear = function clear() {
        this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
        this._path = [];
    };

    var SketchTableLog = function SketchTableLog(target) {
        this._el = $(target);
        this._scroll = this._el.parent('.tab-content');
    };

    SketchTableLog.prototype.chat = function chat(username, msg) {
        var $user = $('').text(username),
            $msg = $('').text(msg),
            $div = $('
').append($user, $msg);

        this._write($div);
    };

    SketchTableLog.prototype.control = function control(msg) {
        var $msg = $('').text(msg),
            $div = $('
').append($msg);
        this._write($div);
    };

    SketchTableLog.prototype._write = function _write(element) {
        this._el.append(element);

        if (this._el.is('.active')) {
            this._scroll.animate({ scrollTop: this._el.height() }, 'slow');
        }
    };

    var PlayerList = function PlayerList(chatLog, target) {
        this._el = $(target);
        this._chat = chatLog;
        this._players = {};
    };

    PlayerList.prototype.joined = function joined(player) {
        this._chat.control(player + ' has joined the table');

        if (!(player in this._players)) {
            var $li = $('
').text(player);

            this._players[player] = $li;
            this._el.append($li);
        }
    };

    PlayerList.prototype.departed = function departed(player, disconnected) {
        if (disconnected) {
            this._chat.control(player + ' has disconnected');
        } else {
            this._chat.control(player + ' has left the table');
        }

        var $li = this._players[player];
        delete this._players[player];
        $li.remove();
    };

    PlayerList.prototype.clear = function clear() {
        var x = this._players;
        this._players = {};
        for (var key in x) {
            x[key].remove();
        }
    };

    var SketchTable = function SketchTable(target) {
        this._root = $(target);
        this._guess_form = this._root.find('.guess-form');
        this._draw_controls = this._root.find('.draw-controls');
        this._draw_word = this._draw_controls.find('.canvas-word');
        this._btn_guess = this._guess_form.find('.canvas-guess');
        this._btn_skip = this._guess_form.find('.canvas-skip');
        this._btn_pass = this._draw_controls.find('.canvas-pass');

        /* Set up skip/pass buttons */
        var that = this;
        this._btn_pass.click(function(evt) { return that._onpass(evt); });
        this._btn_guess.click(function(evt) { return that._onguess(evt); });
        this._btn_skip.click(function(evt) { return that._onskip(evt); });

        /* Initialize the drawing area */
        this._drawing = new DrawingArea(this._root.find('.the-canvas').get(0));
        this._drawing.onstroke = function(path) { console.log(path); };

        /* Initialize the chat log */
        this._chat = new SketchTableLog(this._root.find('.chat-log'));

        /* Initialize the players list */
        this._players = new PlayerList(this._chat,
                                        this._root.find('.player-list'));
    };

    SketchTable.prototype._onpass = function _onpass(evt) {
        this.pass();
        return false;
    };

    SketchTable.prototype._onguess = function _onguess(evt) {
        console.log(evt);
        return false;
    };

    SketchTable.prototype._onskip = function _onskip(evt) {
        console.log(evt);
        return false;
    };

    SketchTable.prototype._log = function _log() {
        return console.log.apply(console, arguments);
    };

    SketchTable.prototype._send = function _send(obj) {
        this._log('Sending:', obj);
        this._socket.send(JSON.stringify(obj));
    };

    SketchTable.prototype._onopen = function _onopen(evt) {
        this._log('Connecting');
        this._players.clear();

        /* Restablish State */
        if (typeof(this._player_name) !== 'undefined') {
            this._chat.control('Registering as ' + this._player_name);
            this._send({verb: 'CONNECT', player_name: this._player_name});
        }

        if (typeof(this._table) !== 'undefined') {
            this.join(this._table);
        }
    };

    SketchTable.prototype._onmessage = function _onmessage(evt) {
        var that = this;
        if (typeof(evt.data) === 'string') {
            this._processMessage(evt.data);
        } else {
            var f = new FileReader();
            f.addEventListener('loadend',
                function() { that._processMessage(f.result); });
            f.readAsText(evt.data);
        }
    };

    SketchTable.prototype._processMessage = function _processMessage(text) {
        try {
            var obj = JSON.parse(text);
            this._log(obj);
        } catch (e) {
            this._log('Error while parsing JSON:', e);
            this._log(text);
            return;
        }

        switch (obj.verb.toUpperCase()) {
        case 'KEEPALIVE':
            break;
        case 'JOINED':
            this._players.joined(obj.player_name);
            break;
        case 'DEPARTED':
            this._players.departed(obj.player_name, obj.disconnected);
            break;
        case 'PASSED':
            this._passed(obj.player_name, obj.word);
            break;
        }
    };

    SketchTable.prototype.login = function login(to, player_name) {
        this._url = to;
        this._player_name = player_name;

        var ws = new ReconnectingWebSocket(this._url);

        var that = this;
        ws.onopen = function(evt) { that._onopen(evt); };
        ws.onmessage = function(evt) { that._onmessage(evt); };

        this._socket = ws;
    };

    SketchTable.prototype.join = function join(table) {
        this._table = table;

        if (this._socket.readyState === WebSocket.OPEN) {
            this._chat.control('Joining table ' + table);
            this._send({verb: 'JOIN', table: table});
        }
    };

    SketchTable.prototype.leave = function leave() {
        delete this._table;
        this._send({verb: 'LEAVE'});
        this._players.clear();
    };

    SketchTable.prototype.pass = function pass() {
        this._send({verb: 'PASS'});
    };

    SketchTable.prototype._passed = function _passed(player_name, word) {
        // Print the active player in the log
        var possessive = player_name + "'s";
        if (player_name.slice(-1) === 's') {
            possessive = _player_name + "'";
        }
        this._chat.control('It is ' + possessive + ' turn');

        // Clear the drawing area
        this._drawing.clear();

        if (this._player_name === player_name && typeof(word) !== 'undefined') {
            // If we're the active player, enable drawing.
            this._drawing.start();

            this._draw_word.text(word);

            this._guess_form.hide();
            this._draw_controls.show();
        } else {
            // If we're not the active player, disable everything.
            this._drawing.stop();

            this._draw_controls.hide();
            this._guess_form.show();
        }
    };

    global.SketchTable = SketchTable;
}(this));

$(function() {
    'use strict';

    var $modal = $('#login-modal'),
        $btn = $('#login-button'),
        $name = $('#login-form-name'),
        $table = $('#login-form-table');

    var game = new SketchTable('.sketch-row');

    $btn.click(function(e) {
        var name = $name.val(),
            table = $table.val();

        var good = true;

        /* Check for valid inputs */
        if (name.length > 0) {
            $name.parent('.form-group').removeClass('has-error');
        } else {
            $name.parent('.form-group').addClass('has-error');
            good = false;
        }

        if (table.length > 0) {
            $table.parent('.form-group').removeClass('has-error');
        } else {
            $table.parent('.form-group').addClass('has-error');
            good = false;
        }

        if (!good) {
            return false;
        }
        $modal.modal('hide');

        /* Get the WebSocket path */
        var loc = window.location, new_uri;
        if (loc.protocol === 'https') {
            new_uri = 'wss';
        } else {
            new_uri = 'ws';
        }

        new_uri += '://' + loc.host + '/game';

        /* Perform the login and join */
        game.login(new_uri, name);
        game.join(table);
        return false;
    });

    $modal.modal({
        backdrop: 'static',
        keyboard: false});

});
<|endoftext|>


<commit_before>mini.parse();
var formRole = new mini.Form("formRole");
var winRole = mini.get("winRole");
var treeRole = mini.get("treeRole");
var selectRole = undefined;
function OpenRoleAdd() {
    if (!selectRole) {
        mini.alert("ѡ񸸽ɫ");
    }
    OpenAddForm(formRole, winRole, "ӽɫ", "icon-add", function () {
        var parRoleId = selectRole.id;
        var parRoleName = selectRole.text;
        mini.get("txtParentId").setValue(parRoleId);
        $('#spanParentName').html(parRoleName);
    });
}
function onRoleSelect(e) {
    selectRole = e.node;
}<commit_msg>转为utf8格式<commit_after>mini.parse();
var formRole = new mini.Form("formRole");
var winRole = mini.get("winRole");
var treeRole = mini.get("treeRole");
var selectRole = undefined;
function OpenRoleAdd() {
    if (!selectRole) {
        mini.alert("请选择父角色");
    }
    OpenAddForm(formRole, winRole, "添加角色", "icon-add", function () {
        var parRoleId = selectRole.id;
        var parRoleName = selectRole.text;
        mini.get("txtParentId").setValue(parRoleId);
        $('#spanParentName').html(parRoleName);
    });
}
function onRoleSelect(e) {
    selectRole = e.node;
}<|endoftext|>


<commit_before>var socket_name = 'http://' + document.domain + ':' + location.port;
var socket = io.connect(socket_name);
var gamemode = null,
    input_type = null;
var username = null;

function main() {
    // create, initiate and append game canvas
    username = window.prompt("Enter a username", "Username");
    init(); // initiate game objects
    $("#container").hide();
    //$(document).keydown(keyDown); //add keylisteners
    //$(document).keyup(keyUp);
    //draw();
}

function init() {
    socket.emit('add user', username);
}

function fillNES() {
    var a_button = $('');
    var b_button = $('');
    var d_pad = $('');
    console.log("here");
    $("#button_layout").append(a_button);
    $("#button_layout").append(b_button);
    $("#button_layout").append(d_pad);
    $("#A_button").click(function() {
        socket.emit("sendInput", {
            user_input: "A"
        });
    });
    $("#B_button").click(function() {
        socket.emit("sendInput", {
            user_input: "B"
        });
    });
    $("#D_pad").click(function(e) {
        var offset = $(this).offset();
        var width = $(this).width();
        var height = $(this).height();
        var relativeX = (e.pageX - offset.left);
        var relativeY = (e.pageY - offset.top);
        var forceX = ((width/2)-relativeX);
        var forceY = ((height/2)-relativeY);
        var command = "";
        if (forceX>0 && Math.abs(forceX)>Math.abs(forceY)) {
            command = "left";
        }
        if (forceX<0 && (Math.abs(forceX))>Math.abs(forceY)) {
            command = "right";
        }
        if(forceY<0 && (Math.abs(forceY))>Math.abs(forceX)){
            command = "down";
        }
        if(forceY>0 && Math.abs(forceY)>Math.abs(forceX)){
            command="up";
        }
        socket.emit("sendInput", {
            user_input: command
        });
    });
}

function fillSNES() {
    fillNES();
    var x_button = $('');
    var y_button = $('');
    $("#button_layout").append(x_button);
    $("#button_layout").append(y_button);
}
function fillKeyboard(){
    $("#container").removeClass('hidden');
}
socket.on('initialize', function(data) {
    console.log(data);
    gamemode = data.mode ? 'chaos' : 'democracy';
    input_type = data.input_type;
    console.log(input_type);
    switch (input_type) {
        case ('NES'):
            {
                fillNES();
                break;
            }
        case ('SNES'):
            {
                fillSNES();
                break;
            }
        case ('Full Keyboard'):
            {
                fillKeyboard();
                break;
            }
        default:
            {
                break;
            }
    }
});
window.beforeunload = function() {
    if (username != null) socket.emit("disconnect", username);
}
main();<commit_msg>Latest Commit from sublime text<commit_after>var socket_name = 'http://' + document.domain + ':' + location.port;
var socket = io.connect(socket_name);
var gamemode = null,
    input_type = null;
var username = null;

function main() {
    // create, initiate and append game canvas
    username = window.prompt("Enter a username", "Username");
    init(); // initiate game objects
    $("#container").hide();
    //$(document).keydown(keyDown); //add keylisteners
    //$(document).keyup(keyUp);
    //draw();
}

function init() {
    socket.emit('add user', username);
}

function fillNES() {
    var a_button = $('');
    var b_button = $('');
    var d_pad = $('');
    console.log("here");
    $("#button_layout").append(a_button);
    $("#button_layout").append(b_button);
    $("#button_layout").append(d_pad);
    $("#A_button").click(function() {
        socket.emit("sendInput", {
            user_input: "A"
        });
    });
    $("#B_button").click(function() {
        socket.emit("sendInput", {
            user_input: "B"
        });
    });
    $("#D_pad").click(function(e) {
        var offset = $(this).offset();
        var width = $(this).width();
        var height = $(this).height();
        var relativeX = (e.pageX - offset.left);
        var relativeY = (e.pageY - offset.top);
        var forceX = ((width/2)-relativeX);
        var forceY = ((height/2)-relativeY);
        var command = "";
        if (forceX>0 && Math.abs(forceX)>Math.abs(forceY)) {
            command = "left";
        }
        if (forceX<0 && (Math.abs(forceX))>Math.abs(forceY)) {
            command = "right";
        }
        if(forceY<0 && (Math.abs(forceY))>Math.abs(forceX)){
            command = "down";
        }
        if(forceY>0 && Math.abs(forceY)>Math.abs(forceX)){
            command="up";
        }
        socket.emit("sendInput", {
            user_input: command
        });
    });
}

function fillSNES() {
    fillNES();
    var x_button = $('');
    var y_button = $('');
    $("#XY_layout").append(x_button);
    $("#XY_layout").append(y_button);
}
function fillKeyboard(){
    $("#container").removeClass('hidden');
}
socket.on('initialize', function(data) {
    console.log(data);
    gamemode = data.mode ? 'chaos' : 'democracy';
    input_type = data.input_type;
    console.log(input_type);
    switch (input_type) {
        case ('NES'):
            {
                fillNES();
                break;
            }
        case ('SNES'):
            {
                fillSNES();
                break;
            }
        case ('Full Keyboard'):
            {
                fillKeyboard();
                break;
            }
        default:
            {
                break;
            }
    }
});
window.beforeunload = function() {
    if (username != null) socket.emit("disconnect", username);
}
main();<|endoftext|>