<commit_before>'use strict';

/*jshint -W069 */

// commonly used data set

var fixture = module.exports = {};

var stats = fixture.stats = {};

var count = {name:'*', type:'Q', aggregate:'count'},
  count_stat = 50;

var O_15 = {name: 'O_15', type: 'O'},
  O_15_stat = {distinct: 15},
  O_30 = {name:'O_30', type:'O'},
  O_30_stat = {distinct: 30};

var q10 = {name: 'Q_10', type: 'Q'},
  q10_stat = {distinct: 10, min:0, max:150};

var o_stat = {distinct: 5},
  q_stat = {distinct: 100, min:0, max:150},
  t_stat = o_stat;

fixture.stat = {
  o_stat: o_stat,
  q_stat: q_stat,
  t_stat: t_stat,
  count_stat: count_stat
};

stats['OxQ'] = {
  1: o_stat,
  2: q_stat,
  count: count_stat
};

stats.OxO = {
  1: o_stat,
  2: o_stat,
  count: count_stat
};

stats['Ox#'] = {
  1: o_stat,
  count: count_stat
};

stats['O_30x#'] = {
  count: count_stat,
  O_30: O_30_stat
};

stats.OxOxQ = {
  1: o_stat,
  2: o_stat,
  3: q_stat,
  count: count_stat
};

stats.OxQxQ = {
  1: o_stat,
  2: q_stat,
  3: q_stat,
  count: count_stat
};

stats['QxQ'] = {
  1: q_stat,
  2: q_stat,
  count: count_stat
};

stats['QxT'] = {
  1: q_stat,
  2: t_stat,
  count: count_stat
};

stats['Q'] = {
  1: q_stat,
  count: count_stat
};

stats['#xQ'] = {
  count: count_stat,
  2: q_stat
};
stats['#xT'] = {
  count: count_stat,
  2: t_stat
};

// fixtures

fixture['O'] = {
  fields: [{name:1, type:'O'}],
  stats: {1: o_stat}
};

fixture['O_15'] = {
  fields: [O_15],
  stats: {O_15: O_15_stat}
};

fixture['O_30'] = {
  fields: [O_30],
  stats: {O_30: O_30_stat}
};

fixture['OxQ'] = {
  fields: [
      {name:1, type:'O'},
      {name:2, type:'Q'}
  ],
  stats: stats['OxQ']
};

fixture['OxA(Q)'] = {
  fields: [
      {name:1, type:'O'},
      {name:2, type:'Q', aggregate: "avg"}
  ],
  stats: stats['OxQ']
};

fixture['Ox#'] = {
  fields: [{name:1, type:'O'}, count],
  stats: stats['Ox#']
};

fixture['O_30x#'] = {
  fields: [O_30, count],
  stats: stats['O_30x#']
};

fixture['OxOx#'] = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'O'},
    count
  ],
  stats: stats.OxO
};

fixture.OxOxQ = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'O'},
    {name:3, type:'Q'}
  ],
  stats: stats.OxOxQ
};

fixture['OxOxA(Q)'] = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'O'},
    {name:3, type:'Q', aggregate:'sum'}
  ],
  stats: stats.OxOxQ
};

fixture.OxQxQ = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'Q'},
    {name:3, type:'Q'}
  ],
  stats: stats.OxQxQ
};

fixture['OxA(Q)xA(Q)'] = {
  fields: [
    {name:1, type:'O'},
    {aggregate:'avg', name:2, type:'Q'},
    {aggregate:'avg', name:3, type:'Q'}
  ],
  stats: stats.OxQxQ
};

fixture['OxQxQxQ'] = {
  fields: [
    {name:1, type: 'O'},
    {name:2, type: 'Q'},
    {name:3, type: 'Q'},
    {name:4, type: 'Q'}
  ],
  stats: {
    1: o_stat,
    2: q_stat,
    3: q_stat,
    4: q_stat
  }
};

fixture['OxOxQxQx#'] = {
  fields: [
    {name:1, type:'Q', selected: undefined},
    {name:2, type:'Q', selected: undefined},
    {name:3, type:'O', selected: undefined},
    {name:4, type:'O', selected: undefined},
    {name:'*', aggregate:'count', selected: undefined}
  ],
  stats: {
    1: q_stat,
    2: q_stat,
    3: o_stat,
    4: o_stat,
    5: count_stat
  }
};

fixture['Q'] = {
  fields: [{name:1, type:'Q'}],
  stats: {1: q_stat}
};

fixture['Q_10'] = {
  fields: [q10],
  stats: {Q_10: q10_stat}
};

fixture['BIN(Q)'] = {
  fields: [{name:1, type:'Q', bin: {maxbins: 15}}],
  stats: {1: q_stat}
};

fixture['QxQ'] = {
  fields: [{name:1, type:'Q'}, {name:2, type:'Q'}],
  stats: stats['QxQ']
};

fixture['Qx#'] = {
  fields: [{name:1, type:'Q'}, count],
  stats: stats.Q
};

fixture['QxT'] = {
  fields: [
    {name:1, type:'Q'},
    {name:2, type:'T'}
  ],
  stats: stats['QxT']
};

fixture['QxYEAR(T)'] = {
  fields: [
    {name:1, type:'Q'},
    {name:2, type:'T', timeUnit: 'year'}
  ],
  stats: stats['QxT']
};

fixture['A(Q)xYEAR(T)'] = {
  fields: [
    {name:1, type:'Q', aggregate: 'avg'},
    {name:2, type:'T', timeUnit: 'year'}
  ],
  stats: stats['QxT']
};

fixture['B(Q)xB(Q)x#'] = {
  fields: [
    {name:1, type:'Q', bin: {maxbins: 15}},
    {name:2, type:'Q', bin: {maxbins: 15}},
    count
  ],
  stats: stats.QxQ
};

fixture['#'] = {
  fields: [count],
  stats: {count: count_stat}
};

// FIXME: swap order for these

fixture['#xB(Q)'] = {
  fields: [
      count,
      {name:2, type:'Q', bin: {maxbins: 15}}
  ],
  stats: stats['#xQ']
};

fixture['#xYR(T)'] = {
  fields: [
      {name:'*', type:'Q', aggregate:'count'},
      {name:2, type:'T', timeUnit:'year'}
  ],
  stats: stats['#xT']
};

fixture['#xT'] = {
  fields: [
      {name:'*', type:'Q', aggregate:'count'},
      {name:2, type:'T'}
  ],
  stats: stats['#xT']
};

fixture.birdstrikes = {};
fixture.birdstrikes.fields = [{"name":"Aircraft__Airline_Operator","type":"O","$$hashKey":"object:12","_any":true},{"name":"Aircraft__Make_Model","type":"O","$$hashKey":"object:13","_any":true},{"name":"Airport__Name","type":"O","$$hashKey":"object:14","_any":true},{"name":"Effect__Amount_of_damage","type":"O","$$hashKey":"object:15","_any":true},{"name":"Origin_State","type":"O","$$hashKey":"object:16","_any":true},{"name":"When__Phase_of_flight","type":"O","$$hashKey":"object:17","_any":true},{"name":"When__Time_of_day","type":"O","$$hashKey":"object:18","_any":true},{"name":"Wildlife__Size","type":"O","$$hashKey":"object:19","_any":true},{"name":"Wildlife__Species","type":"O","$$hashKey":"object:20","_any":true},{"name":"Flight_Date","type":"T","$$hashKey":"object:21","_any":true},{"name":"Cost__Other","type":"Q","$$hashKey":"object:22","_any":true},{"name":"Cost__Repair","type":"Q","$$hashKey":"object:23","_any":true},{"name":"Cost__Total_$","type":"Q","$$hashKey":"object:24","_any":true},{"name":"Speed_IAS_in_knots","type":"Q","$$hashKey":"object:25","_any":true},{"name":"*","aggregate":"count","type":"Q","displayName":"Number of Records","$$hashKey":"object:26","_any":true}];
fixture.birdstrikes.stats = {"Airport__Name":{"min":null,"max":null,"cardinality":50,"count":10000,"maxlength":38,"numNulls":0,"sample":["SACRAMENTO INTL","DALLAS/FORT WORTH INTL ARPT","GREATER PITTSBURGH","KANSAS CITY INTL","LOUISVILLE INTL ARPT","CHICAGO MIDWAY INTL ARPT","CHARLOTTE/DOUGLAS INTL ARPT","MINETA SAN JOSE INTL","EPPLEY AIRFIELD","AUSTIN-BERGSTROM INTL"]},"Aircraft__Make_Model":{"min":null,"max":null,"cardinality":225,"count":10000,"maxlength":18,"numNulls":0,"sample":["B-747-1/200","B-727-200","FOKKER F100","SAAB-340","EMB-120","B-737-400","B-737-200","A-320","DC-9-30","DC-9"]},"Effect__Amount_of_damage":{"min":null,"max":null,"cardinality":6,"count":10000,"maxlength":11,"numNulls":0,"sample":["None","Minor","Substantial","Medium","C","B"]},"Flight_Date":{"min":null,"max":null,"cardinality":3625,"count":10000,"maxlength":13,"numNulls":0,"sample":["10/10/98 0:00","10/5/99 0:00","6/8/02 0:00","5/14/91 0:00","10/26/01 0:00","8/13/94 0:00","7/27/94 0:00","12/12/95 0:00","5/30/02 0:00","10/21/93 0:00"]},"Aircraft__Airline_Operator":{"min":null,"max":null,"cardinality":46,"count":10000,"maxlength":30,"numNulls":0,"sample":["UNITED AIRLINES","DELTA AIR LINES","CONTINENTAL AIRLINES","SOUTHWEST AIRLINES","AMERICAN AIRLINES","US AIRWAYS*","PINNACLE","BUSINESS","ABX AIR","NORTHWEST AIRLINES"]},"Origin_State":{"min":null,"max":null,"cardinality":29,"count":10000,"maxlength":14,"numNulls":0,"sample":["California","New Jersey","New York","Washington","Louisiana","Hawaii","Texas","Utah","Tennessee","Georgia"]},"When__Phase_of_flight":{"min":null,"max":null,"cardinality":7,"count":10000,"maxlength":12,"numNulls":0,"sample":["Landing Roll","Approach","Take-off run","Descent","Climb","Taxi","Parked"]},"Wildlife__Size":{"min":null,"max":null,"cardinality":3,"count":10000,"maxlength":6,"numNulls":0,"sample":["Medium","Small","Large"]},"Wildlife__Species":{"min":null,"max":null,"cardinality":37,"count":10000,"maxlength":21,"numNulls":0,"sample":["Unknown bird - small","Zebra dove","Unknown bird - large","Unknown bird - medium","Chimney swift","Unknown bird or bat","European starling","Killdeer","Horned lark","Barn owl"]},"When__Time_of_day":{"min":null,"max":null,"cardinality":4,"count":10000,"maxlength":5,"numNulls":0,"sample":["Day","Night","Dawn","Dusk"]},"Cost__Other":{"min":0,"max":1565354,"cardinality":65,"count":10000,"maxlength":7,"numNulls":0,"skew":0.023185985633316083,"stdev":18297.3071194526,"mean":424.2411,"median":0,"sample":["0","70","130","137","260","297","401","6860","8250","13364"]},"Cost__Repair":{"min":0,"max":7043545,"cardinality":165,"count":10000,"maxlength":7,"numNulls":0,"skew":0.03709480948374386,"stdev":97865.08006169728,"mean":3630.2865,"median":0,"sample":["0","317","668","2673","5218","7044","14331","14463","21552","40091"]},"Cost__Total_$":{"min":0,"max":7043545,"cardinality":196,"count":10000,"maxlength":7,"numNulls":0,"skew":0.03969958970315394,"stdev":102130.21419911268,"mean":4054.5276,"median":0,"sample":["0","18151","19133","20046","93546","211146","304926","559688","1715077","3811576"]},"Speed_IAS_in_knots":{"min":0,"max":350,"cardinality":123,"count":10000,"maxlength":3,"numNulls":2836,"skew":0.3110428807026861,"stdev":43.51546593453372,"mean":153.53517587939697,"median":140,"sample":["100","120","130","135","140","150","163","200","250","null"]},"count":10000};
<commit_msg>update fixture for count<commit_after>'use strict';

