<commit_before>var game = {
  language: window.location.hash.substring(1) || 'en',
  level: parseInt(localStorage.level, 10) || 0,
  answers: (localStorage.answers && JSON.parse(localStorage.answers)) || {},
  solved: (localStorage.solved && JSON.parse(localStorage.solved)) || [],
  user: localStorage.user || '',

  start: function() {
    game.translate();

    $('#level-counter .total').text(levels.length);
    $('#editor').show();
    $('#share').hide();

    if (!localStorage.user) {
      game.user = '' + (new Date()).getTime() + Math.random().toString(36).slice(1);
      localStorage.setItem('user', game.user);
    }

    this.setHandlers();
    this.loadMenu();
    game.loadLevel(levels[game.level]);
  },

  setHandlers: function() {
    $('#next').on('click', function() {
      $('#code').focus();

      if ($(this).hasClass('disabled')) {
        if (!$('.frog').hasClass('animated')) {
          game.tryagain();
        }

        return;
      }

      $('.frog').addClass('animated bounceOutUp');
      $('.arrow, #next').addClass('disabled');

      setTimeout(function() {
        if (game.level >= levels.length - 1) {
          game.win();
        } else {
          game.next();
        }
      }, 2000);
    });

    $('#code').on('keydown', function(e) {
      if (e.keyCode === 13) {

        if (e.ctrlKey || e.metaKey) {
          e.preventDefault();
          game.check();
          $('#next').click();
          return;
        }

        var max = $(this).data('lines');
        var code = $(this).val();
        var trim = code.trim();
        var codeLength = code.split('\n').length;
        var trimLength = trim.split('\n').length;

        if (codeLength >= max) {

          if (codeLength === trimLength) {
            e.preventDefault();
            $('#next').click();
          } else {
            $('#code').focus().val('').val(trim);
          }
        }
      }
    }).on('input', game.debounce(game.check, 500));

    $('#editor').on('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
      $(this).removeClass();
    });

    $('#labelReset').on('click', function() {
      var warningReset = messages.warningReset[game.language] || messages.warningReset.en;
      var r = confirm(warningReset);

      if (r) {
        game.level = 0;
        game.answers = {};
        game.solved = [];
        game.loadLevel(levels[0]);

        $('.level-marker').removeClass('solved');
      }
    });

    $(window).on('beforeunload', function() {
      game.saveAnswer();
      localStorage.setItem('level', game.level);
      localStorage.setItem('answers', JSON.stringify(game.answers));
      localStorage.setItem('solved', JSON.stringify(game.solved));
    }).on('hashchange', function() {
      game.language = window.location.hash.substring(1) || 'en';
      game.translate();

      $('#tweet iframe').remove();
      var html = 'Tweet ' +
                 'Follow @thomashpark';
      $('#tweet').html(html);
      twttr.widgets.load();

      if (game.language === 'en') {
        history.replaceState({}, document.title, './');
      }
    });
  },

  prev: function() {
    this.level--;

    var levelData = levels[this.level];
    this.loadLevel(levelData);
  },

  next: function() {
    this.level++;

    var levelData = levels[this.level];
    this.loadLevel(levelData);
  },

  loadMenu: function() {
    levels.forEach(function(level, i) {
      var levelMarker = $('').addClass('level-marker').attr('data-level', i).text(i+1);

      if ($.inArray(level.name, game.solved) !== -1) {
        levelMarker.addClass('solved');
      }

      levelMarker.appendTo('#levels');
    });

    $('.level-marker').on('click', function() {
      game.saveAnswer();

      var level = $(this).attr('data-level');
      game.level = parseInt(level, 10);
      game.loadLevel(levels[level]);
    });

    $('#level-indicator').on('click', function() {
      $('#levelsWrapper').toggle();
    });

    $('.arrow.left').on('click', function() {
      if ($(this).hasClass('disabled')) {
        return;
      }

      game.saveAnswer();
      game.prev();
    });

    $('.arrow.right').on('click', function() {
      if ($(this).hasClass('disabled')) {
        return;
      }

      game.saveAnswer();
      game.next();
    });
  },

  loadLevel: function(level) {
    $('#editor').show();
    $('#share').hide();
    $('#background, #pond').removeClass('wrap').attr('style', '').empty();
    $('#levelsWrapper').hide();
    $('.level-marker').removeClass('current').eq(this.level).addClass('current');
    $('#level-counter .current').text(this.level + 1);
    $('#before').text(level.before);
    $('#after').text(level.after);
    $('#next').addClass('disabled');

    var instructions = level.instructions[game.language] || level.instructions.en;
    $('#instructions').html(instructions);

    $('.arrow.disabled').removeClass('disabled');

    if (this.level === 0) {
      $('.arrow.left').addClass('disabled');
    }

    if (this.level === levels.length - 1) {
      $('.arrow.right').addClass('disabled');
    }

    var answer = game.answers[level.name];
    $('#code').val(answer).focus();

    this.loadDocs();

    var lines = Object.keys(level.style).length;
    $('#code').height(20 * lines).data("lines", lines);

    var string = level.board;
    var markup = '';
    var colors = {
      'g': 'green',
      'r': 'red',
      'y': 'yellow'
    };

    for (var i = 0; i < string.length; i++) {
      var c = string.charAt(i);
      var color = colors[c];

      var lilypad = $('
').addClass('lilypad ' + color).data('color', color);
      var frog = $('
').addClass('frog ' + color).data('color', color);

      $('
').addClass('bg').css(game.transform()).appendTo(lilypad);
      $('
').addClass('bg animated pulse infinite').appendTo(frog);

      $('#background').append(lilypad);
      $('#pond').append(frog);
    }

    var classes = level.classes;

    if (classes) {
      for (var rule in classes) {
        $(rule).addClass(classes[rule]);
      }
    }

    var selector = level.selector || '';
    $('#background ' + selector).css(level.style);

    game.applyStyles();
    game.check();
  },

  loadDocs: function() {
    $('#instructions code').each(function() {
      var code = $(this);
      var text = code.text();

      if (text in docs) {
        code.addClass('help');
        code.on('mouseenter', function(e) {
          if ($('#instructions .tooltip').length === 0) {
            var html = docs[text][game.language] || docs[text].en;
            var tooltipX = code.offset().left;
            var tooltipY = code.offset().top + code.height() + 13;
            $('

').html(html).css({top: tooltipY, left: tooltipX}).appendTo($('#instructions'));
          }
        }).on('mouseleave', function() {
          $('#instructions .tooltip').remove();
        });
      }
    });
  },

  applyStyles: function() {
    var level = levels[game.level];
    var code = $('#code').val();
    var selector = level.selector || '';
    $('#pond ' +  selector).attr('style', code);
    game.saveAnswer();
  },

  check: function(level) {
    if (typeof level === 'undefined') {
      level = levels[game.level];
    }

    game.applyStyles();

    var lilypads = {};
    var frogs = {};
    var correct = true;

    $('.frog').each(function() {
      var position = $(this).position();
      position.top = Math.floor(position.top);
      position.left = Math.floor(position.left);

      var key = JSON.stringify(position);
      var val = $(this).data('color');
      frogs[key] = val;
    });

    $('.lilypad').each(function() {
      var position = $(this).position();
      position.top = Math.floor(position.top);
      position.left = Math.floor(position.left);

      var key = JSON.stringify(position);
      var val = $(this).data('color');

      if (!(key in frogs) || frogs[key] !== val) {
        correct = false;
      }
    });

    if (correct) {
      ga('send', {
        hitType: 'event',
        eventCategory: level.name,
        eventAction: 'correct',
        eventLabel: $('#code').val()
      });

      if ($.inArray(level.name, game.solved) === -1) {
        game.solved.push(level.name);
      }

      $('[data-level=' + game.level + ']').addClass('solved');
      $('#next').removeClass('disabled');
    } else {
      ga('send', {
        hitType: 'event',
        eventCategory: level.name,
        eventAction: 'incorrect',
        eventLabel: $('#code').val()
      });

      $('#next').addClass('disabled');
    }
  },

  saveAnswer: function() {
    var level = levels[this.level];
    game.answers[level.name] = $('#code').val();
  },

  tryagain: function() {
    $('#editor').addClass('animated shake');
  },

  win: function() {
    var solution = $('#code').val();

    this.loadLevel(levelWin);

    $('#editor').hide();
    $('#code').val(solution);
    $('#share').show();
    $('.frog .bg').removeClass('pulse').addClass('bounce');
  },

  transform: function() {
    var scale = 1 + ((Math.random() / 5) - 0.2);
    var rotate = 360 * Math.random();

    return {'transform': 'scale(' + scale + ') rotate(' + rotate + 'deg)'};
  },

  translate: function() {
    document.title = messages.title[game.language] || messages.title.en;
    $('html').attr('lang', game.language);

    var level = levels[game.level];
    var instructions = level.instructions[game.language] || level.instructions.en;
    $('#instructions').html(instructions);
    game.loadDocs();

    $('.translate').each(function() {
      var label = $(this).attr('id');
      var text = messages[label][game.language] || messages[label].en;

      $('#' + label).text(text);
    });
  },

  debounce: function(func, wait, immediate) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) func.apply(context, args);
    };
  }
};

$(document).ready(function() {
  game.start();
});
<commit_msg>edit js/game.js to log data in the Firebase database<commit_after>var firebase = new Firebase('https://blinding-heat-5896.firebaseio.com/web/data');
var analytics = firebase.child('analytics');
var game = {
  language: window.location.hash.substring(1) || 'en',
  level: parseInt(localStorage.level, 10) || 0,
  answers: (localStorage.answers && JSON.parse(localStorage.answers)) || {},
  solved: (localStorage.solved && JSON.parse(localStorage.solved)) || [],
  user: localStorage.user || '',
  changed: false,

  start: function() {
    game.translate();

    $('#level-counter .total').text(levels.length);
    $('#editor').show();
    $('#share').hide();

    if (!localStorage.user) {
      game.user = '' + (new Date()).getTime() + Math.random().toString(36).slice(1);
      localStorage.setItem('user', game.user);
    }

    this.setHandlers();
    this.loadMenu();
    game.loadLevel(levels[game.level]);
  },

  setHandlers: function() {
    $('#next').on('click', function() {
      $('#code').focus();

      if ($(this).hasClass('disabled')) {
        if (!$('.frog').hasClass('animated')) {
          game.tryagain();
        }

        return;
      }

      $('.frog').addClass('animated bounceOutUp');
      $('.arrow, #next').addClass('disabled');

      setTimeout(function() {
        if (game.level >= levels.length - 1) {
          game.win();
        } else {
          game.next();
        }
      }, 2000);
    });

    $('#code').on('keydown', function(e) {
      if (e.keyCode === 13) {

        if (e.ctrlKey || e.metaKey) {
          e.preventDefault();
          game.check();
          $('#next').click();
          return;
        }

        var max = $(this).data('lines');
        var code = $(this).val();
        var trim = code.trim();
        var codeLength = code.split('\n').length;
        var trimLength = trim.split('\n').length;

        if (codeLength >= max) {

          if (codeLength === trimLength) {
            e.preventDefault();
            $('#next').click();
          } else {
            $('#code').focus().val('').val(trim);
          }
        }
      }
    }).on('input', game.debounce(game.check, 500))
    .on('input', function() {
      game.changed = true;
    });

    $('#editor').on('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
      $(this).removeClass();
    });

    $('#labelReset').on('click', function() {
      var warningReset = messages.warningReset[game.language] || messages.warningReset.en;
      var r = confirm(warningReset);

      if (r) {
        game.level = 0;
        game.answers = {};
        game.solved = [];
        game.loadLevel(levels[0]);

        $('.level-marker').removeClass('solved');
      }
    });

    $(window).on('beforeunload', function() {
      game.saveAnswer();
      localStorage.setItem('level', game.level);
      localStorage.setItem('answers', JSON.stringify(game.answers));
      localStorage.setItem('solved', JSON.stringify(game.solved));
    }).on('hashchange', function() {
      game.language = window.location.hash.substring(1) || 'en';
      game.translate();

      $('#tweet iframe').remove();
      var html = 'Tweet ' +
                 'Follow @thomashpark';
      $('#tweet').html(html);
      twttr.widgets.load();

      if (game.language === 'en') {
        history.replaceState({}, document.title, './');
      }
    });
  },

  prev: function() {
    this.level--;

    var levelData = levels[this.level];
    this.loadLevel(levelData);
  },

  next: function() {
    this.level++;

    var levelData = levels[this.level];
    this.loadLevel(levelData);
  },

  loadMenu: function() {
    levels.forEach(function(level, i) {
      var levelMarker = $('').addClass('level-marker').attr('data-level', i).text(i+1);

      if ($.inArray(level.name, game.solved) !== -1) {
        levelMarker.addClass('solved');
      }

      levelMarker.appendTo('#levels');
    });

    $('.level-marker').on('click', function() {
      game.saveAnswer();

      var level = $(this).attr('data-level');
      game.level = parseInt(level, 10);
      game.loadLevel(levels[level]);
    });

    $('#level-indicator').on('click', function() {
      $('#levelsWrapper').toggle();
    });

    $('.arrow.left').on('click', function() {
      if ($(this).hasClass('disabled')) {
        return;
      }

      game.saveAnswer();
      game.prev();
    });

    $('.arrow.right').on('click', function() {
      if ($(this).hasClass('disabled')) {
        return;
      }

      game.saveAnswer();
      game.next();
    });
  },

  loadLevel: function(level) {
    $('#editor').show();
    $('#share').hide();
    $('#background, #pond').removeClass('wrap').attr('style', '').empty();
    $('#levelsWrapper').hide();
    $('.level-marker').removeClass('current').eq(this.level).addClass('current');
    $('#level-counter .current').text(this.level + 1);
    $('#before').text(level.before);
    $('#after').text(level.after);
    $('#next').addClass('disabled');

    var instructions = level.instructions[game.language] || level.instructions.en;
    $('#instructions').html(instructions);

    $('.arrow.disabled').removeClass('disabled');

    if (this.level === 0) {
      $('.arrow.left').addClass('disabled');
    }

    if (this.level === levels.length - 1) {
      $('.arrow.right').addClass('disabled');
    }

    var answer = game.answers[level.name];
    $('#code').val(answer).focus();

    this.loadDocs();

    var lines = Object.keys(level.style).length;
    $('#code').height(20 * lines).data("lines", lines);

    var string = level.board;
    var markup = '';
    var colors = {
      'g': 'green',
      'r': 'red',
      'y': 'yellow'
    };

    for (var i = 0; i < string.length; i++) {
      var c = string.charAt(i);
      var color = colors[c];

      var lilypad = $('
').addClass('lilypad ' + color).data('color', color);
      var frog = $('
').addClass('frog ' + color).data('color', color);

      $('
').addClass('bg').css(game.transform()).appendTo(lilypad);
      $('
').addClass('bg animated pulse infinite').appendTo(frog);

      $('#background').append(lilypad);
      $('#pond').append(frog);
    }

    var classes = level.classes;

    if (classes) {
      for (var rule in classes) {
        $(rule).addClass(classes[rule]);
      }
    }

    var selector = level.selector || '';
    $('#background ' + selector).css(level.style);

    game.changed = false;
    game.applyStyles();
    game.check();
  },

  loadDocs: function() {
    $('#instructions code').each(function() {
      var code = $(this);
      var text = code.text();

      if (text in docs) {
        code.addClass('help');
        code.on('mouseenter', function(e) {
          if ($('#instructions .tooltip').length === 0) {
            var html = docs[text][game.language] || docs[text].en;
            var tooltipX = code.offset().left;
            var tooltipY = code.offset().top + code.height() + 13;
            $('

').html(html).css({top: tooltipY, left: tooltipX}).appendTo($('#instructions'));
          }
        }).on('mouseleave', function() {
          $('#instructions .tooltip').remove();
        });
      }
    });
  },

  applyStyles: function() {
    var level = levels[game.level];
    var code = $('#code').val();
    var selector = level.selector || '';
    $('#pond ' +  selector).attr('style', code);
    game.saveAnswer();
  },

  check: function() {
    game.applyStyles();

    var level = levels[game.level];
    var lilypads = {};
    var frogs = {};
    var correct = true;

    $('.frog').each(function() {
      var position = $(this).position();
      position.top = Math.floor(position.top);
      position.left = Math.floor(position.left);

      var key = JSON.stringify(position);
      var val = $(this).data('color');
      frogs[key] = val;
    });

    $('.lilypad').each(function() {
      var position = $(this).position();
      position.top = Math.floor(position.top);
      position.left = Math.floor(position.left);

      var key = JSON.stringify(position);
      var val = $(this).data('color');

      if (!(key in frogs) || frogs[key] !== val) {
        correct = false;
      }
    });

    console.log(game.changed);

    if (correct) {
      ga('send', {
        hitType: 'event',
        eventCategory: level.name,
        eventAction: 'correct',
        eventLabel: $('#code').val()
      });

      analytics.push({
        timeStamp: (new Date()).getTime(),
        user: game.user,
        levelName: level.name,
        changed: game.changed,
        input: $('#code').val(),
        result: 'correct'
      });

      if ($.inArray(level.name, game.solved) === -1) {
        game.solved.push(level.name);
      }

      $('[data-level=' + game.level + ']').addClass('solved');
      $('#next').removeClass('disabled');
    } else {
      ga('send', {
        hitType: 'event',
        eventCategory: level.name,
        eventAction: 'incorrect',
        eventLabel: $('#code').val()
      });

      analytics.push({
        timeStamp: (new Date()).getTime(),
        user: game.user,
        levelName: level.name,
        changed: game.changed,
        input: $('#code').val(),
        result: 'incorrect'
      });

      $('#next').addClass('disabled');
    }
  },

  saveAnswer: function() {
    var level = levels[this.level];
    game.answers[level.name] = $('#code').val();
  },

  tryagain: function() {
    $('#editor').addClass('animated shake');
  },

  win: function() {
    var solution = $('#code').val();

    this.loadLevel(levelWin);

    $('#editor').hide();
    $('#code').val(solution);
    $('#share').show();
    $('.frog .bg').removeClass('pulse').addClass('bounce');
  },

  transform: function() {
    var scale = 1 + ((Math.random() / 5) - 0.2);
    var rotate = 360 * Math.random();

    return {'transform': 'scale(' + scale + ') rotate(' + rotate + 'deg)'};
  },

  translate: function() {
    document.title = messages.title[game.language] || messages.title.en;
    $('html').attr('lang', game.language);

    var level = levels[game.level];
    var instructions = level.instructions[game.language] || level.instructions.en;
    $('#instructions').html(instructions);
    game.loadDocs();

    $('.translate').each(function() {
      var label = $(this).attr('id');
      var text = messages[label][game.language] || messages[label].en;

      $('#' + label).text(text);
    });
  },

  debounce: function(func, wait, immediate) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) func.apply(context, args);
    };
  }
};

$(document).ready(function() {
  game.start();
});<|endoftext|>


<commit_before>var tilesWithoutMines,
    tilesWithoutMinesCounter;

function addEventListenersOnCanvas(tiles, settings) {
    $('canvas').on('click', {tiles: tiles, settings: settings}, onTileLeftClick);
    $('canvas').on('contextmenu', {tiles: tiles, settings: settings}, onTileRightClick);
}

function removeEventListenersFromCanvas() {
    $('canvas').off('click', onTileLeftClick);
    $('canvas').off('contextmenu', onTileRightClick);
}

function onTileLeftClick(event) {
    var tiles = event.data.tiles,
        settings = event.data.settings,
        tile;

    // To enable only left mouse button click. Scroll is disabled
    if (event.button === 0) {
        tile = getClickedTile(event, tiles, settings);
        if (tile && !tile.isVisited && !tile.hasMineFlag) {
            showBehindTile(tile, tiles, settings);
        }
    }
}

function onTileRightClick(event) {
    var tiles = event.data.tiles,
        settings = event.data.settings,
        tile;

    // disable menu
    event.preventDefault();

    tile = getClickedTile(event, tiles, settings);
    if (tile && !tile.isVisited) {
        if (!tile.hasMineFlag) {
            tile.hasMineFlag = true;
            drawMineFlag(tile);
        }
        else {
            tile.hasMineFlag = false;
            drawSingleTile(tile, settings.tileSizeInPx, false);
        }
    }
}

function getClickedTile(event, tiles, settings) {
    var rect = canvas.getBoundingClientRect(),
        x = event.clientX - rect.left,
        y = event.clientY - rect.top,
        tile;

    tile = tiles.find(function (tile) {
        return tile.startXinPx + settings.tileSizeInPx > x &&
            tile.startYinPx + settings.tileSizeInPx > y;
    });

    return tile;
}

function showBehindTile(tile, tiles, settings) {
    if (tile.value === 0) {
        showAllTilesWithoutValue(tile.row, tile.col, tiles, settings);
    }
    else if (tile.value === '*') {
        gameOver(tiles, settings);
    }
    else {
        tile.isVisited = true;
        drawTileWithValue(tile, settings);
        countAndCheckForWin();
    }
}

function isInBoard(row, col, settings) {
    var rowInRange = 0 <= row && row < settings.difficulty.verticalTiles,
        colInRange = 0 <= col && col < settings.difficulty.horizontalTiles;
    return rowInRange && colInRange;
}

function showAllTilesWithoutValue(row, col, tiles, settings) {
    var currentTile;

    // if we are outside the board then stop
    if (!isInBoard(row, col, settings)) {
        return;
    }

    currentTile = tiles.find(function (tile) {
        return tile.row === row && tile.col === col;
    });

    if (currentTile.isVisited) {
        return;
    }

    currentTile.isVisited = true;

    // if we perform the check here we count all tiles
    countAndCheckForWin();

    // when we reach tile indicating the number of mines then draw it and stop
    if (currentTile.value !== 0) {
        drawTileWithValue(currentTile, settings);
        return;
    }

    // if everything is ok then draw the grey tile that was reached
    drawSingleTile(currentTile, settings.tileSizeInPx, true);

    // Invoke recursion to explore all possible directions
    showAllTilesWithoutValue(row, col - 1, tiles, settings); // left
    showAllTilesWithoutValue(row - 1, col, tiles, settings); // up
    showAllTilesWithoutValue(row, col + 1, tiles, settings); // right
    showAllTilesWithoutValue(row + 1, col, tiles, settings); // down

    // diagonally as well to open tiles with values in corners
    showAllTilesWithoutValue(row - 1, col - 1, tiles, settings); // 10 o'clock
    showAllTilesWithoutValue(row - 1, col + 1, tiles, settings); // 2 o'clock
    showAllTilesWithoutValue(row + 1, col + 1, tiles, settings); // 4 o'clock
    showAllTilesWithoutValue(row + 1, col - 1, tiles, settings); // 8 o'clock
}

function countAndCheckForWin() {
    tilesWithoutMinesCounter += 1;

    if (tilesWithoutMinesCounter === tilesWithoutMines) {
        gameWon();
    }
}

function gameWon() {
    $('.alert-success').removeClass('hidden');
    removeEventListenersFromCanvas();
}

// TODO: separate this function to two. One for uncovering all mines
function gameOver(tiles, settings) {
    var currentTile;

    $('.alert-danger').removeClass('hidden');
    removeEventListenersFromCanvas();

    for (var index in tiles) {
        currentTile = tiles[index];
        if (currentTile.value === settings.mineSymbol) {
            drawTileWithValue(currentTile, settings);
        }
    }
}

function hideAlertMessages() {
    $('.alert-danger').addClass('hidden');
    $('.alert-success').addClass('hidden');
}

function setTilesCounters(settings) {
    tilesWithoutMines = (settings.difficulty.verticalTiles * settings.difficulty.horizontalTiles)
        - settings.difficulty.numberOfMines;
    tilesWithoutMinesCounter = 0;
}

function initializeGame(tiles, settings) {
    setTilesCounters(settings);
    addEventListenersOnCanvas(tiles, settings);
    hideAlertMessages();
}<commit_msg>Fixed bug. When you click on button more than once only one event handler is attached to element.<commit_after>var tilesWithoutMines,
    tilesWithoutMinesCounter;

function addEventListenersOnCanvas(tiles, settings) {
    $('canvas').on('click', {tiles: tiles, settings: settings}, onTileLeftClick);
    $('canvas').on('contextmenu', {tiles: tiles, settings: settings}, onTileRightClick);
}

function removeEventListenersFromCanvas() {
    $('canvas').off('click', onTileLeftClick);
    $('canvas').off('contextmenu', onTileRightClick);
}

function onTileLeftClick(event) {
    var tiles = event.data.tiles,
        settings = event.data.settings,
        tile;

    // To enable only left mouse button click. Scroll is disabled
    if (event.button === 0) {
        tile = getClickedTile(event, tiles, settings);
        if (tile && !tile.isVisited && !tile.hasMineFlag) {
            showBehindTile(tile, tiles, settings);
        }
    }
}

function onTileRightClick(event) {
    var tiles = event.data.tiles,
        settings = event.data.settings,
        tile;

    // disable menu
    event.preventDefault();

    tile = getClickedTile(event, tiles, settings);
    if (tile && !tile.isVisited) {
        if (!tile.hasMineFlag) {
            tile.hasMineFlag = true;
            drawMineFlag(tile);
        }
        else {
            tile.hasMineFlag = false;
            drawSingleTile(tile, settings.tileSizeInPx, false);
        }
    }
}

function getClickedTile(event, tiles, settings) {
    var rect = canvas.getBoundingClientRect(),
        x = event.clientX - rect.left,
        y = event.clientY - rect.top,
        tile;

    tile = tiles.find(function (tile) {
        return tile.startXinPx + settings.tileSizeInPx > x &&
            tile.startYinPx + settings.tileSizeInPx > y;
    });

    return tile;
}

function showBehindTile(tile, tiles, settings) {
    if (tile.value === 0) {
        showAllTilesWithoutValue(tile.row, tile.col, tiles, settings);
    }
    else if (tile.value === '*') {
        gameOver(tiles, settings);
    }
    else {
        tile.isVisited = true;
        drawTileWithValue(tile, settings);
        countAndCheckForWin();
    }
}

function isInBoard(row, col, settings) {
    var rowInRange = 0 <= row && row < settings.difficulty.verticalTiles,
        colInRange = 0 <= col && col < settings.difficulty.horizontalTiles;
    return rowInRange && colInRange;
}

function showAllTilesWithoutValue(row, col, tiles, settings) {
    var currentTile;

    // if we are outside the board then stop
    if (!isInBoard(row, col, settings)) {
        return;
    }

    currentTile = tiles.find(function (tile) {
        return tile.row === row && tile.col === col;
    });

    if (currentTile.isVisited) {
        return;
    }

    currentTile.isVisited = true;

    // if we perform the check here we count all tiles
    countAndCheckForWin();

    // when we reach tile indicating the number of mines then draw it and stop
    if (currentTile.value !== 0) {
        drawTileWithValue(currentTile, settings);
        return;
    }

    // if everything is ok then draw the grey tile that was reached
    drawSingleTile(currentTile, settings.tileSizeInPx, true);

    // Invoke recursion to explore all possible directions
    showAllTilesWithoutValue(row, col - 1, tiles, settings); // left
    showAllTilesWithoutValue(row - 1, col, tiles, settings); // up
    showAllTilesWithoutValue(row, col + 1, tiles, settings); // right
    showAllTilesWithoutValue(row + 1, col, tiles, settings); // down

    // diagonally as well to open tiles with values in corners
    showAllTilesWithoutValue(row - 1, col - 1, tiles, settings); // 10 o'clock
    showAllTilesWithoutValue(row - 1, col + 1, tiles, settings); // 2 o'clock
    showAllTilesWithoutValue(row + 1, col + 1, tiles, settings); // 4 o'clock
    showAllTilesWithoutValue(row + 1, col - 1, tiles, settings); // 8 o'clock
}

function countAndCheckForWin() {
    tilesWithoutMinesCounter += 1;

    if (tilesWithoutMinesCounter === tilesWithoutMines) {
        gameWon();
    }
}

function gameWon() {
    $('.alert-success').removeClass('hidden');
    removeEventListenersFromCanvas();
}

// TODO: separate this function to two. One for uncovering all mines
function gameOver(tiles, settings) {
    var currentTile;

    $('.alert-danger').removeClass('hidden');
    removeEventListenersFromCanvas();

    for (var index in tiles) {
        currentTile = tiles[index];
        if (currentTile.value === settings.mineSymbol) {
            drawTileWithValue(currentTile, settings);
        }
    }
}

function hideAlertMessages() {
    $('.alert-danger').addClass('hidden');
    $('.alert-success').addClass('hidden');
}

function setTilesCounters(settings) {
    tilesWithoutMines = (settings.difficulty.verticalTiles * settings.difficulty.horizontalTiles)
        - settings.difficulty.numberOfMines;
    tilesWithoutMinesCounter = 0;
}

function initializeGame(tiles, settings) {
    setTilesCounters(settings);
    removeEventListenersFromCanvas();
    addEventListenersOnCanvas(tiles, settings);
    hideAlertMessages();
}<|endoftext|>


<commit_before>(function() {

'use strict';

var DEBUG = true;

var GAME_WIDTH  = 1920;
var GAME_HEIGHT = 1080;

var GRAVITY = 10000;

var MAX_CHARACTER_VELOCITY = 50;

window.WebFontConfig = {
  google: {
    families: [
      'Lora',
    ],
  },
};

var displayState = function displayState(game, stateLabel) {
  var stateDisplay = game.add.text(
    0, 0,
    'state: ' + stateLabel,
    {
      font:     'Lora',
      fontSize: 36,

      fill:   '#fff',
      stroke: '#000',

      strokeThickness: 3,
    }
  );
};

var constrainVelocity = function constrainVelocity(sprite, maxVelocity) {
  var vx = sprite.body.data.velocity[0];
  var vy = sprite.body.data.velocity[1];

  if (vx * vx + vy * vy > maxVelocity * maxVelocity) {
    var angle = Math.atan2(vy, vx);

    vx = Math.cos(angle) * maxVelocity;
    vy = Math.sin(angle) * maxVelocity;

    sprite.body.data.velocity[0] = vx;
    sprite.body.data.velocity[1] = vy;
  }
};

var loadState = {
  preload: function preload() {
    this.load.script(
      'webfont', '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js'
    );
  },

  create: function create() {
    this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;

    this.scale.pageAlignHorizontally = true;
    this.scale.pageAlignVertically   = true;

    if (DEBUG) {
      displayState(this.game, 'loading');
    }

    this.load.image('null',       'assets/null.png');
    this.load.image('background', 'assets/background.png');
    this.load.image('moon',       'assets/moon.png');

    this.load.image('male',   'assets/characters/male.png');
    this.load.image('female', 'assets/characters/female.png');

    this.load.json('room-data',  'assets/data/rooms.json');
    this.load.json('trait-data', 'assets/data/traits.json');

    this.load.json('character-data',  'assets/data/characters/index.json');
    this.load.json('cook-data',       'assets/data/characters/cook.json');
    this.load.json('gardener-data',   'assets/data/characters/gardener.json');
    this.load.json('lady-data',       'assets/data/characters/lady.json');
    this.load.json('lord-data',       'assets/data/characters/lord.json');
    this.load.json('maid-data',       'assets/data/characters/maid.json');
    this.load.json('mother-data',     'assets/data/characters/mother.json');
    this.load.json('stable-boy-data', 'assets/data/characters/stable-boy.json');

    this.load.physics('physics-data', 'assets/data/physics.json');

    this.load.onLoadComplete.add(function() {
      this.state.start('main');
    }, this);

    this.load.start();
  },
};

var mainState = {
  create: function create() {
    this.setupPhysics();
    this.setupScene();
    this.setupRooms();
    this.setupInput();

    this.addCharacters();

    if (DEBUG) {
      displayState(this.game, 'main');
    }
  },

  update: function update() {
    this.constrainCharacters();

    this.updateRooms();

    this.updateCharacters();
  },

  setupPhysics: function setupPhysics() {
    this.physics.startSystem(Phaser.Physics.P2JS);

    this.floorCollisionGroup     = this.physics.p2.createCollisionGroup();
    this.characterCollisionGroup = this.physics.p2.createCollisionGroup();

    this.physics.p2.updateBoundsCollisionGroup();

    this.physics.p2.gravity.y = GRAVITY;
  },

  setupScene: function setupScene() {
    this.add.image(0, 0, 'background');

    this.add.image(80, 100, 'moon');

    var floor = this.add.sprite(0, 0, 'null');

    this.physics.p2.enable(floor, DEBUG);

    floor.body.clearShapes();
    floor.body.loadPolygon('physics-data', 'floor');

    floor.body.setCollisionGroup(this.floorCollisionGroup);
    floor.body.collides(this.characterCollisionGroup);

    floor.body.static = true;
  },

  setupRooms: function setupRooms() {
    this.rooms = {};

    var roomData = this.cache.getJSON('room-data');

    for (var roomName in roomData) {
      var data = roomData[roomName];

      var shape = new Phaser.Polygon(data.bounds);

      if (DEBUG) {
        var debugShape = this.add.graphics();

        debugShape.lineStyle(1, 0x000000);
        debugShape.beginFill(0x000000, 0.5);
        debugShape.drawPolygon(shape);
        debugShape.endFill();
      }

      this.rooms[roomName] = {
        shape: shape,
      };
    }
  },

  setupInput: function setupInput() {
    this.pointerBody = new p2.Body();

    this.physics.p2.world.addBody(this.pointerBody);

    this.input.onDown.add(this.onPointerDown, this);
    this.input.onUp.add(this.onPointerUp, this);
    this.input.addMoveCallback(this.onPointerMove, this);
  },

  onPointerDown: function onPointerDown(pointer) {
    var bodies = this.physics.p2.hitTest(
      pointer.position,
      this.characters.children
    );

    if (!bodies.length) {
      return;
    }

    var physicsPos = [
      this.physics.p2.pxmi(pointer.position.x),
      this.physics.p2.pxmi(pointer.position.y),
    ];

    var localPointInBody = [ 0, 0 ];

    this.touchedCharacterBody = bodies[0].parent;

    this.touchedCharacterBody.toLocalFrame(localPointInBody, physicsPos);

    this.pointerConstraint = this.physics.p2.createLockConstraint(
      this.pointerBody,
      this.touchedCharacterBody,
      [
        this.physics.p2.mpxi(localPointInBody[0]),
        this.physics.p2.mpxi(localPointInBody[1]),
      ]
    );

    this.touchedCharacterBody.removeCollisionGroup(this.floorCollisionGroup);
  },

  onPointerUp: function onPointerUp() {
    if (this.pointerConstraint) {
      this.physics.p2.removeConstraint(this.pointerConstraint);

      delete this.pointerConstraint;
    }

    if (this.touchedCharacterBody) {
      this.touchedCharacterBody.collides(this.floorCollisionGroup);

      delete this.touchedCharacterBody;
    }
  },

  onPointerMove: function onPointerMove(pointer) {
    this.pointerBody.position[0] = this.physics.p2.pxmi(pointer.position.x);
    this.pointerBody.position[1] = this.physics.p2.pxmi(pointer.position.y);
  },

  addCharacters: function addCharacters() {
    this.characters = this.add.group();

    var characterData = this.cache.getJSON('character-data');

    for (var i = 0; i < characterData.all.length; i++) {
      var type = characterData.all[i];

      var data = this.cache.getJSON(type + '-data');

      var room = this.rooms[data.rooms.home];

      var roomPoints = room.shape.toNumberArray();

      var x = {
        min: this.world.width,
        max: 0,
      };

      var y = {
        min: this.world.height,
        max: 0,
      };

      for (var j = 0; j < roomPoints.length; j++) {
        var coord = roomPoints[j];

        if (j % 2) {
          y.min = Math.min(y.min, coord);
          y.max = Math.max(y.max, coord);
        } else {
          x.min = Math.min(x.min, coord);
          x.max = Math.max(x.max, coord);
        }
      }

      this.addCharacter(
        this.rnd.integerInRange(x.min, x.max),
        (y.min + y.max) / 2,
        this.rnd.pick(data.assets),
        type,
        data
      );
    }
  },

  addCharacter: function addCharacter(x, y, assetName, type, rawData) {
    var character = this.characters.create(x, y, assetName);

    character.type    = type;
    character.rawData = rawData;

    this.physics.p2.enable(character, DEBUG);

    character.body.fixedRotation = true;

    character.body.setCollisionGroup(this.characterCollisionGroup);
    character.body.collides(this.floorCollisionGroup);

    return character;
  },

  constrainCharacters: function constrainCharacters() {
    this.characters.forEachExists(function constrainCharacter(character) {
      constrainVelocity(character, MAX_CHARACTER_VELOCITY);
    }, this);
  },

  updateRooms: function updateRooms() {
    this.characters.forEachExists(this.updateRoom, this);
  },

  updateRoom: function updateRoom(character) {
    if (character.position.equals(character.previousPosition)) {
      return;
    }

    for (var roomName in this.rooms) {
      var room = this.rooms[roomName];

      if (room.shape.contains(character.position.x, character.position.y)) {
        character.room = roomName;
      }
    }
  },

  updateCharacters: function updateCharacters() {
    for (var roomName in this.rooms) {
      var characters = this.characters.filter(
        function isInRoom(character) {
          return character.room === roomName;
        },
        true
      );

      var character = characters.first;

      while (characters.position < characters.total) {
        var happiness = 0;

        happiness += this.calculatePersonHappiness(
          character.rawData, characters
        );

        happiness += this.calculateRoomHappiness(
          character.rawData, roomName
        );

        character.happiness = happiness;

        character = characters.next;
      }
    }
  },

  // Assume we only have one of each type.
  calculatePersonHappiness: function calculatePersonHappiness(
    characterData, characters
  ) {
    for (var i = 0; i < characterData.people.hates.length; i++) {
      if (!characters.getByKey('type', characterData.people.hates[i])) {
        continue;
      }

      return -1;
    }

    for (var j = 0; j < characterData.people.loves.length; j++) {
      if (!characters.getByKey('type', characterData.people.loves[j])) {
        continue;
      }

      return 1;
    }

    var happiness = 0;

    for (var k = 0; k < characters.list.length; k++) {
      var target = characters.list[k];

      if (target.type === characterData.type) {
        continue;
      }

      var trait;

      for (var l = 0; l < characterData.traits.dislikes; l++) {
        trait = characterData.traits.dislikes[l];

        if (target.rawData.traits.own.indexOf(trait) !== -1) {
          happiness--;
        }
      }

      for (var m = 0; m < characterData.traits.likes; m++) {
        trait = characterData.traits.likes[m];

        if (target.rawData.traits.own.indexOf(trait) !== -1) {
          happiness++;
        }
      }
    }

    if (happiness < 0) {
      return -1;
    }

    if (happiness > 0) {
      return 1;
    }

    return 0;
  },

  calculateRoomHappiness: function calculateRoomHappiness(characterData, roomName) {
    if (characterData.rooms.dislikes.indexOf(roomName) !== -1) {
      return -1;
    }

    if (characterData.rooms.likes.indexOf(roomName) !== -1) {
      return 1;
    }

    return 0;
  },
};

window.startGame = function startGame() {
  var game = new Phaser.Game(
    GAME_WIDTH, GAME_HEIGHT,
    Phaser.AUTO
  );

  game.state.add('load', loadState);
  game.state.add('main', mainState);

  game.state.start('load');
};

})();
<commit_msg>Split up the happiness scores<commit_after>(function() {

'use strict';

var DEBUG = true;

var GAME_WIDTH  = 1920;
var GAME_HEIGHT = 1080;

var GRAVITY = 10000;

var MAX_CHARACTER_VELOCITY = 50;

window.WebFontConfig = {
  google: {
    families: [
      'Lora',
    ],
  },
};

var displayState = function displayState(game, stateLabel) {
  var stateDisplay = game.add.text(
    0, 0,
    'state: ' + stateLabel,
    {
      font:     'Lora',
      fontSize: 36,

      fill:   '#fff',
      stroke: '#000',

      strokeThickness: 3,
    }
  );
};

var constrainVelocity = function constrainVelocity(sprite, maxVelocity) {
  var vx = sprite.body.data.velocity[0];
  var vy = sprite.body.data.velocity[1];

  if (vx * vx + vy * vy > maxVelocity * maxVelocity) {
    var angle = Math.atan2(vy, vx);

    vx = Math.cos(angle) * maxVelocity;
    vy = Math.sin(angle) * maxVelocity;

    sprite.body.data.velocity[0] = vx;
    sprite.body.data.velocity[1] = vy;
  }
};

var loadState = {
  preload: function preload() {
    this.load.script(
      'webfont', '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js'
    );
  },

  create: function create() {
    this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;

    this.scale.pageAlignHorizontally = true;
    this.scale.pageAlignVertically   = true;

    if (DEBUG) {
      displayState(this.game, 'loading');
    }

    this.load.image('null',       'assets/null.png');
    this.load.image('background', 'assets/background.png');
    this.load.image('moon',       'assets/moon.png');

    this.load.image('male',   'assets/characters/male.png');
    this.load.image('female', 'assets/characters/female.png');

    this.load.json('room-data',  'assets/data/rooms.json');
    this.load.json('trait-data', 'assets/data/traits.json');

    this.load.json('character-data',  'assets/data/characters/index.json');
    this.load.json('cook-data',       'assets/data/characters/cook.json');
    this.load.json('gardener-data',   'assets/data/characters/gardener.json');
    this.load.json('lady-data',       'assets/data/characters/lady.json');
    this.load.json('lord-data',       'assets/data/characters/lord.json');
    this.load.json('maid-data',       'assets/data/characters/maid.json');
    this.load.json('mother-data',     'assets/data/characters/mother.json');
    this.load.json('stable-boy-data', 'assets/data/characters/stable-boy.json');

    this.load.physics('physics-data', 'assets/data/physics.json');

    this.load.onLoadComplete.add(function() {
      this.state.start('main');
    }, this);

    this.load.start();
  },
};

var mainState = {
  create: function create() {
    this.setupPhysics();
    this.setupScene();
    this.setupRooms();
    this.setupInput();

    this.addCharacters();

    if (DEBUG) {
      displayState(this.game, 'main');
    }
  },

  update: function update() {
    this.constrainCharacters();

    this.updateRooms();

    this.updateCharacters();
  },

  setupPhysics: function setupPhysics() {
    this.physics.startSystem(Phaser.Physics.P2JS);

    this.floorCollisionGroup     = this.physics.p2.createCollisionGroup();
    this.characterCollisionGroup = this.physics.p2.createCollisionGroup();

    this.physics.p2.updateBoundsCollisionGroup();

    this.physics.p2.gravity.y = GRAVITY;
  },

  setupScene: function setupScene() {
    this.add.image(0, 0, 'background');

    this.add.image(80, 100, 'moon');

    var floor = this.add.sprite(0, 0, 'null');

    this.physics.p2.enable(floor, DEBUG);

    floor.body.clearShapes();
    floor.body.loadPolygon('physics-data', 'floor');

    floor.body.setCollisionGroup(this.floorCollisionGroup);
    floor.body.collides(this.characterCollisionGroup);

    floor.body.static = true;
  },

  setupRooms: function setupRooms() {
    this.rooms = {};

    var roomData = this.cache.getJSON('room-data');

    for (var roomName in roomData) {
      var data = roomData[roomName];

      var shape = new Phaser.Polygon(data.bounds);

      if (DEBUG) {
        var debugShape = this.add.graphics();

        debugShape.lineStyle(1, 0x000000);
        debugShape.beginFill(0x000000, 0.5);
        debugShape.drawPolygon(shape);
        debugShape.endFill();
      }

      this.rooms[roomName] = {
        shape: shape,
      };
    }
  },

  setupInput: function setupInput() {
    this.pointerBody = new p2.Body();

    this.physics.p2.world.addBody(this.pointerBody);

    this.input.onDown.add(this.onPointerDown, this);
    this.input.onUp.add(this.onPointerUp, this);
    this.input.addMoveCallback(this.onPointerMove, this);
  },

  onPointerDown: function onPointerDown(pointer) {
    var bodies = this.physics.p2.hitTest(
      pointer.position,
      this.characters.children
    );

    if (!bodies.length) {
      return;
    }

    var physicsPos = [
      this.physics.p2.pxmi(pointer.position.x),
      this.physics.p2.pxmi(pointer.position.y),
    ];

    var localPointInBody = [ 0, 0 ];

    this.touchedCharacterBody = bodies[0].parent;

    this.touchedCharacterBody.toLocalFrame(localPointInBody, physicsPos);

    this.pointerConstraint = this.physics.p2.createLockConstraint(
      this.pointerBody,
      this.touchedCharacterBody,
      [
        this.physics.p2.mpxi(localPointInBody[0]),
        this.physics.p2.mpxi(localPointInBody[1]),
      ]
    );

    this.touchedCharacterBody.removeCollisionGroup(this.floorCollisionGroup);
  },

  onPointerUp: function onPointerUp() {
    if (this.pointerConstraint) {
      this.physics.p2.removeConstraint(this.pointerConstraint);

      delete this.pointerConstraint;
    }

    if (this.touchedCharacterBody) {
      this.touchedCharacterBody.collides(this.floorCollisionGroup);

      delete this.touchedCharacterBody;
    }
  },

  onPointerMove: function onPointerMove(pointer) {
    this.pointerBody.position[0] = this.physics.p2.pxmi(pointer.position.x);
    this.pointerBody.position[1] = this.physics.p2.pxmi(pointer.position.y);
  },

  addCharacters: function addCharacters() {
    this.characters = this.add.group();

    var characterData = this.cache.getJSON('character-data');

    for (var i = 0; i < characterData.all.length; i++) {
      var type = characterData.all[i];

      var data = this.cache.getJSON(type + '-data');

      var room = this.rooms[data.rooms.home];

      var roomPoints = room.shape.toNumberArray();

      var x = {
        min: this.world.width,
        max: 0,
      };

      var y = {
        min: this.world.height,
        max: 0,
      };

      for (var j = 0; j < roomPoints.length; j++) {
        var coord = roomPoints[j];

        if (j % 2) {
          y.min = Math.min(y.min, coord);
          y.max = Math.max(y.max, coord);
        } else {
          x.min = Math.min(x.min, coord);
          x.max = Math.max(x.max, coord);
        }
      }

      this.addCharacter(
        this.rnd.integerInRange(x.min, x.max),
        (y.min + y.max) / 2,
        this.rnd.pick(data.assets),
        type,
        data
      );
    }
  },

  addCharacter: function addCharacter(x, y, assetName, type, rawData) {
    var character = this.characters.create(x, y, assetName);

    character.type    = type;
    character.rawData = rawData;

    this.physics.p2.enable(character, DEBUG);

    character.body.fixedRotation = true;

    character.body.setCollisionGroup(this.characterCollisionGroup);
    character.body.collides(this.floorCollisionGroup);

    return character;
  },

  constrainCharacters: function constrainCharacters() {
    this.characters.forEachExists(function constrainCharacter(character) {
      constrainVelocity(character, MAX_CHARACTER_VELOCITY);
    }, this);
  },

  updateRooms: function updateRooms() {
    this.characters.forEachExists(this.updateRoom, this);
  },

  updateRoom: function updateRoom(character) {
    if (character.position.equals(character.previousPosition)) {
      return;
    }

    for (var roomName in this.rooms) {
      var room = this.rooms[roomName];

      if (room.shape.contains(character.position.x, character.position.y)) {
        character.room = roomName;
      }
    }
  },

  updateCharacters: function updateCharacters() {
    for (var roomName in this.rooms) {
      var characters = this.characters.filter(
        function isInRoom(character) {
          return character.room === roomName;
        },
        true
      );

      var character = characters.first;

      while (characters.position < characters.total) {
        character.personHappiness = this.calculatePersonHappiness(
          character.rawData, characters
        );

        character.roomHappiness = this.calculateRoomHappiness(
          character.rawData, roomName
        );

        character = characters.next;
      }
    }
  },

  // Assume we only have one of each type.
  calculatePersonHappiness: function calculatePersonHappiness(
    characterData, characters
  ) {
    for (var i = 0; i < characterData.people.hates.length; i++) {
      if (!characters.getByKey('type', characterData.people.hates[i])) {
        continue;
      }

      return -1;
    }

    for (var j = 0; j < characterData.people.loves.length; j++) {
      if (!characters.getByKey('type', characterData.people.loves[j])) {
        continue;
      }

      return 1;
    }

    var happiness = 0;

    for (var k = 0; k < characters.list.length; k++) {
      var target = characters.list[k];

      if (target.type === characterData.type) {
        continue;
      }

      var trait;

      for (var l = 0; l < characterData.traits.dislikes; l++) {
        trait = characterData.traits.dislikes[l];

        if (target.rawData.traits.own.indexOf(trait) !== -1) {
          happiness--;
        }
      }

      for (var m = 0; m < characterData.traits.likes; m++) {
        trait = characterData.traits.likes[m];

        if (target.rawData.traits.own.indexOf(trait) !== -1) {
          happiness++;
        }
      }
    }

    if (happiness < 0) {
      return -1;
    }

    if (happiness > 0) {
      return 1;
    }

    return 0;
  },

  calculateRoomHappiness: function calculateRoomHappiness(characterData, roomName) {
    if (characterData.rooms.dislikes.indexOf(roomName) !== -1) {
      return -1;
    }

    if (characterData.rooms.likes.indexOf(roomName) !== -1) {
      return 1;
    }

    return 0;
  },
};

window.startGame = function startGame() {
  var game = new Phaser.Game(
    GAME_WIDTH, GAME_HEIGHT,
    Phaser.AUTO
  );

  game.state.add('load', loadState);
  game.state.add('main', mainState);

  game.state.start('load');
};

})();
<|endoftext|>


<commit_before>'use strict';

function setup() {
    createBoard();
    createInitialCreatures();
}

function createBoard() {
    GAME.board = [];

    for (var i = 0; i < 100; i++) {
        GAME.board[i] = [];

        for (var j = 0; j < 100; j++) {
            GAME.board[i][j] = undefined;
        }
    }
}

function createInitialCreatures() {
    var num_species = GAME.num_species;
    GAME.species = {};
    GAME.start_time = Date.now();

    for (var i = 0; i < num_species; i++) {
        createSpecies(i);

        for (var j = 0; j < (200 / num_species); j++) {
            var dna = generateDNA(i);

            do {
                var randomLoc = randomLocation();
            } while (getCreature(randomLoc.x, randomLoc.y));

            var newCreature = new Creature(dna, randomLoc);

            GAME.board[randomLoc.x][randomLoc.y] = newCreature;
        }
    }

    redraw();
}

function gameLoop() {
    for (var x = 0; x < 100; x++) {
        for (var y = 0; y < 100; y++) {
            var creature = getCreature(x, y);

            if (creature) {
                creature.act();
            }
        }
    }

    if (gameIsOver()) {
        delete GAME.species;

        // Delete all remaining creatures
        for (var x = 0; x < 100; x++) {
            for (var y = 0; y < 100; y++) {
                if (GAME.board[x][y]) {
                    delete GAME.board[x][y];
                }
            }
        }

        createInitialCreatures();
    }

    redraw();
}

function redraw() {
    for (var x = 0; x < 100; x++) {
        for (var y = 0; y < 100; y++) {
            var creature = getCreature(x, y);

            if (creature) {
                setCell(x, y, creature.color);
            } else {
                setCell(x, y, [255, 255, 255]);
            }
        }
    }
}

function gameIsOver() {
    if ((Date.now() - GAME.start_time) > GAME.max_time) {
        return true;
    }

    for (var x = 0; x < 100; x++) {
        for (var y = 0; y < 100; y++) {
            if (getCreature(x, y)) return false;
        }
    }

    return true;
}

(function() {
    function load() {
        if (document.readyState === 'loading') {
            setTimeout(load, 100);
        } else {
            setup();
            setInterval(gameLoop, 100);
        }
    }

    load();
})();
<commit_msg>Easier game configuration<commit_after>'use strict';

GAME.num_species = 20;
GAME.num_indiv = 600;
GAME.max_time = 30000;

function setup() {
    createBoard();
    createInitialCreatures();
}

function createBoard() {
    GAME.board = [];

    for (var i = 0; i < 100; i++) {
        GAME.board[i] = [];

        for (var j = 0; j < 100; j++) {
            GAME.board[i][j] = undefined;
        }
    }
}

function createInitialCreatures() {
    var num_species = GAME.num_species;
    var num_indiv = GAME.num_indiv;
    GAME.species = {};
    GAME.start_time = Date.now();

    for (var i = 0; i < num_species; i++) {
        createSpecies(i);

        for (var j = 0; j < (num_indiv / num_species); j++) {
            var dna = generateDNA(i);
            var randomLoc = randomLocation();

            while (getCreature(randomLoc.x, randomLoc.y)) {
                randomLoc = randomLocation();
            }

            var newCreature = new Creature(dna, randomLoc);

            GAME.board[randomLoc.x][randomLoc.y] = newCreature;
        }
    }

    redraw();
}

function gameLoop() {
    for (var x = 0; x < 100; x++) {
        for (var y = 0; y < 100; y++) {
            var creature = getCreature(x, y);

            if (creature) {
                creature.act();
            }
        }
    }

    if (gameIsOver()) {
        delete GAME.species;

        // Delete all remaining creatures
        for (var x = 0; x < 100; x++) {
            for (var y = 0; y < 100; y++) {
                if (GAME.board[x][y]) {
                    delete GAME.board[x][y];
                }
            }
        }

        createInitialCreatures();
    }

    redraw();
}

function redraw() {
    for (var x = 0; x < 100; x++) {
        for (var y = 0; y < 100; y++) {
            var creature = getCreature(x, y);

            if (creature) {
                setCell(x, y, creature.color);
            } else {
                setCell(x, y, [255, 255, 255]);
            }
        }
    }
}

function gameIsOver() {
    if ((Date.now() - GAME.start_time) > GAME.max_time) {
        return true;
    }

    for (var x = 0; x < 100; x++) {
        for (var y = 0; y < 100; y++) {
            if (getCreature(x, y)) return false;
        }
    }

    return true;
}

(function() {
    function load() {
        if (document.readyState === 'loading') {
            setTimeout(load, 100);
        } else {
            setup();
            setInterval(gameLoop, 100);
        }
    }

    load();
})();
<|endoftext|>


<commit_before>(function($) {
  $.widget('ui.combobox', {

    options: {
      source_url: null  // caller must provide this
    },

    _create: function() {
      var input,
          that = this,
          wasOpen = false,
          loaded = false,  // options list loaded with ajax already?
          select = this.element.hide(),
          selected = select.children(':selected'),
          value = selected.val() ? selected.text() : "",
          wrapper = this.wrapper = $('')
            .addClass('ui-combobox')
            .insertAfter(select);

      function populateSelect(data) {
        for (var i = 0; i < data.options.length; i++) {
          var label = data.options[i].label,
              value = data.options[i].value;
          $('<option>' + label + '</option>')
            .val(value)
            .appendTo(select);
        }
        loaded = true;
        input.autocomplete('search', input.val());  // trigger search to re-render options
      }

      // Load options list with ajax and populate underlying select with loaded data
      $.get(this.options.source_url, populateSelect);

      function removeIfInvalid(element) {
        var value = $(element).val(),
            matcher = new RegExp('^' + $.ui.autocomplete.escapeRegex(value) + '$'),
            valid = false;
        select.children('option').each(function() {
          if ($(this).text().match(matcher)) {
            this.selected = valid = true;
            return false;
          }
        });

        if (!valid) {
          $(element).val('');
          select.val('');
          input.data('autocomplete').term = '';
        }
      }

      input = $('<input>')
              .appendTo(wrapper)
              .val(value)
              .attr('title', '')
              .addClass('ui-state-default ui-combobox-input')
              .autocomplete({
                delay: 0,
                minLength: 0,
                source: function (request, response) {
                  if (!loaded) {
                    response([{
                      label: 'Loading...',
                      value: '',
                      option: {item: ''}
                    }]);
                    return;
                  }
                  var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), 'i');
                  response(select.children('option').map(function() {
                    var text = $(this).text();
                    if (this.value && (!request.term || matcher.test(text))) {
                      return {
                        label: text.replace(
                                 new RegExp(
                                   '(?![^&;]+;)(?!<[^<>]*)(' +
                                   $.ui.autocomplete.escapeRegex(request.term) +
                                   ')(?![^<>]*>)(?![^&;]+;)', 'gi'
                                 ), '$1'),
                        value: text,
                        option: this
                      };
                    }
                  }));
                },
                select: function(event, ui) {
                  ui.item.option.selected = true;
                  that._trigger('selected', event, {item: ui.item.option});
                },
                change: function(event, ui) {
                  if (!ui.item) {
                    removeIfInvalid(this);
                  }
                }
              }).addClass('ui-widget ui-widget-content ui-corner-left');

      input.data('autocomplete')._renderItem = function(ul, item) {
        return $('
')
          .data('item.autocomplete', item)
          .append('' + item.label + '')
          .appendTo(ul);
      };

      $('')
        .attr('tabIndex', -1)
        .attr('title', 'Show all options')
        .appendTo(wrapper)
        .button({
          icons: {
            primary: 'ui-icon-triangle-1-s'
          },
          text: false
        })
        .removeClass('ui-corner-all')
        .addClass('ui-corner-right ui-combobox-toggle')
        .mousedown(function() {
          wasOpen = input.autocomplete('widget').is(':visible');
        })
        .click(function() {
          input.focus();
          if (wasOpen) {
            return;
          }
          input.autocomplete('search', '');
        });
    },

    _destroy: function() {
      this.wrapper.remove();
      this.element.show();
    }
  });
})(jQuery);
<commit_msg>[#4299] ticket:281 Select user if username is typed in combobox and not selected from the list<commit_after>(function($) {
  $.widget('ui.combobox', {

    options: {
      source_url: null  // caller must provide this
    },

    _create: function() {
      var input,
          that = this,
          wasOpen = false,
          loaded = false,  // options list loaded with ajax already?
          select = this.element.hide(),
          selected = select.children(':selected'),
          value = selected.val() ? selected.text() : "",
          wrapper = this.wrapper = $('')
            .addClass('ui-combobox')
            .insertAfter(select);

      function populateSelect(data) {
        for (var i = 0; i < data.options.length; i++) {
          var label = data.options[i].label,
              value = data.options[i].value;
          $('<option>' + label + '</option>')
            .val(value)
            .appendTo(select);
        }
        loaded = true;
        input.autocomplete('search', input.val());  // trigger search to re-render options
      }

      // Load options list with ajax and populate underlying select with loaded data
      $.get(this.options.source_url, populateSelect);

      function removeIfInvalid(element) {
        var value = $(element).val(),
            matcher = new RegExp('^' + $.ui.autocomplete.escapeRegex(value) + '$'),
            valid = false;
        select.children('option').each(function() {
          if ($(this).val().match(matcher)) {
            this.selected = valid = true;
            input.val(this.text);
            return false;
          }
        });

        if (!valid) {
          $(element).val('');
          select.val('');
          input.data('autocomplete').term = '';
        }
      }

      input = $('<input>')
              .appendTo(wrapper)
              .val(value)
              .attr('title', '')
              .addClass('ui-state-default ui-combobox-input')
              .autocomplete({
                delay: 0,
                minLength: 0,
                source: function (request, response) {
                  if (!loaded) {
                    response([{
                      label: 'Loading...',
                      value: '',
                      option: {item: ''}
                    }]);
                    return;
                  }
                  var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), 'i');
                  response(select.children('option').map(function() {
                    var text = $(this).text();
                    if (this.value && (!request.term || matcher.test(text))) {
                      return {
                        label: text.replace(
                                 new RegExp(
                                   '(?![^&;]+;)(?!<[^<>]*)(' +
                                   $.ui.autocomplete.escapeRegex(request.term) +
                                   ')(?![^<>]*>)(?![^&;]+;)', 'gi'
                                 ), '$1'),
                        value: text,
                        option: this
                      };
                    }
                  }));
                },
                select: function(event, ui) {
                  ui.item.option.selected = true;
                  that._trigger('selected', event, {item: ui.item.option});
                },
                change: function(event, ui) {
                  if (!ui.item) {
                    removeIfInvalid(this);
                  }
                }
              }).addClass('ui-widget ui-widget-content ui-corner-left');

      input.data('autocomplete')._renderItem = function(ul, item) {
        return $('
')
          .data('item.autocomplete', item)
          .append('' + item.label + '')
          .appendTo(ul);
      };

      $('')
        .attr('tabIndex', -1)
        .attr('title', 'Show all options')
        .appendTo(wrapper)
        .button({
          icons: {
            primary: 'ui-icon-triangle-1-s'
          },
          text: false
        })
        .removeClass('ui-corner-all')
        .addClass('ui-corner-right ui-combobox-toggle')
        .mousedown(function() {
          wasOpen = input.autocomplete('widget').is(':visible');
        })
        .click(function() {
          input.focus();
          if (wasOpen) {
            return;
          }
          input.autocomplete('search', '');
        });
    },

    _destroy: function() {
      this.wrapper.remove();
      this.element.show();
    }
  });
})(jQuery);
<|endoftext|>


