<commit_before>/**
 * Created by yarden on 11/10/15.
 */

define(function(require) {

  var d3 = require('d3');

  var localWindow = null;
  var root = null;
  var data = null;
  var active = [];
  var mat;
  var valueSelector = 'min';
  var spec;

  var fields = {
    config:  {name: 'config',  type: 'category', values: [], sort: d3.ascending, selected: new Set()},
    dataset: {name: 'dataset', type: 'category', values: [], sort: d3.ascending, selected: new Set()},
    sim:     {name: 'sim',     type: 'category', values: [], sort: simSort,      selected: new Set()},
    jobid:   {name: 'jobid',   type: 'category', values: [], sort: d3.ascending, selected: new Set()},
    color:   {name: 'color',   type: 'fixed',    values: ['*', 'g', 'k', 'b'],   selected: new Set(['*', 'g', 'k', 'b'])}
  };

  var specs = [
    {
      name: 'config/jobid',
      rows: [fields.config],
      cols: [fields.jobid]
    },
    {
      name: 'config,sim/dataset,jobid',
      rows: [fields.config, fields.sim],
      cols: [fields.dataset, fields.jobid]
    },
    {
      name: 'config,dataset,sim/color,jobid',
      rows: [fields.config, fields.dataset, fields.sim],
      cols: [fields.color, fields.jobid]
    }
  ];

  var filterValues = {};

  var VALUES_COLORMAP =["#4575b4", "#74add1", "#abd9e9", "#e0f3f8", "#ffffbf", "#fee090", "#fdae61", "#f46d43", "#d73027"];
  var color = d3.scale.quantize().range(VALUES_COLORMAP);

  var colorname = ['*', 'g', 'k', 'b'];

  function simSort(a,b) {
    a = +a.slice(3);
    b = +b.slice(3);
    return a -b;
  }

  // launch button on the main page
  d3.select('#show-compare')
    .on('click', function() {
      if (localWindow == null || localWindow.closed) {
        localWindow = window.open('compare.html', 'compare');
        d3.select(localWindow).on('load', init);
      }
      else {
        localWindow.focus();
      }
    });

  // init module only it is actually called
  function init() {
    root = localWindow.document.body;

    d3.select(root).select('#select-options')
      .on('change', function (d) { spec = specs[d3.select(this).property('selectedIndex')]; recompute(); })
      .selectAll('option')
      .data(specs)
      .enter()
        .append('option')
        .attr('value', function(d) {return d.name;})
        .text(function(d) { return d.name;});

    d3.csv('data/alldata.csv')
      .row(function(d) {
        //d.jobid = +d.jobid;
        d.color = colorname[d.color];
        d.min = +d.min;
        d.avg = +d.avg;
        d.max = +d.max;
        d.nonzero = +d.nonzero;
        d.navg = +d.navg;
        return d;
      })
      .get(function(error, rows) {
        if (error) {
          // TODO: better error message notification
          console.err(error);
        }
        else {
          d3.select(root).select('#size').text(rows.length);
          if (rows.length == 0) {
            // TODO: better message notification
            console.log('empty dataset');
            return;
          }
          data = rows;

          // TODO: use keys based on data. Issue: how to determine which fields are values
          var keys = ['min', 'avg', 'max', 'nzavg'];

          d3.select(root).select('#select-values')
            .on('change', selectValue)
            .selectAll('option')
            .data(keys)
            .enter()
              .append('option')

            .attr('value', function(d) {return d;})
            .text(function(d) { return d;});

          // init selection and render
          valueSelector = 'max';
          d3.select(root).select('#select-values')
            .property('value', valueSelector);

          setupFields();
          spec = specs[0];
          filter();
        }
      });
  }

  function setupFields() {
    collectValues(data);

    var li = d3.select(root).select('#info #fields').selectAll('li')
      .data(Object.keys(fields))
      .enter()
      .append('li');

    li.append('label')
      .attr('class', 'li-title')
      .text(function(d) {return d;});

    var entry = li.append('ul')
      .attr('class', 'values')
      .selectAll('li')
      .data(function(d) { return fields[d].values.map(function(v) { return [fields[d].name, v];});})
      .enter()
        .append('li')
        .attr('class', 'value');

    entry
      .append('input')
      .attr('type', 'checkbox')
      .property('name', function(d) {return d[0];})
      .property('value', function(d) { return d[1]; })
      .property('checked', true)
      .on('change', function(d) {
        var set = fields[d3.select(this).property('name')].selected;
        if (d3.select(this).property('checked')) set.add(d[1]);
        else set.delete(d[1]);
        filter();
      });

    entry
      .append('text')
      .text(function(d) { return d[1]});
  }

  function collectValues(rows) {
    Object.keys(fields).forEach(function(field) {
      if (fields[field].type == 'category') {
        var set = new Set();
        rows.forEach(function(row) {
          set.add(row[field]);
        });
        fields[field].values = Array.from(set).sort(fields[field].sort);
        fields[field].selected = new Set(fields[field].values);
      }
    });
  }

  function adjustColormap() {
    var max = d3.max(mat.values, function (d) { return d.values[valueSelector]; });
    value_scale.domain([0, max/2, max]);
  }

  function filter() {
    var keys = Object.keys(fields);
    var i, n = keys.length, key;
    active = data.filter(function(row) {
      for (i=0; i<n; i++) {
        key = keys[i];
        if (!fields[key].selected.has(row[key])) return false;
      }
      return true;
    });
    recompute();
  }

  function selectValue() {
    valueSelector = d3.select(this).property('value');
    adjustColormap();
    render(mat);
  }

  function recompute() {
    buildHeader(spec);
    mat = collect(spec,  aggregate(spec));
    adjustColormap();
    render(mat);
  }

  function aggregate(spec) {
    var nest = d3.nest();
    spec.rows.forEach(function(field) { nest.key(function(d) { return d[field.name];}).sortKeys(field.sort); } );
    spec.cols.forEach(function(field) { nest.key(function(d) { return d[field.name];}).sortKeys(field.sort); } );

    return nest.rollup(function(leaves) { return {
        min: d3.min(leaves, function(d) { return d.min; }),
        avg: d3.mean(leaves, function(d) { return d.avg; }),
        max: d3.max(leaves, function(d) { return d.max; }),
        //nonzero: d3.max(leaves, function(d) { return d.nonzero; }),
        nzavg: d3.sum(leaves, function(d) { return d.nzavg * d.nonzero; })/ d3.sum(leaves, function(d) { return d.nonzero; })
      }})
      .entries(active);
  }

  var header;
  var x0 = 20, y0 = 20;
  var dx = 1, dy = 1;
  var w = 15, h = 15;
  var fontSize = 15;
  var colHeight = 15;
  var lastRowWidth = 30;
  var x, y;

  function buildHeader(spec) {
    var root, entry, value, field;

    // collect
    header = {field: spec.cols[0], label: "", values: new Map()};
    active.forEach(function(row) {
      root = header;
      for (var i= 0, n=spec.cols.length; i<n; i++) {
        field = spec.cols[i];
        value = row[field.name];
        entry = root.values.get(value);
        if (!entry) {
          entry =  i<n-1 && {field: spec.cols[i+1], label: value, values: new Map()} || {label: value};
          root.values.set(value, entry);
        }
        root = entry;
      }
    });

    // assign location and size
    visit(header, x0+spec.rows.length*(w+dx)+lastRowWidth-w+5, y0);

    function visit(root, x, y) {
      root.x = x;
      root.y = y;
      if (root.values) {
        y += colHeight + dy;
        var keys = Array.from(root.values.keys()).sort(root.field.sort);
        keys.forEach(function (key) {
          x = visit(root.values.get(key), x, y)+dx;
        });
      } else {
        x += w+dx;
      }
      x -= dx;
      root.w = x - root.x;
      root.h = h;
      return x;
    }

  }

  function collect(spec, nodes) {
    x = x0;
    y = y0 + (spec.cols.length+1)*(colHeight+dy);
    var mat = {header: {rows:[], cols:[]}, values:[]};
    var max_value = 0;

    visit(spec.rows.length, spec.cols.length, nodes, header);
    return mat;

    function visit(nrows, ncols, nodes, header) {
      var i, n, node, nr = spec.rows.length, nc = spec.cols.length;
      if (nrows > 0) {
        for (i=0, n=nodes.length; i<n; i++) {
          node = nodes[i];
          node.label = node.key;
          node.x = x;
          node.y = y;
          x += +dx + (nrows == 1 ? lastRowWidth+5 : fontSize);
          node.last = nrows == 1;
          visit(nrows-1, ncols, node.values, header);
          if (nrows == 1) {
            y += h;
            node.w = lastRowWidth ;
            node.h = y - node.y - dy+1;
          } else {
            node.h = fontSize;
            node.w = y - node.y - dy;
          }
          x = node.x;
          y += dy;
          mat.header.rows.push(node);
        }
      }
      else {
        for (i=0, n=nodes.length; i<n; i++) {
          node = nodes[i];
          var pos = header.values.get(node.key);
          if (ncols == 1) {
            node.x = pos.x;
            node.y = y;
            node.w = w;
            node.h = h;
            x += w;
            mat.values.push(node);
          } else {
            visit(nrows, ncols-1, node.values, pos);
          }
          x += dx;
        }
      }
    }
  }

  function flatten(node) {
    var list = [];
    visit(node);
    list.shift();
    return list;

    function visit(node) {
      if (node) {
        list.push(node);
        if (node.values)
          node.values.forEach(function (node) { visit(node); });
      }
    }
  }

  function render(mat) {

    d3.select(root).select('#results').attr('height', y);

    var cols = d3.select(root).select('#results').selectAll('.col')
      .data(flatten(header));

    cols.enter()
      .append('div')
      .attr('class', 'col');

    cols
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y;})
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .style('overflow', 'hidden')
      .text(function(d) { return d.label;})
    ;

    cols.exit().remove();

    var list = [];
    for (var i= 0, n=spec.cols.length; i<n; i++) {
      list.push({x: header.x+header.w+dx+5, y: header.y+(i+1)*(colHeight+dy), w:40, h: fontSize, label: spec.cols[i].name });
    }

    var colText = d3.select(root).select('#results').selectAll('.colText')
      .data(list);

    colText.enter()
      .append('div')
      .attr('class', 'colText');

    colText
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y; })
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .text(function(d) { return d.label; });

    colText.exit().remove();

    var rows = d3.select(root).select('#results').selectAll('.row')
      .data(mat.header.rows);

    rows.enter()
      .append('div')
      .attr('class', 'row');

    rows
      .classed('rotate', function(d) { return !d.last; })
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y+ (d.last ? 0 : d.w);})
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .style('overflow', 'hidden')
      .text(function(d) { return d.label;})
    ;

    rows.exit().remove();

    var d3nodes = d3.select(root).select('#results').selectAll('.value')
      .data(mat.values);

    d3nodes.enter()
      .append('div')
      .attr('class', 'value');

    d3nodes
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y;})
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .style('background-color', function(d) { return color(d.values[valueSelector]); })
    ;

    d3nodes.exit().remove();
  }

  return {
  };

});<commit_msg>bug fix<commit_after>/**
 * Created by yarden on 11/10/15.
 */