/*jshint -W069 */

// commonly used data set

var fixture = module.exports = {};

var stats = fixture.stats = {};

var count = {name:'*', type:'Q', aggregate:'count'},
  count_stat = {min:0, max:100};

var O_15 = {name: 'O_15', type: 'O'},
  O_15_stat = {distinct: 15},
  O_30 = {name:'O_30', type:'O'},
  O_30_stat = {distinct: 30};

var q10 = {name: 'Q_10', type: 'Q'},
  q10_stat = {distinct: 10, min:0, max:150};

var o_stat = {distinct: 5},
  q_stat = {distinct: 100, min:0, max:150},
  t_stat = o_stat;

fixture.stat = {
  o_stat: o_stat,
  q_stat: q_stat,
  t_stat: t_stat,
  count_stat: count_stat
};

stats['#'] = {
  '*': count_stat
};

stats['OxQ'] = {
  1: o_stat,
  2: q_stat,
  '*': count_stat
};

stats.OxO = {
  1: o_stat,
  2: o_stat,
  '*': count_stat
};

stats['Ox#'] = {
  1: o_stat,
  '*': count_stat
};

stats['O_30x#'] = {
  '*': count_stat,
  O_30: O_30_stat
};

stats.OxOxQ = {
  1: o_stat,
  2: o_stat,
  3: q_stat,
  '*': count_stat
};

stats.OxQxQ = {
  1: o_stat,
  2: q_stat,
  3: q_stat,
  '*': count_stat
};

stats['QxQ'] = {
  1: q_stat,
  2: q_stat,
  '*': count_stat
};

stats['QxT'] = {
  1: q_stat,
  2: t_stat,
  '*': count_stat
};

stats['Q'] = {
  1: q_stat,
  '*': count_stat
};

stats['#xQ'] = {
  '*': count_stat,
  2: q_stat
};
stats['#xT'] = {
  '*': count_stat,
  2: t_stat
};

// fixtures

fixture['O'] = {
  fields: [{name:1, type:'O'}],
  stats: {1: o_stat}
};

fixture['O_15'] = {
  fields: [O_15],
  stats: {O_15: O_15_stat}
};

fixture['O_30'] = {
  fields: [O_30],
  stats: {O_30: O_30_stat}
};

fixture['OxQ'] = {
  fields: [
      {name:1, type:'O'},
      {name:2, type:'Q'}
  ],
  stats: stats['OxQ']
};

fixture['OxA(Q)'] = {
  fields: [
      {name:1, type:'O'},
      {name:2, type:'Q', aggregate: "avg"}
  ],
  stats: stats['OxQ']
};

fixture['Ox#'] = {
  fields: [{name:1, type:'O'}, count],
  stats: stats['Ox#']
};

fixture['O_30x#'] = {
  fields: [O_30, count],
  stats: stats['O_30x#']
};

fixture['OxOx#'] = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'O'},
    count
  ],
  stats: stats.OxO
};

fixture.OxOxQ = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'O'},
    {name:3, type:'Q'}
  ],
  stats: stats.OxOxQ
};

fixture['OxOxA(Q)'] = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'O'},
    {name:3, type:'Q', aggregate:'sum'}
  ],
  stats: stats.OxOxQ
};

fixture.OxQxQ = {
  fields: [
    {name:1, type:'O'},
    {name:2, type:'Q'},
    {name:3, type:'Q'}
  ],
  stats: stats.OxQxQ
};

fixture['OxA(Q)xA(Q)'] = {
  fields: [
    {name:1, type:'O'},
    {aggregate:'avg', name:2, type:'Q'},
    {aggregate:'avg', name:3, type:'Q'}
  ],
  stats: stats.OxQxQ
};

fixture['OxQxQxQ'] = {
  fields: [
    {name:1, type: 'O'},
    {name:2, type: 'Q'},
    {name:3, type: 'Q'},
    {name:4, type: 'Q'}
  ],
  stats: {
    1: o_stat,
    2: q_stat,
    3: q_stat,
    4: q_stat
  }
};

fixture['OxOxQxQx#'] = {
  fields: [
    {name:1, type:'Q', selected: undefined},
    {name:2, type:'Q', selected: undefined},
    {name:3, type:'O', selected: undefined},
    {name:4, type:'O', selected: undefined},
    {name:'*', aggregate:'count', selected: undefined}
  ],
  stats: {
    1: q_stat,
    2: q_stat,
    3: o_stat,
    4: o_stat,
    5: count_stat
  }
};

fixture['Q'] = {
  fields: [{name:1, type:'Q'}],
  stats: {1: q_stat}
};

fixture['Q_10'] = {
  fields: [q10],
  stats: {Q_10: q10_stat}
};

fixture['BIN(Q)'] = {
  fields: [{name:1, type:'Q', bin: {maxbins: 15}}],
  stats: {1: q_stat}
};

fixture['QxQ'] = {
  fields: [{name:1, type:'Q'}, {name:2, type:'Q'}],
  stats: stats['QxQ']
};

fixture['Qx#'] = {
  fields: [{name:1, type:'Q'}, count],
  stats: stats.Q
};

fixture['QxT'] = {
  fields: [
    {name:1, type:'Q'},
    {name:2, type:'T'}
  ],
  stats: stats['QxT']
};

fixture['QxYEAR(T)'] = {
  fields: [
    {name:1, type:'Q'},
    {name:2, type:'T', timeUnit: 'year'}
  ],
  stats: stats['QxT']
};

fixture['A(Q)xYEAR(T)'] = {
  fields: [
    {name:1, type:'Q', aggregate: 'avg'},
    {name:2, type:'T', timeUnit: 'year'}
  ],
  stats: stats['QxT']
};

fixture['B(Q)xB(Q)x#'] = {
  fields: [
    {name:1, type:'Q', bin: {maxbins: 15}},
    {name:2, type:'Q', bin: {maxbins: 15}},
    count
  ],
  stats: stats.QxQ
};

fixture['#'] = {
  fields: [count],
  stats: {'*': count_stat}
};

// FIXME: swap order for these

fixture['#xB(Q)'] = {
  fields: [
      count,
      {name:2, type:'Q', bin: {maxbins: 15}}
  ],
  stats: stats['#xQ']
};

fixture['#xYR(T)'] = {
  fields: [
      {name:'*', type:'Q', aggregate:'count'},
      {name:2, type:'T', timeUnit:'year'}
  ],
  stats: stats['#xT']
};

fixture['#xT'] = {
  fields: [
      {name:'*', type:'Q', aggregate:'count'},
      {name:2, type:'T'}
  ],
  stats: stats['#xT']
};

