<commit_before>/**
 * jQuery Tiles v0.3.0
 *
 * Tiles takes care of loading and zooming of tiled images. This jQuery
 * plugin depends on jQuery and jQuery UI (draggable). The tiled images
 * may be generated on the server using the associated shell script.
 *
 * Distributed under the terms of the MIT License.
 *
 * http://tiles.hackyon.com
 */
(function($) {

  var Layer = function(zoom, $viewport, config) {
    this.config = config;
    this.zoom = zoom;
    this.$viewport = $viewport;
    this.$layer = $('<div/>');

    this.width  = config.original.width  / zoom;
    this.height = config.original.height / zoom;
  };

  Layer.prototype.move = function(centerX, centerY) {
    // The centerX and centerY are interpreted as the coordinates of the
    // original image and not of the current zoom.

    var viewportWidth  = this.$viewport.width();
    var viewportHeight = this.$viewport.height();

    var positionTop  = (centerY / this.zoom) - viewportHeight/2;
    var positionLeft = (centerX / this.zoom) - viewportWidth /2;

    // Be aware of bounds
    var maxLeft = -(viewportWidth - this.width)
    var maxTop  = -(viewportHeight - this.height)

    positionTop  = Math.max(0, Math.min(maxTop, positionTop));
    positionLeft = Math.max(0, Math.min(maxLeft, positionLeft));

    if (viewportWidth > this.width) {
      positionLeft = -(viewportWidth - this.width)/2;
    }
    if (viewportHeight > this.height) {
      positionTop = -(viewportHeight - this.height)/2;
    }

    this.$layer.css('top', -positionTop);
    this.$layer.css('left', -positionLeft);

    // Recalculate the center since it may have changed due to containment
    this.centerX = (positionLeft + viewportWidth /2) * this.zoom;
    this.centerY = (positionTop  + viewportHeight/2) * this.zoom;

    if (viewportWidth > this.width) {
      this.centerX = this.config.original.width/2;
    }
    if (viewportHeight > this.height) {
      this.centerY = this.config.original.height/2;
    }

    this._ondrag();
  };

  Layer.prototype.show = function() {
    this.$layer.css('z-index', 2);
    this.$layer.css('display', 'block');
  };

  Layer.prototype.hide = function() {
    this.$layer.css('z-index', 1);
    this.$layer.css('display', 'none');
  };

  Layer.prototype.load = function() {
    var $viewport = this.$viewport;
    var $layer = this.$layer;
    var zoom   = this.zoom;
    var config = this.config;

    var width  = this.width;
    var height = this.height;

    var tileSize = config.tileSize;

    $layer.css('position', 'absolute');

    var cols = Math.ceil(width  / tileSize);
    var rows = Math.ceil(height / tileSize);

    for (var r = 1; r <= rows; r++) {
      var $row = $('<div/>');
      for (var c = 1; c <= cols; c++) {
        var $tile = $('<div/>');
        $tile.css('width',  tileSize);
        $tile.css('height', tileSize);
        $tile.css('float', 'left');
        $tile.css('text-align', 'left');
        $tile.css('vertical-align', 'top');

        if (config.loading) {
          $tile.css('background', 'url(' + config.loading + ') center center no-repeat');
        }

        var $image = $('<img/>');
        if (r !== rows) {
          $image.attr('height', tileSize);
        } else {
          $image.attr('height', height % tileSize);
        }

        if (c !== cols) {
          $image.attr('width', tileSize);
        } else {
          $image.attr('width', width % tileSize);
        }

        var selector = ['tiles', zoom, c, r].join('-');
        $image.addClass(selector);

        $image.data('loaded', false);
        $image.data('src', config.basePath + 'tiles/' + zoom + '/' + c + '_' + r + '.jpg');

        $tile.append($image);
        $row.append($tile);
      }
      $row.css('width', cols * tileSize);
      $layer.append($row);
    }

    $viewport.append($layer);

    var offset = $viewport.offset();
    var layer = this;

    var containment = [
      offset.left + $viewport.width() - width,
      offset.top + $viewport.height() - height,
      offset.left,
      offset.top
    ];
    if ($viewport.width() > width) {
      containment[0] = offset.left + ($viewport.width() - width)/2;
      containment[2] = offset.left + ($viewport.width() - width)/2;
    }
    if ($viewport.height() > height) {
      containment[1] = offset.top + ($viewport.height() - height)/2;
      containment[3] = offset.top + ($viewport.height() - height)/2;
    }
    $layer.draggable({
      containment: containment,
      drag: function() { layer._ondrag(); }
    });
    this._ondrag();

    this.hide();
  };

  Layer.prototype._ondrag = function() {
    var tileSize = this.config.tileSize;
    var position = this.$layer.position();

    var startCol = Math.floor(-position.left / tileSize)+1;
    var endCol   = Math.ceil((-position.left + this.$viewport.width()) / tileSize);

    var startRow = Math.floor(-position.top / tileSize)+1;
    var endRow   = Math.ceil((-position.top + this.$viewport.height()) / tileSize);

    for (var c = startCol; c <= endCol; c++) {
      for (var r = startRow; r <= endRow; r++) {
        var selector= ['.tiles', this.zoom, c, r].join('-');
        var $image = this.$layer.find(selector);

        if (!$image.data('loaded')) {
          $image.attr('src', $image.data('src'));
          $image.data('loaded', true);
          $image.load(function() {
            $(this).fadeOut(0).fadeIn(250);
          });
        }
      }
    }

    this.centerX = (-position.left + this.$viewport.width()/2)  * this.zoom;
    this.centerY = (-position.top  + this.$viewport.height()/2) * this.zoom;
  };

  var DummyLayer = function(zoom, $viewport, config) {
    this.config = config;
    this.zoom = zoom;
    this.$viewport = $viewport;

    var $layer = $('<div/>');
    $viewport.children().each(function(index) {
      $(this).detach().appendTo($layer)
    });
    this.$layer = $layer;

    this.centerX = 0;
    this.centerY = 0;
  };

  DummyLayer.prototype.show = function() {
    this.$layer.css('z-index', 2);
    this.$layer.css('display', 'block');
  };

  DummyLayer.prototype.hide = function() {
    this.$layer.css('z-index', 1);
    this.$layer.css('display', 'none');
  };

  DummyLayer.prototype.load = function() {
    this.$viewport.append(this.$layer);
  };

  DummyLayer.prototype.move = function(centerX, centerY) {
    this.centerX = centerX;
    this.centerY = centerY;
  };

  var methods = {
    init : function(options) {
      var config = $.extend({
        original: { width: null, height: null },
        tileSize: 500,
        basePath: '',
        loading: '',
        zoom: 0,
        no0zoom: false
      }, options);

      // Basic sanitation check
      if (typeof config.original.width  !== 'number'
       || typeof config.original.height !== 'number') {
        throw 'Missing required fields original.width and original.height.';
      }
      if (config.original.width <= 0 || config.original.height <= 0) {
        throw 'Both original.width and original.height must be > 0';
      }

      // The basePath needs to end with a / if it is not empty
      var basePath = $.trim(config.basePath)
      if (basePath) {
        if (basePath.indexOf('/', basePath.length-1) === -1) {
          basePath += '/';
        }
      }
      config.basePath = basePath;

      this.data('config', config);

      return this.each(function() {
        var $this = $(this);
        $this.css('position', 'relative');
        $this.css('overflow', 'hidden');

        var layers = { };

        if (!config.no0zoom) {
          // Load the original layer to save the HTML content that
          // was inside viewport
          layers[0] = new DummyLayer(0, $this, config);
          layers[0].load();
          layers[0].hide();
        } else if (config.zoom == 0) {
          throw "You must specify a non-zero zoom if no0zoom is true";
        }

        var zoom = config.zoom;
        if (zoom != 0) {
          layers[zoom] = new Layer(zoom, $this, config);
          layers[zoom].load();
        }
        layers[zoom].show();

        $this.data('layers', layers);
        $this.data('zoom', zoom);
      });
    },
    zoom: function(factor) {
      var config = this.data('config');

      return this.each(function() {
        var $this = $(this);

        var zoom = $this.data('zoom');
        if (zoom == factor) return;

        var layers = $this.data('layers');

        var centerX = layers[zoom].centerX;
        var centerY = layers[zoom].centerY;
        layers[zoom].hide();
        zoom = factor;

        if (!layers[zoom]) {
          layers[zoom] = new Layer(zoom, $this, config);
          layers[zoom].load();
        }
        layers[zoom].show();
        layers[zoom].move(centerX, centerY);

        $this.data('layers', layers);
        $this.data('zoom', zoom);
      });
    },
    move: function(centerX, centerY) {
      var config = this.data('config');

      return this.each(function() {
        var $this = $(this);

        var zoom   = $this.data('zoom');
        var layers = $this.data('layers');

        layers[zoom].move(centerX*zoom, centerY*zoom);
      });
    },
    center: function() {
      var config = this.data('config');

      return this.each(function() {
        var $this = $(this);

        var zoom   = $this.data('zoom');
        var layers = $this.data('layers');

        layers[zoom].move(config.original.width/2, config.original.height/2);
      });
    }
  };

  $.fn.tiles = function (method) {
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method == 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error ('No such method: ' + method);
    }
  };

})(jQuery);
<commit_msg>Fade out the image before it loads<commit_after>/**
 * jQuery Tiles v0.3.0
 *
 * Tiles takes care of loading and zooming of tiled images. This jQuery
 * plugin depends on jQuery and jQuery UI (draggable). The tiled images
 * may be generated on the server using the associated shell script.
 *
 * Distributed under the terms of the MIT License.
 *
 * http://tiles.hackyon.com
 */