define(function(require) {

  var d3 = require('d3');

  var localWindow = null;
  var root = null;
  var data = null;
  var active = [];
  var mat;
  var valueSelector = 'min';
  var spec;

  var fields = {
    config:  {name: 'config',  type: 'category', values: [], sort: d3.ascending, selected: new Set()},
    dataset: {name: 'dataset', type: 'category', values: [], sort: d3.ascending, selected: new Set()},
    sim:     {name: 'sim',     type: 'category', values: [], sort: simSort,      selected: new Set()},
    jobid:   {name: 'jobid',   type: 'category', values: [], sort: d3.ascending, selected: new Set()},
    color:   {name: 'color',   type: 'fixed',    values: ['*', 'g', 'k', 'b'],   selected: new Set(['*', 'g', 'k', 'b'])}
  };

  var specs = [
    {
      name: 'config/jobid',
      rows: [fields.config],
      cols: [fields.jobid]
    },
    {
      name: 'config,sim/dataset,jobid',
      rows: [fields.config, fields.sim],
      cols: [fields.dataset, fields.jobid]
    },
    {
      name: 'config,dataset,sim/color,jobid',
      rows: [fields.config, fields.dataset, fields.sim],
      cols: [fields.color, fields.jobid]
    }
  ];

  var filterValues = {};

  var VALUES_COLORMAP =["#4575b4", "#74add1", "#abd9e9", "#e0f3f8", "#ffffbf", "#fee090", "#fdae61", "#f46d43", "#d73027"];
  var color = d3.scale.quantize().range(VALUES_COLORMAP);

  var colorname = ['*', 'g', 'k', 'b'];

  function simSort(a,b) {
    a = +a.slice(3);
    b = +b.slice(3);
    return a -b;
  }

  // launch button on the main page
  d3.select('#show-compare')
    .on('click', function() {
      if (localWindow == null || localWindow.closed) {
        localWindow = window.open('compare.html', 'compare');
        d3.select(localWindow).on('load', init);
      }
      else {
        localWindow.focus();
      }
    });

  // init module only it is actually called
  function init() {
    root = localWindow.document.body;

    d3.select(root).select('#select-options')
      .on('change', function (d) { spec = specs[d3.select(this).property('selectedIndex')]; recompute(); })
      .selectAll('option')
      .data(specs)
      .enter()
        .append('option')
        .attr('value', function(d) {return d.name;})
        .text(function(d) { return d.name;});

    d3.csv('data/alldata.csv')
      .row(function(d) {
        //d.jobid = +d.jobid;
        d.color = colorname[d.color];
        d.min = +d.min;
        d.avg = +d.avg;
        d.max = +d.max;
        d.nonzero = +d.nonzero;
        d.navg = +d.navg;
        return d;
      })
      .get(function(error, rows) {
        if (error) {
          // TODO: better error message notification
          console.err(error);
        }
        else {
          d3.select(root).select('#size').text(rows.length);
          if (rows.length == 0) {
            // TODO: better message notification
            console.log('empty dataset');
            return;
          }
          data = rows;

          // TODO: use keys based on data. Issue: how to determine which fields are values
          var keys = ['min', 'avg', 'max', 'nzavg'];

          d3.select(root).select('#select-values')
            .on('change', selectValue)
            .selectAll('option')
            .data(keys)
            .enter()
              .append('option')

            .attr('value', function(d) {return d;})
            .text(function(d) { return d;});

          // init selection and render
          valueSelector = 'max';
          d3.select(root).select('#select-values')
            .property('value', valueSelector);

          setupFields();
          spec = specs[0];
          filter();
        }
      });
  }

  function setupFields() {
    collectValues(data);

    var li = d3.select(root).select('#info #fields').selectAll('li')
      .data(Object.keys(fields))
      .enter()
      .append('li');

    li.append('label')
      .attr('class', 'li-title')
      .text(function(d) {return d;});

    var entry = li.append('ul')
      .attr('class', 'values')
      .selectAll('li')
      .data(function(d) { return fields[d].values.map(function(v) { return [fields[d].name, v];});})
      .enter()
        .append('li')
        .attr('class', 'value');

    entry
      .append('input')
      .attr('type', 'checkbox')
      .property('name', function(d) {return d[0];})
      .property('value', function(d) { return d[1]; })
      .property('checked', true)
      .on('change', function(d) {
        var set = fields[d3.select(this).property('name')].selected;
        if (d3.select(this).property('checked')) set.add(d[1]);
        else set.delete(d[1]);
        filter();
      });

    entry
      .append('text')
      .text(function(d) { return d[1]});
  }

  function collectValues(rows) {
    Object.keys(fields).forEach(function(field) {
      if (fields[field].type == 'category') {
        var set = new Set();
        rows.forEach(function(row) {
          set.add(row[field]);
        });
        fields[field].values = Array.from(set).sort(fields[field].sort);
        fields[field].selected = new Set(fields[field].values);
      }
    });
  }

  function adjustColormap() {
    var max = d3.max(mat.values, function (d) { return d.vgit alues[valueSelector]; });
    color.domain([0, max/2, max]);
  }

  function filter() {
    var keys = Object.keys(fields);
    var i, n = keys.length, key;
    active = data.filter(function(row) {
      for (i=0; i<n; i++) {
        key = keys[i];
        if (!fields[key].selected.has(row[key])) return false;
      }
      return true;
    });
    recompute();
  }

  function selectValue() {
    valueSelector = d3.select(this).property('value');
    adjustColormap();
    render(mat);
  }

  function recompute() {
    buildHeader(spec);
    mat = collect(spec,  aggregate(spec));
    adjustColormap();
    render(mat);
  }

  function aggregate(spec) {
    var nest = d3.nest();
    spec.rows.forEach(function(field) { nest.key(function(d) { return d[field.name];}).sortKeys(field.sort); } );
    spec.cols.forEach(function(field) { nest.key(function(d) { return d[field.name];}).sortKeys(field.sort); } );

    return nest.rollup(function(leaves) { return {
        min: d3.min(leaves, function(d) { return d.min; }),
        avg: d3.mean(leaves, function(d) { return d.avg; }),
        max: d3.max(leaves, function(d) { return d.max; }),
        //nonzero: d3.max(leaves, function(d) { return d.nonzero; }),
        nzavg: d3.sum(leaves, function(d) { return d.nzavg * d.nonzero; })/ d3.sum(leaves, function(d) { return d.nonzero; })
      }})
      .entries(active);
  }

  var header;
  var x0 = 20, y0 = 20;
  var dx = 1, dy = 1;
  var w = 15, h = 15;
  var fontSize = 15;
  var colHeight = 15;
  var lastRowWidth = 30;
  var x, y;

  function buildHeader(spec) {
    var root, entry, value, field;

    // collect
    header = {field: spec.cols[0], label: "", values: new Map()};
    active.forEach(function(row) {
      root = header;
      for (var i= 0, n=spec.cols.length; i<n; i++) {
        field = spec.cols[i];
        value = row[field.name];
        entry = root.values.get(value);
        if (!entry) {
          entry =  i<n-1 && {field: spec.cols[i+1], label: value, values: new Map()} || {label: value};
          root.values.set(value, entry);
        }
        root = entry;
      }
    });

    // assign location and size
    visit(header, x0+spec.rows.length*(w+dx)+lastRowWidth-w+5, y0);

    function visit(root, x, y) {
      root.x = x;
      root.y = y;
      if (root.values) {
        y += colHeight + dy;
        var keys = Array.from(root.values.keys()).sort(root.field.sort);
        keys.forEach(function (key) {
          x = visit(root.values.get(key), x, y)+dx;
        });
      } else {
        x += w+dx;
      }
      x -= dx;
      root.w = x - root.x;
      root.h = h;
      return x;
    }

  }

  function collect(spec, nodes) {
    x = x0;
    y = y0 + (spec.cols.length+1)*(colHeight+dy);
    var mat = {header: {rows:[], cols:[]}, values:[]};
    var max_value = 0;

    visit(spec.rows.length, spec.cols.length, nodes, header);
    return mat;

    function visit(nrows, ncols, nodes, header) {
      var i, n, node, nr = spec.rows.length, nc = spec.cols.length;
      if (nrows > 0) {
        for (i=0, n=nodes.length; i<n; i++) {
          node = nodes[i];
          node.label = node.key;
          node.x = x;
          node.y = y;
          x += +dx + (nrows == 1 ? lastRowWidth+5 : fontSize);
          node.last = nrows == 1;
          visit(nrows-1, ncols, node.values, header);
          if (nrows == 1) {
            y += h;
            node.w = lastRowWidth ;
            node.h = y - node.y - dy+1;
          } else {
            node.h = fontSize;
            node.w = y - node.y - dy;
          }
          x = node.x;
          y += dy;
          mat.header.rows.push(node);
        }
      }
      else {
        for (i=0, n=nodes.length; i<n; i++) {
          node = nodes[i];
          var pos = header.values.get(node.key);
          if (ncols == 1) {
            node.x = pos.x;
            node.y = y;
            node.w = w;
            node.h = h;
            x += w;
            mat.values.push(node);
          } else {
            visit(nrows, ncols-1, node.values, pos);
          }
          x += dx;
        }
      }
    }
  }

  function flatten(node) {
    var list = [];
    visit(node);
    list.shift();
    return list;

    function visit(node) {
      if (node) {
        list.push(node);
        if (node.values)
          node.values.forEach(function (node) { visit(node); });
      }
    }
  }

  function render(mat) {

    d3.select(root).select('#results').attr('height', y);

    var cols = d3.select(root).select('#results').selectAll('.col')
      .data(flatten(header));

    cols.enter()
      .append('div')
      .attr('class', 'col');

    cols
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y;})
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .style('overflow', 'hidden')
      .text(function(d) { return d.label;})
    ;

    cols.exit().remove();

    var list = [];
    for (var i= 0, n=spec.cols.length; i<n; i++) {
      list.push({x: header.x+header.w+dx+5, y: header.y+(i+1)*(colHeight+dy), w:40, h: fontSize, label: spec.cols[i].name });
    }

    var colText = d3.select(root).select('#results').selectAll('.colText')
      .data(list);

    colText.enter()
      .append('div')
      .attr('class', 'colText');

    colText
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y; })
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .text(function(d) { return d.label; });

    colText.exit().remove();

    var rows = d3.select(root).select('#results').selectAll('.row')
      .data(mat.header.rows);

    rows.enter()
      .append('div')
      .attr('class', 'row');

    rows
      .classed('rotate', function(d) { return !d.last; })
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y+ (d.last ? 0 : d.w);})
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .style('overflow', 'hidden')
      .text(function(d) { return d.label;})
    ;

    rows.exit().remove();

    var d3nodes = d3.select(root).select('#results').selectAll('.value')
      .data(mat.values);

    d3nodes.enter()
      .append('div')
      .attr('class', 'value');

    d3nodes
      .style('left', function(d) { return d.x;})
      .style('top', function(d) { return d.y;})
      .style('width', function(d) { return d.w;})
      .style('height', function(d) { return d.h;})
      .style('background-color', function(d) { return color(d.values[valueSelector]); })
    ;

    d3nodes.exit().remove();
  }

  return {
  };

});<|endoftext|>


<commit_before>'use strict';
var config = require('config');
var sleep = require('co-sleep');
var request = require('co-request');
var logger = require('logger');
var co = require('co');
var mongoose = require('mongoose');