fixture.birdstrikes = {};
fixture.birdstrikes.fields = [{"name":"Aircraft__Airline_Operator","type":"O","$$hashKey":"object:12","_any":true},{"name":"Aircraft__Make_Model","type":"O","$$hashKey":"object:13","_any":true},{"name":"Airport__Name","type":"O","$$hashKey":"object:14","_any":true},{"name":"Effect__Amount_of_damage","type":"O","$$hashKey":"object:15","_any":true},{"name":"Origin_State","type":"O","$$hashKey":"object:16","_any":true},{"name":"When__Phase_of_flight","type":"O","$$hashKey":"object:17","_any":true},{"name":"When__Time_of_day","type":"O","$$hashKey":"object:18","_any":true},{"name":"Wildlife__Size","type":"O","$$hashKey":"object:19","_any":true},{"name":"Wildlife__Species","type":"O","$$hashKey":"object:20","_any":true},{"name":"Flight_Date","type":"T","$$hashKey":"object:21","_any":true},{"name":"Cost__Other","type":"Q","$$hashKey":"object:22","_any":true},{"name":"Cost__Repair","type":"Q","$$hashKey":"object:23","_any":true},{"name":"Cost__Total_$","type":"Q","$$hashKey":"object:24","_any":true},{"name":"Speed_IAS_in_knots","type":"Q","$$hashKey":"object:25","_any":true},{"name":"*","aggregate":"count","type":"Q","displayName":"Number of Records","$$hashKey":"object:26","_any":true}];
fixture.birdstrikes.stats = {"Airport__Name":{"min":null,"max":null,"cardinality":50,"count":10000,"maxlength":38,"numNulls":0,"sample":["SACRAMENTO INTL","DALLAS/FORT WORTH INTL ARPT","GREATER PITTSBURGH","KANSAS CITY INTL","LOUISVILLE INTL ARPT","CHICAGO MIDWAY INTL ARPT","CHARLOTTE/DOUGLAS INTL ARPT","MINETA SAN JOSE INTL","EPPLEY AIRFIELD","AUSTIN-BERGSTROM INTL"]},"Aircraft__Make_Model":{"min":null,"max":null,"cardinality":225,"count":10000,"maxlength":18,"numNulls":0,"sample":["B-747-1/200","B-727-200","FOKKER F100","SAAB-340","EMB-120","B-737-400","B-737-200","A-320","DC-9-30","DC-9"]},"Effect__Amount_of_damage":{"min":null,"max":null,"cardinality":6,"count":10000,"maxlength":11,"numNulls":0,"sample":["None","Minor","Substantial","Medium","C","B"]},"Flight_Date":{"min":null,"max":null,"cardinality":3625,"count":10000,"maxlength":13,"numNulls":0,"sample":["10/10/98 0:00","10/5/99 0:00","6/8/02 0:00","5/14/91 0:00","10/26/01 0:00","8/13/94 0:00","7/27/94 0:00","12/12/95 0:00","5/30/02 0:00","10/21/93 0:00"]},"Aircraft__Airline_Operator":{"min":null,"max":null,"cardinality":46,"count":10000,"maxlength":30,"numNulls":0,"sample":["UNITED AIRLINES","DELTA AIR LINES","CONTINENTAL AIRLINES","SOUTHWEST AIRLINES","AMERICAN AIRLINES","US AIRWAYS*","PINNACLE","BUSINESS","ABX AIR","NORTHWEST AIRLINES"]},"Origin_State":{"min":null,"max":null,"cardinality":29,"count":10000,"maxlength":14,"numNulls":0,"sample":["California","New Jersey","New York","Washington","Louisiana","Hawaii","Texas","Utah","Tennessee","Georgia"]},"When__Phase_of_flight":{"min":null,"max":null,"cardinality":7,"count":10000,"maxlength":12,"numNulls":0,"sample":["Landing Roll","Approach","Take-off run","Descent","Climb","Taxi","Parked"]},"Wildlife__Size":{"min":null,"max":null,"cardinality":3,"count":10000,"maxlength":6,"numNulls":0,"sample":["Medium","Small","Large"]},"Wildlife__Species":{"min":null,"max":null,"cardinality":37,"count":10000,"maxlength":21,"numNulls":0,"sample":["Unknown bird - small","Zebra dove","Unknown bird - large","Unknown bird - medium","Chimney swift","Unknown bird or bat","European starling","Killdeer","Horned lark","Barn owl"]},"When__Time_of_day":{"min":null,"max":null,"cardinality":4,"count":10000,"maxlength":5,"numNulls":0,"sample":["Day","Night","Dawn","Dusk"]},"Cost__Other":{"min":0,"max":1565354,"cardinality":65,"count":10000,"maxlength":7,"numNulls":0,"skew":0.023185985633316083,"stdev":18297.3071194526,"mean":424.2411,"median":0,"sample":["0","70","130","137","260","297","401","6860","8250","13364"]},"Cost__Repair":{"min":0,"max":7043545,"cardinality":165,"count":10000,"maxlength":7,"numNulls":0,"skew":0.03709480948374386,"stdev":97865.08006169728,"mean":3630.2865,"median":0,"sample":["0","317","668","2673","5218","7044","14331","14463","21552","40091"]},"Cost__Total_$":{"min":0,"max":7043545,"cardinality":196,"count":10000,"maxlength":7,"numNulls":0,"skew":0.03969958970315394,"stdev":102130.21419911268,"mean":4054.5276,"median":0,"sample":["0","18151","19133","20046","93546","211146","304926","559688","1715077","3811576"]},"Speed_IAS_in_knots":{"min":0,"max":350,"cardinality":123,"count":10000,"maxlength":3,"numNulls":2836,"skew":0.3110428807026861,"stdev":43.51546593453372,"mean":153.53517587939697,"median":140,"sample":["100","120","130","135","140","150","163","200","250","null"]},"count":10000};
<|endoftext|>


<commit_before>var fs = require('fs');
var childProcess = require('child_process');
var passError = require('passerror');
var async = require('async');
var getTemporaryFilePath = require('gettemporaryfilepath');
var getTextByFontFace = require('../util/getTextByFontFace');

module.exports = function (queryObj) {
    return function subsetFonts(assetGraph, cb) {
        var textByFontFace = getTextByFontFace(assetGraph);

        var fontFamiliesToSubset = Object.keys(textByFontFace);

        async.eachLimit(fontFamiliesToSubset, 5, function (fontFamilyName, cb) {
            var chars = textByFontFace[fontFamilyName].chars;
            var cssFontFaceSrc = textByFontFace[fontFamilyName].cssFontFaceSrc;
            var inputFileName = getTemporaryFilePath({suffix: cssFontFaceSrc.to.extension});
            var outputFileName = getTemporaryFilePath({suffix: cssFontFaceSrc.to.extension});
            fs.writeFile(inputFileName, cssFontFaceSrc.to.rawSrc, passError(cb, function () {
                var javaProcess = childProcess.spawn('java', ['-jar', 'node_modules/fontler/lib/sfntly.jar', '-s', chars.join(''), inputFileName, outputFileName]);
                javaProcess.stdout.on('data', function () {});
                javaProcess.stderr.on('data', function () {});
                javaProcess.on('exit', function (exitCode) {
                    if (exitCode) {
                        return cb(new Error('java/sfntly exited with a non-zero exit code: ' + exitCode));
                    }
                    fs.readFile(outputFileName, passError(cb, function (rawSrc) {
                        if (rawSrc.length < cssFontFaceSrc.to.rawSrc.length - 2048) {
                            var subsetFontAsset = new assetGraph.Asset({
                                url: assetGraph.root + 'subset-' + (cssFontFaceSrc.to.fileName || encodeURIComponent(fontFamilyName)) + cssFontFaceSrc.to.extension,
                                rawSrc: rawSrc
                            });
                            assetGraph.addAsset(subsetFontAsset);
                            cssFontFaceSrc.node.parent.append({
                                name: 'font-face'
                            });
                            var newFontFaceRule = cssFontFaceSrc.node.parent.last;
                            newFontFaceRule.append({
                                prop: 'font-family',
                                value: fontFamilyName
                            });
                            var unicodeRangeTokens = [];
                            var currentRangeStart;
                            var currentRangeEnd;
                            function flush() {
                                if (currentRangeStart) {
                                    var unicodeRangeToken = 'U+' + currentRangeStart.toString(16).toUpperCase();
                                    if (currentRangeStart !== currentRangeEnd) {
                                        unicodeRangeToken += '-' + currentRangeEnd.toString(16).toUpperCase();
                                    }
                                    unicodeRangeTokens.push(unicodeRangeToken);
                                    currentRangeStart = currentRangeEnd = undefined;
                                }
                            }
                            chars.forEach(function (ch, i) {
                                var charCode = ch.charCodeAt(0);
                                if (currentRangeStart) {
                                    if (charCode === currentRangeEnd + 1) {
                                        currentRangeEnd = charCode;
                                    } else {
                                        flush();
                                        currentRangeStart = currentRangeEnd = charCode;
                                    }
                                } else {
                                    currentRangeStart = currentRangeEnd = charCode;
                                }
                            });
                            flush();
                            newFontFaceRule.append({
                                prop: 'unicode-range',
                                value: unicodeRangeTokens.join(', ')
                            });
                            assetGraph.addRelation(new assetGraph.CssFontFaceSrc({
                                node: newFontFaceRule,
                                parentNode: newFontFaceRule.parent,
                                from: cssFontFaceSrc.from,
                                to: subsetFontAsset
                            }), 'after', cssFontFaceSrc);
                            cssFontFaceSrc.from.markDirty();
                            cb();
                        } else {
                            // Not worth it
                            cb();
                        }
                    }));
                });
            }));
        }, cb);
    };
};
<commit_msg>Promisify the subsetFonts transform<commit_after>var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var childProcess = require('child_process');
var getTemporaryFilePath = require('gettemporaryfilepath');
var getTextByFontFace = require('../util/getTextByFontFace');