(function($) {

  var Layer = function(zoom, $viewport, config) {
    this.config = config;
    this.zoom = zoom;
    this.$viewport = $viewport;
    this.$layer = $('<div/>');

    this.width  = config.original.width  / zoom;
    this.height = config.original.height / zoom;
  };

  Layer.prototype.move = function(centerX, centerY) {
    // The centerX and centerY are interpreted as the coordinates of the
    // original image and not of the current zoom.

    var viewportWidth  = this.$viewport.width();
    var viewportHeight = this.$viewport.height();

    var positionTop  = (centerY / this.zoom) - viewportHeight/2;
    var positionLeft = (centerX / this.zoom) - viewportWidth /2;

    // Be aware of bounds
    var maxLeft = -(viewportWidth - this.width)
    var maxTop  = -(viewportHeight - this.height)

    positionTop  = Math.max(0, Math.min(maxTop, positionTop));
    positionLeft = Math.max(0, Math.min(maxLeft, positionLeft));

    if (viewportWidth > this.width) {
      positionLeft = -(viewportWidth - this.width)/2;
    }
    if (viewportHeight > this.height) {
      positionTop = -(viewportHeight - this.height)/2;
    }

    this.$layer.css('top', -positionTop);
    this.$layer.css('left', -positionLeft);

    // Recalculate the center since it may have changed due to containment
    this.centerX = (positionLeft + viewportWidth /2) * this.zoom;
    this.centerY = (positionTop  + viewportHeight/2) * this.zoom;

    if (viewportWidth > this.width) {
      this.centerX = this.config.original.width/2;
    }
    if (viewportHeight > this.height) {
      this.centerY = this.config.original.height/2;
    }

    this._ondrag();
  };

  Layer.prototype.show = function() {
    this.$layer.css('z-index', 2);
    this.$layer.css('display', 'block');
  };

  Layer.prototype.hide = function() {
    this.$layer.css('z-index', 1);
    this.$layer.css('display', 'none');
  };

  Layer.prototype.load = function() {
    var $viewport = this.$viewport;
    var $layer = this.$layer;
    var zoom   = this.zoom;
    var config = this.config;

    var width  = this.width;
    var height = this.height;

    var tileSize = config.tileSize;

    $layer.css('position', 'absolute');

    var cols = Math.ceil(width  / tileSize);
    var rows = Math.ceil(height / tileSize);

    for (var r = 1; r <= rows; r++) {
      var $row = $('<div/>');
      for (var c = 1; c <= cols; c++) {
        var $tile = $('<div/>');
        $tile.css('width',  tileSize);
        $tile.css('height', tileSize);
        $tile.css('float', 'left');
        $tile.css('text-align', 'left');
        $tile.css('vertical-align', 'top');

        if (config.loading) {
          $tile.css('background', 'url(' + config.loading + ') center center no-repeat');
        }

        var $image = $('<img/>');
        if (r !== rows) {
          $image.attr('height', tileSize);
        } else {
          $image.attr('height', height % tileSize);
        }

        if (c !== cols) {
          $image.attr('width', tileSize);
        } else {
          $image.attr('width', width % tileSize);
        }

        var selector = ['tiles', zoom, c, r].join('-');
        $image.addClass(selector);

        $image.data('loaded', false);
        $image.data('src', config.basePath + 'tiles/' + zoom + '/' + c + '_' + r + '.jpg');
        $image.fadeOut(0);

        $tile.append($image);
        $row.append($tile);
      }
      $row.css('width', cols * tileSize);
      $layer.append($row);
    }

    $viewport.append($layer);

    var offset = $viewport.offset();
    var layer = this;

    var containment = [
      offset.left + $viewport.width() - width,
      offset.top + $viewport.height() - height,
      offset.left,
      offset.top
    ];
    if ($viewport.width() > width) {
      containment[0] = offset.left + ($viewport.width() - width)/2;
      containment[2] = offset.left + ($viewport.width() - width)/2;
    }
    if ($viewport.height() > height) {
      containment[1] = offset.top + ($viewport.height() - height)/2;
      containment[3] = offset.top + ($viewport.height() - height)/2;
    }
    $layer.draggable({
      containment: containment,
      drag: function() { layer._ondrag(); }
    });
    this._ondrag();

    this.hide();
  };

  Layer.prototype._ondrag = function() {
    var tileSize = this.config.tileSize;
    var position = this.$layer.position();

    var startCol = Math.floor(-position.left / tileSize)+1;
    var endCol   = Math.ceil((-position.left + this.$viewport.width()) / tileSize);

    var startRow = Math.floor(-position.top / tileSize)+1;
    var endRow   = Math.ceil((-position.top + this.$viewport.height()) / tileSize);

    for (var c = startCol; c <= endCol; c++) {
      for (var r = startRow; r <= endRow; r++) {
        var selector= ['.tiles', this.zoom, c, r].join('-');
        var $image = this.$layer.find(selector);

        if (!$image.data('loaded')) {
          $image.attr('src', $image.data('src'));
          $image.data('loaded', true);
          $image.load(function() {
            $(this).fadeIn(250);
          });
        }
      }
    }

    this.centerX = (-position.left + this.$viewport.width()/2)  * this.zoom;
    this.centerY = (-position.top  + this.$viewport.height()/2) * this.zoom;
  };

  var DummyLayer = function(zoom, $viewport, config) {
    this.config = config;
    this.zoom = zoom;
    this.$viewport = $viewport;

    var $layer = $('<div/>');
    $viewport.children().each(function(index) {
      $(this).detach().appendTo($layer)
    });
    this.$layer = $layer;

    this.centerX = 0;
    this.centerY = 0;
  };

  DummyLayer.prototype.show = function() {
    this.$layer.css('z-index', 2);
    this.$layer.css('display', 'block');
  };

  DummyLayer.prototype.hide = function() {
    this.$layer.css('z-index', 1);
    this.$layer.css('display', 'none');
  };

  DummyLayer.prototype.load = function() {
    this.$viewport.append(this.$layer);
  };

  DummyLayer.prototype.move = function(centerX, centerY) {
    this.centerX = centerX;
    this.centerY = centerY;
  };

  var methods = {
    init : function(options) {
      var config = $.extend({
        original: { width: null, height: null },
        tileSize: 500,
        basePath: '',
        loading: '',
        zoom: 0,
        no0zoom: false
      }, options);

      // Basic sanitation check
      if (typeof config.original.width  !== 'number'
       || typeof config.original.height !== 'number') {
        throw 'Missing required fields original.width and original.height.';
      }
      if (config.original.width <= 0 || config.original.height <= 0) {
        throw 'Both original.width and original.height must be > 0';
      }

      // The basePath needs to end with a / if it is not empty
      var basePath = $.trim(config.basePath)
      if (basePath) {
        if (basePath.indexOf('/', basePath.length-1) === -1) {
          basePath += '/';
        }
      }
      config.basePath = basePath;

      this.data('config', config);

      return this.each(function() {
        var $this = $(this);
        $this.css('position', 'relative');
        $this.css('overflow', 'hidden');

        var layers = { };

        if (!config.no0zoom) {
          // Load the original layer to save the HTML content that
          // was inside viewport
          layers[0] = new DummyLayer(0, $this, config);
          layers[0].load();
          layers[0].hide();
        } else if (config.zoom == 0) {
          throw "You must specify a non-zero zoom if no0zoom is true";
        }

        var zoom = config.zoom;
        if (zoom != 0) {
          layers[zoom] = new Layer(zoom, $this, config);
          layers[zoom].load();
        }
        layers[zoom].show();

        $this.data('layers', layers);
        $this.data('zoom', zoom);
      });
    },
    zoom: function(factor) {
      var config = this.data('config');

      return this.each(function() {
        var $this = $(this);

        var zoom = $this.data('zoom');
        if (zoom == factor) return;

        var layers = $this.data('layers');

        var centerX = layers[zoom].centerX;
        var centerY = layers[zoom].centerY;
        layers[zoom].hide();
        zoom = factor;

        if (!layers[zoom]) {
          layers[zoom] = new Layer(zoom, $this, config);
          layers[zoom].load();
        }
        layers[zoom].show();
        layers[zoom].move(centerX, centerY);

        $this.data('layers', layers);
        $this.data('zoom', zoom);
      });
    },
    move: function(centerX, centerY) {
      var config = this.data('config');

      return this.each(function() {
        var $this = $(this);

        var zoom   = $this.data('zoom');
        var layers = $this.data('layers');

        layers[zoom].move(centerX*zoom, centerY*zoom);
      });
    },
    center: function() {
      var config = this.data('config');

      return this.each(function() {
        var $this = $(this);

        var zoom   = $this.data('zoom');
        var layers = $this.data('layers');

        layers[zoom].move(config.original.width/2, config.original.height/2);
      });
    }
  };

  $.fn.tiles = function (method) {
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method == 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error ('No such method: ' + method);
    }
  };

})(jQuery);
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    chalk = require('chalk'),
    output_file = './gitlogg.json';

console.log(chalk.yellow('Generating JSON output...'));

var changes = function(data, index) {
  var v = data.split(',')[index] || 0;
  var w = 0;
  if (v !== 0) {
    var w = v.split(' ')[1]; // the number of changes is second on the array
  }
  return parseInt(w);
};

console.time(chalk.green('JSON output generated in'));