var uriMigrate = process.env.MIGRATE_URI || config.get('migrate.uri');
var mongoUri = process.env.MONGO_URI || 'mongodb://' + config.get('mongodb.host') + ':' + config.get('mongodb.port') + '/' + config.get('mongodb.database');

let Subscription = require('models/subscription');

var microserviceClient = require('vizz.microservice-client');

var obtainData = function*(cursor) {
    let url = uriMigrate;
    if (cursor) {
        url += '?cursor=' + cursor;
    }
    logger.debug('Doing request to ', url);
    var response = yield request({
        url: url,
        method: 'GET',
        json: true
    });
    if(response.statusCode !== 200){
        logger.error(response);
        logger.info('Waiting 5 seconds and trying');
        yield sleep(5000);
        response = yield request({
            url: url,
            method: 'GET',
            json: true
        });
    }
    return response.body;
};

let cacheUsers = {};
var obtainNewUserId = function*(userId) {
    try{
        logger.info('Obtaining user with data', userId);
        if(cacheUsers[userId]){
            return cacheUsers[userId];
        }
        let result = yield microserviceClient.requestToMicroservice({
          uri: '/user/oldId/' + userId,
          method: 'GET',
          json: true
        });

        cacheUsers[userId] = result.body.data.id;
        return result.body.data.id;
    }catch(e){
        logger.error(e);
    }
};
logger.info('Setting info', process.env.API_GATEWAY_URL_MIGRATE);
microserviceClient.setDataConnection({
    apiGatewayUrl: process.env.API_GATEWAY_URL_MIGRATE
});

var oldDatasets = {
    "alerts/treeloss": "umd-loss-gain",
    "alerts/terra": "terrai-alerts",
    "alerts/glad": "glad-alerts"
    "alerts/prodes": "prodes-loss",
    "alerts/viirs": "viirs-active-fires",
    "alerts/guyra": "guira-loss",
    "alerts/sad": "imazon-alerts"
};

var tranformDataset = function(oldDataset){
    if(oldDatasets[oldDataset]){
        return oldDatasets[oldDataset];
    }
    return oldDataset;
}

var transformAndSaveData = function*(data){
    logger.info('Saving data');
    if(data){
         for(let i = 0, length = data.length; i < length; i++){
             if(data[i].confirmed){
                //  logger.debug('Saving data', data[i]);
                 let userId = null;
                 if(data[i].user_id){
                     userId = yield obtainNewUserId(data[i].user_id);
                 }else {
                     logger.info('Subscription without user_id');
                 }
                 let language = data[i].language  || 'en';

                 yield new Subscription({
                     name: data[i].name,
                     confirmed: data[i].confirmed,
                     resource:{
                         type: 'EMAIL',
                         content: data[i].email
                     },
                     userId: userId,
                     createdAt: data[i].created,
                     datasets: [tranformDataset(data[i].topic)],
                     language: language.toLowerCase(),
                     params:{
                         iso:{
                             country: data[i].iso,
                             region: data[i].id1
                         },
                         geostore: data[i].geostore,
                         wdpaid: data[i].wdpaid,
                         use: data[i].use,
                         useId: data[i].useid,
                         ifl: data[i].ifl,
                         fl_id1: data[i].fl_id1
                     }
                 }).save();

             } else {
                 logger.debug('not confirmed');
             }
         }
    } else {
        logger.ingo('Empty list');
    }
};

var migrate = function*() {
    logger.info('Obtaining data');
    var data = yield obtainData();

    while (data) {
        logger.debug('Obtained data');

        let element = null;
        let model, idConn = null;
        yield transformAndSaveData(data.subscriptions);
        if(data.cursor){
            data = yield obtainData(data.cursor);
        } else {
            data = null;
        }
    }

    logger.debug('Finished migration');
};
var onDbReady = function() {
    co(function*() {
        logger.info('Starting migration');

        yield migrate();
        process.exit();
    });
};
mongoose.connect(mongoUri, onDbReady);
<commit_msg>fix error<commit_after>'use strict';
var config = require('config');
var sleep = require('co-sleep');
var request = require('co-request');
var logger = require('logger');
var co = require('co');
var mongoose = require('mongoose');

var uriMigrate = process.env.MIGRATE_URI || config.get('migrate.uri');
var mongoUri = process.env.MONGO_URI || 'mongodb://' + config.get('mongodb.host') + ':' + config.get('mongodb.port') + '/' + config.get('mongodb.database');

let Subscription = require('models/subscription');

var microserviceClient = require('vizz.microservice-client');

var obtainData = function*(cursor) {
    let url = uriMigrate;
    if (cursor) {
        url += '?cursor=' + cursor;
    }
    logger.debug('Doing request to ', url);
    var response = yield request({
        url: url,
        method: 'GET',
        json: true
    });
    if(response.statusCode !== 200){
        logger.error(response);
        logger.info('Waiting 5 seconds and trying');
        yield sleep(5000);
        response = yield request({
            url: url,
            method: 'GET',
            json: true
        });
    }
    return response.body;
};

let cacheUsers = {};
var obtainNewUserId = function*(userId) {
    try{
        logger.info('Obtaining user with data', userId);
        if(cacheUsers[userId]){
            return cacheUsers[userId];
        }
        let result = yield microserviceClient.requestToMicroservice({
          uri: '/user/oldId/' + userId,
          method: 'GET',
          json: true
        });

        cacheUsers[userId] = result.body.data.id;
        return result.body.data.id;
    }catch(e){
        logger.error(e);
    }
};
logger.info('Setting info', process.env.API_GATEWAY_URL_MIGRATE);
microserviceClient.setDataConnection({
    apiGatewayUrl: process.env.API_GATEWAY_URL_MIGRATE
});

var oldDatasets = {
    "alerts_treeloss": "umd-loss-gain",
    "alerts_terra": "terrai-alerts",
    "alerts_glad": "glad-alerts"
    "alerts_prodes": "prodes-loss",
    "alerts_viirs": "viirs-active-fires",
    "alerts_guyra": "guira-loss",
    "alerts_sad": "imazon-alerts"
};