module.exports = function (queryObj) {
    return function subsetFonts(assetGraph) {
        var textByFontFace = getTextByFontFace(assetGraph);

        var fontFamiliesToSubset = Object.keys(textByFontFace);

        return Promise.map(fontFamiliesToSubset, function (fontFamilyName) {
            var chars = textByFontFace[fontFamilyName].chars;
            var cssFontFaceSrc = textByFontFace[fontFamilyName].cssFontFaceSrc;
            var inputFileName = getTemporaryFilePath({suffix: cssFontFaceSrc.to.extension});
            var outputFileName = getTemporaryFilePath({suffix: cssFontFaceSrc.to.extension});
            return fs.writeFileAsync(inputFileName, cssFontFaceSrc.to.rawSrc).then(function () {
                return Promise.fromNode(function (cb) {
                    var javaProcess = childProcess.spawn('java', ['-jar', 'node_modules/fontler/lib/sfntly.jar', '-s', chars.join(''), inputFileName, outputFileName]);
                    javaProcess.stdout.on('data', function () {});
                    javaProcess.stderr.on('data', function () {});
                    javaProcess.on('exit', function (exitCode) {
                        if (exitCode) {
                            return cb(new Error('java/sfntly exited with a non-zero exit code: ' + exitCode));
                        } else {
                            cb();
                        }
                    });
                }).then(function () {
                    return fs.readFileAsync(outputFileName);
                }).then(function (rawSrc) {
                    if (rawSrc.length < cssFontFaceSrc.to.rawSrc.length - 2048) {
                        var subsetFontAsset = new assetGraph.Asset({
                            url: assetGraph.root + 'subset-' + (cssFontFaceSrc.to.fileName || encodeURIComponent(fontFamilyName)) + cssFontFaceSrc.to.extension,
                            rawSrc: rawSrc
                        });
                        assetGraph.addAsset(subsetFontAsset);
                        cssFontFaceSrc.node.parent.append({
                            name: 'font-face'
                        });
                        var newFontFaceRule = cssFontFaceSrc.node.parent.last;
                        newFontFaceRule.append({
                            prop: 'font-family',
                            value: fontFamilyName
                        });
                        var unicodeRangeTokens = [];
                        var currentRangeStart;
                        var currentRangeEnd;
                        function flush() {
                            if (currentRangeStart) {
                                var unicodeRangeToken = 'U+' + currentRangeStart.toString(16).toUpperCase();
                                if (currentRangeStart !== currentRangeEnd) {
                                    unicodeRangeToken += '-' + currentRangeEnd.toString(16).toUpperCase();
                                }
                                unicodeRangeTokens.push(unicodeRangeToken);
                                currentRangeStart = currentRangeEnd = undefined;
                            }
                        }
                        chars.forEach(function (ch, i) {
                            var charCode = ch.charCodeAt(0);
                            if (currentRangeStart) {
                                if (charCode === currentRangeEnd + 1) {
                                    currentRangeEnd = charCode;
                                } else {
                                    flush();
                                    currentRangeStart = currentRangeEnd = charCode;
                                }
                            } else {
                                currentRangeStart = currentRangeEnd = charCode;
                            }
                        });
                        flush();
                        newFontFaceRule.append({
                            prop: 'unicode-range',
                            value: unicodeRangeTokens.join(', ')
                        });
                        assetGraph.addRelation(new assetGraph.CssFontFaceSrc({
                            node: newFontFaceRule,
                            parentNode: newFontFaceRule.parent,
                            from: cssFontFaceSrc.from,
                            to: subsetFontAsset
                        }), 'after', cssFontFaceSrc);
                        cssFontFaceSrc.from.markDirty();
                    } else {
                        // Not worth it
                    }
                });
            });
        }, {concurrency: 5});
    };
};
<|endoftext|>


<commit_before>var path    = require('path');
var _       = require('underscore');
var helpers = require('yeoman-test');
var assert  = require('yeoman-assert');

var data = require('./data');
var dependencies = data.booleanDeps;
var appFiles     = data.appFiles;
var configFiles  = data.configFiles;
var projectFiles = data.projectFiles;

var booleanAnswers = function(value) {
    value = value ? true : false;
    return {
        jsinspect:  value,
        a11y:       value,
        imagemin:   value,
        benchmarks: value,
        coveralls:  value,
        styleguide: value
    };
};

function scaffoldApp(options) {
    var appDir         = options.appDirectory;
    var scriptBundler  = options.scriptBundler;
    var cssProcessor   = options.styleProcessor;
    var templateLang   = options.templateTechnology;
    var allAnswersTrue = options.allAnswersTrue;
    var SKIP_INSTALL = {skipInstall: true};
    return helpers.run(path.join(__dirname, '../generators/app'))
        .withOptions(SKIP_INSTALL)
        .withPrompts(_.extend(_.clone(booleanAnswers(true)), {
            appDir: appDir,
            scriptBundler: scriptBundler,
            cssPreprocessor: cssProcessor,
            templateTechnology: templateLang
        }));
}

function scaffoldAppWith(options) {
    return helpers.run(path.join(__dirname, '../generators/app'))
        .withOptions({
            skipInstall: true,
            defaults: options.defaults,
            scriptBundler: options.scriptBundler,
            cssPreprocessor: options.cssPreprocessor,
            templateTechnology: options.templateTechnology
        });
}

function createPlugin(options) {
    var testOptions = {};
    if (options.customDependency && options.alias) {
        testOptions.customDependency = options.customDependency;
        testOptions.alias = options.alias;
    } else {
        options.dependencies.forEach(function(dep) {
            testOptions[dep] = true;
        });
    }
    return helpers.run(path.join(__dirname, '../generators/plugin'))
        .withLocalConfig({appDir: './'})
        .withArguments([options.name])
        .withPrompts({dependencies: options.dependencies})
        .withOptions(options.useCommandLineOptions ? testOptions : {})
        .toPromise();
}

function verifyFiles(appDir) {
    assert.file(configFiles);
    assert.file(projectFiles);
    assert.file(appFiles.map(function(file) {return appDir + file;}));
    assert.file('tasks/build.js');
    assert.file('tasks/app.js');
    assert.fileContent('.gitignore', 'app/templates.js');
    assert.fileContent('.gitignore', 'app/style.css');
    assert.fileContent('package.json', '"deploy": "cp -a dist/. dist/."');
}

function verifyConfiguration(options) {
    var appDir = options.appDirectory ? options.appDirectory : './';
    verifyWorkflowDependencies(options.workflow);
    //verifyGruntfilePlugins(options.workflow);
    //verifyBenchmarkJs(options.workflow);
    verifyBrowserifySupport(options.scriptBundler === 'browserify', appDir);
    if (options.styleProcessor === 'less') {
        verifyLessSupport(true, appDir);
    } else if (options.styleProcessor === 'sass') {
        verifySassSupport(true, appDir);
    } else {
        verifyLessSupport(false, appDir);
        verifySassSupport(false, appDir);
    }
    verifyHandlebarsSupport(options.templateTechnology === 'handlebars', appDir);
}

function verifyWorkflowDependencies(added) {
    var verify = added ? assert.fileContent : assert.noFileContent;
    dependencies.forEach(function(dep) {
        verify('package.json', dep);
    });
}

function verifyGruntfilePlugins(configured) {
    var verify = configured ? assert.fileContent : assert.noFileContent;
    verify('Gruntfile.js', 'jsinspect: {');
    verify('Gruntfile.js', 'imagemin: {');
    verify('Gruntfile.js', 'a11y: {');
    verify('Gruntfile.js', 'accessibility: {');
    verify('Gruntfile.js', 'benchmark: {');
    verify('Gruntfile.js', 'styleguide: {');
    verify('Gruntfile.js', 'mdcss');
}

function verifyBenchmarkJs(configured) {
    var verify = configured ? assert.file : assert.noFile;
    verify('test/benchmarks/example.benchmark.js');
}

function verifyCoveralls(configured) {
    var verify = configured ? assert.fileContent : assert.noFileContent;
    //verify('Gruntfile.js', 'coveralls: {');
    if (configured) {
        //assert.fileContent('package.json', '"test-ci": "npm test && grunt coveralls"');
    } else {
        assert.fileContent('package.json', '"test-ci": "npm test"');
    }
}

function verifyHandlebarsSupport(exists, appDir) {
    appDir = appDir ? appDir: '.';
    var verify;
    if (exists) {
        verify =  assert.fileContent;
        assert.file(appDir + '/app/helpers/handlebars.helpers.js');
        assert.noFileContent('Gruntfile.js', 'jst: {');
        //assert.noFileContent('package.json', '"grunt-contrib-jst": ');
        assert.noFileContent('tasks/build.js', 'jst:main');
    } else {
        verify = assert.noFileContent;
        assert.noFile(appDir + '/app/helpers/handlebars.helpers.js');
        assert.fileContent('Gruntfile.js', 'jst: {');
        //assert.fileContent('package.json', '"grunt-contrib-jst": ');
        assert.fileContent('tasks/build.js', 'jst:main');
    }
    //verify('package.json', '"handlebars": ');
    //verify('package.json', '"grunt-contrib-handlebars": ');
    verify(appDir + '/app/app.js', './helpers/handlebars.helpers');
}

function verifyBrowserifySupport(exists, appDir) {
    appDir = appDir ? appDir: '.';
    var verify;
    if (exists) {
        verify =  assert.fileContent;
        assert.noFileContent('tasks/build.js', 'requirejs:bundle');
    } else {
        verify = assert.noFileContent;
        assert.fileContent('tasks/build.js', 'requirejs:bundle');
    }
    //verify('package.json', '"browserify": {');
    //verify('package.json', 'grunt-browserify');
    //verify('package.json', 'grunt-replace');
    //verify('package.json', 'deamdify');
    //verify('package.json', 'aliasify');
    verify('Gruntfile.js', 'replace: {');
    verify('Gruntfile.js', 'browserify: {');
    verify('tasks/build.js', 'browserify:bundle');
    verify('tasks/build.js', 'replace:bundle-url');
    verify('tasks/build.js', 'uglify:bundle');
}

function verifyLessSupport(exists, appDir) {
    appDir = appDir ? appDir : '.';
    var verify;
    if (exists) {
        verify = assert.fileContent;
        assert.file(appDir + '/assets/less/reset.less');
        assert.file(appDir + '/assets/less/style.less');
        assert.noFile(appDir + '/assets/sass/reset.scss');
        assert.noFile(appDir + '/assets/sass/style.scss');
        assert.noFileContent('Gruntfile.js', 'sass: {');
        assert.noFileContent('config/default.json', 'sass/**/*.scss');
        assert.noFileContent('package.json', 'grunt-contrib-sass');
    } else {
        verify = assert.noFileContent;
    }
    verify('config/default.json', 'less/**/*.less');
    //verify('package.json', 'grunt-contrib-less');
    verify('Gruntfile.js', 'less: {');
}