var output = fs.readFileSync('gitlogg.tmp', 'utf8')
  .trim()
  .split('\n')
  .map(line => line.split('\\t'))
  .reduce((commits, item) => {

    // vars based on sequential values ( sanitise " to ' on fields that accept user input )
    var repository =                     item[3],                            // color-consolidator
        commit_nr =                      item[0],                            // 3
        commit_hash =                    item[5],                            // 5109ad5a394a4873290ff7f7a38b7ca2e1b3b8e1
        commit_hash_abbreviated =        item[7],                            // 5109ad5
        tree_hash =                      item[9],                            // a1606ea8d6e24e1c832b52cb9c04ae1df2242ed4
        tree_hash_abbreviated =          item[11],                           // a1606ea
        parent_hashes =                  item[13],                           // 7082fa621bf93503fe173d06ada3c6111054a62b
        parent_hashes_abbreviated =      item[15],                           // 7082fa6
        author_name =                    item[17].replace(/"/g, "'"),        // Wallace Sidhrée
        author_name_mailmap =            item[19],                           // Wallace Sidhrée
        author_email =                   item[21],                           // i@dreamyguy.com
        author_email_mailmap =           item[23],                           // i@dreamyguy.com
        author_date =                    item[25],                           // Fri Jan 3 14:16:56 2014 +0100
        author_date_RFC2822 =            item[27],                           // Fri, 3 Jan 2014 14:16:56 +0100
        author_date_relative =           item[29],                           // 2 years, 5 months ago
        author_date_unix_timestamp =     item[31],                           // 1388755016
        author_date_iso_8601 =           item[33],                           // 2014-01-03 14:16:56 +0100
        author_date_iso_8601_strict =    item[35],                           // 2014-01-03T14:16:56+01:00
        committer_name =                 item[37].replace(/"/g, "'"),        // Wallace Sidhrée
        committer_name_mailmap =         item[39],                           // Wallace Sidhrée
        committer_email =                item[41],                           // i@dreamyguy.com
        committer_email_mailmap =        item[43],                           // i@dreamyguy.com
        committer_date =                 item[45],                           // Fri Jan 3 14:16:56 2014 +0100
        committer_date_RFC2822 =         item[47],                           // Fri, 3 Jan 2014 14:16:56 +0100
        committer_date_relative =        item[49],                           // 2 years, 5 months ago
        committer_date_unix_timestamp =  item[51],                           // 1388755016
        committer_date_iso_8601 =        item[53],                           // 2014-01-03 14:16:56 +0100
        committer_date_iso_8601_strict = item[55],                           // 2014-01-03T14:16:56+01:00
        ref_names =                      item[57].replace(/"/g, "'"),        // ""
        ref_names_no_wrapping =          item[59].replace(/"/g, "'"),        // ""
        encoding =                       item[61],                           // ""
        subject =                        item[63].replace(/"/g, "'"),        // Upgrade FontAwesome from 3.2.1 to 4.0.3"
        subject_sanitized =              item[65],                           // Upgrade-FontAwesome-from-3.2.1-to-4.0.3"
        commit_notes =                   item[67].replace(/"/g, "'"),        // ""
        stats =                          item[69].slice(1);                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)`
    // vars that require manipulation
    var time_array =                     author_date.split(' '),             // Fri Jan 3 14:16:56 2014 +0100 => [Fri, Jan, 3, 14:16:56, 2014, +0100]
        time_array_clock =               time_array[3].split(':'),           // 14:16:56 => [14, 16, 56]
        time_hour =                      parseInt(time_array_clock[0], 10),  // [14, 16, 56] => 14
        time_minutes =                   parseInt(time_array_clock[1], 10),  // [14, 16, 56] => 16
        time_seconds =                   parseInt(time_array_clock[2], 10),  // [14, 16, 56] => 56
        time_gmt =                       time_array[5],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => +0100
        date_array =                     author_date_iso_8601.split(' ')[0], // 2014-01-03 14:16:56 +0100 => 2014-01-03
        date_day_week =                  time_array[0],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => Fri
        date_iso_8601 =                  date_array,                         // 2014-01-03
        date_month_day =                 parseInt(date_array.split('-')[2], 10),  // 2014-01-03 => [2014, 01, 03] => 03
        date_month_name =                time_array[1],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => Jan
        date_month_number =              parseInt(date_array.split('-')[1], 10),  // 2014-01-03 => [2014, 01, 03] => 01
        date_year =                      time_array[4],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => 2014
        files_changed =                  changes(stats, 0),                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)` => 9
        insertions =                     changes(stats, 1),                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)` => 507
        deletions =                      changes(stats, 2),                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)` => 2102
        impact =                         (insertions - deletions);           // 507 - 2102 => -1595

    commits[item[1]] = commits[item[1]] || [];
    commits[item[1]].push({
      repository: repository,
      commit_nr: commit_nr,
      commit_hash: commit_hash,
      // commit_hash_abbreviated: commit_hash_abbreviated,
      // tree_hash: tree_hash,
      // tree_hash_abbreviated: tree_hash_abbreviated,
      // parent_hashes: parent_hashes,
      // parent_hashes_abbreviated: parent_hashes_abbreviated,
      author_name: author_name,
      // author_name_mailmap: author_name_mailmap,
      author_email: author_email,
      // author_email_mailmap: author_email_mailmap,
      author_date: author_date,
      // author_date_RFC2822: author_date_RFC2822,
      author_date_relative: author_date_relative,
      author_date_unix_timestamp: author_date_unix_timestamp,
      author_date_iso_8601: author_date_iso_8601,
      // author_date_iso_8601_strict: author_date_iso_8601_strict,
      // committer_name: committer_name,
      // committer_name_mailmap: committer_name_mailmap,
      // committer_email: committer_email,
      // committer_email_mailmap: committer_email_mailmap,
      // committer_date: committer_date,
      // committer_date_RFC2822: committer_date_RFC2822,
      // committer_date_relative: committer_date_relative,
      // committer_date_unix_timestamp: committer_date_unix_timestamp,
      // committer_date_iso_8601: committer_date_iso_8601,
      // committer_date_iso_8601_strict: committer_date_iso_8601_strict,
      // ref_names: ref_names,
      // ref_names_no_wrapping: ref_names_no_wrapping,
      // encoding: encoding,
      subject: subject,
      subject_sanitized: subject_sanitized,
      // commit_notes: commit_notes,
      stats: stats,
      time_hour: time_hour,
      time_minutes: time_minutes,
      time_seconds: time_seconds,
      time_gmt: time_gmt,
      date_day_week: date_day_week,
      date_month_day: date_month_day,
      date_month_name: date_month_name,
      date_month_number: date_month_number,
      date_year: date_year,
      date_iso_8601: date_iso_8601,
      files_changed: files_changed,
      insertions: insertions,
      deletions: deletions,
      impact: impact
    });
    return commits;
  }, {});

console.timeEnd(chalk.green('JSON output generated in'));

console.log(chalk.yellow('Writing output to file...'));

// console.log('output', JSON.stringify(output, null, 2)) // comment this out to see the output on the terminal as well

fs.writeFile(output_file, JSON.stringify(output, null, 2), function(err) {
    if(err) {
        return console.log(chalk.red(err, 'Something went wrong, the file could not be written / saved'));
    }
    console.log(chalk.green('The file ' + chalk.blue(output_file) + ' was saved! '));
});
<commit_msg>Parse 'commit_nr' as an integer, not a string<commit_after>var fs = require('fs'),
    path = require('path'),
    chalk = require('chalk'),
    output_file = './gitlogg.json';

console.log(chalk.yellow('Generating JSON output...'));

var changes = function(data, index) {
  var v = data.split(',')[index] || 0;
  var w = 0;
  if (v !== 0) {
    var w = v.split(' ')[1]; // the number of changes is second on the array
  }
  return parseInt(w);
};

console.time(chalk.green('JSON output generated in'));

var output = fs.readFileSync('gitlogg.tmp', 'utf8')
  .trim()
  .split('\n')
  .map(line => line.split('\\t'))
  .reduce((commits, item) => {

    // vars based on sequential values ( sanitise " to ' on fields that accept user input )
    var repository =                     item[3],                            // color-consolidator
        commit_nr =                      parseInt(item[0], 10),              // 3
        commit_hash =                    item[5],                            // 5109ad5a394a4873290ff7f7a38b7ca2e1b3b8e1
        commit_hash_abbreviated =        item[7],                            // 5109ad5
        tree_hash =                      item[9],                            // a1606ea8d6e24e1c832b52cb9c04ae1df2242ed4
        tree_hash_abbreviated =          item[11],                           // a1606ea
        parent_hashes =                  item[13],                           // 7082fa621bf93503fe173d06ada3c6111054a62b
        parent_hashes_abbreviated =      item[15],                           // 7082fa6
        author_name =                    item[17].replace(/"/g, "'"),        // Wallace Sidhrée
        author_name_mailmap =            item[19],                           // Wallace Sidhrée
        author_email =                   item[21],                           // i@dreamyguy.com
        author_email_mailmap =           item[23],                           // i@dreamyguy.com
        author_date =                    item[25],                           // Fri Jan 3 14:16:56 2014 +0100
        author_date_RFC2822 =            item[27],                           // Fri, 3 Jan 2014 14:16:56 +0100
        author_date_relative =           item[29],                           // 2 years, 5 months ago
        author_date_unix_timestamp =     item[31],                           // 1388755016
        author_date_iso_8601 =           item[33],                           // 2014-01-03 14:16:56 +0100
        author_date_iso_8601_strict =    item[35],                           // 2014-01-03T14:16:56+01:00
        committer_name =                 item[37].replace(/"/g, "'"),        // Wallace Sidhrée
        committer_name_mailmap =         item[39],                           // Wallace Sidhrée
        committer_email =                item[41],                           // i@dreamyguy.com
        committer_email_mailmap =        item[43],                           // i@dreamyguy.com
        committer_date =                 item[45],                           // Fri Jan 3 14:16:56 2014 +0100
        committer_date_RFC2822 =         item[47],                           // Fri, 3 Jan 2014 14:16:56 +0100
        committer_date_relative =        item[49],                           // 2 years, 5 months ago
        committer_date_unix_timestamp =  item[51],                           // 1388755016
        committer_date_iso_8601 =        item[53],                           // 2014-01-03 14:16:56 +0100
        committer_date_iso_8601_strict = item[55],                           // 2014-01-03T14:16:56+01:00
        ref_names =                      item[57].replace(/"/g, "'"),        // ""
        ref_names_no_wrapping =          item[59].replace(/"/g, "'"),        // ""
        encoding =                       item[61],                           // ""
        subject =                        item[63].replace(/"/g, "'"),        // Upgrade FontAwesome from 3.2.1 to 4.0.3"
        subject_sanitized =              item[65],                           // Upgrade-FontAwesome-from-3.2.1-to-4.0.3"
        commit_notes =                   item[67].replace(/"/g, "'"),        // ""
        stats =                          item[69].slice(1);                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)`
    // vars that require manipulation
    var time_array =                     author_date.split(' '),             // Fri Jan 3 14:16:56 2014 +0100 => [Fri, Jan, 3, 14:16:56, 2014, +0100]
        time_array_clock =               time_array[3].split(':'),           // 14:16:56 => [14, 16, 56]
        time_hour =                      parseInt(time_array_clock[0], 10),  // [14, 16, 56] => 14
        time_minutes =                   parseInt(time_array_clock[1], 10),  // [14, 16, 56] => 16
        time_seconds =                   parseInt(time_array_clock[2], 10),  // [14, 16, 56] => 56
        time_gmt =                       time_array[5],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => +0100
        date_array =                     author_date_iso_8601.split(' ')[0], // 2014-01-03 14:16:56 +0100 => 2014-01-03
        date_day_week =                  time_array[0],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => Fri
        date_iso_8601 =                  date_array,                         // 2014-01-03
        date_month_day =                 parseInt(date_array.split('-')[2], 10),  // 2014-01-03 => [2014, 01, 03] => 03
        date_month_name =                time_array[1],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => Jan
        date_month_number =              parseInt(date_array.split('-')[1], 10),  // 2014-01-03 => [2014, 01, 03] => 01
        date_year =                      time_array[4],                      // [Fri, Jan, 3, 14:16:56, 2014, +0100] => 2014
        files_changed =                  changes(stats, 0),                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)` => 9
        insertions =                     changes(stats, 1),                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)` => 507
        deletions =                      changes(stats, 2),                  // ` 9 files changed, 507 insertions(+), 2102 deletions(-)` => 2102
        impact =                         (insertions - deletions);           // 507 - 2102 => -1595

    commits[item[1]] = commits[item[1]] || [];
    commits[item[1]].push({
      repository: repository,
      commit_nr: commit_nr,
      commit_hash: commit_hash,
      // commit_hash_abbreviated: commit_hash_abbreviated,
      // tree_hash: tree_hash,
      // tree_hash_abbreviated: tree_hash_abbreviated,
      // parent_hashes: parent_hashes,
      // parent_hashes_abbreviated: parent_hashes_abbreviated,
      author_name: author_name,
      // author_name_mailmap: author_name_mailmap,
      author_email: author_email,
      // author_email_mailmap: author_email_mailmap,
      author_date: author_date,
      // author_date_RFC2822: author_date_RFC2822,
      author_date_relative: author_date_relative,
      author_date_unix_timestamp: author_date_unix_timestamp,
      author_date_iso_8601: author_date_iso_8601,
      // author_date_iso_8601_strict: author_date_iso_8601_strict,
      // committer_name: committer_name,
      // committer_name_mailmap: committer_name_mailmap,
      // committer_email: committer_email,
      // committer_email_mailmap: committer_email_mailmap,
      // committer_date: committer_date,
      // committer_date_RFC2822: committer_date_RFC2822,
      // committer_date_relative: committer_date_relative,
      // committer_date_unix_timestamp: committer_date_unix_timestamp,
      // committer_date_iso_8601: committer_date_iso_8601,
      // committer_date_iso_8601_strict: committer_date_iso_8601_strict,
      // ref_names: ref_names,
      // ref_names_no_wrapping: ref_names_no_wrapping,
      // encoding: encoding,
      subject: subject,
      subject_sanitized: subject_sanitized,
      // commit_notes: commit_notes,
      stats: stats,
      time_hour: time_hour,
      time_minutes: time_minutes,
      time_seconds: time_seconds,
      time_gmt: time_gmt,
      date_day_week: date_day_week,
      date_month_day: date_month_day,
      date_month_name: date_month_name,
      date_month_number: date_month_number,
      date_year: date_year,
      date_iso_8601: date_iso_8601,
      files_changed: files_changed,
      insertions: insertions,
      deletions: deletions,
      impact: impact
    });
    return commits;
  }, {});

console.timeEnd(chalk.green('JSON output generated in'));

console.log(chalk.yellow('Writing output to file...'));

// console.log('output', JSON.stringify(output, null, 2)) // comment this out to see the output on the terminal as well

fs.writeFile(output_file, JSON.stringify(output, null, 2), function(err) {
    if(err) {
        return console.log(chalk.red(err, 'Something went wrong, the file could not be written / saved'));
    }
    console.log(chalk.green('The file ' + chalk.blue(output_file) + ' was saved! '));
});
<|endoftext|>


<commit_before>'use strict';

const request = require('request');
const core = require('./../core/core.js');
const TelegramBot = require('node-telegram-bot-api');

/**
 * CREDENTIALS
 **/
const TELEGRAM_ACCESS_TOKEN = process.env.TELEGRAM_ACCESS_TOKEN;

var telegram = new TelegramBot(TELEGRAM_ACCESS_TOKEN, { polling: true });

telegram.on("text", (message) => {
    receivedMessage(message);
    //telegram.sendMessage(message.chat.id, "Hello world");
});

telegram.on("location", (message) => {
    receivedLocation(message);
    //telegram.sendMessage(message.chat.id, "Hello world");
});

/*
* Fonction appelé par quand on recoit une localisation
*/
function receivedLocation(message) {
    console.log(JSON.stringify(message));
    var senderID = message.chat.id;
    var message = {
        channel: "Telegram",
        senderID: senderID.toString(),
        timestamp: message.date,
        first_name: message.from.first_name,
        last_name: message.from.last_name,
        location: {
            lat: message.location.latitude,
            long: message.location.longitude
        }
    };
    core.receivedMessage(message);
}

/*
* Fonction appelé par quand on recoit un message
*/
function receivedMessage(message) {
    console.log(JSON.stringify(message));
    var senderID = message.chat.id;
    var message = {
        channel: "Telegram",
        senderID: senderID.toString(),
        timestamp: message.date,
        text: message.text,
        first_name: message.from.first_name,
        last_name: message.from.last_name
    };
    core.receivedMessage(message);
}

/*
* Fonction appelé par le core pour envoyer un message sur la channel Facebook
*/
function sendMessage(message) {
    switch(message.type) {
        case "text":
            sendTextMessage(message);
        break;
        case "quickreply":
            sendQuickReplyMessage(message);
        break;
        case "location":
            sendLocationMessage(message);
        break;
        case "template":
            sendTemplateMessage(message);
        break;
    }
}

/*
* Fonction appelé par le core pour envoyer des messages sur la channel Facebook
*/
function sendMessages(messages) {
    for(var i=0;i<messages.length;i++) {
        sendMessage(messages[i]);
    }
}

/*
* Fonction qui envoie un message de type text
*/
function sendTextMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        telegram.sendMessage(message.senderID, message.text);
    }
}

/*
* Fonction qui envoie un message de type quickreply
*/
function sendQuickReplyMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var replykeyboard = {keyboard:[]};
        for(var i=0;i<message.choices.length;i++) {
            var button = [{
                text: message.choices[i]
            }];
            replykeyboard.keyboard.push(button);
        }
        //console.log(JSON.stringify({reply_markup: {keyboard:[[{text:"coucou"}]]}}));
        telegram.sendMessage(message.senderID, message.text, {reply_markup: replykeyboard});
    }
}

/*
* Fonction qui envoie un message de type location
*/
function sendLocationMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var replykeyboard = {keyboard:[], one_time_keyboard:true};
        var button = [{
            text: message.text,
            request_location : true
        }];
        replykeyboard.keyboard.push(button);
        telegram.sendMessage(message.senderID, message.text, {reply_markup: replykeyboard});
    }
}

/*
* Fonction qui envoie un message de type location
*/
function sendTemplateMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.attachment != undefined) {
        var elements = [];
        /*
        *   Envoie du message avant le template
        */
        telegram.sendMessage(message.senderID, message.text);
        telegram.sendVenue(message.senderID, message.attachment[i].lat, message.attachment[i].long, message.attachment[i].title, message.attachment[i].subtitle);
        /*for(var i=0;i<message.attachment.length;i++) {
            telegram.sendVenue(message.senderID, message.attachment[i].lat, message.attachment[i].long, message.attachment[i].title, message.attachment[i].subtitle)
            if(i==3)break;
        }*/
    }
}

/*
* Fonction qui envoie un message audio/file/image/video
*/
function sendFileMessage(message) {
    /*console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                attachment:{
                    type: message.type,
                    payload: {
                        url: message.text
                    }
                }
            }
        };
        callSendAPI(messageData);
    }*/
}

exports.sendMessage = sendMessage
exports.sendMessages = sendMessages<commit_msg>Fix bug<commit_after>'use strict';

const request = require('request');
const core = require('./../core/core.js');
const TelegramBot = require('node-telegram-bot-api');

/**
 * CREDENTIALS
 **/
const TELEGRAM_ACCESS_TOKEN = process.env.TELEGRAM_ACCESS_TOKEN;

var telegram = new TelegramBot(TELEGRAM_ACCESS_TOKEN, { polling: true });

telegram.on("text", (message) => {
    receivedMessage(message);
    //telegram.sendMessage(message.chat.id, "Hello world");
});

telegram.on("location", (message) => {
    receivedLocation(message);
    //telegram.sendMessage(message.chat.id, "Hello world");
});

/*
* Fonction appelé par quand on recoit une localisation
*/
function receivedLocation(message) {
    console.log(JSON.stringify(message));
    var senderID = message.chat.id;
    var message = {
        channel: "Telegram",
        senderID: senderID.toString(),
        timestamp: message.date,
        first_name: message.from.first_name,
        last_name: message.from.last_name,
        location: {
            lat: message.location.latitude,
            long: message.location.longitude
        }
    };
    core.receivedMessage(message);
}

/*
* Fonction appelé par quand on recoit un message
*/
function receivedMessage(message) {
    console.log(JSON.stringify(message));
    var senderID = message.chat.id;
    var message = {
        channel: "Telegram",
        senderID: senderID.toString(),
        timestamp: message.date,
        text: message.text,
        first_name: message.from.first_name,
        last_name: message.from.last_name
    };
    core.receivedMessage(message);
}

/*
* Fonction appelé par le core pour envoyer un message sur la channel Facebook
*/
function sendMessage(message) {
    switch(message.type) {
        case "text":
            sendTextMessage(message);
        break;
        case "quickreply":
            sendQuickReplyMessage(message);
        break;
        case "location":
            sendLocationMessage(message);
        break;
        case "template":
            sendTemplateMessage(message);
        break;
    }
}

/*
* Fonction appelé par le core pour envoyer des messages sur la channel Facebook
*/
function sendMessages(messages) {
    for(var i=0;i<messages.length;i++) {
        sendMessage(messages[i]);
    }
}

/*
* Fonction qui envoie un message de type text
*/
function sendTextMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        telegram.sendMessage(message.senderID, message.text);
    }
}

/*
* Fonction qui envoie un message de type quickreply
*/
function sendQuickReplyMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var replykeyboard = {keyboard:[]};
        for(var i=0;i<message.choices.length;i++) {
            var button = [{
                text: message.choices[i]
            }];
            replykeyboard.keyboard.push(button);
        }
        //console.log(JSON.stringify({reply_markup: {keyboard:[[{text:"coucou"}]]}}));
        telegram.sendMessage(message.senderID, message.text, {reply_markup: replykeyboard});
    }
}

/*
* Fonction qui envoie un message de type location
*/
function sendLocationMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var replykeyboard = {keyboard:[], one_time_keyboard:true};
        var button = [{
            text: message.text,
            request_location : true
        }];
        replykeyboard.keyboard.push(button);
        telegram.sendMessage(message.senderID, message.text, {reply_markup: replykeyboard});
    }
}

/*
* Fonction qui envoie un message de type location
*/
function sendTemplateMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.attachment != undefined) {
        var elements = [];
        /*
        *   Envoie du message avant le template
        */
        telegram.sendMessage(message.senderID, message.text);
        telegram.sendVenue(message.senderID, message.attachment[0].lat, message.attachment[0].long, message.attachment[0].title, message.attachment[0].subtitle);
        /*for(var i=0;i<message.attachment.length;i++) {
            telegram.sendVenue(message.senderID, message.attachment[i].lat, message.attachment[i].long, message.attachment[i].title, message.attachment[i].subtitle)
            if(i==3)break;
        }*/
    }
}

/*
* Fonction qui envoie un message audio/file/image/video
*/
function sendFileMessage(message) {
    /*console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                attachment:{
                    type: message.type,
                    payload: {
                        url: message.text
                    }
                }
            }
        };
        callSendAPI(messageData);
    }*/
}

exports.sendMessage = sendMessage
exports.sendMessages = sendMessages<|endoftext|>


<commit_before>dojo.provide("dijit.util.PopupManager");

dojo.require("dijit.util.BackgroundIframe");
dojo.require("dijit.util.FocusManager");
dojo.require("dijit.util.place");
dojo.require("dijit.util.window");

dijit.util.PopupManager = new function(){
	// summary:
	//		This class is used to show/hide popups.
	//
	//		The widget must implement a close() callback, which is called when someone
	//		clicks somewhere random on the screen.  It will hide the [chain of] context menus

	var stack = [];
	var beginZIndex=1000;

	this.open = function(/*Event*/ e, /*Widget*/widget, /*Object*/ padding){
		// summary:
		//		Open the widget at mouse position
		//		TODO: if widget has href, attach to onLoaded() and reposition

		var x = e.pageX, y = e.pageY;
		// FIXME: consider skipping everything up to _open
		// if x == y == 0, allowing the popup to appear
		// wherever it was last time.
		var win = dijit.util.window.getDocumentWindow(e.target.ownerDocument);
		var iframe = win._frameElement || win.frameElement;
		if(iframe){
			var cood = dojo.coords(iframe, true);
			x += cood.x - dojo.withGlobal(win, dijit.util.getScroll).left;
			y += cood.y - dojo.withGlobal(win, dijit.util.getScroll).top;
		}
		dijit.util.placeOnScreen(widget.domNode, x, y, padding, true);

		_open(widget);
	}

	this.openAround = function(/*Widget*/parent, /*Widget*/widget, /*String?*/orient, /*Array?*/padding){
		// summary:
		//		Open the widget relative to parent widget (typically as a drop down to that widget)
		//		TODO: if widget has href attach to onLoaded and reposition

		dijit.util.placeOnScreenAroundElement(widget.domNode, parent, padding, orient);

		_open(widget);
	};

	function _open(widget){
		// summary:
		//		Utility function to help opening

		// display temporarily, and move into position, then hide again
		with(widget.domNode.style){
			zIndex = beginZIndex + stack.length;
			position = "absolute";
		}

		if(stack.length == 0){
			beforeTopOpen(null, widget);
		}

		stack.push(widget);

		// TODO: use effects
		dojo.style(widget.domNode, "display", "");

		if(dojo.isIE && dojo.isIE < 7){
			if(!widget.bgIframe){
				widget.bgIframe = new dijit.util.BackgroundIframe();
				widget.bgIframe.setZIndex(widget.domNode);
			}
			widget.bgIframe.size(widget.domNode);
			widget.bgIframe.show();
		}

	};

	this.close = function(){
		// summary:
		//		Close top level popup

		var widget = stack.pop();

		dojo.style(widget.domNode, "display", "none");
		if(dojo.isIE && dojo.isIE < 7){
			widget.bgIframe.hide();
		}

		if(stack.length == 0){
			afterTopClose(widget);
		}
	};

	///////////////////////////////////////////////////////////////////////
	// Utility functions for making mouse click close popup chain
	var currentTrigger;

	function beforeTopOpen(/*Widget*/ button, /*Widget*/menu){
		// summary:
		//	Called when a popup is opened, typically a button opening a menu.
		//	Registers handlers so that clicking somewhere else on the screen will close the popup

		// TODO: should do this at every level of popup?
		dijit.util.FocusManager.save(menu);

		currentTrigger=button;

		// setup handlers to catch screen clicks and close current menu
		setWindowEvents("connect");
	};

	function afterTopClose(/*Widget*/menu){
		// summary:
		//	called when the top level popup is closed, but before it performs it's actions
		//	removes handlers for mouse movement detection

		// remove handlers to catch screen clicks and close current menu
		// TODO: this doesn't seem to have any effect; try it after scott's new event code.
		setWindowEvents("disconnect");

		currentTrigger = null;

		dijit.util.FocusManager.restore(menu);
	};

	function onKeyPress(/*Event*/e){
		// summary
		//	Handles keystrokes, passing them up the chain of menus
		if((!e.keyCode) && (e.charCode != dojo.keys.SPACE)){ return; }
		if(stack.length==0){ return; }

		// loop from child menu up ancestor chain, ending at button that spawned the menu
		var m = stack[stack.length-1];
		while(m){
			if(m.processKey(e)){
				e.preventDefault();
				e.stopPropagation();
				break;
			}
			m = m.parentPopup || m.parentMenu;
		}
	};

	function onMouse(/*Event*/e){
		// summary
		// Monitor clicks in the screen.  If popup has requested it than
		// clicking anywhere on the screen will close the current menu hierarchy

		if(stack.length==0){ return; }

		//PORT #2804. Use isAncestor
		var isDescendantOf = function(/*Node*/node, /*Node*/ancestor){
			//	summary
			//	Returns boolean if node is a descendant of ancestor
			// guaranteeDescendant allows us to be a "true" isDescendantOf function

			while(node){
				if(node === ancestor){
					return true; // boolean
				}
				node = node.parentNode;
			}
			return false; // boolean
		}

		// if they clicked on the trigger node (often a button), ignore the click
		if(currentTrigger && isDescendantOf(e.target, currentTrigger)){
			return;
		}

		// if they clicked on the popup itself then ignore it
		if(dojo.some(stack, function(widget){
			return isDescendantOf(e.target, widget.domNode);
		}))
		{
			return;
		}

		// the click didn't fall within the open menu tree so close it
		stack[0].close(true);
	};

	function setWindowEvents(/*String*/ command, /*Window*/targetWindow){
		// summary:
		//		This function connects or disconnects listeners on all the iframes
		//		and the top window, so that whereever the user clicks in the page,
		//		the popup menu will be closed

		if(!targetWindow){ //see comment below
			targetWindow = dijit.util.window.getDocumentWindow(window.top && window.top.document || window.document);
		}

		if(command == 'connect'){
			targetWindow._onmousedownhandler = dojo.connect(targetWindow.document, "onmousedown", null, onMouse);
			targetWindow._onscrollhandler = dojo.connect(targetWindow, "onscroll", null, onMouse);
			targetWindow._onkeyhandler = dojo.connect(targetWindow.document, "onkeypress", null, onKeyPress);
		}else{
			dojo.disconnect(targetWindow._onmousedownhandler);
			targetWindow._onmousedownhandler = null;
			dojo.disconnect(targetWindow._onscrollhandler);
			targetWindow._onscrollhandler = null;
			dojo.disconnect(targetWindow._onkeyhandler);
			targetWindow._onkeyhandler = null;
		}

		for(var i = 0; i < targetWindow.frames.length; i++){
			try{
				//do not remove dijit.util.window.getDocumentWindow, see comment in it
				var win = dijit.util.window.getDocumentWindow(targetWindow.frames[i].document);
				if(win){
					setWindowEvents(command, win);
				}
			}catch(e){ /* squelch error for cross domain iframes */ }
		}
	};
	dojo.addOnUnload(function(){ setWindowEvents("disconnect"); });
}();<commit_msg>Fixes #3013.  Added test for processKey function.<commit_after>dojo.provide("dijit.util.PopupManager");

dojo.require("dijit.util.BackgroundIframe");
dojo.require("dijit.util.FocusManager");
dojo.require("dijit.util.place");
dojo.require("dijit.util.window");

dijit.util.PopupManager = new function(){
	// summary:
	//		This class is used to show/hide popups.
	//
	//		The widget must implement a close() callback, which is called when someone
	//		clicks somewhere random on the screen.  It will hide the [chain of] context menus

	var stack = [];
	var beginZIndex=1000;

	this.open = function(/*Event*/ e, /*Widget*/widget, /*Object*/ padding){
		// summary:
		//		Open the widget at mouse position
		//		TODO: if widget has href, attach to onLoaded() and reposition

		var x = e.pageX, y = e.pageY;
		// FIXME: consider skipping everything up to _open
		// if x == y == 0, allowing the popup to appear
		// wherever it was last time.
		var win = dijit.util.window.getDocumentWindow(e.target.ownerDocument);
		var iframe = win._frameElement || win.frameElement;
		if(iframe){
			var cood = dojo.coords(iframe, true);
			x += cood.x - dojo.withGlobal(win, dijit.util.getScroll).left;
			y += cood.y - dojo.withGlobal(win, dijit.util.getScroll).top;
		}
		dijit.util.placeOnScreen(widget.domNode, x, y, padding, true);

		_open(widget);
	}

	this.openAround = function(/*Widget*/parent, /*Widget*/widget, /*String?*/orient, /*Array?*/padding){
		// summary:
		//		Open the widget relative to parent widget (typically as a drop down to that widget)
		//		TODO: if widget has href attach to onLoaded and reposition

		dijit.util.placeOnScreenAroundElement(widget.domNode, parent, padding, orient);

		_open(widget);
	};

	function _open(widget){
		// summary:
		//		Utility function to help opening

		// display temporarily, and move into position, then hide again
		with(widget.domNode.style){
			zIndex = beginZIndex + stack.length;
			position = "absolute";
		}

		if(stack.length == 0){
			beforeTopOpen(null, widget);
		}

		stack.push(widget);

		// TODO: use effects
		dojo.style(widget.domNode, "display", "");

		if(dojo.isIE && dojo.isIE < 7){
			if(!widget.bgIframe){
				widget.bgIframe = new dijit.util.BackgroundIframe();
				widget.bgIframe.setZIndex(widget.domNode);
			}
			widget.bgIframe.size(widget.domNode);
			widget.bgIframe.show();
		}

	};

	this.close = function(){
		// summary:
		//		Close top level popup

		var widget = stack.pop();

		dojo.style(widget.domNode, "display", "none");
		if(dojo.isIE && dojo.isIE < 7){
			widget.bgIframe.hide();
		}

		if(stack.length == 0){
			afterTopClose(widget);
		}
	};

	///////////////////////////////////////////////////////////////////////
	// Utility functions for making mouse click close popup chain
	var currentTrigger;

	function beforeTopOpen(/*Widget*/ button, /*Widget*/menu){
		// summary:
		//	Called when a popup is opened, typically a button opening a menu.
		//	Registers handlers so that clicking somewhere else on the screen will close the popup

		// TODO: should do this at every level of popup?
		dijit.util.FocusManager.save(menu);

		currentTrigger=button;

		// setup handlers to catch screen clicks and close current menu
		setWindowEvents("connect");
	};

	function afterTopClose(/*Widget*/menu){
		// summary:
		//	called when the top level popup is closed, but before it performs it's actions
		//	removes handlers for mouse movement detection

		// remove handlers to catch screen clicks and close current menu
		// TODO: this doesn't seem to have any effect; try it after scott's new event code.
		setWindowEvents("disconnect");

		currentTrigger = null;

		dijit.util.FocusManager.restore(menu);
	};

	function onKeyPress(/*Event*/e){
		// summary
		//	Handles keystrokes, passing them up the chain of menus
		if((!e.keyCode) && (e.charCode != dojo.keys.SPACE)){ return; }
		if(stack.length==0){ return; }

		// loop from child menu up ancestor chain, ending at button that spawned the menu
		var m = stack[stack.length-1];
		while(m){
			if(m.processKey && m.processKey(e)){
				e.preventDefault();
				e.stopPropagation();
				break;
			}
			m = m.parentPopup || m.parentMenu;
		}
	};

	function onMouse(/*Event*/e){
		// summary
		// Monitor clicks in the screen.  If popup has requested it than
		// clicking anywhere on the screen will close the current menu hierarchy

		if(stack.length==0){ return; }

		//PORT #2804. Use isAncestor
		var isDescendantOf = function(/*Node*/node, /*Node*/ancestor){
			//	summary
			//	Returns boolean if node is a descendant of ancestor
			// guaranteeDescendant allows us to be a "true" isDescendantOf function

			while(node){
				if(node === ancestor){
					return true; // boolean
				}
				node = node.parentNode;
			}
			return false; // boolean
		}

		// if they clicked on the trigger node (often a button), ignore the click
		if(currentTrigger && isDescendantOf(e.target, currentTrigger)){
			return;
		}

		// if they clicked on the popup itself then ignore it
		if(dojo.some(stack, function(widget){
			return isDescendantOf(e.target, widget.domNode);
		}))
		{
			return;
		}

		// the click didn't fall within the open menu tree so close it
		stack[0].close(true);
	};

	function setWindowEvents(/*String*/ command, /*Window*/targetWindow){
		// summary:
		//		This function connects or disconnects listeners on all the iframes
		//		and the top window, so that whereever the user clicks in the page,
		//		the popup menu will be closed

		if(!targetWindow){ //see comment below
			targetWindow = dijit.util.window.getDocumentWindow(window.top && window.top.document || window.document);
		}

		if(command == 'connect'){
			targetWindow._onmousedownhandler = dojo.connect(targetWindow.document, "onmousedown", null, onMouse);
			targetWindow._onscrollhandler = dojo.connect(targetWindow, "onscroll", null, onMouse);
			targetWindow._onkeyhandler = dojo.connect(targetWindow.document, "onkeypress", null, onKeyPress);
		}else{
			dojo.disconnect(targetWindow._onmousedownhandler);
			targetWindow._onmousedownhandler = null;
			dojo.disconnect(targetWindow._onscrollhandler);
			targetWindow._onscrollhandler = null;
			dojo.disconnect(targetWindow._onkeyhandler);
			targetWindow._onkeyhandler = null;
		}

		for(var i = 0; i < targetWindow.frames.length; i++){
			try{
				//do not remove dijit.util.window.getDocumentWindow, see comment in it
				var win = dijit.util.window.getDocumentWindow(targetWindow.frames[i].document);
				if(win){
					setWindowEvents(command, win);
				}
			}catch(e){ /* squelch error for cross domain iframes */ }
		}
	};
	dojo.addOnUnload(function(){ setWindowEvents("disconnect"); });
}();<|endoftext|>


<commit_before>/**
 * Author: Michał Gołębiowski <michal.golebiowski@laboratorium.ee>
 * Author: Brandon Aaron (http://brandonaaron.net)
 * Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
 * Copyright (c) 2013 Laboratorium EE (http://laboratorium.ee)
 */

(function ($) {
    'use strict';

    if ($.fn.wheel) { // already polyfilled
        return;
    }

    // Modern browsers support 'wheel', others - 'mousewheel'.
    var nativeEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

    // Normalizing event properties for the 'wheel' event (like event.which etc.).
    if (nativeEvent === 'wheel') {
        $.event.fixHooks.wheel = $.event.mouseHooks;
    } else {
        // We can't attach hooks to 'wheel' only since we need a type matching to originalEvent.type
        // and this field is non-mutable.
        $.event.fixHooks.mousewheel = $.event.mouseHooks;
    }

    function handler(orgEvent) {
        // Handler for the 'mousewheel' event (Chrome, Opera, Safari).
        /* jshint validthis: true */ // event handler

        var event = $.event.fix(orgEvent);

        if (nativeEvent === 'wheel') {
            event.deltaMode = orgEvent.deltaMode;
            event.deltaX = orgEvent.deltaX;
            event.deltaY = orgEvent.deltaY;
            event.deltaZ = orgEvent.deltaZ;
        } else {
            event.type = 'wheel';
            event.deltaMode = 0; // deltaMode === 0 => scrolling in pixels (in Chrome default wheelDeltaY is 120)
            event.deltaX = -1 * orgEvent.wheelDeltaX;
            event.deltaY = -1 * orgEvent.wheelDeltaY;
            event.deltaZ = 0; // not supported
        }

        // Exchange original event for the modified one in arguments list.
        var args = [].slice.call(arguments, 0);
        args[0] = event;

        return $.event.dispatch.apply(this, args);
    }

    // Implementing 'wheel' using non-standard 'mousewheel' event.
    $.event.special.wheel = {
        setup: function () {
            this.addEventListener(nativeEvent, handler, false);
        },

        teardown: function () {
            this.removeEventListener(nativeEvent, handler, false);
        }
    };

    // Implement `$object.wheel()` and `$object.wheel(handler)`.
    $.fn.wheel = function (data, fn) {
        return arguments.length > 0 ?
            this.on('wheel', null, data, fn) :
            this.trigger('wheel');
    };
})(jQuery);
<commit_msg>updated copyright (the plugin has little in common with its basis), added license<commit_after>/**
 * Author & Copyright: Michał Gołębiowski <m.goleb@gmail.com>
 * License: MIT
 *
 * Thanks to Brandon Aaron (http://brandonaaron.net) for the idea of this plugin.
 */

(function ($) {
    'use strict';

    if ($.fn.wheel) { // already polyfilled
        return;
    }

    // Modern browsers support 'wheel', others - 'mousewheel'.
    var nativeEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

    // Normalizing event properties for the 'wheel' event (like event.which etc.).
    if (nativeEvent === 'wheel') {
        $.event.fixHooks.wheel = $.event.mouseHooks;
    } else {
        // We can't attach hooks to 'wheel' only since we need a type matching to originalEvent.type
        // and this field is non-mutable.
        $.event.fixHooks.mousewheel = $.event.mouseHooks;
    }

    function handler(orgEvent) {
        // Handler for the 'mousewheel' event (Chrome, Opera, Safari).
        /* jshint validthis: true */ // event handler

        var event = $.event.fix(orgEvent);

        if (nativeEvent === 'wheel') {
            event.deltaMode = orgEvent.deltaMode;
            event.deltaX = orgEvent.deltaX;
            event.deltaY = orgEvent.deltaY;
            event.deltaZ = orgEvent.deltaZ;
        } else {
            event.type = 'wheel';
            event.deltaMode = 0; // deltaMode === 0 => scrolling in pixels (in Chrome default wheelDeltaY is 120)
            event.deltaX = -1 * orgEvent.wheelDeltaX;
            event.deltaY = -1 * orgEvent.wheelDeltaY;
            event.deltaZ = 0; // not supported
        }

        // Exchange original event for the modified one in arguments list.
        var args = [].slice.call(arguments, 0);
        args[0] = event;

        return $.event.dispatch.apply(this, args);
    }

    // Implementing 'wheel' using non-standard 'mousewheel' event.
    $.event.special.wheel = {
        setup: function () {
            this.addEventListener(nativeEvent, handler, false);
        },

        teardown: function () {
            this.removeEventListener(nativeEvent, handler, false);
        }
    };

    // Implement `$object.wheel()` and `$object.wheel(handler)`.
    $.fn.wheel = function (data, fn) {
        return arguments.length > 0 ?
            this.on('wheel', null, data, fn) :
            this.trigger('wheel');
    };
})(jQuery);
<|endoftext|>


<commit_before>const EventEmitter = require('events');
const Docker = require('dockerode');
const concat = require('concat-stream');

// Docker connection
const docker = new Docker();

// Time to wait between checking that the command has been executed (milliseconds)
const EXEC_WAIT_TIME_MS = 250;

// JavaBox eventEmitter
const javaBox = new EventEmitter();

javaBox.on('runJava', runJava);
javaBox.on('runJunit', runJunit);

// Run the Main.java inside the tar and outputs the result to the socket
function runJava(clientId, main, tarPath, timeLimitCompile, timeLimitExecution) {

    const className = main.split('.')[0];

    const javacCmd = ['javac', '-cp', 'home:junit/junit-4.12:junit/hamcrest-core-1.3', 'home/' + main];
    const javaCmd = ['java', '-cp', 'home:junit/junit-4.12:junit/hamcrest-core-1.3', className];

    const sourceLocation = tarPath;
    const execution = dockerCommand(javacCmd, timeLimitCompile, dockerCommand(javaCmd, timeLimitExecution));

    createJContainer(clientId, sourceLocation, false, execution);
};

function runJunit(clientId, junitFileNames, tarPath, timeLimitCompile, timeLimitExecution) {

    let junitFiles = [];
    junitFileNames.forEach((f)=>{
        junitFiles.push( f.name.split('.')[0]);
    });

    const className = 'TestRunner';

    const javacCmd = ['javac', '-cp', 'home:libs/junit-4.12:libs/hamcrest-core-1.3:libs/json-simple-1.1.1'];
    let javaCmd = ['java', '-cp', 'home:libs/junit-4.12:libs/hamcrest-core-1.3:libs/json-simple-1.1.1', className];

    junitFiles.forEach((file)=>{
        javacCmd.push('home/' + file + '.java');
        javaCmd.push(file);
    });
    javacCmd.push('home/' + className + '.java');

    const sourceLocation = tarPath;
    const execution = dockerCommand(javacCmd, timeLimitCompile, dockerCommand(javaCmd, timeLimitExecution));

    createJContainer(clientId, sourceLocation, true, execution);
};

// Creates and starts a container with bash, JDK SE and more
function createJContainer(clientId, javaSourceTar, isJunit, callback) {

    let copyToCall = 3;

    const tryCallback = (container) => {

        if (copyToCall === 0) {

            callback(null, container);
        }
    };

    const createOpts = {Image: 'openjdk:8u111-jdk', Tty: true, Cmd: ['/bin/bash']};
    docker.createContainer(createOpts, (err, container) => {

        if (err) {callback(err, container); return}

        container['clientId'] = clientId;

        const startOpts = {};
        container.start(startOpts, (err, data) => {

            if (err) {callback(err, data); return};

            if (isJunit) {

                const tarOptsRunner = {path: 'home'};
                container.putArchive('./archives/TestRunner.java.tar', tarOptsRunner, (err, data) => {
                    copyToCall--;
                    if (err) callback(err, data);
                    else tryCallback(container);

                });

                const tarOptsLibs = {path: '/'};
                container.putArchive('./archives/libs.tar', tarOptsLibs, (err, data) => {
                    copyToCall--;
                    if (err) callback(err, data);
                    else tryCallback(container);
                });
            } else {
                copyToCall = 1;
            }

            const tarOptsSource = {path: 'home'};
            container.putArchive(javaSourceTar, tarOptsSource, (err, data) => {
                copyToCall--;
                if (err) callback(err, data);
                else tryCallback(container);
            });
        });
    });
};

/*
 * Returns a function that on some given container,
 * executes a specific command, attaches the specific output listener and
 * after the command is executed pipelines the next one
 */
function dockerCommand(command, commandTimeLimit, nextCommand) {

    const opts = {Cmd: command, AttachStdout: true, AttachStderr: true};

    const execution = (err, container) => {

        if (!err) container.exec(opts, (err, exec) => {
            exec.start((err, stream) => {

                let stdOut = '';
                let stdErr = '';
                const stdOutStream = concat({}, (data) => {
                    stdOut += data;
                });
                const stdErrStream = concat({}, (data) => {
                    stdErr += data;
                });

                container.modem.demuxStream(stream, stdOutStream, stdErrStream);

                const streamManager = {

                    readOut: () => {return stdOut},
                    readErr: () => {return stdErr},
                    endStream: () => {
                        stdOutStream.end();
                        stdErrStream.end();
                    }
                };

                waitCmdExit(container, exec, nextCommand, streamManager, commandTimeLimit);
            });
        });
    };

    return execution;
};

// Ensures that the exec process is terminated and fires the next command
function waitCmdExit(container, exec, nextCommand, streamManager, commandTimeOut, previousTime){

    let timeSpent = previousTime || 0;

    const checkExit = (err, data) => {

        if (data.Running) { // command is still running, check later or send time out

            timeSpent += EXEC_WAIT_TIME_MS;                             // count time spent

            if (timeSpent >= commandTimeOut){                           // time period expired

                feedbackAndClose(container, streamManager, false, true);

            } else {

            waitCmdExit(container, exec, nextCommand, streamManager, commandTimeOut, timeSpent);

            }

        } else if ((data.ExitCode === 0) && (nextCommand)) { // command successful, has next command

            nextCommand(null, container);

        /* * * *
        * if test files exist (and passed is true):
        *
        * output: {
        *
        *   clientId,
        *   passed: Boolean (false if compile/runtime errors true otherwise),
        *   output: String,
        *   errorMessage: String (empty if `passed` is true),
        *   timeOut: Boolean,
        *   totalNumberOfTests: Integer,
        *   numberOfTestsPassed: Integer,
        *   testsOutput: String (output of all failed tests)
        * }
        *
        * otherwise:
        *
        * output: {
        *
        *   clientId,
        *   passed: Boolean (false if compile/runtime errors true otherwise),
        *   output: String,
        *   errorMessage: String (empty if `passed` is false),
        *   timeOut: Boolean
        * * * */

        } else if (data.ExitCode === 0) { // command successful, it was the last command

            feedbackAndClose(container, streamManager, true, false)

        } else { // command failed

            feedbackAndClose(container, streamManager, false, false);
        }
    };

    setTimeout(() => exec.inspect(checkExit), EXEC_WAIT_TIME_MS);
};

// Sends back the feedback and closes the container
function feedbackAndClose(container, streamManager, compile, timeOut) {

    streamManager.endStream();

    const feedback = {
        clientId: container.clientId,
        compile: compile,
        output: (!timeOut) ? streamManager.readOut() : '',
        errorMessage: (!timeOut) ? streamManager.readErr() : "Reached maximum time limit",
        timeOut: timeOut

    };

    const parsed = parseOutput(feedback.output);
    feedback.output = parsed.normalOutput;
    feedback.totalNumberOfTests = parsed.totalNumberOfTests;
    feedback.numberOfTestsPassed = parsed.numberOfTestsPassed;
    feedback.testsOutput = parsed.testsOutput;

    javaBox.emit('result', feedback);

    container.kill({}, () =>
        container.remove({v: true}, () => {}));
}

function parseOutput(input){

    const _INPUT_DELIMITER_ = '_!*^&_test-output';

    const wholeOutput = {};

    wholeOutput.normalOutput = input.split(_INPUT_DELIMITER_)[0];

    let testOutput = null;

    try {
         testOutput = JSON.parse(input.split(_INPUT_DELIMITER_)[1]);

    } catch(err) {
        console.log(err);
        console.log('INPUT', input);
    }

    if (testOutput){
        wholeOutput.totalNumberOfTests  = testOutput.totalNumberOfTests;
        wholeOutput.numberOfTestsPassed = testOutput.numberOfTestsPassed;
        wholeOutput.testsOutput         = testOutput.testsOutput;
    }

    return wholeOutput;
}

module.exports = javaBox;
<commit_msg>Minor refactoring<commit_after>const EventEmitter = require('events');
const Docker = require('dockerode');
const concat = require('concat-stream');

// Docker connection
const docker = new Docker();

// Time to wait between checking that the command has been executed (milliseconds)
const EXEC_WAIT_TIME_MS = 250;

// JavaBox eventEmitter
const javaBox = new EventEmitter();

javaBox.on('runJava', runJava);
javaBox.on('runJunit', runJunit);

// Run the Main.java inside the tar and outputs the result to the socket
function runJava(clientId, main, tarPath, timeLimitCompile, timeLimitExecution) {

    const className = main.split('.')[0];

    const javacCmd = ['javac', '-cp', 'home:junit/junit-4.12:junit/hamcrest-core-1.3', 'home/' + main];
    const javaCmd = ['java', '-cp', 'home:junit/junit-4.12:junit/hamcrest-core-1.3', className];

    const sourceLocation = tarPath;
    const execution = dockerCommand(javacCmd, timeLimitCompile, dockerCommand(javaCmd, timeLimitExecution));

    createJContainer(clientId, sourceLocation, false, execution);
};

function runJunit(clientId, junitFileNames, tarPath, timeLimitCompile, timeLimitExecution) {

    let junitFiles = [];
    junitFileNames.forEach((f)=>{
        junitFiles.push( f.name.split('.')[0]);
    });

    const className = 'TestRunner';

    const javacCmd = ['javac', '-cp', 'home:libs/junit-4.12:libs/hamcrest-core-1.3:libs/json-simple-1.1.1'];
    let javaCmd = ['java', '-cp', 'home:libs/junit-4.12:libs/hamcrest-core-1.3:libs/json-simple-1.1.1', className];

    junitFiles.forEach((file)=>{
        javacCmd.push('home/' + file + '.java');
        javaCmd.push(file);
    });
    javacCmd.push('home/' + className + '.java');

    const sourceLocation = tarPath;
    const execution = dockerCommand(javacCmd, timeLimitCompile, dockerCommand(javaCmd, timeLimitExecution));

    createJContainer(clientId, sourceLocation, true, execution);
};

// Creates and starts a container with bash, JDK SE and more
function createJContainer(clientId, javaSourceTar, isJunit, callback) {

    let copyToCall = 3;

    const tryCallback = (container) => {

        if (copyToCall === 0) {

            callback(null, container);
        }
    };

    const createOpts = {Image: 'openjdk:8u111-jdk', Tty: true, Cmd: ['/bin/bash']};
    docker.createContainer(createOpts, (err, container) => {

        if (err) {callback(err, container); return}

        container['clientId'] = clientId;

        const startOpts = {};
        container.start(startOpts, (err, data) => {

            if (err) {callback(err, data); return};

            if (isJunit) {

                const tarOptsRunner = {path: 'home'};
                container.putArchive('./archives/TestRunner.java.tar', tarOptsRunner, (err, data) => {
                    copyToCall--;
                    if (err) callback(err, data);
                    else tryCallback(container);

                });

                const tarOptsLibs = {path: '/'};
                container.putArchive('./archives/libs.tar', tarOptsLibs, (err, data) => {
                    copyToCall--;
                    if (err) callback(err, data);
                    else tryCallback(container);
                });
            } else {
                copyToCall = 1;
            }

            const tarOptsSource = {path: 'home'};
            container.putArchive(javaSourceTar, tarOptsSource, (err, data) => {
                copyToCall--;
                if (err) callback(err, data);
                else tryCallback(container);
            });
        });
    });
};

/*
 * Returns a function that on some given container,
 * executes a specific command, attaches the specific output listener and
 * after the command is executed pipelines the next one
 */
function dockerCommand(command, commandTimeLimit, nextCommand) {

    const opts = {Cmd: command, AttachStdout: true, AttachStderr: true};

    const execution = (err, container) => {

        if (!err) container.exec(opts, (err, exec) => {
            exec.start((err, stream) => {

                let stdOut = '';
                let stdErr = '';
                const stdOutStream = concat({}, (data) => {
                    stdOut += data;
                });
                const stdErrStream = concat({}, (data) => {
                    stdErr += data;
                });

                container.modem.demuxStream(stream, stdOutStream, stdErrStream);

                const streamManager = {

                    readOut: () => {return stdOut},
                    readErr: () => {return stdErr},
                    endStream: () => {
                        stdOutStream.end();
                        stdErrStream.end();
                    }
                };

                waitCmdExit(container, exec, nextCommand, streamManager, commandTimeLimit);
            });
        });
    };

    return execution;
};

// Ensures that the exec process is terminated and fires the next command
function waitCmdExit(container, exec, nextCommand, streamManager, commandTimeOut, previousTime){

    let timeSpent = previousTime || 0;

    const checkExit = (err, data) => {

        if (data.Running) { // command is still running, check later or send time out

            timeSpent += EXEC_WAIT_TIME_MS;                             // count time spent

            if (timeSpent >= commandTimeOut){                           // time period expired

                feedbackAndClose(container, streamManager, false, true);

            } else {

            waitCmdExit(container, exec, nextCommand, streamManager, commandTimeOut, timeSpent);

            }

        } else if ((data.ExitCode === 0) && (nextCommand)) { // command successful, has next command

            nextCommand(null, container);

        /* * * *
        * if test files exist (and passed is true):
        *
        * output: {
        *
        *   clientId,
        *   passed: Boolean (false if compile/runtime errors true otherwise),
        *   output: String,
        *   errorMessage: String (empty if `passed` is true),
        *   timeOut: Boolean,
        *   totalNumberOfTests: Integer,
        *   numberOfTestsPassed: Integer,
        *   testsOutput: String (output of all failed tests)
        * }
        *
        * otherwise:
        *
        * output: {
        *
        *   clientId,
        *   passed: Boolean (false if compile/runtime errors true otherwise),
        *   output: String,
        *   errorMessage: String (empty if `passed` is false),
        *   timeOut: Boolean
        * * * */

        } else if (data.ExitCode === 0) { // command successful, it was the last command

            feedbackAndClose(container, streamManager, true, false)

        } else { // command failed

            feedbackAndClose(container, streamManager, false, false);
        }
    };

    setTimeout(() => exec.inspect(checkExit), EXEC_WAIT_TIME_MS);
};

// Sends back the feedback and closes the container
function feedbackAndClose(container, streamManager, compile, timeOut) {

    streamManager.endStream();

    const feedback = {
        clientId: container.clientId,
        compile: compile,
        output: (!timeOut) ? streamManager.readOut() : '',
        errorMessage: (!timeOut) ? streamManager.readErr() : "Reached maximum time limit",
        timeOut: timeOut

    };

    const parsed = parseOutput(feedback.output);
    feedback.output = parsed.normalOutput;
    feedback.totalNumberOfTests = parsed.totalNumberOfTests;
    feedback.numberOfTestsPassed = parsed.numberOfTestsPassed;
    feedback.testsOutput = parsed.testsOutput;

    javaBox.emit('result', feedback);

    container.kill({}, () =>
        container.remove({v: true}, () => {}));
}

function parseOutput(input){

    const _INPUT_DELIMITER_ = '_!*^&_test-output';

    const wholeOutput = {};

    wholeOutput.normalOutput = input.split(_INPUT_DELIMITER_)[0];

    let testOutput = null;

    try {
         testOutput = JSON.parse(input.split(_INPUT_DELIMITER_)[1]);

    } catch(err) {
        console.log('no junit');
    }

    if (testOutput){
        wholeOutput.totalNumberOfTests  = testOutput.totalNumberOfTests;
        wholeOutput.numberOfTestsPassed = testOutput.numberOfTestsPassed;
        wholeOutput.testsOutput         = testOutput.testsOutput;
    }

    return wholeOutput;
}

module.exports = javaBox;
<|endoftext|>


<commit_before>"use strict";
window.gokart = (function(self) {
    $(document).foundation();
    svg4everybody();

    var $self = $(self)
    var ui = self.ui = {};

    ui.sizes = {
        "tool-size-small": 16,
        "tool-size-medium": 32,
        "tool-size-large": 64
    };

    ui.colours = {
    };

    // bind menu side-tabs to reveal the side pane
    var offCanvasLeft = $("#offCanvasLeft")
    $("#menu-tabs").on("change.zf.tabs", function(ev) {
        offCanvasLeft.addClass("reveal-for-medium");
        self.map.updateSize();
    }).on("click", ".tabs-title a[aria-selected=false]", function(ev) {
        offCanvasLeft.addClass("reveal-for-medium");
        $(this).attr("aria-selected", true);
        self.map.updateSize();
    }).on("click", ".tabs-title a[aria-selected=true]", function(ev) {
        offCanvasLeft.removeClass("reveal-for-medium");
        $(this).attr("aria-selected", false);
        self.map.updateSize();
    });

    // hovering layer information panel
    ui.info = new Vue({
        el: '#info',
        // variables
        data: {
            features: [],
            coordinate: "",
            offset: 20,
            pixel: [0, 0],
        },
        // parts of the template to be computed live
        computed: {
            // because the viewport size changes when the tabs open, don't cache the map width and height
            mapWidth: { cache: false, get: function() { return $("#map").width() }},
            mapHeight: { cache: false, get: function() { return $("#map").height() }},
            // viewport should be positioned near the mouse in the quadrant furthest away from the viewport edges
            css: function() {
                var css = {
                    "left": this.pixel[0] + this.offset + "px",
                    "top": this.pixel[1] + this.offset + "px",
                    "bottom": this.mapHeight - this.pixel[1] + this.offset + "px",
                    "right": this.mapWidth - this.pixel[0] + this.offset + "px"
                }
                if (this.pixel[0] < this.mapWidth / 2) { delete css.right } else { delete css.left };
                if (this.pixel[1] < this.mapHeight / 2) { delete css.bottom } else { delete css.top };
                return css;
            }
        },
        // methods callable from inside the template
        methods: {
            // update the panel content
            display: function(event) {
                if (event.dragging) { return };
                var pixel = self.map.getEventPixel(event.originalEvent);
                var features = {}
                var featureFound = self.map.forEachFeatureAtPixel(pixel, function(f) {
                    features[f.getGeometry().getExtent().join(" ")] = f.getProperties();
                });
                features = Object.values(features);
                if (features.length > 0) {
                    this.features = features;
                    this.coordinate = ol.coordinate.toStringXY(self.map.getCoordinateFromPixel(pixel), 3);
                    this.pixel = pixel;
                }
            }
        }
    });

    // update "Map Layers" pane
    self.initLayers = function() {
        ui.layers = new Vue({
            el: "#menu-tab-layers",
            // variables
            data: {
                sliderOpacity: 0,
                layer: {},
                olLayers: [],
                catalogue: {},
                swapBaseLayers: true,
                search: "",
                searchAttrs: ["name", "id"],
            },
            // parts of the template to be computed live
            computed: { graticule: {cache: false, get: function() { return self.graticule.getMap() == self.map }} },
            // methods callable from inside the template
            methods: {
                toggleGraticule: function() {
                    if (this.graticule) {
                        self.graticule.setMap(null);
                    } else {
                        self.graticule.setMap(self.map);
                    }
                },
                update: function() {
                    var vm = this;
                    vm.olLayers = [];
                    Vue.nextTick(function() {
                        vm.olLayers = gokart.map.getLayers().getArray();
                    });
                },
                removeLayer: function(olLayer) {
                    olLayer.get("catalogueEntry").toggled = false;
                    self.map.removeLayer(olLayer);
                },
                // change order of OL layers based on "Map Layers" list order
                updateOrder: function(el) {
                    Array.prototype.slice.call(el.parentNode.children).reverse().forEach(function(row) {
                        var layer = self.layerById(row.dataset.id);
                        self.map.removeLayer(layer);
                        self.map.addLayer(layer);
                    });
                },
                // toggle a layer in the Layer Catalogue
                toggleLayer: function(layer) {
                    var vm = this;
                    if (layer.toggled) {
                        if (layer.base) {
                            // "Switch out base layers automatically" is enabled, remove
                            // all other layers with the "base" option set.
                            if (vm.swapBaseLayers) {
                                vm.olLayers.forEach(function(olLayer) {
                                    if (olLayer.get("catalogueEntry").base) {
                                        vm.removeLayer(olLayer);
                                    }
                                });
                            }
                            // add new base layer to bottom
                            self.map.getLayers().insertAt(0, layer.init());
                        } else {
                            self.map.addLayer(layer.init());
                        }
                    } else {
                        vm.removeLayer(layer.olLayer);
                    }
                }
            },
            ready: function () { dragula([document.querySelector("#layers-active")]).on("dragend", this.updateOrder); }
        });
        ui.layers.olLayers = self.map.getLayers().getArray();
        ui.layers.catalogue = self.catalogue;
    }

    self.initAnnotations = function() {
        ui.annotations = new Vue({
            el: "#menu-tab-annotations",
            data: {
                mode: "pan",
                size: 12,
                colour: "#cc0000",
                colours: [
                    ["red", "#cc0000"],
                    ["orange", "#f57900"],
                    ["yellow", "#edd400"],
                    ["green", "#73d216"],
                    ["blue", "#3465a4"],
                    ["violet", "#75507b"],
                    ["brown", "#8f5902"],
                    ["grey", "#555753"],
                    ["black", "#000000"]
                ],
                advanced: false
            },
            methods: {
                setMode: function(mode) {
                    this.mode = mode
                }
            }
        });
    }

    $self.on("init_map", function() {
        // setup scale events
        self.map.on("postrender", function() { if (self.mapControls) { self.mapControls.scale = self.getScale() }});
        // display hover popups
        self.map.on('pointermove', ui.info.display);
        if (document.querySelector("#menu-tab-layers")) { gokart.initLayers() };
        if (document.querySelector("#menu-tab-annotations")) { gokart.initAnnotations() };
    });

    return self;
})(window.gokart || {});

<commit_msg>comment typo<commit_after>"use strict";
window.gokart = (function(self) {
    $(document).foundation();
    svg4everybody();

    var $self = $(self)
    var ui = self.ui = {};

    ui.sizes = {
        "tool-size-small": 16,
        "tool-size-medium": 32,
        "tool-size-large": 64
    };

    ui.colours = {
    };

    // bind menu side-tabs to reveal the side pane
    var offCanvasLeft = $("#offCanvasLeft")
    $("#menu-tabs").on("change.zf.tabs", function(ev) {
        offCanvasLeft.addClass("reveal-for-medium");
        self.map.updateSize();
    }).on("click", ".tabs-title a[aria-selected=false]", function(ev) {
        offCanvasLeft.addClass("reveal-for-medium");
        $(this).attr("aria-selected", true);
        self.map.updateSize();
    }).on("click", ".tabs-title a[aria-selected=true]", function(ev) {
        offCanvasLeft.removeClass("reveal-for-medium");
        $(this).attr("aria-selected", false);
        self.map.updateSize();
    });

    // hovering layer information panel
    ui.info = new Vue({
        el: '#info',
        // variables
        data: {
            features: [],
            coordinate: "",
            offset: 20,
            pixel: [0, 0],
        },
        // parts of the template to be computed live
        computed: {
            // because the viewport size changes when the tab pane opens, don't cache the map width and height
            mapWidth: { cache: false, get: function() { return $("#map").width() }},
            mapHeight: { cache: false, get: function() { return $("#map").height() }},
            // info panel should be positioned near the mouse in the quadrant furthest away from the viewport edges
            css: function() {
                var css = {
                    "left": this.pixel[0] + this.offset + "px",
                    "top": this.pixel[1] + this.offset + "px",
                    "bottom": this.mapHeight - this.pixel[1] + this.offset + "px",
                    "right": this.mapWidth - this.pixel[0] + this.offset + "px"
                }
                if (this.pixel[0] < this.mapWidth / 2) { delete css.right } else { delete css.left };
                if (this.pixel[1] < this.mapHeight / 2) { delete css.bottom } else { delete css.top };
                return css;
            }
        },
        // methods callable from inside the template
        methods: {
            // update the panel content
            display: function(event) {
                if (event.dragging) { return };
                var pixel = self.map.getEventPixel(event.originalEvent);
                var features = {}
                var featureFound = self.map.forEachFeatureAtPixel(pixel, function(f) {
                    features[f.getGeometry().getExtent().join(" ")] = f.getProperties();
                });
                features = Object.values(features);
                if (features.length > 0) {
                    this.features = features;
                    this.coordinate = ol.coordinate.toStringXY(self.map.getCoordinateFromPixel(pixel), 3);
                    this.pixel = pixel;
                }
            }
        }
    });

    // update "Map Layers" pane
    self.initLayers = function() {
        ui.layers = new Vue({
            el: "#menu-tab-layers",
            // variables
            data: {
                sliderOpacity: 0,
                layer: {},
                olLayers: [],
                catalogue: {},
                swapBaseLayers: true,
                search: "",
                searchAttrs: ["name", "id"],
            },
            // parts of the template to be computed live
            computed: { graticule: {cache: false, get: function() { return self.graticule.getMap() == self.map }} },
            // methods callable from inside the template
            methods: {
                toggleGraticule: function() {
                    if (this.graticule) {
                        self.graticule.setMap(null);
                    } else {
                        self.graticule.setMap(self.map);
                    }
                },
                update: function() {
                    var vm = this;
                    vm.olLayers = [];
                    Vue.nextTick(function() {
                        vm.olLayers = gokart.map.getLayers().getArray();
                    });
                },
                removeLayer: function(olLayer) {
                    olLayer.get("catalogueEntry").toggled = false;
                    self.map.removeLayer(olLayer);
                },
                // change order of OL layers based on "Map Layers" list order
                updateOrder: function(el) {
                    Array.prototype.slice.call(el.parentNode.children).reverse().forEach(function(row) {
                        var layer = self.layerById(row.dataset.id);
                        self.map.removeLayer(layer);
                        self.map.addLayer(layer);
                    });
                },
                // toggle a layer in the Layer Catalogue
                toggleLayer: function(layer) {
                    var vm = this;
                    if (layer.toggled) {
                        if (layer.base) {
                            // "Switch out base layers automatically" is enabled, remove
                            // all other layers with the "base" option set.
                            if (vm.swapBaseLayers) {
                                vm.olLayers.forEach(function(olLayer) {
                                    if (olLayer.get("catalogueEntry").base) {
                                        vm.removeLayer(olLayer);
                                    }
                                });
                            }
                            // add new base layer to bottom
                            self.map.getLayers().insertAt(0, layer.init());
                        } else {
                            self.map.addLayer(layer.init());
                        }
                    } else {
                        vm.removeLayer(layer.olLayer);
                    }
                }
            },
            ready: function () { dragula([document.querySelector("#layers-active")]).on("dragend", this.updateOrder); }
        });
        ui.layers.olLayers = self.map.getLayers().getArray();
        ui.layers.catalogue = self.catalogue;
    }

    self.initAnnotations = function() {
        ui.annotations = new Vue({
            el: "#menu-tab-annotations",
            data: {
                mode: "pan",
                size: 12,
                colour: "#cc0000",
                colours: [
                    ["red", "#cc0000"],
                    ["orange", "#f57900"],
                    ["yellow", "#edd400"],
                    ["green", "#73d216"],
                    ["blue", "#3465a4"],
                    ["violet", "#75507b"],
                    ["brown", "#8f5902"],
                    ["grey", "#555753"],
                    ["black", "#000000"]
                ],
                advanced: false
            },
            methods: {
                setMode: function(mode) {
                    this.mode = mode
                }
            }
        });
    }

    $self.on("init_map", function() {
        // setup scale events
        self.map.on("postrender", function() { if (self.mapControls) { self.mapControls.scale = self.getScale() }});
        // display hover popups
        self.map.on('pointermove', ui.info.display);
        if (document.querySelector("#menu-tab-layers")) { gokart.initLayers() };
        if (document.querySelector("#menu-tab-annotations")) { gokart.initAnnotations() };
    });

    return self;
})(window.gokart || {});

<|endoftext|>