#!/usr/bin/env node
function getLatestVersion(){var e=execSync("git tag"),r=_(e).split("\n").compact().sort(semver.gt).last();return console.log("Latest tag is ",r),r}function runSuite(e,r){e.on("complete",function(){r()}).run({async:!0})}function setDefaultOptions(e){return e.args=e.args||[[]],e.setup=e.setup||function(){},e}function handleMultipleArgs(e,r){return e.concat(r.args.map(function(e){return _.defaults({args:e},r)}))}function setName(e){return e.name=e.name+"("+e.args.join(",")+")",e}function matchesGrep(e){return!!grep.exec(e.name)}function doesNotMatch(e){return!reject.exec(e.name)}function createSuite(e){function r(r,t){var i=e.name+" "+t;try{e.setup(1),e.fn(r,function(){})}catch(a){return console.error(i+" Errored"),void(o=!0)}n.add(i,function(n){e.fn(r,function(){n.resolve()})},_.extend({versionName:t,setup:_.partial.apply(null,[e.setup].concat(s)),onError:function(e){console.log(e.stack)}},benchOptions))}var n=new Benchmark.Suite,s=e.args,o=!1;return r(versions[0],versionNames[0]),r(versions[1],versionNames[1]),n.on("cycle",function(e){var r=1e3*e.target.stats.mean;console.log(e.target+", "+r.toPrecision(3)+"ms per run");var n=e.target.options.versionName;o||(totalTime[n]+=r)}).on("error",function(e){console.error(e)}).on("complete",function(){if(!o){var e=this.filter("fastest");if(2===e.length)console.log("Tie");else{var r=e[0].options.versionName;console.log(r+" is faster"),wins[r]++}}console.log("--------------------------------------")})}function requireVersion(e){return"current"===e?async:require("./versions/"+e+"/")}function cloneVersion(e,r){if("current"===e)return r();var n=__dirname+"/versions/"+e;mkdirp.sync(n),fs.open(n+"/package.json","r",function(s,o){if(!s)return fs.close(o),r();var t=path.join(__dirname,".."),i="git clone --branch "+e+" "+t+" "+n;exec(i,function(e){if(e)throw e;r()})})}var _=require("lodash"),Benchmark=require("benchmark"),exec=require("child_process").exec,execSync=require("child_process").execSync,fs=require("fs"),path=require("path"),mkdirp=require("mkdirp"),async=require("../"),suiteConfigs=require("./suites"),semver=require("semver"),args=require("yargs").usage("Usage: $0 [options] [tag1] [tag2]").describe("g","run only benchmarks whose names match this regex").alias("g","grep")["default"]("g",".*").describe("i","skip benchmarks whose names match this regex").alias("i","reject")["default"]("i","^$").describe("l","maximum running time per test (in seconds)").alias("l","limit")["default"]("l",2).help("h").alias("h","help").example("$0 0.9.2 0.9.0","Compare v0.9.2 with v0.9.0").example("$0 0.9.2","Compare v0.9.2 with the current working version").example("$0","Compare the latest tag with the current working version").example("$0 -g each","only run the each(), eachLimit() and  eachSeries() benchmarks").example("").argv,grep=new RegExp(args.g,"i"),reject=new RegExp(args.i,"i"),version0=args._[0]||getLatestVersion(),version1=args._[1]||"current",versionNames=[version0,version1],benchOptions={defer:!0,minSamples:1,maxTime:+args.l},versions,wins={},totalTime={};totalTime[version0]=wins[version0]=0,totalTime[version1]=wins[version1]=0,console.log("Comparing "+version0+" with "+version1+" on Node "+process.version),console.log("--------------------------------------"),async.eachSeries(versionNames,cloneVersion,function(e){if(e)throw e;versions=versionNames.map(requireVersion);var r=suiteConfigs.map(setDefaultOptions).reduce(handleMultipleArgs,[]).map(setName).filter(matchesGrep).filter(doesNotMatch).map(createSuite);async.eachSeries(r,runSuite,function(){var e=+totalTime[version0].toPrecision(3),r=+totalTime[version1].toPrecision(3),n=wins[version0],s=wins[version1];Math.abs(e/r-1)<.01?console.log("Both versions are about equal ("+e+"ms total vs. "+r+"ms total)"):e<r?console.log(version0+" faster overall ("+e+"ms total vs. "+r+"ms total)"):r<e&&console.log(version1+" faster overall ("+r+"ms total vs. "+e+"ms total)"),n>s?console.log(version0+" won more benchmarks ("+n+" vs. "+s+")"):s>n?console.log(version1+" won more benchmarks ("+s+" vs. "+n+")"):console.log("Both versions won the same number of benchmarks ("+n+" vs. "+s+")")})});