function verifySassSupport(exists, appDir) {
    appDir = appDir ? appDir : '.';
    var verify;
    if (exists) {
        verify = assert.fileContent;
        assert.file(appDir + '/assets/sass/reset.scss');
        assert.file(appDir + '/assets/sass/style.scss');
        assert.noFile(appDir + '/assets/less/reset.less');
        assert.noFile(appDir + '/assets/less/style.less');
        assert.noFileContent('Gruntfile.js', 'less: {');
        assert.noFileContent('config/default.json', 'less/**/*.less');
        assert.noFileContent('package.json', 'grunt-contrib-less');
    } else {
        verify = assert.noFileContent;
    }
    verify('config/default.json', 'sass/**/*.scss');
    //verify('package.json', 'grunt-contrib-sass');
    verify('Gruntfile.js', 'sass: {');
}

module.exports = {
    scaffoldApp: scaffoldApp,
    scaffoldAppWith: scaffoldAppWith,
    createPlugin: createPlugin,
    verifyFiles: verifyFiles,
    verifyConfiguration: verifyConfiguration,
    verifyCoveralls: verifyCoveralls
};
<commit_msg>Un-commented some lines in unit tests<commit_after>var path    = require('path');
var _       = require('underscore');
var helpers = require('yeoman-test');
var assert  = require('yeoman-assert');

var data = require('./data');
var dependencies = data.booleanDeps;
var appFiles     = data.appFiles;
var configFiles  = data.configFiles;
var projectFiles = data.projectFiles;

var booleanAnswers = function(value) {
    value = value ? true : false;
    return {
        jsinspect:  value,
        a11y:       value,
        imagemin:   value,
        benchmarks: value,
        coveralls:  value,
        styleguide: value
    };
};

function scaffoldApp(options) {
    var appDir         = options.appDirectory;
    var scriptBundler  = options.scriptBundler;
    var cssProcessor   = options.styleProcessor;
    var templateLang   = options.templateTechnology;
    var allAnswersTrue = options.allAnswersTrue;
    var SKIP_INSTALL = {skipInstall: true};
    return helpers.run(path.join(__dirname, '../generators/app'))
        .withOptions(SKIP_INSTALL)
        .withPrompts(_.extend(_.clone(booleanAnswers(true)), {
            appDir: appDir,
            scriptBundler: scriptBundler,
            cssPreprocessor: cssProcessor,
            templateTechnology: templateLang
        }));
}

function scaffoldAppWith(options) {
    return helpers.run(path.join(__dirname, '../generators/app'))
        .withOptions({
            skipInstall: true,
            defaults: options.defaults,
            scriptBundler: options.scriptBundler,
            cssPreprocessor: options.cssPreprocessor,
            templateTechnology: options.templateTechnology
        });
}

function createPlugin(options) {
    var testOptions = {};
    if (options.customDependency && options.alias) {
        testOptions.customDependency = options.customDependency;
        testOptions.alias = options.alias;
    } else {
        options.dependencies.forEach(function(dep) {
            testOptions[dep] = true;
        });
    }
    return helpers.run(path.join(__dirname, '../generators/plugin'))
        .withLocalConfig({appDir: './'})
        .withArguments([options.name])
        .withPrompts({dependencies: options.dependencies})
        .withOptions(options.useCommandLineOptions ? testOptions : {})
        .toPromise();
}

function verifyFiles(appDir) {
    assert.file(configFiles);
    assert.file(projectFiles);
    assert.file(appFiles.map(function(file) {return appDir + file;}));
    assert.file('tasks/build.js');
    assert.file('tasks/app.js');
    assert.fileContent('.gitignore', 'app/templates.js');
    assert.fileContent('.gitignore', 'app/style.css');
    assert.fileContent('package.json', '"deploy": "cp -a dist/. dist/."');
}

function verifyConfiguration(options) {
    var appDir = options.appDirectory ? options.appDirectory : './';
    verifyWorkflowDependencies(options.workflow);
    //verifyGruntfilePlugins(options.workflow);
    //verifyBenchmarkJs(options.workflow);
    verifyBrowserifySupport(options.scriptBundler === 'browserify', appDir);
    if (options.styleProcessor === 'less') {
        verifyLessSupport(true, appDir);
    } else if (options.styleProcessor === 'sass') {
        verifySassSupport(true, appDir);
    } else {
        verifyLessSupport(false, appDir);
        verifySassSupport(false, appDir);
    }
    verifyHandlebarsSupport(options.templateTechnology === 'handlebars', appDir);
}

function verifyWorkflowDependencies(added) {
    var verify = added ? assert.fileContent : assert.noFileContent;
    dependencies.forEach(function(dep) {
        verify('package.json', dep);
    });
}

function verifyGruntfilePlugins(configured) {
    var verify = configured ? assert.fileContent : assert.noFileContent;
    verify('Gruntfile.js', 'jsinspect: {');
    verify('Gruntfile.js', 'imagemin: {');
    verify('Gruntfile.js', 'a11y: {');
    verify('Gruntfile.js', 'accessibility: {');
    verify('Gruntfile.js', 'benchmark: {');
    verify('Gruntfile.js', 'styleguide: {');
    verify('Gruntfile.js', 'mdcss');
}

function verifyBenchmarkJs(configured) {
    var verify = configured ? assert.file : assert.noFile;
    verify('test/benchmarks/example.benchmark.js');
}

function verifyCoveralls(configured) {
    var verify = configured ? assert.fileContent : assert.noFileContent;
    //verify('Gruntfile.js', 'coveralls: {');
    if (configured) {
        //assert.fileContent('package.json', '"test-ci": "npm test && grunt coveralls"');
    } else {
        assert.fileContent('package.json', '"test-ci": "npm test"');
    }
}

function verifyHandlebarsSupport(exists, appDir) {
    appDir = appDir ? appDir: '.';
    var verify;
    if (exists) {
        verify =  assert.fileContent;
        assert.file(appDir + '/app/helpers/handlebars.helpers.js');
        assert.noFileContent('Gruntfile.js', 'jst: {');
        //assert.noFileContent('package.json', '"grunt-contrib-jst": ');
        assert.noFileContent('tasks/build.js', 'jst:main');
    } else {
        verify = assert.noFileContent;
        assert.noFile(appDir + '/app/helpers/handlebars.helpers.js');
        assert.fileContent('Gruntfile.js', 'jst: {');
        //assert.fileContent('package.json', '"grunt-contrib-jst": ');
        assert.fileContent('tasks/build.js', 'jst:main');
    }
    //verify('package.json', '"handlebars": ');
    //verify('package.json', '"grunt-contrib-handlebars": ');
    verify(appDir + '/app/app.js', './helpers/handlebars.helpers');
}

function verifyBrowserifySupport(exists, appDir) {
    appDir = appDir ? appDir: '.';
    var verify;
    if (exists) {
        verify =  assert.fileContent;
        assert.noFileContent('tasks/build.js', 'requirejs:bundle');
    } else {
        verify = assert.noFileContent;
        assert.fileContent('tasks/build.js', 'requirejs:bundle');
    }
    verify('package.json', '"browserify": {');
    // verify('package.json', 'grunt-browserify');
    // verify('package.json', 'grunt-replace');
    verify('package.json', 'deamdify');
    verify('package.json', 'aliasify');
    verify('Gruntfile.js', 'replace: {');
    verify('Gruntfile.js', 'browserify: {');
    verify('tasks/build.js', 'browserify:bundle');
    verify('tasks/build.js', 'replace:bundle-url');
    verify('tasks/build.js', 'uglify:bundle');
}

function verifyLessSupport(exists, appDir) {
    appDir = appDir ? appDir : '.';
    var verify;
    if (exists) {
        verify = assert.fileContent;
        assert.file(appDir + '/assets/less/reset.less');
        assert.file(appDir + '/assets/less/style.less');
        assert.noFile(appDir + '/assets/sass/reset.scss');
        assert.noFile(appDir + '/assets/sass/style.scss');
        assert.noFileContent('Gruntfile.js', 'sass: {');
        assert.noFileContent('config/default.json', 'sass/**/*.scss');
        assert.noFileContent('package.json', 'grunt-contrib-sass');
    } else {
        verify = assert.noFileContent;
    }
    verify('config/default.json', 'less/**/*.less');
    //verify('package.json', 'grunt-contrib-less');
    verify('Gruntfile.js', 'less: {');
}

function verifySassSupport(exists, appDir) {
    appDir = appDir ? appDir : '.';
    var verify;
    if (exists) {
        verify = assert.fileContent;
        assert.file(appDir + '/assets/sass/reset.scss');
        assert.file(appDir + '/assets/sass/style.scss');
        assert.noFile(appDir + '/assets/less/reset.less');
        assert.noFile(appDir + '/assets/less/style.less');
        assert.noFileContent('Gruntfile.js', 'less: {');
        assert.noFileContent('config/default.json', 'less/**/*.less');
        assert.noFileContent('package.json', 'grunt-contrib-less');
    } else {
        verify = assert.noFileContent;
    }
    verify('config/default.json', 'sass/**/*.scss');
    //verify('package.json', 'grunt-contrib-sass');
    verify('Gruntfile.js', 'sass: {');
}

module.exports = {
    scaffoldApp: scaffoldApp,
    scaffoldAppWith: scaffoldAppWith,
    createPlugin: createPlugin,
    verifyFiles: verifyFiles,
    verifyConfiguration: verifyConfiguration,
    verifyCoveralls: verifyCoveralls
};
<|endoftext|>


<commit_before>'use strict';

var fs    = require('fs');
var path  = require('path');
var _     = require('lodash');
var async = require('async');

var pako_utils = require('../lib/utils/common');
var pako  = require('../index');