var tranformDataset = function(oldDataset){
    if(oldDataset && oldDatasets[oldDataset.replace(/\//g, '_')]){
        return oldDatasets[oldDataset];
    }
    return oldDataset;
}

var transformAndSaveData = function*(data){
    logger.info('Saving data');
    if(data){
         for(let i = 0, length = data.length; i < length; i++){
             if(data[i].confirmed){
                //  logger.debug('Saving data', data[i]);
                 let userId = null;
                 if(data[i].user_id){
                     userId = yield obtainNewUserId(data[i].user_id);
                 }else {
                     logger.info('Subscription without user_id');
                 }
                 let language = data[i].language  || 'en';

                 yield new Subscription({
                     name: data[i].name,
                     confirmed: data[i].confirmed,
                     resource:{
                         type: 'EMAIL',
                         content: data[i].email
                     },
                     userId: userId,
                     createdAt: data[i].created,
                     datasets: [tranformDataset(data[i].topic)],
                     language: language.toLowerCase(),
                     params:{
                         iso:{
                             country: data[i].iso,
                             region: data[i].id1
                         },
                         geostore: data[i].geostore,
                         wdpaid: data[i].wdpaid,
                         use: data[i].use,
                         useId: data[i].useid,
                         ifl: data[i].ifl,
                         fl_id1: data[i].fl_id1
                     }
                 }).save();

             } else {
                 logger.debug('not confirmed');
             }
         }
    } else {
        logger.ingo('Empty list');
    }
};

var migrate = function*() {
    logger.info('Obtaining data');
    var data = yield obtainData();

    while (data) {
        logger.debug('Obtained data');

        let element = null;
        let model, idConn = null;
        yield transformAndSaveData(data.subscriptions);
        if(data.cursor){
            data = yield obtainData(data.cursor);
        } else {
            data = null;
        }
    }

    logger.debug('Finished migration');
};
var onDbReady = function() {
    co(function*() {
        logger.info('Starting migration');

        yield migrate();
        process.exit();
    });
};
mongoose.connect(mongoUri, onDbReady);
<|endoftext|>


<commit_before>import { GamePlayers, socket } from '../sockets'
import Easystar from 'easystarjs'
import throttle from 'lodash.throttle'
import Enemy from '../constructor/Enemy'
import Loot from '../constructor/Loot'
import loadMaps from './utils/loadMaps'
import buildMaps from './utils/buildMaps'
import createCursors from './utils/createCursors'
import createPlayer from './utils/createPlayer'
import createProjectile from './utils/createProjectile'
import playerMovement from './utils/playerMovement'
import playerAttack from './utils/playerAttack'
import mapTransition from './utils/mapTransition'

let map
  , cursors
  , playerObject
  , player
  , projectile
  , graveyard = []
  , enemyCounter = 0
  , lootCounter = 0

const localState = {
  players: [],
  enemies: {},
  loot: []
}

const fantasyState = {
  init(character) {
    if (character) player = character
  },

  preload() {
    loadMaps.fantasy()
  },

  create() {
    this.physics.startSystem(Phaser.Physics.ARCADE)

    cursors = createCursors()
    map = buildMaps.fantasy()

    socket.emit('setupState', player, 'fantasyState')

    playerObject = createPlayer(player)
    localState.players.push(playerObject)
    projectile = createProjectile.bullet(playerObject)

    this.makeCollisionMap()
    this.spawnEnemy()
    this.spawnLoot()

    this.physics.setBoundsToWorld(true, true, true, true, false)

    StackQuest.game.input.onDown.add((pointer, mouseEvent) => playerAttack(pointer, mouseEvent, playerObject, projectile), this)
  },

  update() {
    graveyard.forEach(enemy => enemy.destroy())
    graveyard = []

    if (Math.random() * 1000 <= 20) this.spawnEnemy()

    playerMovement(playerObject, cursors)
    mapTransition(player, playerObject, 'spaceState')

    for (const enemyKey in localState.enemies) {
      this.enemyPathFinding(enemyKey)
    }
    // get this guy out, need to detect collsion better
    this.physics.arcade.collide(playerObject, localState.loot[0], function(player, loot) {
      console.log('collision ')
      console.log('loot', loot)
      loot.destroy()
    })
  },

  render() {
    this.game.debug.cameraInfo(this.camera, 32, 32)
  },

  enemyPathFinding(enemyKey) {
    const enemy = localState.enemies[enemyKey]
    StackQuest.game.physics.arcade.overlap(projectile.bullets, enemy, () => {
      graveyard.push(enemy)
      delete localState.enemies[enemyKey]
    })
    StackQuest.game.physics.arcade.overlap(enemy, playerObject, () => {
      playerObject.position.x = 200
      playerObject.position.y = 200
    })
    const closestPlayer = enemy.findClosestPlayer(localState)
    this.easystar.findPath(Math.floor(enemy.position.x / map.width), Math.floor(enemy.position.y / map.height), Math.floor(closestPlayer.position.x / map.width), Math.floor(closestPlayer.position.y / map.height), (path) => enemy.move(path, this))
    this.easystar.calculate()
  },

  makeCollisionMap() {
    const collisionArray = []
    for (let rowIdx = 0; rowIdx < map.height; rowIdx++) {
      const rowArray = []
      for (let colIdx = 0; colIdx < map.width; colIdx++) {
        let collision = false
        for (const layer of map.layers) {
          if (layer.data[rowIdx][colIdx].collides) {
            collision = true
            break
          }
        }
        rowArray.push(Number(collision))
      }
      collisionArray.push(rowArray)
    }
    this.easystar = new Easystar.js()
    this.easystar.setGrid(collisionArray)
    this.easystar.setAcceptableTiles([0])
    this.easystar.enableDiagonals()
  },

  getPointFromGrid(rowIdx, colIdx) {
    const y = (rowIdx * map.height) + (map.height / 2)
    const x = (colIdx * map.width) + (map.width / 2)
    return new Phaser.Point(x, y)
  },

  spawnEnemy() {
    localState.enemies[enemyCounter++] = new Enemy(this.game, 'Soldier', { x: Math.random() * 1920, y: Math.random() * 1920 }, `${Math.random() > 0.5 ? 'soldier' : 'soldieralt'}`)
  },
  spawnLoot() {
    localState.loot[lootCounter++] = new Loot(this.game, 'Item', { x: Math.random() * 400, y: Math.random() * 400 }, 'item')
  }
}

export default fantasyState
<commit_msg>add more collision events<commit_after>import { GamePlayers, socket } from '../sockets'
import Easystar from 'easystarjs'
import throttle from 'lodash.throttle'
import Enemy from '../constructor/Enemy'
import Loot from '../constructor/Loot'
import loadMaps from './utils/loadMaps'
import buildMaps from './utils/buildMaps'
import createCursors from './utils/createCursors'
import createPlayer from './utils/createPlayer'
import createProjectile from './utils/createProjectile'
import playerMovement from './utils/playerMovement'
import playerAttack from './utils/playerAttack'
import mapTransition from './utils/mapTransition'

let map
  , cursors
  , playerObject
  , player
  , projectile
  , graveyard = []
  , enemyCounter = 0
  , lootCounter = 0

const localState = {
  players: [],
  enemies: {},
  loot: []
}

const fantasyState = {
  init(character) {
    if (character) player = character
  },

  preload() {
    loadMaps.fantasy()
  },

  create() {
    this.physics.startSystem(Phaser.Physics.ARCADE)

    cursors = createCursors()
    map = buildMaps.fantasy()

    socket.emit('setupState', player, 'fantasyState')

    playerObject = createPlayer(player)
    localState.players.push(playerObject)
    projectile = createProjectile.bullet(playerObject)

    this.makeCollisionMap()
    this.spawnEnemy()
    this.spawnLoot()

    this.physics.setBoundsToWorld(true, true, true, true, false)

    StackQuest.game.input.onDown.add((pointer, mouseEvent) => playerAttack(pointer, mouseEvent, playerObject, projectile), this)
  },

  update() {
    graveyard.forEach(enemy => enemy.destroy())
    graveyard = []

    if (Math.random() * 1000 <= 20) this.spawnEnemy()

    playerMovement(playerObject, cursors)
    mapTransition(player, playerObject, 'spaceState')

    for (const enemyKey in localState.enemies) {
      this.enemyPathFinding(enemyKey)
    }
    // get this guy out, need to detect collsion better
    this.physics.arcade.collide(playerObject, localState.loot[0], function(player, loot) {
      console.log('play obj ', playerObject)
      console.log('loot', loot)
      // playerObject.
      loot.destroy()
    })
  },

  render() {
    this.game.debug.cameraInfo(this.camera, 32, 32)
  },

  enemyPathFinding(enemyKey) {
    const enemy = localState.enemies[enemyKey]
    StackQuest.game.physics.arcade.overlap(projectile.bullets, enemy, () => {
      graveyard.push(enemy)
      delete localState.enemies[enemyKey]
    })
    StackQuest.game.physics.arcade.overlap(enemy, playerObject, () => {
      playerObject.position.x = 200
      playerObject.position.y = 200
    })
    const closestPlayer = enemy.findClosestPlayer(localState)
    this.easystar.findPath(Math.floor(enemy.position.x / map.width), Math.floor(enemy.position.y / map.height), Math.floor(closestPlayer.position.x / map.width), Math.floor(closestPlayer.position.y / map.height), (path) => enemy.move(path, this))
    this.easystar.calculate()
  },

  makeCollisionMap() {
    const collisionArray = []
    for (let rowIdx = 0; rowIdx < map.height; rowIdx++) {
      const rowArray = []
      for (let colIdx = 0; colIdx < map.width; colIdx++) {
        let collision = false
        for (const layer of map.layers) {
          if (layer.data[rowIdx][colIdx].collides) {
            collision = true
            break
          }
        }
        rowArray.push(Number(collision))
      }
      collisionArray.push(rowArray)
    }
    this.easystar = new Easystar.js()
    this.easystar.setGrid(collisionArray)
    this.easystar.setAcceptableTiles([0])
    this.easystar.enableDiagonals()
  },

  getPointFromGrid(rowIdx, colIdx) {
    const y = (rowIdx * map.height) + (map.height / 2)
    const x = (colIdx * map.width) + (map.width / 2)
    return new Phaser.Point(x, y)
  },

  spawnEnemy() {
    localState.enemies[enemyCounter++] = new Enemy(this.game, 'Soldier', { x: Math.random() * 1920, y: Math.random() * 1920 }, `${Math.random() > 0.5 ? 'soldier' : 'soldieralt'}`)
  },
  spawnLoot() {
    localState.loot[lootCounter++] = new Loot(this.game, 'Item', { x: Math.random() * 400, y: Math.random() * 400 }, 'item')
  }
}

export default fantasyState
<|endoftext|>


<commit_before>/*!
 * @package   ElkArte Forum
 * @copyright ElkArte Forum contributors
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
 *
 * @version 2.0 dev
 *
 * Original code from Aziz, redone and refactored for ElkArte
 */

/**
 * This javascript searches the message for video links and replaces them
 * with a clickable preview thumbnail of the video.  Once the image is clicked
 * the video is embedded in to the page to play.
 *
 * Currently works with youtube, vimeo and dailymotion
 *
 */
(function ($)
{
	'use strict';

	/**
	 * @param {object} oInstanceSettings holds the text strings to use in the html created
	 * @param {int} msgid optional to only search for links in a specific id
	 */
	$.fn.linkifyvideo = function (oInstanceSettings, msgid)
	{
		var oDefaultsSettings = {
			embed_limit: 25,
			preview_image: '',
			ctp_video: '',
			hide_video: '',
			youtube: '',
			vimeo: '',
			dailymotion: ''
		};

		// Account for user options
		var oSettings = $.extend({}, oDefaultsSettings, oInstanceSettings || {});

		/**
		 * Takes the generic embed tag and inserts the proper video source
		 *
		 * @param {string} source source string to use in the embed src call
		 */
		function getEmbed(source)
		{
			return embed_html.replace('{src}', source);
		}

		/**
		 * Replaces the image with the created embed code to show the video
		 * Called from click / double click events attached to the image
		 *
		 * @param {string} tag anchor tag we are replacing with the embed tag
		 * @param {string} eURL the load or place source link
		 */
		function showFlash(tag, eURL)
		{
			$(tag).replaceWith(getEmbed(eURL));
		}

		/**
		 * Shows the video image and sets up the link
		 * Sets up single click event to play videoID and double click to load it
		 *
		 * @param {string} a videoID link
		 * @param {string} src source of image
		 * @param {string} eURL load link
		 * @param {string} eURLa play link
		 */
		function getIMG(a, src, eURL, eURLa)
		{
			return $('

')
				.on('dblclick', function (e)
				{
					// double click loads the video but does not autoplay
					e.preventDefault();

					// clear the single click event
					clearTimeout(this.tagID);
					showFlash(this, eURL);
				})
				.on('click', function (e)
				{
					// single click to begin playing the video
					e.preventDefault();
					var tag = this;

					this.tagID = setTimeout(function ()
					{
						showFlash(tag, eURLa);
					}, 200);
				});
		}

		/**
		 * Get a vimeo videos thumbnail
		 *
		 * @param {string} videoID
		 * @param {string} callback function to call once the json results are returned.
		 */
		function getVimeoIMG(videoID, callback)
		{
			var img = 'assets.vimeo.com/images/logo_vimeo_land.png';

			$.getJSON('http://www.vimeo.com/api/v2/video/' + videoID + '.json?callback=?', {format: "json"},
				function (data)
				{
					if (typeof data[0].thumbnail_large !== "undefined")
					{
						callback(data[0].thumbnail_large);
					}
					else
					{
						callback(img);
					}
				});
		}

		/**
		 * Get a dailymotion video thumbnail
		 *
		 * @param {string} videoID
		 * @param {string} callback function to call once the json results are returned.
		 */
		function getDailymotionIMG(videoID, callback)
		{
			var img = 'assets.vimeo.com/images/logo_vimeo_land.png';

			$.getJSON('https://api.dailymotion.com/video/' + videoID + '?fields=thumbnail_480_url', {},
				function (data)
				{
					if (typeof data.thumbnail_480_url !== "undefined")
					{
						callback(data.thumbnail_480_url);
					}
					else
					{
						callback(img);
					}
				}
			);
		}

		/**
		 * Returns either an image link or an embed link
		 *
		 * @param {boolean} embed true returns the video embed code, false the image preview
		 * @param {string} a link tag of the video
		 * @param {string} src link of the preview image
		 * @param {string} eURL double click event load video
		 * @param {string} eURLa single click event play video
		 */
		function embedOrIMG(embed, a, src, eURL, eURLa)
		{
			return embed ? getEmbed(eURL) : getIMG(a, src, eURL, eURLa);
		}

		var domain_regex = /^[^:]*:\/\/(?:www\.)?([^\/]+)(\/.*)$/,
			already_embedded = 0,
			embed_html = '

',
			handlers = {};

		// Youtube and variants link handler
		handlers['youtube.com'] = function (path, a, embed)
		{
			var videoID = path.match(/\bv[=/]([^&#?$]+)/i) || path.match(/#p\/(?:a\/)?[uf]\/\d+\/([^?$]+)/i) || path.match(/(?:\/)([\w-]{11})/i);
			if (!videoID || !(videoID = videoID[1]))
			{
				return;
			}

			// There are two types of YouTube timestamped links
			// http://youtu.be/lLOE3fBZcUU?t=1m37s when you click share underneath the video
			// http://youtu.be/lLOE3fBZcUU?t=97 when you right click on a video and choose "Copy video URL at current time"
			// For embedding, you need to use "?start=97" instead, so we have to convert t=1m37s to seconds while also supporting t=97
			var startAt = path.match(/t=(?:([1-9]{1,2})h)?(?:([1-9]{1,2})m)?(?:([1-9]+)s?)/),
				startAtPar = '';
			if (startAt)
			{
				var startAtSeconds = 0;

				// Hours
				if (typeof startAt[1] !== 'undefined')
				{
					startAtSeconds += parseInt(startAt[1]) * 3600;
				}
				// Minutes
				if (typeof startAt[2] !== 'undefined')
				{
					startAtSeconds += parseInt(startAt[2]) * 60;
				}
				// Seconds
				if (typeof startAt[3] !== 'undefined')
				{
					startAtSeconds += parseInt(startAt[3]);
				}

				startAtPar = '&start=' + startAtSeconds.toString();
			}

			var embedURL = '//www.youtube-nocookie.com/embed/' + videoID + '?rel=0' + startAtPar,
				tag = embedOrIMG(embed, a, '//img.youtube.com/vi/' + videoID + '/0.jpg', embedURL, embedURL + '&autoplay=1');

			return [oSettings.youtube, tag];
		};
		handlers['m.youtube.com'] = handlers['youtube.com'];
		handlers['youtu.be'] = handlers['youtube.com'];

		// Vimeo link handler
		handlers['vimeo.com'] = function (path, a, embed)
		{
			var videoID = path.match(/^\/(\d+)/i);
			if (!videoID || !(videoID = videoID[1]))
			{
				return;
			}

			var embedURL = '//player.vimeo.com/video/' + videoID,
				tag = null,
				img = '//assets.vimeo.com/images/logo_vimeo_land.png';

			// Get the preview image or embed tag
			if (!embed)
			{
				// We need to use a callback to get the thumbnail
				getVimeoIMG(videoID, function (img)
				{
					$(a).parent().next().find("img").attr("src", img);
				});

				// This is to show something while we wait for our callback to return
				tag = embedOrIMG(embed, a, img, embedURL, embedURL + '?autoplay=1');
			}
			else
			{
				tag = embedOrIMG(embed, a, img, embedURL, embedURL + '?autoplay=1');
			}

			return [oSettings.vimeo, tag];
		};

		// Dailymotion link handler
		handlers['dailymotion.com'] = function (path, a, embed)
		{
			var videoID = path.match(/^\/(?:video|swf)\/([a-z0-9]{1,18})/i);
			if (!videoID || !(videoID = videoID[1]))
			{
				return;
			}

			var embedURL = '//dailymotion.com/embed/video/' + videoID,
				tag = null,
				img = '//dailymotion.com/thumbnail/video/' + videoID;

			// Get the preview image or embed tag
			if (!embed)
			{
				// We use a callback to get the thumbnail we want
				getDailymotionIMG(videoID, function (img)
				{
					$(a).parent().next().find("img").attr("src", img);
				});

				// This is to show something while we wait for our callback to return
				tag = embedOrIMG(embed, a, img, embedURL, embedURL + '?related=0&autoplay=1');
			}
			else
			{
				tag = embedOrIMG(embed, a, img, embedURL + '?related=0', embedURL + '?related=0&autoplay=1');
			}

			return [oSettings.dailymotion, tag];
		};

		// Get the links in the id="msg_1234 divs.
		var links = null;

		if (typeof msgid !== "undefined" && msgid !== null)
		{
			links = $('#' + msgid + ' a');
		}
		else
		{
			links = $('[id^=msg_] a');
		}

		// Create the show/hide button
		var showhideBtn = $('" src="' + elk_images_url + '/selected.png">').on('click', function ()
		{
			var $img = $(this).find("img"),
				$vid = $(this).parent().next();

			// Toggle slide the video and change the icon
			$img.attr("src", elk_images_url + ($vid.is(":hidden") !== true ? "/selected_open.png" : "/selected.png"));
			$vid.slideToggle();
		});

		// Loop though each link old skool style for speed
		for (var i = links.length - 1; i > -1; i--)
		{
			var tag = links[i],
				text = tag.innerText || tag.textContent || "";

			// Ignore in sentences
			if (tag.previousSibling && tag.previousSibling.nodeName === '#text')
			{
				continue;
			}

			// Ignore in quotes and signatures
			if ("bbc_quote;signature".indexOf(tag.parentNode.className) !== -1)
			{
				continue;
			}

			// No href or inner text not equal to href attr then we move along
			if (tag.href === "" || tag.href.indexOf(text) !== 0)
			{
				continue;
			}

			// Get domain and validate we know how to handle it
			var m = tag.href.match(domain_regex),
				handler = null,
				args = null;

			// One of our video provider domains?
			if (already_embedded < oSettings.embed_limit && m !== null && typeof handlers[m[1]] !== "undefined" && handlers[m[1]] !== null)
			{
				// Call the handler and get the tag to insert
				handler = handlers[m[1]];

				args = handler(m[2], tag, false);
				if (args)
				{
					already_embedded++;
					$(tag).wrap('
').text(args[0]).after(showhideBtn.clone(true));
					$(tag).parent().after(args[1]);
				}
			}
		}
	};
})(jQuery);
<commit_msg>! cleanup embed video code<commit_after>/*!
 * @package   ElkArte Forum
 * @copyright ElkArte Forum contributors
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
 *
 * @version 2.0 dev
 *
 * Original code from Aziz, redone and refactored for ElkArte
 */

/**
 * This javascript searches the message for video links and replaces them
 * with a clickable preview thumbnail of the video.  Once the image is clicked
 * the video is embedded in to the page to play.
 *
 * Currently works with youtube, vimeo and dailymotion
 *
 */
(function ($)
{
	'use strict';

	/**
	 * @param {object} oInstanceSettings holds the text strings to use in the html created
	 * @param {int} msgid optional to only search for links in a specific id
	 */
	$.fn.linkifyvideo = function (oInstanceSettings, msgid)
	{
		let oDefaultsSettings = {
			embed_limit: 25,
			preview_image: '',
			ctp_video: '',
			hide_video: '',
			youtube: '',
			vimeo: '',
			dailymotion: ''
		};

		// Account for user options
		let oSettings = $.extend({}, oDefaultsSettings, oInstanceSettings || {});

		/**
		 * Takes the generic embed tag and inserts the proper video source
		 *
		 * @param {string} source source string to use in the embed src call
		 */
		function getEmbed(source)
		{
			return embed_html.replace('{src}', source);
		}

		/**
		 * Replaces the image with the created embed code to show the video
		 * Called from click / double click events attached to the image
		 *
		 * @param {string} tag anchor tag we are replacing with the embed tag
		 * @param {string} eURL the load or place source link
		 */
		function showFlash(tag, eURL)
		{
			$(tag).replaceWith(getEmbed(eURL));
		}

		/**
		 * Shows the video image and sets up the link
		 * Sets up single click event to play videoID and double click to load it
		 *
		 * @param {object} a videoID link
		 * @param {string} src source of image
		 * @param {string} eURL load link
		 * @param {string} eURLa play link
		 */
		function getIMG(a, src, eURL, eURLa)
		{
			return $('' +
				'
' +
					'' +
						'' +
					'' +
				'
')
				.on('dblclick', function (e)
				{
					// double click loads the video but does not autoplay
					e.preventDefault();

					// clear the single click event
					clearTimeout(this.tagID);
					showFlash(this, eURL);
				})
				.on('click', function (e)
				{
					// single click to begin playing the video
					e.preventDefault();
					let tag = this;

					this.tagID = setTimeout(function ()
					{
						showFlash(tag, eURLa);
					}, 200);
				});
		}

		/**
		 * Get a vimeo videos thumbnail
		 *
		 * @param {string} videoID
		 * @param {string} callback function to call once the json results are returned.
		 */
		function getVimeoIMG(videoID, callback)
		{
			let img = 'assets.vimeo.com/images/logo_vimeo_land.png';

			$.getJSON('http://www.vimeo.com/api/v2/video/' + videoID + '.json?callback=?', {format: "json"},
				function (data)
				{
					if (typeof data[0].thumbnail_large !== "undefined")
					{
						callback(data[0].thumbnail_large);
					}
					else
					{
						callback(img);
					}
				});
		}

		/**
		 * Get a dailymotion video thumbnail
		 *
		 * @param {string} videoID
		 * @param {string} callback function to call once the json results are returned.
		 */
		function getDailymotionIMG(videoID, callback)
		{
			let img = 'assets.vimeo.com/images/logo_vimeo_land.png';

			$.getJSON('https://api.dailymotion.com/video/' + videoID + '?fields=thumbnail_480_url', {},
				function (data)
				{
					if (typeof data.thumbnail_480_url !== "undefined")
					{
						callback(data.thumbnail_480_url);
					}
					else
					{
						callback(img);
					}
				}
			);
		}

		/**
		 * Returns either an image link or an embed link
		 *
		 * @param {boolean} embed true returns the video embed code, false the image preview
		 * @param {string} a link tag of the video
		 * @param {string} src link of the preview image
		 * @param {string} eURL double click event load video
		 * @param {string} eURLa single click event play video
		 */
		function embedOrIMG(embed, a, src, eURL, eURLa)
		{
			return embed ? getEmbed(eURL) : getIMG(a, src, eURL, eURLa);
		}

		let domain_regex = /^[^:]*:\/\/(?:www\.)?([^\/]+)(\/.*)$/,
			already_embedded = 0,
			embed_html = '

',
			handlers = {};

		// Youtube and variants link handler
		handlers['youtube.com'] = function (path, a, embed)
		{
			let videoID = path.match(/\bv[=/]([^&#?$]+)/i) || path.match(/#p\/(?:a\/)?[uf]\/\d+\/([^?$]+)/i) || path.match(/(?:\/)([\w-]{11})/i);
			if (!videoID || !(videoID = videoID[1]))
			{
				return;
			}

			// There are two types of YouTube timestamped links
			// http://youtu.be/lLOE3fBZcUU?t=1m37s when you click share underneath the video
			// http://youtu.be/lLOE3fBZcUU?t=97 when you right click on a video and choose "Copy video URL at current time"
			// For embedding, you need to use "?start=97" instead, so we have to convert t=1m37s to seconds while also supporting t=97
			let startAt = path.match(/t=(?:([1-9]{1,2})h)?(?:([1-9]{1,2})m)?(?:([1-9]+)s?)/),
				startAtPar = '';

			if (startAt)
			{
				let startAtSeconds = 0;

				// Hours
				if (typeof startAt[1] !== 'undefined')
				{
					startAtSeconds += parseInt(startAt[1]) * 3600;
				}

				// Minutes
				if (typeof startAt[2] !== 'undefined')
				{
					startAtSeconds += parseInt(startAt[2]) * 60;
				}

				// Seconds
				if (typeof startAt[3] !== 'undefined')
				{
					startAtSeconds += parseInt(startAt[3]);
				}

				startAtPar = '&start=' + startAtSeconds.toString();
			}

			let embedURL = '//www.youtube-nocookie.com/embed/' + videoID + '?rel=0' + startAtPar,
				tag = embedOrIMG(embed, a, '//i.ytimg.com/vi/' + videoID + '/sddefault.jpg', embedURL, embedURL + '&autoplay=1');

			return [oSettings.youtube, tag];
		};
		handlers['m.youtube.com'] = handlers['youtube.com'];
		handlers['youtu.be'] = handlers['youtube.com'];

		// Vimeo link handler
		handlers['vimeo.com'] = function (path, a, embed)
		{
			let videoID = path.match(/^\/(\d+)/i);
			if (!videoID || !(videoID = videoID[1]))
			{
				return;
			}

			let embedURL = '//player.vimeo.com/video/' + videoID,
				tag = null,
				img = '//assets.vimeo.com/images/logo_vimeo_land.png';

			// Get the preview image or embed tag
			if (!embed)
			{
				// We need to use a callback to get the thumbnail
				getVimeoIMG(videoID, function (img)
				{
					$(a).parent().next().find("img").attr("src", img);
				});

				// This is to show something while we wait for our callback to return
				tag = embedOrIMG(embed, a, img, embedURL, embedURL + '?autoplay=1');
			}
			else
			{
				tag = embedOrIMG(embed, a, img, embedURL, embedURL + '?autoplay=1');
			}

			return [oSettings.vimeo, tag];
		};

		// Dailymotion link handler
		handlers['dailymotion.com'] = function (path, a, embed)
		{
			let videoID = path.match(/^\/(?:video|swf)\/([a-z0-9]{1,18})/i);
			if (!videoID || !(videoID = videoID[1]))
			{
				return;
			}

			let embedURL = '//dailymotion.com/embed/video/' + videoID,
				tag = null,
				img = '//dailymotion.com/thumbnail/video/' + videoID;

			// Get the preview image or embed tag
			if (!embed)
			{
				// We use a callback to get the thumbnail we want
				getDailymotionIMG(videoID, function (img)
				{
					$(a).parent().next().find("img").attr("src", img);
				});

				// This is to show something while we wait for our callback to return
				tag = embedOrIMG(embed, a, img, embedURL, embedURL + '?related=0&autoplay=1');
			}
			else
			{
				tag = embedOrIMG(embed, a, img, embedURL + '?related=0', embedURL + '?related=0&autoplay=1');
			}

			return [oSettings.dailymotion, tag];
		};

		// Get the links in the id="msg_1234 divs.
		let links;

		if (typeof msgid !== "undefined")
		{
			links = $('#' + msgid + ' a');
		}
		else
		{
			links = $('[id^=msg_] a');
		}

		// Create the show/hide button
		let showhideBtn = $('' +
			'' +
				'" src="' + elk_images_url + '/selected.png">' +
			'').on('click', function ()
		{
			let $img = $(this).find("img"),
				$vid = $(this).parent().next();

			// Toggle slide the video and change the icon
			$img.attr("src", elk_images_url + ($vid.is(":hidden") !== true ? "/selected_open.png" : "/selected.png"));
			$vid.slideToggle();
		});

		// Loop though each link old skool style for speed
		for (let i = links.length - 1; i > -1; i--)
		{
			let tag = links[i],
				text = tag.innerText || tag.textContent || "";

			// Ignore in sentences
			if (tag.previousSibling && tag.previousSibling.nodeName === '#text')
			{
				continue;
			}

			// Ignore in quotes and signatures
			if ("bbc_quote;signature".indexOf(tag.parentNode.className) !== -1)
			{
				continue;
			}

			// No href or inner text not equal to href attr then we move along
			if (tag.href === "" || tag.href.indexOf(text) !== 0)
			{
				continue;
			}

			// Get domain and validate we know how to handle it
			let m = tag.href.match(domain_regex),
				handler = null,
				args = null;

			// One of our video provider domains?
			if (already_embedded < oSettings.embed_limit && m !== null && typeof handlers[m[1]] !== "undefined" && handlers[m[1]] !== null)
			{
				// Call the handler and get the tag to insert
				handler = handlers[m[1]];

				args = handler(m[2], tag, false);
				if (args)
				{
					already_embedded++;
					$(tag).wrap('
').text(args[0]).after(showhideBtn.clone(true));
					$(tag).parent().after(args[1]);
				}
			}
		}
	};
})(jQuery);

(function(window, document, undefined) {
	"use strict";

	// List of Video Vendors embeds you want to support
	var players = ['iframe[src*="youtube.com"]', 'iframe[src*="vimeo.com"]'];

	// Select videos
	var fitVids = document.querySelectorAll(players.join(","));

	// If there are videos on the page...
	if (fitVids.length) {
		// Loop through videos
		for (var i = 0; i < fitVids.length; i++) {
			// Get Video Information
			var fitVid = fitVids[i];
			var width = fitVid.getAttribute("width");
			var height = fitVid.getAttribute("height");
			var aspectRatio = height / width;
			var parentDiv = fitVid.parentNode;

			// Wrap it in a DIV
			var div = document.createElement("div");
			div.className = "fitVids-wrapper";
			div.style.paddingBottom = aspectRatio * 100 + "%";
			parentDiv.insertBefore(div, fitVid);
			fitVid.remove();
			div.appendChild(fitVid);

			// Clear height/width from fitVid
			fitVid.removeAttribute("height");
			fitVid.removeAttribute("width");
		}
	}
})(window, document);
<|endoftext|>


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

/**
 * Linkscape API client.
 */
var Linkscape = function(accessId, secret) {
    this.configure({ accessId: accessId, secret: secret });
}

exports.Linkscape = Linkscape;

(function() {

    this.defaults = {
        hostname    : 'lsapi.seomoz.com',
        path        : 'linkscape',
        userAgent   : 'node-linkscape (https://github.com/mjp/node-linkscape)',
        accessId    : null,
        secret      : null
    };

    this.configure = function(options) {
        var options = options || {};
        this.options = {};

        for (var key in this.defaults) {
            this.options[key] = options[key] !== undefined ? options[key] : this.defaults[key];
        }

        return this;
    }

    /**
     * URL Metrics API
     *
     * http://apiwiki.seomoz.org/w/page/13991153/URL-Metrics-API
     */
    this.urlMetrics = function() {
        //
    };

    /**
     * Links API
     *
     * http://apiwiki.seomoz.org/w/page/13991141/Links-API
     */
    this.links = function() {
        //
    };

    /**
     * Anchor Text API
     *
     * http://apiwiki.seomoz.org/w/page/13991127/Anchor-Text-API
     */
    this.anchorText = function() {
        //
    };

    this.get = function(apiPath, params, callback) {
        return this.send(apiPath, params, 'GET', callback);
    };

    this.post = function(apiPath, params, callback) {
        return this.send(apiPath, params, 'POST', callback);
    };

    this.send = function(apiPath, params, method, callback) {
        var client = http.createClient(80, this.options.hostname);

        var headers = {
            'host': 'lsapi.seomoz.com',
            'Authorization': 'Basic ' + new Buffer(this.options.accessId + ':' + this.options.secret).toString('base64'),
            'User-Agent': this.options.userAgent,
            'Content-Length': '0'
        };

        var path = 'http://' + this.options.hostname + '/' + this.options.path + '/' + apiPath;

        var args = [];
        for (var key in params) {
            args.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
        }
        var queryString = args.join('&');

        if (queryString) {
            switch (method) {
                case 'GET':
                    path += '?' + queryString;
                    break;
                case 'POST':
                    headers['Content-Length'] = queryString.length;
                    break;
            }
        }

        var request = client.request(method, path, headers);
        if (method == 'POST') {
            request.write(queryString);
        }

        request.addListener('response', function(response) {
            if (response.statusCode > 200) {
                callback({ status: response.statusCode, msg: response.status });
                return;
            }

            response.setEncoding('utf8');

            var body = [];
            response.addListener('data', function(chunk) {
                body.push(chunk);
            });

            response.addListener('end', function() {
                callback(null, body.join(''));
            });
        });

        request.end();
    };

}).call(Linkscape.prototype);
<commit_msg>Added initial support for urlMetrics<commit_after>var http = require('http');

/**
 * Linkscape API client.
 */
var Linkscape = function(accessId, secret) {
    this.configure({ accessId: accessId, secret: secret });
}

exports.Linkscape = Linkscape;

(function() {

    this.defaults = {
        hostname    : 'lsapi.seomoz.com',
        path        : 'linkscape',
        userAgent   : 'node-linkscape (https://github.com/mjp/node-linkscape)',
        accessId    : null,
        secret      : null
    };

    this.configure = function(options) {
        var options = options || {};
        this.options = {};

        for (var key in this.defaults) {
            this.options[key] = options[key] !== undefined ? options[key] : this.defaults[key];
        }

        return this;
    }

    /**
     * URL Metrics API
     *
     * http://apiwiki.seomoz.org/w/page/13991153/URL-Metrics-API
     */
    this.urlMetrics = function(url, callback) {
        var apiPath = 'url-metrics/' + encodeURIComponent(url);
        this.get(apiPath, {}, callback);
    };

    /**
     * Links API
     *
     * http://apiwiki.seomoz.org/w/page/13991141/Links-API
     */
    this.links = function() {
        //
    };

    /**
     * Anchor Text API
     *
     * http://apiwiki.seomoz.org/w/page/13991127/Anchor-Text-API
     */
    this.anchorText = function() {
        //
    };

    this.get = function(apiPath, params, callback) {
        return this.send(apiPath, params, 'GET', callback);
    };

    this.post = function(apiPath, params, callback) {
        return this.send(apiPath, params, 'POST', callback);
    };

    this.send = function(apiPath, params, method, callback) {
        var client = http.createClient(80, this.options.hostname);

        var headers = {
            'host': 'lsapi.seomoz.com',
            'Authorization': 'Basic ' + new Buffer(this.options.accessId + ':' + this.options.secret).toString('base64'),
            'User-Agent': this.options.userAgent,
            'Content-Length': '0'
        };

        var path = 'http://' + this.options.hostname + '/' + this.options.path + '/' + apiPath;

        var args = [];
        for (var key in params) {
            args.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
        }
        var queryString = args.join('&');

        if (queryString) {
            switch (method) {
                case 'GET':
                    path += '?' + queryString;
                    break;
                case 'POST':
                    headers['Content-Length'] = queryString.length;
                    break;
            }
        }

        var request = client.request(method, path, headers);
        if (method == 'POST') {
            request.write(queryString);
        }

        request.addListener('response', function(response) {
            if (response.statusCode > 200) {
                callback({ status: response.statusCode, msg: response.status });
                return;
            }

            response.setEncoding('utf8');

            var body = [];
            response.addListener('data', function(chunk) {
                body.push(chunk);
            });

            response.addListener('end', function() {
                callback(null, JSON.parse(body.join('')));
            });
        });

        request.end();
    };

}).call(Linkscape.prototype);
<|endoftext|>


<commit_before>const {dialog} = require('electron').remote;

const { getLangs, getKeysInFiles, getFilesInDirDeep, writeLangFile } = require('./lang');

const {ipcRenderer} = require('electron');
const fs = require('fs');
const path = require('path');

const config = require('./config.js');

// Array diff
Array.prototype.diff = function(a) {
    return this.filter(function(i) {return a.indexOf(i) < 0;});
};

function getDirectory(){
  return new Promise((resolve, reject) => {
    dialog.showOpenDialog({properties: ['openDirectory']}, (paths) => {
      resolve(paths[0]);
    });
  });
}

document.ondragover = (ev) => {
  ev.preventDefault()
};
document.ondrop = (ev) => {
  app.setRootDir(ev.dataTransfer.files[0].path);
  ev.preventDefault()
};

ipcRenderer.on('save', (event) => {
  app.save();
});
ipcRenderer.on('open', (event) => {
  app.open();
});
ipcRenderer.on('reload', (event) => {
  app.reload();
});

const app = new Vue({
  el: '#app',
  created(){
    if(this.rootDir){
      this.setRootDir(this.rootDir);
    }
  },
  data(){
    return {
      rootDir: config.get("rootDir") || null,
      selectedLangKey: null,
      langs: {},
      scannedKeys: null,
      scannedKeysFound: null,
      scannedKeysFoundSelected: null,
      showModal: false,
      query: '',
      newLangName: null,
      langDir: '/resources/lang',
      scanDirs: ['/resources/views','/app'],
      filterOnKeys: null,
    };
  },
  methods:{
    isLaravelDir(root_dir){
      try{
        return fs.statSync(root_dir+this.langDir).isDirectory();
      } catch(e){
        return false;
      }
    },
    open(){
      getDirectory().then((dir) => {
        this.setRootDir(dir);
      });
    },
    setRootDir(dir){
      if(!this.isLaravelDir(dir)){
        alert("🚨 Doesn't look like a Laravel directory");
        return false;
      }
      this.rootDir = dir;
      config.set("rootDir", dir);

      const langs = getLangs(this.rootDir+this.langDir);
      if(Object.keys(langs).length > 0){
        this.langs = langs;
        this.selectedLangKey = Object.keys(this.langs)[0] || null;
      }
      else{
        this.langs = {};
        this.selectedLangKey = null;
      }
      this.scan();
      document.title = this.rootDir;
    },
    scan(){
      let files = [];
      this.scanDirs.forEach((dir) => {
        files = files.concat(getFilesInDirDeep(this.rootDir+dir));
      });
      files = Array.from(files);
      let keysInfo = getKeysInFiles(files, config.get('functionSearch', []));
      this.scannedKeys = keysInfo.keys;
      this.scannedKeysFound = keysInfo.found;
    },
    reload(){
      if(confirm("Sure? You will lose any unsaved changes 😱")){
        this.setRootDir(this.rootDir);
      }
    },
    save(){
      Promise.all(Object.keys(this.langs).map((lang_key) => {
        return writeLangFile(path.join(this.rootDir, this.langDir, lang_key+".json"), this.langs[lang_key]);
      })).then(() => {
        alert("🙌 Files saved");
      }).catch((err) => {
        console.error(err);
        alert("😢 Something went wrong while saving");
      });
    },
    updateValue(key, value){
      Vue.set(this.langs[this.selectedLangKey], key, value);
    },
    deleteValue(key){
      Vue.delete(this.langs[this.selectedLangKey], key);
    },
    showFound(key){
      let counts = {};
      this.scannedKeysFound[key].map((item) => item.replace(this.rootDir, ''))
      .forEach((item) => {
        if(!counts[item]) counts[item] = 0;
        counts[item]++;
      });
      this.scannedKeysFoundSelected = counts;
      this.showModal = true;
    },
    closeModal(){
      this.showModal = false;
    },
    addLang(){
      let lang_key = this.newLangName.toLowerCase();
      if(Object.keys(this.langs).find(item => item == lang_key)){
        alert("Language already exists");
        this.selectedLangKey = lang_key;
        this.newLangName = '';
        return;
      }
      let emptyLang = {};
      this.allKeys.forEach(key => {
        emptyLang[key] = (lang_key == config.get('baseLanguage')) ? key : null;
      });
      Vue.set(this.langs, lang_key, emptyLang);
      this.selectedLangKey = lang_key;
      this.newLangName = '';
    },
    toggleFilterOnKeysMissing(){
      if(this.filterOnKeys !== null){
        this.filterOnKeys = null;
        return;
      }
      this.filterOnKeys = this.missingKeys;
    }
  },
  computed:{
    selectedLang(){
      return this.langs[this.selectedLangKey] || {};
    },
    missingKeys(){
      if(!this.selectedLang) return [];

      let selectedKeys = Object.keys(this.selectedLang) || [];
      let scannedKeys = this.scannedKeys || [];

      return scannedKeys.diff(selectedKeys);
    },
    extraKeys(){
      let selectedKeys = Object.keys(this.selectedLang) || [];
      let scannedKeys = this.scannedKeys || [];

      return selectedKeys.diff(scannedKeys);
    },
    allKeys(){
      let keys = [];
      Object.keys(this.langs).forEach((lang_key) => {
        keys = keys.concat(Object.keys(this.langs[lang_key]));
      });
      keys = keys.concat(this.scannedKeys);
      return Array.from(new Set(keys));
    },
    allItems(){
      return this.allKeys.map((key) => {
        return {key, value: this.selectedLang[key] || null };
      });
    },
    filteredLangItems(){
      let q = this.query.toLowerCase();
      return this.allItems
        .filter((item) => {
          if(this.filterOnKeys == null) return true;
          return this.filterOnKeys.indexOf(item.key) !== -1;
        })
        .filter((item) => {
        return q == '' || item.key.toLowerCase().indexOf(q) > -1;
      }).sort((a, b) => {
        if(a.key.toLowerCase() < b.key.toLowerCase()) return -1;
        if(a.key.toLowerCase() > b.key.toLowerCase()) return 1;
        return 0;
      });
    },
    numLangs(){
      return Object.keys(this.langs).length;
    }
  }
});
<commit_msg>search the routes directory as well<commit_after>const {dialog} = require('electron').remote;

const { getLangs, getKeysInFiles, getFilesInDirDeep, writeLangFile } = require('./lang');

const {ipcRenderer} = require('electron');
const fs = require('fs');
const path = require('path');

const config = require('./config.js');

// Array diff
Array.prototype.diff = function(a) {
    return this.filter(function(i) {return a.indexOf(i) < 0;});
};

function getDirectory(){
  return new Promise((resolve, reject) => {
    dialog.showOpenDialog({properties: ['openDirectory']}, (paths) => {
      resolve(paths[0]);
    });
  });
}

document.ondragover = (ev) => {
  ev.preventDefault()
};
document.ondrop = (ev) => {
  app.setRootDir(ev.dataTransfer.files[0].path);
  ev.preventDefault()
};

ipcRenderer.on('save', (event) => {
  app.save();
});
ipcRenderer.on('open', (event) => {
  app.open();
});
ipcRenderer.on('reload', (event) => {
  app.reload();
});

const app = new Vue({
  el: '#app',
  created(){
    if(this.rootDir){
      this.setRootDir(this.rootDir);
    }
  },
  data(){
    return {
      rootDir: config.get("rootDir") || null,
      selectedLangKey: null,
      langs: {},
      scannedKeys: null,
      scannedKeysFound: null,
      scannedKeysFoundSelected: null,
      showModal: false,
      query: '',
      newLangName: null,
      langDir: '/resources/lang',
      scanDirs: ['/resources/views', '/app', '/routes'],
      filterOnKeys: null,
    };
  },
  methods:{
    isLaravelDir(root_dir){
      try{
        return fs.statSync(root_dir+this.langDir).isDirectory();
      } catch(e){
        return false;
      }
    },
    open(){
      getDirectory().then((dir) => {
        this.setRootDir(dir);
      });
    },
    setRootDir(dir){
      if(!this.isLaravelDir(dir)){
        alert("🚨 Doesn't look like a Laravel directory");
        return false;
      }
      this.rootDir = dir;
      config.set("rootDir", dir);

      const langs = getLangs(this.rootDir+this.langDir);
      if(Object.keys(langs).length > 0){
        this.langs = langs;
        this.selectedLangKey = Object.keys(this.langs)[0] || null;
      }
      else{
        this.langs = {};
        this.selectedLangKey = null;
      }
      this.scan();
      document.title = this.rootDir;
    },
    scan(){
      let files = [];
      this.scanDirs.forEach((dir) => {
        files = files.concat(getFilesInDirDeep(this.rootDir+dir));
      });
      files = Array.from(files);
      let keysInfo = getKeysInFiles(files, config.get('functionSearch', []));
      this.scannedKeys = keysInfo.keys;
      this.scannedKeysFound = keysInfo.found;
    },
    reload(){
      if(confirm("Sure? You will lose any unsaved changes 😱")){
        this.setRootDir(this.rootDir);
      }
    },
    save(){
      Promise.all(Object.keys(this.langs).map((lang_key) => {
        return writeLangFile(path.join(this.rootDir, this.langDir, lang_key+".json"), this.langs[lang_key]);
      })).then(() => {
        alert("🙌 Files saved");
      }).catch((err) => {
        console.error(err);
        alert("😢 Something went wrong while saving");
      });
    },
    updateValue(key, value){
      Vue.set(this.langs[this.selectedLangKey], key, value);
    },
    deleteValue(key){
      Vue.delete(this.langs[this.selectedLangKey], key);
    },
    showFound(key){
      let counts = {};
      this.scannedKeysFound[key].map((item) => item.replace(this.rootDir, ''))
      .forEach((item) => {
        if(!counts[item]) counts[item] = 0;
        counts[item]++;
      });
      this.scannedKeysFoundSelected = counts;
      this.showModal = true;
    },
    closeModal(){
      this.showModal = false;
    },
    addLang(){
      let lang_key = this.newLangName.toLowerCase();
      if(Object.keys(this.langs).find(item => item == lang_key)){
        alert("Language already exists");
        this.selectedLangKey = lang_key;
        this.newLangName = '';
        return;
      }
      let emptyLang = {};
      this.allKeys.forEach(key => {
        emptyLang[key] = (lang_key == config.get('baseLanguage')) ? key : null;
      });
      Vue.set(this.langs, lang_key, emptyLang);
      this.selectedLangKey = lang_key;
      this.newLangName = '';
    },
    toggleFilterOnKeysMissing(){
      if(this.filterOnKeys !== null){
        this.filterOnKeys = null;
        return;
      }
      this.filterOnKeys = this.missingKeys;
    }
  },
  computed:{
    selectedLang(){
      return this.langs[this.selectedLangKey] || {};
    },
    missingKeys(){
      if(!this.selectedLang) return [];

      let selectedKeys = Object.keys(this.selectedLang) || [];
      let scannedKeys = this.scannedKeys || [];

      return scannedKeys.diff(selectedKeys);
    },
    extraKeys(){
      let selectedKeys = Object.keys(this.selectedLang) || [];
      let scannedKeys = this.scannedKeys || [];

      return selectedKeys.diff(scannedKeys);
    },
    allKeys(){
      let keys = [];
      Object.keys(this.langs).forEach((lang_key) => {
        keys = keys.concat(Object.keys(this.langs[lang_key]));
      });
      keys = keys.concat(this.scannedKeys);
      return Array.from(new Set(keys));
    },
    allItems(){
      return this.allKeys.map((key) => {
        return {key, value: this.selectedLang[key] || null };
      });
    },
    filteredLangItems(){
      let q = this.query.toLowerCase();
      return this.allItems
        .filter((item) => {
          if(this.filterOnKeys == null) return true;
          return this.filterOnKeys.indexOf(item.key) !== -1;
        })
        .filter((item) => {
        return q == '' || item.key.toLowerCase().indexOf(q) > -1;
      }).sort((a, b) => {
        if(a.key.toLowerCase() < b.key.toLowerCase()) return -1;
        if(a.key.toLowerCase() > b.key.toLowerCase()) return 1;
        return 0;
      });
    },
    numLangs(){
      return Object.keys(this.langs).length;
    }
  }
});
<|endoftext|>


<commit_before>// Packages
const {copy} = require('copy-paste')
const ip = require('ip')
const pathType = require('path-type')
const chalk = require('chalk')
const boxen = require('boxen')
const {coroutine, promisify} = require('bluebird')

const copyAsync = promisify(copy)

const copyToClipboard = coroutine(function * (text) {
  try {
    yield copyAsync(text)
    return true
  } catch (err) {
    return false
  }
})

module.exports = coroutine(function * (server, current, inUse) {
  const details = server.address()
  const isTTY = process.stdout.isTTY

  process.on('SIGINT', () => {
    server.close()
    process.exit(0)
  })

  const isDir = yield pathType.dir(current)

  if (!isDir) {
    console.error(chalk.red('Specified directory doesn\'t exist!'))
    process.exit(1)
  }

  if (process.env.NODE_ENV !== 'production') {
    let message = chalk.green('Serving!')

    if (inUse) {
      message += ' ' + chalk.red(`(on port ${inUse.open},` +
      ` because ${inUse.old} is already in use)`)
    }

    message += '\n\n'

    const localURL = `http://localhost:${details.port}`

    message += `- ${chalk.bold('Local:           ')} ${localURL}\n`

    try {
      const ipAddress = ip.address()
      const url = `http://${ipAddress}:${details.port}`

      message += `- ${chalk.bold('On Your Network: ')} ${url}\n\n`
    } catch (err) {
      message += `\n`
    }

    if (isTTY && process.platform === 'darwin') {
      const copied = yield copyToClipboard(localURL)

      if (copied) {
        message += `${chalk.grey('Copied local address to clipboard!')}`
      }
    }

    console.log(boxen(message, {
      padding: 1,
      borderColor: 'green',
      margin: 1
    }))
  }
})
<commit_msg>Prettier newlines in terminal message<commit_after>// Packages
const {copy} = require('copy-paste')
const ip = require('ip')
const pathType = require('path-type')
const chalk = require('chalk')
const boxen = require('boxen')
const {coroutine, promisify} = require('bluebird')

const copyAsync = promisify(copy)

const copyToClipboard = coroutine(function * (text) {
  try {
    yield copyAsync(text)
    return true
  } catch (err) {
    return false
  }
})

module.exports = coroutine(function * (server, current, inUse) {
  const details = server.address()
  const isTTY = process.stdout.isTTY

  process.on('SIGINT', () => {
    server.close()
    process.exit(0)
  })

  const isDir = yield pathType.dir(current)

  if (!isDir) {
    console.error(chalk.red('Specified directory doesn\'t exist!'))
    process.exit(1)
  }

  if (process.env.NODE_ENV !== 'production') {
    let message = chalk.green('Serving!')

    if (inUse) {
      message += ' ' + chalk.red(`(on port ${inUse.open},` +
      ` because ${inUse.old} is already in use)`)
    }

    message += '\n\n'

    const localURL = `http://localhost:${details.port}`

    message += `- ${chalk.bold('Local:           ')} ${localURL}`

    try {
      const ipAddress = ip.address()
      const url = `http://${ipAddress}:${details.port}`

      message += `\n\n- ${chalk.bold('On Your Network: ')} ${url}`
    } catch (err) {}

    if (isTTY && process.platform === 'darwin') {
      const copied = yield copyToClipboard(localURL)

      if (copied) {
        message += `\n\n${chalk.grey('Copied local address to clipboard!')}`
      }
    }

    console.log(boxen(message, {
      padding: 1,
      borderColor: 'green',
      margin: 1
    }))
  }
})
<|endoftext|>


<commit_before>'use strict';

const Stream = SYS.use('stream/Stream');
const User = SYS.use('entity/User');

new Stream(User.source([1, 4])).pipe(function(value) {
  value.entity.name = value.entity.id;
}).pipe(function(value) {
  console.log(value.entity.name);
}).pipe(function(value) {
  User.save(value.entity, this.goon(function() {
    this.next();
  }));
}).pipe(function(value) {
  console.log(value.entity.name);
}).run();
<commit_msg>add test<commit_after>'use strict';

const Stream = SYS.use('stream/Stream');
const User = SYS.use('entity/User');

new Stream(User.source([1, 4])).pipe(function(value) {
  value.entity.name = value.entity.id;
}).pipe(function(value) {
  console.log(value.entity.name);
}).pipe(function(value) {
  User.save(value.entity, this.goon(function() {
    this.next();
  }));
}).pipe(function(value) {
  console.log(value.entity.name);
}).run();

// test 1<|endoftext|>


<commit_before>var isArray = Array.isArray;
var hasOwn = Object.prototype.hasOwnProperty;

var MAX_ARRAY_DEPTH = 3;

function Renderer(interpreter, callbacks) {
  this.callBefore = callbacks && callbacks.before || this.noop;
  this.callAfter = callbacks && callbacks.after || this.noop;

  this.interpreter = interpreter;
};

Renderer.prototype = {
  render: function renderJSX(tree) {
    if (!tree) throw new Error('JSX tree is not presented');

    if (!this.isTagDescriptor(tree)) {
      throw new Error('Tree top level item should be a tag');
    }

    tree = this.callBefore(tree);
    tree = this.renderChild(tree);
    tree = this.callAfter(tree);

    return tree;
  },
  renderChild: function(thing) {
    if (thing == null) {
      return null;
    }

    if (this.isTagDescriptor(thing)) {
      return this.handleTag(thing);
    }

    return thing;
  },
  walkChildren: function(children, handler, depth) {
    var length = children.length;
    var i = 0;
    var child;

    depth = depth | 0;

    for (; i < length; i++) {
      child = children[i];

      if (child == null) continue;
      if (isArray(child) && depth < MAX_ARRAY_DEPTH) {
        this.walkChildren(child, handler);
        continue;
      }

      handler(this.renderChild(child));
    }
  },

  handleTag: function(descriptor) {
    var tag = descriptor.tag + '';
    var props = descriptor.props;
    var children = descriptor.children;
    var parent;

    // Put children handling here if bottom-to-top handling is better

    props = props && this.interpreter.props(tag, props);
    parent = this.interpreter.enter(tag, props);

    if (isArray(children) && children.length) {
      parent = this.handleChildren(tag, children, parent);
    }

    parent = this.interpreter.leave(tag, parent);

    return parent;
  },

  handleChildren: function(tag, children, parent) {
    var self = this;

    this.walkChildren(children, function(child) {
      // probably move this to handleTag() method
      // and provide parentValue for renderChild() call
      parent = self.interpreter.child(tag, parent, child);
    });

    return parent;
  },
  handlePrivimite: function(thing) {
    return thing;
  },

  isPrimitive: function(thing) {
    switch (typeof thing) {
      case 'string':
      case 'boolean':
      case 'number':
        return true;
    }

    return false;
  },
  isTagDescriptor: function(object) {
    return object && typeof object === 'object' && 'tag' in object &&
      'props' in object && 'children' in object;
  },

  noop: function(a) { return a }
};

module.exports = Renderer;<commit_msg>Update top level render input<commit_after>var isArray = Array.isArray;
var hasOwn = Object.prototype.hasOwnProperty;

var MAX_ARRAY_DEPTH = 3;

function Renderer(interpreter, callbacks) {
  this.callBefore = callbacks && callbacks.before || this.noop;
  this.callAfter = callbacks && callbacks.after || this.noop;

  this.interpreter = interpreter;
};

Renderer.prototype = {
  render: function renderJSX(element, props, children) {
    if (!element) throw new Error('JSX element is not presented');

    if (typeof element === 'string') {
      element = {
        tag: element,
        props: props,
        children: children
      };
    } else if (typeof element === 'function') {
      element = element({
        tag: element.name || element.displayName || '',
        props: props,
        children: children
      });
    }

    if (!this.isTagDescriptor(element)) {
      throw new Error('Top level element should be a tag or function which returns a tag');
    }

    element = this.callBefore(element);
    element = this.renderChild(element);
    element = this.callAfter(element);

    return element;
  },
  renderChild: function(thing) {
    if (typeof thing === 'function') {
      thing = thing();
    }

    if (thing == null) {
      return null;
    }

    if (this.isTagDescriptor(thing)) {
      return this.handleTag(thing);
    }

    return thing;
  },
  walkChildren: function(children, handler, depth) {
    var length = children.length;
    var i = 0;
    var child;

    depth = depth | 0;

    for (; i < length; i++) {
      child = children[i];

      if (child == null) continue;
      if (isArray(child) && depth < MAX_ARRAY_DEPTH) {
        this.walkChildren(child, handler);
        continue;
      }

      handler(this.renderChild(child));
    }
  },

  handleTag: function(descriptor) {
    var tag = descriptor.tag + '';
    var props = descriptor.props;
    var children = descriptor.children;
    var parent;

    // Put children handling here if bottom-to-top handling is better

    props = props && this.interpreter.props(tag, props);
    parent = this.interpreter.enter(tag, props);

    if (isArray(children) && children.length) {
      parent = this.handleChildren(tag, children, parent);
    }

    parent = this.interpreter.leave(tag, parent);

    return parent;
  },

  handleChildren: function(tag, children, parent) {
    var self = this;

    this.walkChildren(children, function(child) {
      // probably move this to handleTag() method
      // and provide parentValue for renderChild() call
      parent = self.interpreter.child(tag, parent, child);
    });

    return parent;
  },
  handlePrivimite: function(thing) {
    return thing;
  },

  isPrimitive: function(thing) {
    switch (typeof thing) {
      case 'string':
      case 'boolean':
      case 'number':
        return true;
    }

    return false;
  },
  isTagDescriptor: function(object) {
    return object && typeof object === 'object' && 'tag' in object &&
      'props' in object && 'children' in object;
  },

  noop: function(a) { return a }
};

module.exports = Renderer;<|endoftext|>


<commit_before>// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.

const electron = require('electron');
const React = require("react");
const ReactDOM = require("react-dom");
const App = require("./dist/containers/App");

ReactDOM.render(React.createElement(App), document.getElementById("app"));

console.log(`Renderer JavaScript Startup Time: ${performance.now() - global.startTime}ms`);

// Allow opening links in browser with CMD+CLICK
(() => {
  document.addEventListener('click', e => {
    if (e.target.tagName === 'A') {
      const url = e.target.getAttribute('href');
      if (url && e.metaKey) {
        electron.shell.openExternal(url)
        e.preventDefault();
      }
    }
  });

  document.addEventListener('keydown', e => {
    if (e.key === 'Meta') {
      document.body.classList.add('links');
    }
  });

  document.addEventListener('keyup', e => {
    if (e.key === 'Meta') {
      document.body.classList.remove('links');
    }
  });
})();
<commit_msg>Fix links with nested elements<commit_after>// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.

const electron = require('electron');
const React = require('react');
const ReactDOM = require('react-dom');
const App = require('./dist/containers/App');

ReactDOM.render(React.createElement(App), document.getElementById('app'));

console.log(`Renderer JavaScript Startup Time: ${performance.now() - global.startTime}ms`);

// Allow opening links in browser with CMD+CLICK
(() => {
  document.addEventListener('click', e => {
    const elem = e.target.tagName === 'A' ? e.target : e.target.parentElement;
    if (elem.tagName === 'A') {
      const url = elem.getAttribute('href');
      if (url && e.metaKey) {
        electron.shell.openExternal(url);
        e.preventDefault();
      }
    }
  });

  document.addEventListener('keydown', e => {
    if (e.key === 'Meta') {
      document.body.classList.add('links');
    }
  });

  document.addEventListener('keyup', e => {
    if (e.key === 'Meta') {
      document.body.classList.remove('links');
    }
  });
})();
<|endoftext|>