<commit_before>/**
 * Definition of the EasyMiner Help class
 * @param params : object (optional)
 * @constructor
 */
var EMHelp=function(params){

  //region init
  /**
   * Init function - sets the help parameters
   * @param params
   */
  this.init = function(params){
    this.lang = (typeof params.lang === 'undefined') ? 'en' : params.lang;
    if (typeof params.dataDirectoryUrl !== 'undefined'){
      this.dataDirectoryUrl=params.dataDirectoryUrl;
      if (this.dataDirectoryUrl!="" && this.dataDirectoryUrl.substr(this.dataDirectoryUrl.length-1,1)!="/"){
        this.dataDirectoryUrl += "/";
      }
    }
    if (typeof params.dataFile !== 'undefined'){
      this.dataFile=params.dataFile;
      if (this.dataFile!="" && this.dataFile.substr(this.dataFile.length-4,4).toLowerCase()!=".xml"){
        this.dataFile += ".xml";
      }
    }
  };
  if (typeof params !== "undefined"){this.init(params);}
  //endregion

  var $jq = jQuery;
  var $jqhelpColor = "";
  var q = 0;
  var num = 1;

  var highlight = function(id) {
   $jq("#" + id + "").addClass("helpHighlighted");
   $jq("#" + id + "").fadeTo("slow", 1);
  };

  var darken = function(id) {
   $jq("#"+id+"").removeClass("helpHighlighted");
  };

  var draggable = function(e) {
    window.drag = {};
    drag.pageX0 = e.pageX;
    drag.pageY0 = e.pageY;
    drag.elem = this;
    drag.offset0 = $jq(this).offset();
    var handle_dragging = function (e){
      var left = drag.offset0.left + (e.pageX - drag.pageX0);
      var top = drag.offset0.top + (e.pageY - drag.pageY0);
      $jq(drag.elem)
        .offset({top: top, left: left});
    };
    var handle_mouseup = function (e){
      $jq('body')
        .off('mousemove', handle_dragging)
        .off('mouseup', handle_mouseup);
    };
    $jq('body')
      .on('mouseup', handle_mouseup)
      .on('mousemove', handle_dragging);
  };

  /**
   * Show the given help file...
   */
  this.show = function() {
    var $jqcover = $jq("
");
    var $jqhelpBox = $jq("
");
    var $jqtitle = $jq("
");
    var $jqdescription = $jq("
");
    var $jqcontent = $jq("
");

    var $jqcloseButton = $jq('<button/>', {
      id: 'helpCloseButton',
      text: 'X',
      click: function () {
        $jqcover.fadeOut("fast", function () {
          $jqcover.remove();
        });
        $jqhelpBox.fadeOut("fast", function () {
          $jqhelpBox.remove();
        });
        this.closeXml();
      }.bind(this)
    });

    var $jqnextButton = $jq('<button/>', {
      id: 'helpNextButton',
      class: 'helpBtn',
      click: function () {
        num++;
        this.getXml(num);
      }.bind(this)
    });

    var $jqprevButton = $jq('<button/>', {
      id: 'helpPrevButton',
      class: 'helpBtn',
      click: function () {
        num--;
        this.getXml(num);
      }.bind(this)
    });

    $jqhelpBox.mousedown(draggable);

    $jqhelpBox.append($jqtitle);
    $jqhelpBox.append($jqdescription);
    $jqhelpBox.append($jqcontent);
    $jqhelpBox.append($jqnextButton);
    $jqhelpBox.append($jqprevButton);
    $jqhelpBox.append($jqcloseButton);

    $jq(document.body).append($jqcover);
    $jq(document.body).append($jqhelpBox);
    $jqhelpBox.fadeToggle("slow");

    $jq(document).keyup(function (e) {
      if (e.keyCode == 27) {
        $jqcover.fadeOut("fast", function () {
          $jqcover.remove();
        });
        $jqhelpBox.fadeOut("fast", function () {
          $jqhelpBox.remove();
        });
        this.closeXml();
      }
    }.bind(this));

    /**
     * @private
     * @param i
     */
    this.getXml = function (i) {
      $jq.ajax({
        url: this.dataDirectoryUrl + this.dataFile,
        dataType: 'xml',
        success: function (data) {
          $jq("#helpVideo").remove();
          $jqcontent.html("");
          $jqnextButton.removeAttr('disabled');
          $jqprevButton.removeAttr('disabled');
          if (i > $jq(data).find('steps').eq(q).children().size()) {
            q++;
            i = 1;
            num = 1;
          }
          if (i == 0) {
            q--;
            i = $jq(data).find('steps').eq(q).children().size();
            num = $jq(data).find('steps').eq(q).children().size();
          }
          if (i == 1 && q == 0) {
            $jqprevButton.attr('disabled', 'disabled');
          }
          $jq(data).find('step').each(function () {
            $jq(this).find('id').each(function () {
              darken($jq(this).text());
            });
          });
          $jq(data).find('steps').eq(q).each(function () {
            $jq(this).find('step:nth-child(' + i + ')').each(function () {
              $jq(this).find('id').each(function () {
                highlight($jq(this).text());
                id = $jq(this).text();
              });
              $jq("html, body").animate({scrollTop: $jq("#" + id + "").offset().top - 20}, 1000);
              $jqtitle.html($jq(data).find('section').eq(q).text() + " step " + i + " / " + $jq(data).find('steps').eq(q).children().size() + "
" + $jq(this).find('title').find(this.lang).text());
              $jq(this).find('text').each(function () {
                $jqdescription.html($jq(this).find('en').text());
              }.bind(this));
              $jq(this).find('html').each(function () {
                $jq("#helpContent").load("../_help/html/" + $jq(this).text(), function (response, status, xhr) {
                  if (status == "error") {
                    var msg = "Sorry but there was an error: ";
                    alert(msg);
                  }
                });
              });
              $jq(this).find('video').each(function () {
                $jqcontent.append($jq("<video id='helpVideo' width='320' height='240' controls/>"));
                $jq("#helpVideo").attr('src', $jq(this).text());
              });
            });
          });
          if (i == $jq(data).find('steps').eq(q).children().size() && q == $jq(data).find('steps').size() - 1) {
            $jqnextButton.attr('disabled', 'disabled');
          }
          $jq(".helpNavline").each(function () {
            $jq(this).removeClass('currentNavline');
            var numSub = "";
            for (var y = 0; y <= $jq(this).html().length - 1; y++) {
              if ($jq(this).html().charAt(y) == '.') {
                y++;
                while ($jq.isNumeric($jq(this).html().charAt(y))) {
                  numSub += $jq(this).html().charAt(y);
                  y++;
                }
                break;
              }
            }
            if (num == parseInt(numSub) && q == parseInt($jq(this).html().substr(3, $jq(this).html().indexOf('.')) - 1)) {
              $jq(this).addClass('currentNavline');
            }
          });
        },
        error: function () {
          $jq('.timeline').text('Failed to get feed');
        }
      });
    };

    this.closeXml = function () {
      $jq.ajax({
        url: this.dataDirectoryUrl + this.dataFile,
        dataType: 'xml',
        success: function (data) {
          $jq(data).find('step').each(function () {
            $jq(this).find('id').each(function () {
              darken($jq(this).text());
            });
          });
          $jq("#helpNav").remove();
        },
        error: function () {
          $jq('.timeline').text('Failed to get feed');
        }
      });
    };

    this.createNav = function () {
      var $jqnav = $jq("
");
      var $jqnavcon = $jq("
");
      var $jqmin = $jq('<button/>', {
                id: 'helpMinButton',
                text: '-',
                click: function () {
                  $jqnavcon.toggle();
                  $jq(this).text(function(i,text) {
                          return text === "-" ? "+" : "-";
                      });
                }
              });
      $jqnav.append($jq("
Navigation
"));
      $jqnav.append($jqmin);
      $jq(document.body).append($jqnav);
      $jq.ajax({
      url: this.dataDirectoryUrl + this.dataFile,
      dataType: 'xml',
      success: function(data) {
        p = 0;
        $jq(data).find('section').each(function() {
          var $jqul = $jq("
");
          var $jqli = $jq("
");
          var $jqul2 = $jq("
");
          $jqli.html("
" + $jq(this).text() + "+
");
          $jqli.find('h3').click(function() {
              $jq(this).find('span').text(function(i,text) {
                return text === "-" ? "+" : "-";
              });
              $jq(this).parent().find('ul').toggle();
          });
          $jqli.append($jqul2);
          $jqul.append($jqli);
          $jqnavcon.append($jqul);
          $jq(data).find('steps').eq(p).each(function() {
            j = 1;
            $jq(this).find('step').each(function () {

              var $jqnavli = $jq('
', {
                class: 'helpNavline',
                click: function() {
                  q = parseInt($jq(this).html().substr(3,$jq(this).html().indexOf('.')) - 1);
                  var numSub = "";
                  for (var i = 0; i <= $jq(this).html().length - 1; i++) {
                    if ($jq(this).html().charAt(i) == '.') {
                      i++;
                      while ($jq.isNumeric($jq(this).html().charAt(i))) {
                        numSub += $jq(this).html().charAt(i);
                        i++;
                      }
                    break;
                    }
                  };
                 num = parseInt(numSub);
                 this.getXml(num);
                }
              });
              $jqnavli.html("
" + (p+1) + "." + j + " " + $jq(this).find('title').find('en').text() + "
");
              if (p == q && j == num) {
                $jqnavli.addClass('currentNavline');
              }
              $jqul2.append($jqnavli);
              j++;

            });
          });
          p++;
        });
        $jqnav.append($jqnavcon);
      },
      error: function() {
        $jq('.timeline').text('Failed to get feed');
      }
  });

};

    //run
    this.createNav();
    this.getXml(num);
  }

};
<commit_msg>Oprava problému s parametrem lang<commit_after>/**
 * Definition of the EasyMiner Help class
 * @param params : object (optional)
 * @constructor
 */
var EMHelp=function(params){

  //region init
  /**
   * Init function - sets the help parameters
   * @param params
   */
  this.init = function(params){
    this.lang = (typeof params.lang === 'undefined') ? 'en' : params.lang;
    if (typeof params.dataDirectoryUrl !== 'undefined'){
      this.dataDirectoryUrl=params.dataDirectoryUrl;
      if (this.dataDirectoryUrl!="" && this.dataDirectoryUrl.substr(this.dataDirectoryUrl.length-1,1)!="/"){
        this.dataDirectoryUrl += "/";
      }
    }
    if (typeof params.dataFile !== 'undefined'){
      this.dataFile=params.dataFile;
      if (this.dataFile!="" && this.dataFile.substr(this.dataFile.length-4,4).toLowerCase()!=".xml"){
        this.dataFile += ".xml";
      }
    }
  };
  if (typeof params !== "undefined"){this.init(params);}
  //endregion

  var $jq = jQuery;
  var $jqhelpColor = "";
  var q = 0;
  var num = 1;

  var highlight = function(id) {
   $jq("#" + id + "").addClass("helpHighlighted");
   $jq("#" + id + "").fadeTo("slow", 1);
  };

  var darken = function(id) {
   $jq("#"+id+"").removeClass("helpHighlighted");
  };

  var draggable = function(e) {
    window.drag = {};
    drag.pageX0 = e.pageX;
    drag.pageY0 = e.pageY;
    drag.elem = this;
    drag.offset0 = $jq(this).offset();
    var handle_dragging = function (e){
      var left = drag.offset0.left + (e.pageX - drag.pageX0);
      var top = drag.offset0.top + (e.pageY - drag.pageY0);
      $jq(drag.elem)
        .offset({top: top, left: left});
    };
    var handle_mouseup = function (e){
      $jq('body')
        .off('mousemove', handle_dragging)
        .off('mouseup', handle_mouseup);
    };
    $jq('body')
      .on('mouseup', handle_mouseup)
      .on('mousemove', handle_dragging);
  };

  /**
   * Show the given help file...
   */
  this.show = function() {
    var $jqcover = $jq("
");
    var $jqhelpBox = $jq("
");
    var $jqtitle = $jq("
");
    var $jqdescription = $jq("
");
    var $jqcontent = $jq("
");

    var $jqcloseButton = $jq('<button/>', {
      id: 'helpCloseButton',
      text: 'X',
      click: function () {
        $jqcover.fadeOut("fast", function () {
          $jqcover.remove();
        });
        $jqhelpBox.fadeOut("fast", function () {
          $jqhelpBox.remove();
        });
        this.closeXml();
      }.bind(this)
    });

    var $jqnextButton = $jq('<button/>', {
      id: 'helpNextButton',
      class: 'helpBtn',
      click: function () {
        num++;
        this.getXml(num);
      }.bind(this)
    });

    var $jqprevButton = $jq('<button/>', {
      id: 'helpPrevButton',
      class: 'helpBtn',
      click: function () {
        num--;
        this.getXml(num);
      }.bind(this)
    });

    $jqhelpBox.mousedown(draggable);

    $jqhelpBox.append($jqtitle);
    $jqhelpBox.append($jqdescription);
    $jqhelpBox.append($jqcontent);
    $jqhelpBox.append($jqnextButton);
    $jqhelpBox.append($jqprevButton);
    $jqhelpBox.append($jqcloseButton);

    $jq(document.body).append($jqcover);
    $jq(document.body).append($jqhelpBox);
    $jqhelpBox.fadeToggle("slow");

    $jq(document).keyup(function (e) {
      if (e.keyCode == 27) {
        $jqcover.fadeOut("fast", function () {
          $jqcover.remove();
        });
        $jqhelpBox.fadeOut("fast", function () {
          $jqhelpBox.remove();
        });
        this.closeXml();
      }
    }.bind(this));

    /**
     * @private
     * @param i
     */
    this.getXml = function (i) {
      var lang=this.lang;
      $jq.ajax({
        url: this.dataDirectoryUrl + this.dataFile,
        dataType: 'xml',
        success: function (data) {
          $jq("#helpVideo").remove();
          $jqcontent.html("");
          $jqnextButton.removeAttr('disabled');
          $jqprevButton.removeAttr('disabled');
          if (i > $jq(data).find('steps').eq(q).children().size()) {
            q++;
            i = 1;
            num = 1;
          }
          if (i == 0) {
            q--;
            i = $jq(data).find('steps').eq(q).children().size();
            num = $jq(data).find('steps').eq(q).children().size();
          }
          if (i == 1 && q == 0) {
            $jqprevButton.attr('disabled', 'disabled');
          }
          $jq(data).find('step').each(function () {
            $jq(this).find('id').each(function () {
              darken($jq(this).text());
            });
          });
          $jq(data).find('steps').eq(q).each(function () {
            $jq(this).find('step:nth-child(' + i + ')').each(function () {
              $jq(this).find('id').each(function () {
                highlight($jq(this).text());
                id = $jq(this).text();
              });
              $jq("html, body").animate({scrollTop: $jq("#" + id + "").offset().top - 20}, 1000);
              $jqtitle.html($jq(data).find('section').eq(q).text() + " step " + i + " / " + $jq(data).find('steps').eq(q).children().size() + "
" + $jq(this).find('title').find(lang).text());
              $jq(this).find('text').each(function () {
                $jqdescription.html($jq(this).find(lang).text());
              });
              $jq(this).find('html').each(function () {
                $jq("#helpContent").load("../_help/html/" + $jq(this).text(), function (response, status, xhr) {
                  if (status == "error") {
                    var msg = "Sorry but there was an error: ";
                    alert(msg);
                  }
                });
              });
              $jq(this).find('video').each(function () {
                $jqcontent.append($jq("<video id='helpVideo' width='320' height='240' controls/>"));
                $jq("#helpVideo").attr('src', $jq(this).text());
              });
            }.bind(this));
          });
          if (i == $jq(data).find('steps').eq(q).children().size() && q == $jq(data).find('steps').size() - 1) {
            $jqnextButton.attr('disabled', 'disabled');
          }
          $jq(".helpNavline").each(function () {
            $jq(this).removeClass('currentNavline');
            var numSub = "";
            for (var y = 0; y <= $jq(this).html().length - 1; y++) {
              if ($jq(this).html().charAt(y) == '.') {
                y++;
                while ($jq.isNumeric($jq(this).html().charAt(y))) {
                  numSub += $jq(this).html().charAt(y);
                  y++;
                }
                break;
              }
            }
            if (num == parseInt(numSub) && q == parseInt($jq(this).html().substr(3, $jq(this).html().indexOf('.')) - 1)) {
              $jq(this).addClass('currentNavline');
            }
          });
        },
        error: function () {
          $jq('.timeline').text('Failed to get feed');
        }
      });
    };

    this.closeXml = function () {
      $jq.ajax({
        url: this.dataDirectoryUrl + this.dataFile,
        dataType: 'xml',
        success: function (data) {
          $jq(data).find('step').each(function () {
            $jq(this).find('id').each(function () {
              darken($jq(this).text());
            });
          });
          $jq("#helpNav").remove();
        },
        error: function () {
          $jq('.timeline').text('Failed to get feed');
        }
      });
    };

    this.createNav = function () {
      var $jqnav = $jq("
");
      var $jqnavcon = $jq("
");
      var $jqmin = $jq('<button/>', {
                id: 'helpMinButton',
                text: '-',
                click: function () {
                  $jqnavcon.toggle();
                  $jq(this).text(function(i,text) {
                          return text === "-" ? "+" : "-";
                      });
                }
              });
      $jqnav.append($jq("
Navigation
"));
      $jqnav.append($jqmin);
      $jq(document.body).append($jqnav);
      $jq.ajax({
      url: this.dataDirectoryUrl + this.dataFile,
      dataType: 'xml',
      success: function(data) {
        p = 0;
        $jq(data).find('section').each(function() {
          var $jqul = $jq("
");
          var $jqli = $jq("
");
          var $jqul2 = $jq("
");
          $jqli.html("
" + $jq(this).text() + "+
");
          $jqli.find('h3').click(function() {
              $jq(this).find('span').text(function(i,text) {
                return text === "-" ? "+" : "-";
              });
              $jq(this).parent().find('ul').toggle();
          });
          $jqli.append($jqul2);
          $jqul.append($jqli);
          $jqnavcon.append($jqul);
          $jq(data).find('steps').eq(p).each(function() {
            j = 1;
            $jq(this).find('step').each(function () {

              var $jqnavli = $jq('
', {
                class: 'helpNavline',
                click: function() {
                  q = parseInt($jq(this).html().substr(3,$jq(this).html().indexOf('.')) - 1);
                  var numSub = "";
                  for (var i = 0; i <= $jq(this).html().length - 1; i++) {
                    if ($jq(this).html().charAt(i) == '.') {
                      i++;
                      while ($jq.isNumeric($jq(this).html().charAt(i))) {
                        numSub += $jq(this).html().charAt(i);
                        i++;
                      }
                    break;
                    }
                  }
                 num = parseInt(numSub);
                 this.getXml(num);
                }.bind(this)
              });
              $jqnavli.html("
" + (p+1) + "." + j + " " + $jq(this).find('title').find('en').text() + "
");
              if (p == q && j == num) {
                $jqnavli.addClass('currentNavline');
              }
              $jqul2.append($jqnavli);
              j++;

            });
          });
          p++;
        });
        $jqnav.append($jqnavcon);
      },
      error: function() {
        $jq('.timeline').text('Failed to get feed');
      }
  });

};

    //run
    this.createNav();
    this.getXml(num);
  }

};
<|endoftext|>


<commit_before>'use strict';

var mongoose = require('mongoose'),
  Message = mongoose.model('Message'),
  User = mongoose.model('User'),
  passport = require('passport');

var twilio = require('twilio');

/**
 *
 * @param resp
 * @param res
 */
function twilioResponse(res, resp) {
  res.writeHead(200, {
    'Content-Type': 'text/xml'
  });
  res.end(resp.toString());
}

/**
 * Incoming Voice
 */
exports.voice = function (req, res, next) {
  // Create a TwiML response
  var resp = new twilio.TwimlResponse();

  resp.say({voice: 'woman'}, 'Hello, this is PartyBot.  Please send me a text message.  Party on!');

  twilioResponse(res, resp);

};

/**
 * Incoming SMS
 */
exports.sms = function (req, res, next) {

  /**
   * Create a message
   */
  var message = new Message({
    state: 'pending',
    type: 'broadcast',
    content: '{message:testing}'
  });
  message.save(function (err) {
    if (err) return res.json(500, err);

    // Create a TwiML response
    var resp = new twilio.TwimlResponse();
    resp.message('Party! Message id ' + message._id);
    twilioResponse(res, resp);
  });

};<commit_msg>twilio incoming parses details<commit_after>'use strict';

var mongoose = require('mongoose'),
  Message = mongoose.model('Message'),
  User = mongoose.model('User'),
  passport = require('passport');

var twilio = require('twilio');

/**
 *
 * @param resp
 * @param res
 */
function twilioResponse(res, resp) {
  res.writeHead(200, {
    'Content-Type': 'text/xml'
  });
  res.end(resp.toString());
}

/**
 * Incoming Voice
 */
exports.voice = function (req, res, next) {
  // Create a TwiML response
  var resp = new twilio.TwimlResponse();

  resp.say({voice: 'woman'}, 'Hello, this is PartyBot.  Please send me a text message.  Party on!');

  twilioResponse(res, resp);

};

/**
 * Incoming SMS
 */
exports.sms = function (req, res, next) {

  /**
   * Create a message
   */
  var message = new Message({
    state: 'pending',
    type: 'broadcast',
    content: {
      Body: req.body.Body,
      NumMedia: req.body.NumMedia,
      MessageSid: req.body.MessageSid,
      SmsSid: req.body.SmsSid,
      AccountSid: req.body.AccountSid,
      From: req.body.From,
      To: req.body.To
    }
  });
  message.save(function (err) {
    if (err) return res.json(500, err);

    // Create a TwiML response
    var resp = new twilio.TwimlResponse();
    resp.message('Party! Message id ' + message._id);
    twilioResponse(res, resp);
  });

};<|endoftext|>


<commit_before>function subarray(a, b) {
	var temp = [];
	for (i = 0; i  epoch) {
		$('#countdown').text(Math.floor(target-epoch));
	} else {
		$('#countdown').text('0');
	}
	setTimeout(function() {
		countdown();
	}, 1000);
}

$('document').ready(function() {
	//Initialize the sideNav
	$(".button-collapse").sideNav();
	//Initialize the modal
	$('.modal-trigger').leanModal();

	countdown();

	if(typeof(Storage) !== 'undefined') {
		if(!localStorage['home_new']) {
			localStorage.setItem('home_new', 'false');
			$('#helpmodal').openModal();
		}
	} else {
		$('#helpmodal').openModal();
	}

	var $list = $('#system p').hide();
	$list.slice(0, 5).show();
	var list_size = $list.length;
	var x = 5;
	var start = 0;
	var running = false;

	$('#back').click(function() {
		if (start + x < list_size && !running) {
			running = true;
			$list.slice(start, start + x).fadeOut('medium', function() {
				$list.slice(start, start + x).fadeIn('medium', function() {
					running = false;
				});
			});
			start += x;
		}
		return false;
	});

	$('#forward').click(function() {
		if (start - x >= 0 && !running) {
			running = true;
			$list.slice(start, start + x).fadeOut('medium', function() {
				$list.slice(start, start + x).fadeIn('medium', function() {
					running = false;
				});
			});
			start -= x;
		}
		return false;
	});

	$.ajax({
		type: 'GET',
		url: '/api/home/graph/',
		success: function(data) {
			if (data.success === false) {
				$('.valign-wrapper').empty();
				$('.valign-wrapper').html('
' + data.message + '
');
				return false;
			}
			var options = {
				chart: {
					renderTo: 'graph'
				},
				xAxis: {
					type: 'datetime'
				},
				series: [{
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Total Earned (Raw+Bonus)',
					data: data.total_score
				}, {
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Total IP',
					data: data.total_ip
				}, {
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Successful IP',
					data: data.successful_ip
				}, {
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Failed IP',
					data: subarray(data.total_ip, data.successful_ip)
				}, ],
				credits: {
					enabled: false
				},
				title: {
					text: 'System Statistics'
				},
				yAxis: {
					title: 'Value',
					floor: 0
				}
			}

			var d = new Date();
			Highcharts.setOptions({
				global: {
					timezoneOffset: d.getTimezoneOffset()
				}
			});

			var chart = new Highcharts.Chart(options);
		}
	});
});<commit_msg>Comment Home.JS<commit_after>//Function used to subtract arrays and return difference
function subarray(a, b) {
	var temp = [];
	for (i = 0; i  epoch) {
		$('#countdown').text(Math.floor(target-epoch));
	} else {
		$('#countdown').text('0');
	}
	setTimeout(function() {
		countdown();
	}, 1000);
}

$('document').ready(function() {
	//Initialize the sideNav
	$(".button-collapse").sideNav();
	//Initialize the modal
	$('.modal-trigger').leanModal();

	//Initialize countdown
	countdown();

	//Check if this site has been accessed and if not open the help modal
	if(typeof(Storage) !== 'undefined') {
		if(!localStorage['home_new']) {
			localStorage.setItem('home_new', 'false');
			$('#helpmodal').openModal();
		}
	} else {
		$('#helpmodal').openModal();
	}

	//Create a var that selects an attribute and hides it
	var $list = $('#system p').hide();
	//Split and shoe the list
	$list.slice(0, 5).show();
	//Copy length to new var
	var list_size = $list.length;
	//Create a list with the size of 5
	var x = 5;
	//Start the list at 0
	var start = 0;
	//Start it off
	var running = false;

	//When the back button is hit, go back in time to previous messages
	$('#back').click(function() {
		if (start + x < list_size && !running) {
			running = true;
			$list.slice(start, start + x).fadeOut('medium', function() {
				$list.slice(start, start + x).fadeIn('medium', function() {
					running = false;
				});
			});
			start += x;
		}
		return false;
	});

	//When the forward button is hit, go forward in time to newer messages
	$('#forward').click(function() {
		if (start - x >= 0 && !running) {
			running = true;
			$list.slice(start, start + x).fadeOut('medium', function() {
				$list.slice(start, start + x).fadeIn('medium', function() {
					running = false;
				});
			});
			start -= x;
		}
		return false;
	});

	//Get data for the home graph
	$.ajax({
		type: 'GET',
		url: '/api/home/graph/',
		success: function(data) {
			if (data.success === false) {
				//Clear wrapper and add a heading and center it
				$('.valign-wrapper').empty();
				$('.valign-wrapper').html('
' + data.message + '
');
				return false;
			}
			var options = {
				chart: {
					renderTo: 'graph'
				},
				//The X Axis type
				xAxis: {
					type: 'datetime'
				},
				//Data to graph
				series: [{
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Total Earned (Raw+Bonus)',
					data: data.total_score
				}, {
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Total IP',
					data: data.total_ip
				}, {
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Successful IP',
					data: data.successful_ip
				}, {
					pointStart: data.start * 1000,
					pointInterval: data.interval * 1000,
					name: 'Failed IP',
					data: subarray(data.total_ip, data.successful_ip)
				}, ],
				//Credits option
				credits: {
					enabled: false
				},
				//Title
				title: {
					text: 'System Statistics'
				},
				//The Y Axis type
				yAxis: {
					title: 'Value',
					floor: 0
				}
			}

			//New date adjusted to TimeZones
			var d = new Date();
			Highcharts.setOptions({
				global: {
					timezoneOffset: d.getTimezoneOffset()
				}
			});

			//Create a chart with the options
			var chart = new Highcharts.Chart(options);
		}
	});
});<|endoftext|>


<commit_before>'use strict'
var EventEmitter2 = require('eventemitter2').EventEmitter2
var util = require('util')
var logger = require('../util/logger.js')
var parser = require('../parser/parser.js')

function LogEventEmitter () {
  this.DATA_RAW = 'data.raw'
  this.DATA_PARSED = 'data.parsed'

  EventEmitter2.call(this, {
    wildcard: true,
    delemiter: '.',
    newListener: true,
    maxListeners: 30
  })
  this.onAny(function (event) {
    logger.debug('Event received:' + JSON.stringify(arguments))
  })
}

LogEventEmitter.prototype.rawDataEvent = function (data, metadata) {
  this.emit(this.DATA_RAW, data, metadata)
}

LogEventEmitter.prototype.parsedEvent = function (data, metadata) {
  this.emit(this.DATA_PARSED, data, metadata)
}

util.inherits(LogEventEmitter, EventEmitter2)

var logEmitter = new LogEventEmitter()

module.exports = logEmitter
<commit_msg>moving from EventEmitter2 to standard EventEmitter, result double throughput<commit_after>'use strict'
var EventEmitter = require('events').EventEmitter
var util = require('util')
var logger = require('../util/logger.js')
var parser = require('../parser/parser.js')

function LogEventEmitter () {
  this.DATA_RAW = 'data.raw'
  this.DATA_PARSED = 'data.parsed'
}

LogEventEmitter.prototype.rawDataEvent = function (data, metadata) {
  this.emit(this.DATA_RAW, data, metadata)
}

LogEventEmitter.prototype.parsedEvent = function (data, metadata) {
  this.emit(this.DATA_PARSED, data, metadata)
}

util.inherits(LogEventEmitter, EventEmitter)

var logEmitter = new LogEventEmitter()

module.exports = logEmitter
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2012 Andreas Madsen
 * MIT License
 */

(function () {
  "use strict";

  var util = require('util');
  var events = require('events');

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

  function MonitorAbstract(options, ready) {
    this.options = options;
    this.ready = ready;

    this.stdout = helpers.createStream();
    this.stderr = helpers.createStream();
  }
  util.inherits(MonitorAbstract, events.EventEmitter);
  module.exports = MonitorAbstract;

})();
<commit_msg>[fix] streams was moved to core module<commit_after>/**
 * Copyright (c) 2012 Andreas Madsen
 * MIT License
 */

(function () {
  "use strict";

  var util = require('util');
  var path = require('path');
  var events = require('events');

  var helpers = require('../helpers.js');
  var streams = require(path.join(helpers.core, 'streams.js'));

  function MonitorAbstract(options, ready) {
    this.options = options;
    this.ready = ready;

    this.stdout = new streams.RelayStream();
    this.stderr = new streams.RelayStream();
  }
  util.inherits(MonitorAbstract, events.EventEmitter);
  module.exports = MonitorAbstract;

})();
<|endoftext|>


<commit_before>/*
 * crude-test-case
 * The test case of the crude package
 * https://github.com/thanpolas/crude-test-case
 *
 * Copyright (c) 2014 Thanasis Polychronakis
 * Licensed under the MIT license.
 */

/**
 * @fileOverview crude-test-case Base.
 */

var testCase = module.exports = {};

var srcCrude = null;

/**
 * DI the crude package.
 *
 * @param {crude} crude The crude package.
 */
testCase.setCrude = function (crude) {
  srcCrude = crude;
  testCase.expressApp.setCrude(crude);
  testCase.UserCtrl.setCrude(crude);
};

testCase.db = require('./lib/db.lib');
testCase.libUser = require('./lib/fixture-user.lib');
testCase.tester = require('./lib/tester.lib');
testCase.web = require('./lib/web.lib');

testCase.fixUser = require('./fixtures/user.fix');

testCase.bootstrap = require('./setup/bootstrap');
testCase.Database = require('./setup/database');
testCase.expressApp = require('./setup/expressApp');
testCase.UserCtrl = require('./setup/user.ctrl');
testCase.UserEnt = require('./setup/user.ent');
testCase.UserMongoose = require('./setup/user.mongoose');

<commit_msg>properly expose modules<commit_after>/*
 * crude-test-case
 * The test case of the crude package
 * https://github.com/thanpolas/crude-test-case
 *
 * Copyright (c) 2014 Thanasis Polychronakis
 * Licensed under the MIT license.
 */

/**
 * @fileOverview crude-test-case Base.
 */

var testCase = module.exports = {};

var srcCrude = null;

/**
 * DI the crude package.
 *
 * @param {crude} crude The crude package.
 */
testCase.setCrude = function (crude) {
  srcCrude = crude;
  testCase.expressApp.setCrude(crude);
  testCase.UserCtrl.setCrude(crude);
};

testCase.db = require('./lib/db.lib');
testCase.libUser = require('./lib/fixture-user.lib');
testCase.tester = require('./lib/tester.lib');
testCase.Web = require('./lib/web.lib');

testCase.fixUser = require('./fixtures/user.fix');

testCase.bootstrap = require('./setup/bootstrap');
testCase.Database = require('./setup/database');
testCase.expressApp = require('./setup/expressApp');
testCase.UserCtrl = require('./setup/user.ctrl');
testCase.UserEnt = require('./setup/user.ent');
testCase.UserMongoose = require('./setup/user.mongoose.model');

<|endoftext|>