function writeToFile(buffer, name) {
	var filename = 'test/fixtures/zlib_output/' + name;
	fs.writeFileSync(filename, buffer);
}

// Load fixtures to test
// return: { 'filename1': content1, 'filename2': content2, ...}
//
function loadSamples(subdir) {
  var result = {};
  var dir = path.join(__dirname, 'fixtures', subdir || 'samples');

  fs.readdirSync(dir).sort().forEach(function (sample) {
    var filepath = path.join(dir, sample),
        extname  = path.extname(filepath),
        basename = path.basename(filepath, extname),
        content  = new Uint8Array(fs.readFileSync(filepath));

    if (basename[0] === '_') { return; } // skip files with name, started with dash

    result[basename] = content;
  });

  return result;
}

// Compare 2 buffers (can be Array, Uint8Array, Buffer).
//
function cmpBuf(a, b) {
  if (a.length !== b.length) {
    return false;
  }

  for (var i=0, l=a.length; i<l; i++) {
    if (a[i] !== b[i]) {
      //console.log('pos: ' +i+ ' - ' + a[i].toString(16) + '/' + b[i].toString(16));
      return false;
    }
  }

  return true;
}

// Helper to test deflate/inflate with different options.
// Use zlib streams, because it's the only way to define options.
//
function testSingle(zlib_factory, pako_deflate, data, options, callback, name) {

  var zlib_options = _.clone(options);

  // hack for testing negative windowBits
  if (zlib_options.windowBits < 0) { zlib_options.windowBits = -zlib_options.windowBits; }

  var zlibStream = zlib_factory(zlib_options);
  var buffers = [], nread = 0;

  zlibStream.on('error', function(err) {
    zlibStream.removeAllListeners();
    zlibStream=null;
    callback(err);
  });

  zlibStream.on('data', function(chunk) {
    buffers.push(chunk);
    nread += chunk.length;
  });

  zlibStream.on('end', function() {
    zlibStream.removeAllListeners();
    zlibStream=null;

    var buffer = Buffer.concat(buffers);

    var pako_result = pako_deflate(data, options);

    if (name) writeToFile(buffer, name);

	if (!cmpBuf(buffer, pako_result)) {
      callback(new Error('zlib result != pako result'));
      return;
    }

    callback(null);
  });

  zlibStream.write(new Buffer(data));
  zlibStream.end();
}

function testSamples(zlib_factory, pako_deflate, samples, options, callback, prefix) {
  var queue = [];

  _.forEach(samples, function(data, name) {
    // with untyped arrays
    queue.push(function (done) {
      pako_utils.setTyped(false);

      testSingle(zlib_factory, pako_deflate, data, options, function (err) {
        if (err) {
          done('Error in "' + name + '" - zlib result != pako result');
          return;
        }
        done();
      });
    });

    // with typed arrays
    queue.push(function (done) {
      pako_utils.setTyped(true);

      testSingle(zlib_factory, pako_deflate, data, options, function (err) {
        if (err) {
          done('Error in "' + name + '" - zlib result != pako result');
          return;
        }
        done();
      }, prefix + "-" + name);
    });
  });

  async.series(queue, callback);
}

function testInflate(samples, inflateOptions, deflateOptions, callback) {
  var name, data, deflated, inflated;

  // inflate options have windowBits = 0 to force autodetect window size
  //
  for (name in samples) {
    data = samples[name];

    // always use the same data type to generate sample
    pako_utils.setTyped(true);
    deflated = pako.deflate(data, deflateOptions);

    // with untyped arrays
    pako_utils.setTyped(false);
    inflated = pako.inflate(deflated, inflateOptions);
    pako_utils.setTyped(true);

    if (!cmpBuf(inflated, data)) {
      callback('Error in "' + name + '" - inflate result != original');
      return;
    }

    // with typed arrays
    inflated = pako.inflate(deflated, inflateOptions);

    if (!cmpBuf(inflated, data)) {
      callback('Error in "' + name + '" - inflate result != original');
      return;
    }
  }

  callback();
}

exports.cmpBuf = cmpBuf;
exports.testSamples = testSamples;
exports.testInflate = testInflate;
exports.loadSamples = loadSamples;
<commit_msg>helpers.js: only test typedarrays, and write zlib_output relative to current test<commit_after>'use strict';

var fs    = require('fs');
var path  = require('path');
var _     = require('lodash');
var async = require('async');

var pako_utils = require('../lib/utils/common');
var pako  = require('../index');

function writeToFile(buffer, name) {
	var filename = path.join(__dirname, 'fixtures/zlib_output/' + name);
	//console.log(filename + "  (" + buffer.length + ")");
	fs.writeFileSync(filename, buffer);
}

// Load fixtures to test
// return: { 'filename1': content1, 'filename2': content2, ...}
//
function loadSamples(subdir) {
  var result = {};
  var dir = path.join(__dirname, 'fixtures', subdir || 'samples');

  fs.readdirSync(dir).sort().forEach(function (sample) {
    var filepath = path.join(dir, sample),
        extname  = path.extname(filepath),
        basename = path.basename(filepath, extname),
        content  = new Uint8Array(fs.readFileSync(filepath));

    if (basename[0] === '_') { return; } // skip files with name, started with dash

    result[basename] = content;
  });

  return result;
}

// Compare 2 buffers (can be Array, Uint8Array, Buffer).
//
function cmpBuf(a, b) {
  if (a.length !== b.length) {
    return false;
  }

  for (var i=0, l=a.length; i<l; i++) {
    if (a[i] !== b[i]) {
      //console.log('pos: ' +i+ ' - ' + a[i].toString(16) + '/' + b[i].toString(16));
      return false;
    }
  }

  return true;
}

// Helper to test deflate/inflate with different options.
// Use zlib streams, because it's the only way to define options.
//
function testSingle(zlib_factory, pako_deflate, data, options, callback, name) {

  var zlib_options = _.clone(options);

  // hack for testing negative windowBits
  if (zlib_options.windowBits < 0) { zlib_options.windowBits = -zlib_options.windowBits; }

  var zlibStream = zlib_factory(zlib_options);
  var buffers = [], nread = 0;

  zlibStream.on('error', function(err) {
    zlibStream.removeAllListeners();
    zlibStream=null;
    console.log("zlib err");
	callback(err);
  });

  zlibStream.on('data', function(chunk) {
    buffers.push(chunk);
    nread += chunk.length;
  });

  zlibStream.on('end', function() {
    zlibStream.removeAllListeners();
    zlibStream=null;

    var buffer = Buffer.concat(buffers);

    var pako_result = pako_deflate(data, options);

    if (name) {
		writeToFile(buffer, name);
		//console.log(options);
	}

	if (!cmpBuf(buffer, pako_result)) {
      callback(new Error('zlib result != pako result'));
      return;
    }

    callback(null);
  });

  zlibStream.write(new Buffer(data));
  zlibStream.end();
}

function testSamples(zlib_factory, pako_deflate, samples, options, callback, prefix) {
  var queue = [];

  _.forEach(samples, function(data, name) {
    // with untyped arrays
    /*queue.push(function (done) {
      pako_utils.setTyped(false);

      testSingle(zlib_factory, pako_deflate, data, options, function (err) {
        if (err) {
          done('Error in "' + name + '" - zlib result != pako result');
          return;
        }
        done();
      });
    });*/

    // with typed arrays
    queue.push(function (done) {
      pako_utils.setTyped(true);

      testSingle(zlib_factory, pako_deflate, data, options, function (err) {
        if (err) {
          done('Error in "' + name + '" - zlib result != pako result');
          return;
        }
        done();
      }, prefix + "-" + name);
    });
  });

  async.series(queue, callback);
}

function testInflate(samples, inflateOptions, deflateOptions, callback) {
  var name, data, deflated, inflated;

  // inflate options have windowBits = 0 to force autodetect window size
  //
  for (name in samples) {
    data = samples[name];

    // always use the same data type to generate sample
    pako_utils.setTyped(true);
    deflated = pako.deflate(data, deflateOptions);

    // with untyped arrays
    pako_utils.setTyped(false);
    inflated = pako.inflate(deflated, inflateOptions);
    pako_utils.setTyped(true);

    if (!cmpBuf(inflated, data)) {
      callback('Error in "' + name + '" - inflate result != original');
      return;
    }

    // with typed arrays
    inflated = pako.inflate(deflated, inflateOptions);

    if (!cmpBuf(inflated, data)) {
      callback('Error in "' + name + '" - inflate result != original');
      return;
    }
  }

  callback();
}

exports.cmpBuf = cmpBuf;
exports.testSamples = testSamples;
exports.testInflate = testInflate;
exports.loadSamples = loadSamples;
<|endoftext|>


<commit_before>let SIZE = 800
let canvas
let wheel
let group
let parts
let angle = 0
let colors
let proportional

$(function() {
    SIZE = $('body').width()
    canvas = $('#wheel')
    canvas[0].width = SIZE
    canvas[0].height = SIZE
    wheel = canvas[0].getContext('2d')

    wheel.beginPath()
    wheel.arc(SIZE / 2, SIZE / 2, SIZE / 2 - 50, 0, 2 * Math.PI, false)
    wheel.fill()

    $('#popup').hide()

    populateGroups()

    $('#groups').change(function() {
        reloadGroup(setColors)
    })

    $('#proportional').change(function() {
        group.proportional = $(this).is(':checked')
        updateGroup(reloadGroup)
    })

    $('#run').click(function() {
        run(selectChoice)
    })

    $('#reset').click(reset)
    $('#add-group').click(function() {
        openPopup('Add a group<input id="new-group-name" placeholder="Group name"><textarea id="new-group-choices" rows="20" placeholder="Choices, each on a new line"></textarea>', addGroup)
    })
})

const setColors = function() {
    if (group.choices !== undefined) {
        colors = []
        group.choices.forEach(function(choice) {
            colors.push(getRandomBrightColor())
        })
    }
}

const reloadGroup = function(callback) {
    $.getJSON('php/getGroup.php', {
        name: $('#groups').val()
    }, function(data) {
        group = JSON.parse(data)
        if (callback !== undefined) {
            callback()
        }
        proportional = group.proportional == 'true'
        $('#proportional').prop('checked', proportional)
        parts = calculateParts()
        drawGroup()
    })
}

const save = function() {
    $.post('php/save.php', {
        file: {
            group: 'test-1',
            choices: [{
                name: 'user 1',
                points: 3
            }, {
                name: 'user 2',
                points: 1
            }]
        }
    }, function(data) {
        alert(data)
    })
}

const populateGroups = function(callback) {
    $.getJSON('php/populateGroups.php', function(data) {
        const groups = $('#groups')
        groups.html('')
        $.each(data, function(id) {
            groups.append($('<option>', {
                val: data[id],
                text: data[id].substr(0, data[id].length - 5)
            }))
        })
        reloadGroup(setColors)
        if (callback !== undefined) {
            callback(data)
        }
    })
}

const drawGroup = function() {
    let start = 0
    let end = 0
    let color = 0
    Object.keys(parts).forEach(function(name) {
        if (parts[name] == 0) {
            color = (color + 1) % colors.length
            return
        }
        start = end
        end = start + parts[name]
        wheel.beginPath()
        wheel.arc(SIZE / 2, SIZE / 2, SIZE / 2 - 60, start + angle, end + angle, false)
        wheel.lineTo(SIZE / 2, SIZE / 2)
        wheel.fillStyle = colors[color]
        wheel.strokeStyle = '#000'
        wheel.lineWidth = 3
        wheel.fill()
        wheel.stroke()
        color = (color + 1) % colors.length

        const text = name + ' (' + (Math.round(10000 * parts[name] / (2 * Math.PI)) / 100) + '%)'
        wheel.translate(SIZE / 2, SIZE / 2)
        wheel.rotate(start + angle)
        wheel.fillStyle = '#000'
        wheel.font = '20pt sans-serif'
        wheel.fillText(text, SIZE / 2 - 65 - wheel.measureText(text).width, 25)
        wheel.rotate(-start - angle)
        wheel.translate(-SIZE / 2, -SIZE / 2)
    })
    drawNeedle()
}

const drawNeedle = function() {
    wheel.beginPath()
    wheel.moveTo(SIZE - 100, SIZE / 2)
    wheel.lineTo(SIZE - 10, SIZE / 2 - 10)
    wheel.lineTo(SIZE, SIZE / 2)
    wheel.lineTo(SIZE - 10, SIZE / 2 + 10)
    wheel.fillStyle = '#000'
    wheel.fill()
}

const calculateParts = function() {
    const min = getMin()
    const total = proportional ? getTotalProportional(min) : getTotalSimple(min)
    const parts = {}
    group.choices.forEach(function(choice) {
        const part = proportional ? getProportion(choice.points, min) : (choice.points == min ? 1 : 0)
        parts[choice.name] = part / total * 2 * Math.PI
    })
    return parts
}

const getMin = function() {
    let min = Infinity
    group.choices.forEach(function(choice) {
        min = Math.min(choice.points, min)
    })
    return min
}

const getTotalSimple = function(min) {
    let total = 0
    group.choices.forEach(function(choice) {
        total += choice.points == min ? 1 : 0
    })
    return total
}

const getTotalProportional = function(min) {
    let total = 0
    group.choices.forEach(function(choice) {
        total += getProportion(choice.points, min)
    })
    return total
}

const getProportion = function(value, min) {
    return 1 / Math.pow(2, value - min + 1)
}

const run = function(finished) {
    if (parts === undefined) {
        return
    }
    $('#working *').prop('disabled', true)
    let speed = 0.3 * Math.random() + 0.2
    const slowDown = 0.001
    const timer = setInterval(function() {
        angle += speed
        speed -= slowDown
        drawGroup()
        if (speed <= 0) {
            clearTimeout(timer)
            $('#working *').prop('disabled', false)
            finished()
        }
    }, 1000 / 60)
}

const selectChoice = function() {
    while (angle > 0) {
        angle -= 2 * Math.PI
    }

    let sum = 0
    let selected
    Object.keys(parts).forEach(function(part) {
        sum += parts[part]
        if (-angle <= sum && selected === undefined) {
            selected = part
        }
    })
    if (selected !== undefined) {
        group.choices.forEach(function(choice) {
            if (choice.name == selected) {
                choice.points++
            }
        })
        openPopup(selected, function() {
            updateGroup(reloadGroup)
        })
    }
}

const openPopup = function(content, callback) {
    $('#popup-text').html(content)
    $('#popup').fadeIn()
    $('#ok').unbind('click')
    $('#ok').click(function() {
        callback()
        closePopup()
    })
    $('#cancel').unbind('click')
    $('#cancel').click(closePopup)
}

const closePopup = function() {
    $('#popup').fadeOut()
    $('#popup-text').text('')
}

const updateGroup = function(callback) {
    $.post('php/save.php', {
        file: group
    }, function(data) {
        callback()
    })
}

const reset = function() {
    openPopup('Are you sure you want to reset?', confirmReset)
}

const confirmReset = function() {
    group.choices.forEach(function(choice) {
        choice.points = 0
    })
    updateGroup(reloadGroup)
}

const addGroup = function() {
    let newName = $('#new-group-name').val()
    const newChoices = $('#new-group-choices')
        .val()
        .split(/[\r\n]+/)
        .map(function(element) {
            return element.trim()
        })
        .filter(function(element) {
            return element
        })

    if (!newName) {
        console.log('Name required')
        return
    }
    while ($('#groups').find(':contains(' + newName + ')').length > 0) {
        newName += '_'
    }
    if (newChoices.length == 0) {
        console.log('Non-empty lines required')
        return
    }

    const newGroup = {}
    newGroup.group = newName
    newGroup.proportional = false
    newGroup.choices = []
    newChoices.forEach(function(choice) {
        newGroup.choices.push({
            name: choice,
            points: 0
        })
    })
    group = newGroup
    updateGroup(function() {
        populateGroups(function() {
            $('#groups').val(newName + '.json')
            reloadGroup(setColors)
        })
    })
}

const getRandomBrightColor = function() {
    const letters = '0123456789abcdef'
    let code = ''
    for (let i = 0; i < 2; i++) {
        code += letters[Math.floor(Math.random() * letters.length)]
    }

    let color = '#'

    const type = Math.floor(Math.random() * 6)
    switch (type) {
        case 0: // Red -> Yellow
            color += 'ff' + code + '00'
            break

        case 1: // Yellow -> Green
            color += code + 'ff00'
            break

        case 2: // Green -> Cyan
            color += '00ff' + code
            break

        case 3: // Cyan -> Blue
            color += '00' + code + 'ff'
            break

        case 4: // Blue -> Magenta
            color += code + '00ff'
            break

        case 5: // Magenta -> Red
            color += 'ff00' + code
            break

        default:
            return undefined
    }
    return color
}
<commit_msg>Empty popup in its callback<commit_after>let SIZE = 800
let canvas
let wheel
let group
let parts
let angle = 0
let colors
let proportional

$(function() {
    SIZE = $('body').width()
    canvas = $('#wheel')
    canvas[0].width = SIZE
    canvas[0].height = SIZE
    wheel = canvas[0].getContext('2d')

    wheel.beginPath()
    wheel.arc(SIZE / 2, SIZE / 2, SIZE / 2 - 50, 0, 2 * Math.PI, false)
    wheel.fill()

    $('#popup').hide()

    populateGroups()

    $('#groups').change(function() {
        reloadGroup(setColors)
    })

    $('#proportional').change(function() {
        group.proportional = $(this).is(':checked')
        updateGroup(reloadGroup)
    })

    $('#run').click(function() {
        run(selectChoice)
    })

    $('#reset').click(reset)
    $('#add-group').click(function() {
        openPopup('Add a group<input id="new-group-name" placeholder="Group name"><textarea id="new-group-choices" rows="20" placeholder="Choices, each on a new line"></textarea>', addGroup)
    })
})

const setColors = function() {
    if (group.choices !== undefined) {
        colors = []
        group.choices.forEach(function(choice) {
            colors.push(getRandomBrightColor())
        })
    }
}

const reloadGroup = function(callback) {
    $.getJSON('php/getGroup.php', {
        name: $('#groups').val()
    }, function(data) {
        group = JSON.parse(data)
        if (callback !== undefined) {
            callback()
        }
        proportional = group.proportional == 'true'
        $('#proportional').prop('checked', proportional)
        parts = calculateParts()
        drawGroup()
    })
}

const save = function() {
    $.post('php/save.php', {
        file: {
            group: 'test-1',
            choices: [{
                name: 'user 1',
                points: 3
            }, {
                name: 'user 2',
                points: 1
            }]
        }
    }, function(data) {
        alert(data)
    })
}

const populateGroups = function(callback) {
    $.getJSON('php/populateGroups.php', function(data) {
        const groups = $('#groups')
        groups.html('')
        $.each(data, function(id) {
            groups.append($('<option>', {
                val: data[id],
                text: data[id].substr(0, data[id].length - 5)
            }))
        })
        reloadGroup(setColors)
        if (callback !== undefined) {
            callback(data)
        }
    })
}

const drawGroup = function() {
    let start = 0
    let end = 0
    let color = 0
    Object.keys(parts).forEach(function(name) {
        if (parts[name] == 0) {
            color = (color + 1) % colors.length
            return
        }
        start = end
        end = start + parts[name]
        wheel.beginPath()
        wheel.arc(SIZE / 2, SIZE / 2, SIZE / 2 - 60, start + angle, end + angle, false)
        wheel.lineTo(SIZE / 2, SIZE / 2)
        wheel.fillStyle = colors[color]
        wheel.strokeStyle = '#000'
        wheel.lineWidth = 3
        wheel.fill()
        wheel.stroke()
        color = (color + 1) % colors.length

        const text = name + ' (' + (Math.round(10000 * parts[name] / (2 * Math.PI)) / 100) + '%)'
        wheel.translate(SIZE / 2, SIZE / 2)
        wheel.rotate(start + angle)
        wheel.fillStyle = '#000'
        wheel.font = '20pt sans-serif'
        wheel.fillText(text, SIZE / 2 - 65 - wheel.measureText(text).width, 25)
        wheel.rotate(-start - angle)
        wheel.translate(-SIZE / 2, -SIZE / 2)
    })
    drawNeedle()
}

const drawNeedle = function() {
    wheel.beginPath()
    wheel.moveTo(SIZE - 100, SIZE / 2)
    wheel.lineTo(SIZE - 10, SIZE / 2 - 10)
    wheel.lineTo(SIZE, SIZE / 2)
    wheel.lineTo(SIZE - 10, SIZE / 2 + 10)
    wheel.fillStyle = '#000'
    wheel.fill()
}

const calculateParts = function() {
    const min = getMin()
    const total = proportional ? getTotalProportional(min) : getTotalSimple(min)
    const parts = {}
    group.choices.forEach(function(choice) {
        const part = proportional ? getProportion(choice.points, min) : (choice.points == min ? 1 : 0)
        parts[choice.name] = part / total * 2 * Math.PI
    })
    return parts
}

const getMin = function() {
    let min = Infinity
    group.choices.forEach(function(choice) {
        min = Math.min(choice.points, min)
    })
    return min
}

const getTotalSimple = function(min) {
    let total = 0
    group.choices.forEach(function(choice) {
        total += choice.points == min ? 1 : 0
    })
    return total
}

const getTotalProportional = function(min) {
    let total = 0
    group.choices.forEach(function(choice) {
        total += getProportion(choice.points, min)
    })
    return total
}

const getProportion = function(value, min) {
    return 1 / Math.pow(2, value - min + 1)
}

const run = function(finished) {
    if (parts === undefined) {
        return
    }
    $('#working *').prop('disabled', true)
    let speed = 0.3 * Math.random() + 0.2
    const slowDown = 0.001
    const timer = setInterval(function() {
        angle += speed
        speed -= slowDown
        drawGroup()
        if (speed <= 0) {
            clearTimeout(timer)
            $('#working *').prop('disabled', false)
            finished()
        }
    }, 1000 / 60)
}

const selectChoice = function() {
    while (angle > 0) {
        angle -= 2 * Math.PI
    }

    let sum = 0
    let selected
    Object.keys(parts).forEach(function(part) {
        sum += parts[part]
        if (-angle <= sum && selected === undefined) {
            selected = part
        }
    })
    if (selected !== undefined) {
        group.choices.forEach(function(choice) {
            if (choice.name == selected) {
                choice.points++
            }
        })
        openPopup(selected, function() {
            updateGroup(reloadGroup)
        })
    }
}

const openPopup = function(content, callback) {
    $('#popup-text').html(content)
    $('#popup').fadeIn()
    $('#ok').unbind('click')
    $('#ok').click(function() {
        callback()
        closePopup()
    })
    $('#cancel').unbind('click')
    $('#cancel').click(closePopup)
}

const closePopup = function() {
    $('#popup').fadeOut(400, function() {
        $('#popup-text').text('')
    })
}

const updateGroup = function(callback) {
    $.post('php/save.php', {
        file: group
    }, function(data) {
        callback()
    })
}

const reset = function() {
    openPopup('Are you sure you want to reset?', confirmReset)
}

const confirmReset = function() {
    group.choices.forEach(function(choice) {
        choice.points = 0
    })
    updateGroup(reloadGroup)
}

const addGroup = function() {
    let newName = $('#new-group-name').val()
    const newChoices = $('#new-group-choices')
        .val()
        .split(/[\r\n]+/)
        .map(function(element) {
            return element.trim()
        })
        .filter(function(element) {
            return element
        })

    if (!newName) {
        console.log('Name required')
        return
    }
    while ($('#groups').find(':contains(' + newName + ')').length > 0) {
        newName += '_'
    }
    if (newChoices.length == 0) {
        console.log('Non-empty lines required')
        return
    }

    const newGroup = {}
    newGroup.group = newName
    newGroup.proportional = false
    newGroup.choices = []
    newChoices.forEach(function(choice) {
        newGroup.choices.push({
            name: choice,
            points: 0
        })
    })
    group = newGroup
    updateGroup(function() {
        populateGroups(function() {
            $('#groups').val(newName + '.json')
            reloadGroup(setColors)
        })
    })
}

const getRandomBrightColor = function() {
    const letters = '0123456789abcdef'
    let code = ''
    for (let i = 0; i < 2; i++) {
        code += letters[Math.floor(Math.random() * letters.length)]
    }

    let color = '#'

    const type = Math.floor(Math.random() * 6)
    switch (type) {
        case 0: // Red -> Yellow
            color += 'ff' + code + '00'
            break

        case 1: // Yellow -> Green
            color += code + 'ff00'
            break

        case 2: // Green -> Cyan
            color += '00ff' + code
            break

        case 3: // Cyan -> Blue
            color += '00' + code + 'ff'
            break

        case 4: // Blue -> Magenta
            color += code + '00ff'
            break

        case 5: // Magenta -> Red
            color += 'ff00' + code
            break

        default:
            return undefined
    }
    return color
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import {Point, Range} from 'atom';

import {toNativePathSep} from '../helpers';
import Marker from '../atom/marker';
import Decoration from '../atom/decoration';
import GithubDotcomMarkdown from './github-dotcom-markdown';
import Timeago from './timeago';

export default class PullRequestCommentsView extends React.Component {
  render() {
    if (!this.props.reviews) {
      return null;
    }

    return this.props.reviews.nodes.map(review => {
      return review.comments.nodes.map(comment => {
        if (!comment.position) {
          return null;
        }

        const nativePath = toNativePathSep(comment.path);
        const row = this.props.multiFilePatch.getBufferRowForDiffPosition(nativePath, comment.position);
        const point = new Point(row, 0);
        const range = new Range(point, point);

        return (
          <Marker key={`pr-comment-${comment.id}`} bufferRange={range} invalidate="never">
            <Decoration type="block" position="after" className="github-PrComment">
              <PullRequestCommentView comment={comment} switchToIssueish={this.props.switchToIssueish} />
            </Decoration>
          </Marker>
        );
      });
    });
  }
}

class PullRequestCommentView extends React.Component {
  render() {
    const author = this.props.comment.author;
    return (

          {author ? author.login : 'someone'} commented{' '}

            <Timeago time={this.props.comment.createdAt} />

          <GithubDotcomMarkdown html={this.props.comment.bodyHTML} switchToIssueish={this.props.switchToIssueish} />

    );
  }
}
<commit_msg>WIP sort comments in correct order. Red herring. seems like they're coming back sorted, but rendering in the wrong order<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import {Point, Range} from 'atom';

import {toNativePathSep} from '../helpers';
import Marker from '../atom/marker';
import Decoration from '../atom/decoration';
import GithubDotcomMarkdown from './github-dotcom-markdown';
import Timeago from './timeago';

export default class PullRequestCommentsView extends React.Component {
  render() {
    if (!this.props.reviews) {
      return null;
    }

    const commentsByPosition = new Map();
    this.props.reviews.nodes.forEach(review => {
      review.comments.nodes.forEach(comment => {
        const nativePath = toNativePathSep(comment.path);
        const row = this.props.multiFilePatch.getBufferRowForDiffPosition(nativePath, comment.position);
        const commentsAtRow = commentsByPosition.get(row);
        if (commentsAtRow) {
          commentsAtRow.add(comment);
        } else {
          commentsByPosition.set(row, new Set([comment]));
        }
      });
    });

    return [...commentsByPosition].map(([row, comments]) => {
      const getUnixTime = epoch => new Date(epoch).getTime() / 1000;
      console.log([...comments]);
      const sortedComments = [...comments].sort((a, b) => getUnixTime(a.createdAt) - getUnixTime(b.createdAt));

      console.log(sortedComments);
      return sortedComments.map(comment => {
        if (!comment.position) {
          return null;
        }

        const point = new Point(row, 0);
        const range = new Range(point, point);

        return (
          <Marker key={`pr-comment-${comment.id}`} bufferRange={range} invalidate="never">
            <Decoration type="block" position="after" className="github-PrComment">
              <PullRequestCommentView comment={comment} switchToIssueish={this.props.switchToIssueish} />
            </Decoration>
          </Marker>
        );
      });
    });

    // debugger;
    //
    // return this.props.reviews.nodes.map(review => {
    //   return review.comments.nodes.map(comment => {
    //     if (!comment.position) {
    //       return null;
    //     }
    //
    //     const nativePath = toNativePathSep(comment.path);
    //     const row = this.props.multiFilePatch.getBufferRowForDiffPosition(nativePath, comment.position);
    //     const point = new Point(row, 0);
    //     const range = new Range(point, point);
    //
    //     return (
    //       <Marker key={`pr-comment-${comment.id}`} bufferRange={range} invalidate="never">
    //         <Decoration type="block" position="after" className="github-PrComment">
    //           <PullRequestCommentView comment={comment} switchToIssueish={this.props.switchToIssueish} />
    //         </Decoration>
    //       </Marker>
    //     );
    //   });
    // });
  }
}

class PullRequestCommentView extends React.Component {
  render() {
    const author = this.props.comment.author;
    return (

          {author ? author.login : 'someone'} commented{' '}

            <Timeago time={this.props.comment.createdAt} />

          <GithubDotcomMarkdown html={this.props.comment.bodyHTML} switchToIssueish={this.props.switchToIssueish} />

    );
  }
}
<|endoftext|>