<commit_before>
//positioning settings
var width = 740;
var height = 4000;
var pad = { left: 10, right: 0, top: 60, bottom: 10 };
var vertSpace = 45;
var xName = 20;

var xPrct = 520;
var xChange = 640;
var xNumF = 260;
var xTotal = 380;

var rectW = 80;
var rectH = 35;
var yHeader = 20;
var ySubHead = 40;

//define scales
var scaleRB6 = ['rgb(178,24,43)','rgb(239,138,98)','rgb(253,219,199)','rgb(209,229,240)','rgb(103,169,207)','rgb(33,102,172)'];
var colors = d3.scale.quantize().domain([30, 0]).range(scaleRB6);
var sizeNumF = d3.scale.linear().domain([10, 100]).range([11, 30]);
var sizeTotal = d3.scale.linear().domain([50, 500]).range([11, 30]);
var changeH = d3.scale.linear().domain([0, 13]).range([0, 18]);
var prctBar = d3.scale.linear().domain([0, 32]).range([0, 25]);

//create container elements
var svg = d3.select(".top25").append("svg")
            .attr("width", width + pad.left + pad.right)
            .attr("height", height + pad.top + pad.bottom);

//create header (background) tiles
var headerTiles = svg.append("g").attr("class", "headerTile").attr("transform", "translate(" + pad.left + ",0)");
var activeTile = headerTiles.append("rect").attr({x: xPrct-45, y: 7, width: 90, height: 43, class: "prct"}).style("fill", "#eee").on("click", rankPrct);
headerTiles.append("rect").attr({x: xChange-70, y: 7, width: 140, height: 43, fill: "white", class: "change"}).on("click", rankChange);
headerTiles.append("rect").attr({x: xNumF-65, y: 7, width: 130, height: 43, fill: "white", class: "numF"}).on("click", rankNumF);
headerTiles.append("rect").attr({x: xTotal-37, y: 7, width: 74, height: 43, fill: "white", class: "total"}).on("click", rankTotal);
headerTiles.selectAll("rect").style("cursor", "pointer");

//create header text
var header = svg.append("g").attr("class", "header").attr("transform", "translate(" + pad.left + "," + yHeader + ")");
header.append("text").text("Science Majors").attr("x", xPrct).on("click", rankPrct);
header.append("text").text("Researchers").attr("x", xChange).on("click", rankChange);
header.append("text").text("Explicit").attr("x", xNumF).on("click", rankNumF);
header.append("text").text("Implicit").attr("x", xTotal).on("click", rankTotal);
var subHead = svg.append("g").attr("class", "subHead").attr("transform", "translate(" + pad.left + "," + ySubHead + ")");
subHead.append("text").text("% Women").attr("x", xPrct).on("click", rankPrct);
subHead.append("text").text("% Women").attr("x", xChange).on("click", rankChange);
subHead.append("text").text("Stereotypes").attr("x", xNumF).on("click", rankNumF);
subHead.append("text").text("Stereotypes").attr("x", xTotal).on("click", rankTotal);
header.selectAll("text").style("cursor", "pointer");
subHead.selectAll("text").style("cursor", "pointer");
//event handlers for resorting the rows
function rankPrct() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .prct");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rank - 0.5) + ")"; });
}
function rankChange() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .change");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rankChange - 0.5) + ")"; });
}
function rankNumF() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .numF");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rankNumF - 0.5) + ")"; });
}
function rankTotal() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .total");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rankTotal - 0.5) + ")"; });
}

//create header line and content SVG group
svg.append("line").attr({ x1: 0, x2: width, y1: 2, y2: 2}).style({"stroke-width": 2, stroke: "#222"});
svg.append("line").attr({ x1: 0, x2: width, y1: pad.top-5, y2: pad.top-5}).style({"stroke-width": 2, stroke: "#222"});
var g = svg.append("g").attr("transform", "translate(" + pad.left + ", " + pad.top + ")");

//load data...
d3.csv("data/top25.csv", function(data) {

  ///////////////////////////////
  //  FIXED POSITION ELEMENTS  //
  ///////////////////////////////

  //add lines in between
  g.selectAll("line.sep").data(data).enter().append("line")
    .attr({ x1: -pad.left, x2: width-pad.left, class: "sep"})
    .attr("y1", function(d) { return vertSpace*d.rank; })
    .attr("y2", function(d) { return vertSpace*d.rank; })
    .style({"stroke-width": 0.5, stroke: "#888"});

  //ranking text
  g.selectAll("text.rank").data(data).enter().append("text")
    .attr("class", "rank")
    .text(function(d) { return d.rank + "."; })
    .attr("y", function(d) { return vertSpace*(d.rank - 0.5); })
    .attr("x", 5);

  /////////////////////////////////
  //  DYNAMIC POSITION ELEMENTS  //
  /////////////////////////////////

  //add grouping elements
  var rows = g.selectAll(".rows")
              .data(data).enter()
              .append("g")
              .attr("class", "row")
              .attr("transform", function(d) {
                return "translate(0," + vertSpace*(+d.rank - 0.5) + ")";
              });

  //for each school...
  rows.each(function(d) {

    //get a D3 selection of the g SVG element
    var s = d3.select(this);

    //school name
    s.append("text")
      .attr("class", "name")
      .text(function(d) { return d.abbrev; })
      .attr("x", xName);

    //percent women text
    s.append("text")
      .attr("class", "prct")
      .text(function(d) { return d.prctStr; })
      .attr("x", xPrct)
      .style("fill", "#333")
      .style("font-size", 25);

    //change percent text
    s.append("text")
      .attr("class", "change")
      .text(function(d) { return d.changeStr; })
      .attr("x", xChange)
      .style("font-size", 25);

    //number women text
    s.append("text")
      .attr("class", "numF")
      .text(function(d) { return d.numF; })
      .attr("x", xNumF)
      .style("font-size", 25);
      //.style("font-size", function(d) { return sizeNumF(d.numF); });

    //total number text
    s.append("text")
      .attr("class", "total")
      .text(function(d) { return d.total; })
      .attr("x", xTotal)
      .style("font-size", 25);
      //.style("font-size", function(d) { return sizeTotal(d.total); });

  });

});<commit_msg>small edit<commit_after>
//positioning settings
var width = 740;
var height = 4000;
var pad = { left: 10, right: 0, top: 60, bottom: 10 };
var vertSpace = 45;
var xName = 20;

var xPrct = 520;
var xChange = 640;
var xNumF = 260;
var xTotal = 380;

var rectW = 80;
var rectH = 35;
var yHeader = 20;
var ySubHead = 40;

//define scales
var scaleRB6 = ['rgb(178,24,43)','rgb(239,138,98)','rgb(253,219,199)','rgb(209,229,240)','rgb(103,169,207)','rgb(33,102,172)'];
var colors = d3.scale.quantize().domain([30, 0]).range(scaleRB6);
var sizeNumF = d3.scale.linear().domain([10, 100]).range([11, 30]);
var sizeTotal = d3.scale.linear().domain([50, 500]).range([11, 30]);
var changeH = d3.scale.linear().domain([0, 13]).range([0, 18]);
var prctBar = d3.scale.linear().domain([0, 32]).range([0, 25]);

//create container elements
var svg = d3.select(".top25").append("svg")
            .attr("width", width + pad.left + pad.right)
            .attr("height", height + pad.top + pad.bottom);

//create header (background) tiles
var headerTiles = svg.append("g").attr("class", "headerTile").attr("transform", "translate(" + pad.left + ",0)");
var activeTile = headerTiles.append("rect").attr({x: xPrct-45, y: 7, width: 90, height: 43, class: "prct"}).style("fill", "#eee").on("click", rankPrct);
headerTiles.append("rect").attr({x: xChange-70, y: 7, width: 140, height: 43, fill: "white", class: "change"}).on("click", rankChange);
headerTiles.append("rect").attr({x: xNumF-65, y: 7, width: 130, height: 43, fill: "white", class: "numF"}).on("click", rankNumF);
headerTiles.append("rect").attr({x: xTotal-37, y: 7, width: 74, height: 43, fill: "white", class: "total"}).on("click", rankTotal);
headerTiles.selectAll("rect").style("cursor", "pointer");

//create header text
var header = svg.append("g").attr("class", "header").attr("transform", "translate(" + pad.left + "," + yHeader + ")");
header.append("text").text("Sci. Majors").attr("x", xPrct).on("click", rankPrct);
header.append("text").text("Researchers").attr("x", xChange).on("click", rankChange);
header.append("text").text("Explicit").attr("x", xNumF).on("click", rankNumF);
header.append("text").text("Implicit").attr("x", xTotal).on("click", rankTotal);
var subHead = svg.append("g").attr("class", "subHead").attr("transform", "translate(" + pad.left + "," + ySubHead + ")");
subHead.append("text").text("% Women").attr("x", xPrct).on("click", rankPrct);
subHead.append("text").text("% Women").attr("x", xChange).on("click", rankChange);
subHead.append("text").text("Stereotypes").attr("x", xNumF).on("click", rankNumF);
subHead.append("text").text("Stereotypes").attr("x", xTotal).on("click", rankTotal);
header.selectAll("text").style("cursor", "pointer");
subHead.selectAll("text").style("cursor", "pointer");
//event handlers for resorting the rows
function rankPrct() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .prct");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rank - 0.5) + ")"; });
}
function rankChange() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .change");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rankChange - 0.5) + ")"; });
}
function rankNumF() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .numF");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rankNumF - 0.5) + ")"; });
}
function rankTotal() {
  activeTile.style("fill", "white");
  activeTile = d3.select(".headerTile .total");
  activeTile.style("fill", "#eee");
  d3.selectAll("g.row")
    .transition().duration(800)
    .attr("transform", function(d) { return "translate(0," + vertSpace*(+d.rankTotal - 0.5) + ")"; });
}

//create header line and content SVG group
svg.append("line").attr({ x1: 0, x2: width, y1: 2, y2: 2}).style({"stroke-width": 2, stroke: "#222"});
svg.append("line").attr({ x1: 0, x2: width, y1: pad.top-5, y2: pad.top-5}).style({"stroke-width": 2, stroke: "#222"});
var g = svg.append("g").attr("transform", "translate(" + pad.left + ", " + pad.top + ")");

//load data...
d3.csv("data/top25.csv", function(data) {

  ///////////////////////////////
  //  FIXED POSITION ELEMENTS  //
  ///////////////////////////////

  //add lines in between
  g.selectAll("line.sep").data(data).enter().append("line")
    .attr({ x1: -pad.left, x2: width-pad.left, class: "sep"})
    .attr("y1", function(d) { return vertSpace*d.rank; })
    .attr("y2", function(d) { return vertSpace*d.rank; })
    .style({"stroke-width": 0.5, stroke: "#888"});

  //ranking text
  g.selectAll("text.rank").data(data).enter().append("text")
    .attr("class", "rank")
    .text(function(d) { return d.rank + "."; })
    .attr("y", function(d) { return vertSpace*(d.rank - 0.5); })
    .attr("x", 5);

  /////////////////////////////////
  //  DYNAMIC POSITION ELEMENTS  //
  /////////////////////////////////

  //add grouping elements
  var rows = g.selectAll(".rows")
              .data(data).enter()
              .append("g")
              .attr("class", "row")
              .attr("transform", function(d) {
                return "translate(0," + vertSpace*(+d.rank - 0.5) + ")";
              });

  //for each school...
  rows.each(function(d) {

    //get a D3 selection of the g SVG element
    var s = d3.select(this);

    //school name
    s.append("text")
      .attr("class", "name")
      .text(function(d) { return d.abbrev; })
      .attr("x", xName);

    //percent women text
    s.append("text")
      .attr("class", "prct")
      .text(function(d) { return d.prctStr; })
      .attr("x", xPrct)
      .style("fill", "#333")
      .style("font-size", 25);

    //change percent text
    s.append("text")
      .attr("class", "change")
      .text(function(d) { return d.changeStr; })
      .attr("x", xChange)
      .style("font-size", 25);

    //number women text
    s.append("text")
      .attr("class", "numF")
      .text(function(d) { return d.numF; })
      .attr("x", xNumF)
      .style("font-size", 25);
      //.style("font-size", function(d) { return sizeNumF(d.numF); });

    //total number text
    s.append("text")
      .attr("class", "total")
      .text(function(d) { return d.total; })
      .attr("x", xTotal)
      .style("font-size", 25);
      //.style("font-size", function(d) { return sizeTotal(d.total); });

  });

});<|endoftext|>


<commit_before>(function() {
  window.EmberDev = window.EmberDev || {};

  // hack qunit to not suck for Ember objects
  var originalTypeof = QUnit.jsDump.typeOf;

  QUnit.jsDump.typeOf = function(obj) {
    if (Ember && Ember.Object && Ember.Object.detectInstance(obj)) {
      return "emberObject";
    }

    return originalTypeof.call(this, obj);
  };

  QUnit.jsDump.parsers.emberObject = function(obj) {
    return obj.toString();
  };

  var originalModule = module;
  module = function(name, origOpts) {
    var opts = {};
    if (origOpts && origOpts.setup) { opts.setup = origOpts.setup; }
    opts.teardown = function() {
      if (origOpts && origOpts.teardown) { origOpts.teardown(); }

      if (Ember && Ember.run) {
        if (Ember.run.currentRunLoop) {
          ok(false, "Should not be in a run loop at end of test");
          while (Ember.run.currentRunLoop) {
            Ember.run.end();
          }
        }
        if (Ember.run.hasScheduledTimers()) {
          // Use `ok` so we get full description.
          // Gate inside of `if` so that we don't mess up `expects` counts
          ok(false, "Ember run should not have scheduled timers at end of test");
          Ember.run.cancelTimers();
        }
      }

      if (EmberDev.afterEach) {
        EmberDev.afterEach();
      }
    };
    return originalModule(name, opts);
  };

  // Tests should time out after 5 seconds
  QUnit.config.testTimeout = 5000;

  // Hide passed tests by default
  QUnit.config.hidepassed = true;

  // Handle JSHint
  QUnit.config.urlConfig.push('nojshint');

  EmberDev.jsHint = !QUnit.urlParams.nojshint;

  EmberDev.jsHintReporter = function (file, errors) {
    if (!errors) { return ''; }

    var len = errors.length,
        str = '',
        error, idx;

    if (len === 0) { return ''; }

    for (idx=0; idx<len; idx++) {
      error = errors[idx];
      str += file  + ': line ' + error.line + ', col ' +
          error.character + ', ' + error.reason + '\n';
    }

    return str + "\n" + len + ' error' + ((len === 1) ? '' : 's');
  };

  // A light class for stubbing
  //
  function MethodCallExpectation(target, property){
    this.target = target;
    this.property = property;
  };

  MethodCallExpectation.prototype = {
    handleCall: function(){
      this.sawCall = true;
      return this.originalMethod.apply(this.target, arguments);
    },
    stubMethod: function(replacementFunc){
      var context = this,
          property = this.property;

      this.originalMethod = this.target[property];

      if (typeof replacementFunc === 'function') {
        this.target[property] = replacementFunc;
      } else {
        this.target[property] = function(){
          return context.handleCall.apply(context, arguments);
        };
      }
    },
    restoreMethod: function(){
      this.target[this.property] = this.originalMethod;
    },
    runWithStub: function(fn, replacementFunc){
      try {
        this.stubMethod(replacementFunc);
        fn();
      } finally {
        this.restoreMethod();
      }
    },
    assert: function() {
      this.runWithStub.apply(this, arguments);
      ok(this.sawCall, "Expected "+this.property+" to be called.");
    }
  };

  function AssertExpectation(message){
    MethodCallExpectation.call(this, Ember, 'assert');
    this.expectedMessage = message;
  };
  AssertExpectation.Error = function(){};
  AssertExpectation.prototype = Object.create(MethodCallExpectation.prototype);
  AssertExpectation.prototype.handleCall = function(message, test){
    this.sawCall = true;
    if (test) return; // Only get message for failures
    this.actualMessage = message;
    // Halt execution
    throw new AssertExpectation.Error();
  };
  AssertExpectation.prototype.assert = function(fn){
    try {
      this.runWithStub(fn);
    } catch (e) {
      if (!(e instanceof AssertExpectation.Error))
        throw e;
    }

    // Run assertions in an order that is useful when debugging a test failure.
    //
    if (!this.sawCall) {
      ok(false, "Expected Ember.assert to be called (Not called with any value).");
    } else if (!this.actualMessage) {
      ok(false, 'Expected a failing Ember.assert (Ember.assert called, but without a failing test).');
    } else {
      if (this.expectedMessage) {
        if (this.expectedMessage instanceof RegExp) {
          ok(this.expectedMessage.test(this.actualMessage), "Expected failing Ember.assert: '" + this.expectedMessage + "', but got '" + this.actualMessage + "'.");
        } else {
          equal(this.actualMessage, this.expectedMessage, "Expected failing Ember.assert: '" + this.expectedMessage + "', but got '" + this.actualMessage + "'.");
        }
      } else {
        // Positive assertion that assert was called
        ok(true, 'Expected a failing Ember.assert.');
      }
    }
  };

  // Looks for an exception raised within the fn.
  //
  // expectAssertion(function(){
  //   Ember.assert("Homie don't roll like that");
  // } /* , optionalMessageStringOrRegex */);
  //
  window.expectAssertion = function expectAssertion(fn, message){
    (new AssertExpectation(message)).assert(fn);
  };

  window.ignoreAssertion = function ignoreAssertion(fn){
    var stubber = new MethodCallExpectation(Ember, 'assert'),
        noop = function(){};

    stubber.runWithStub(fn, noop);
  };

  EmberDev.deprecations = {
    NONE: 99, // 99 problems and a deprecation ain't one
    expecteds: null,
    actuals: null,
    stubEmber: function(){
      if (!EmberDev.deprecations.originalEmberDeprecate && Ember.deprecate !== EmberDev.deprecations.originalEmberDeprecate) {
        EmberDev.deprecations.originalEmberDeprecate = Ember.deprecate;
      }
      Ember.deprecate = function(msg, test) {
        EmberDev.deprecations.actuals = EmberDev.deprecations.actuals || [];
        EmberDev.deprecations.actuals.push([msg, test]);
      };
    },
    restoreEmber: function(){
      Ember.deprecate = EmberDev.deprecations.originalEmberDeprecate;
    }
  };

  // Expects no deprecation to happen from the time of calling until
  // the end of the test.
  //
  // expectNoDeprecation(/* optionalStringOrRegex */);
  // Ember.deprecate("Old And Busted");
  //
  window.expectNoDeprecation = function(message) {
    if (typeof EmberDev.deprecations.expecteds === 'array') {
      throw("No deprecation was expected after expectDeprecation was called!");
    }
    EmberDev.deprecations.stubEmber();
    EmberDev.deprecations.expecteds = EmberDev.deprecations.NONE;
  };

  // Expect a deprecation to happen within a function, or if no function
  // is pass, from the time of calling until the end of the test. Can be called
  // multiple times to assert deprecations with different specific messages
  // were fired.
  //
  // expectDeprecation(function(){
  //   Ember.deprecate("Old And Busted");
  // }, /* optionalStringOrRegex */);
  //
  // expectDeprecation(/* optionalStringOrRegex */);
  // Ember.deprecate("Old And Busted");
  //
  window.expectDeprecation = function(fn, message) {
    if (EmberDev.deprecations.expecteds === EmberDev.deprecations.NONE) {
      throw("A deprecation was expected after expectNoDeprecation was called!");
    }
    EmberDev.deprecations.stubEmber();
    EmberDev.deprecations.expecteds = EmberDev.deprecations.expecteds || [];
    if (fn && typeof fn !== 'function') {
      // fn is a message
      EmberDev.deprecations.expecteds.push(fn);
    } else {
      EmberDev.deprecations.expecteds.push(message || /.*/);
      if (fn) {
        fn();
        window.assertDeprecation();
      }
    }
  };

  // Forces an assert the deprecations occurred, and resets the globals
  // storing asserts for the next run.
  //
  // expectNoDeprecation(/Old/);
  // setTimeout(function(){
  //   Ember.deprecate("Old And Busted");
  //   assertDeprecation();
  // });
  //
  // assertDeprecation is called after each test run to catch any expectations
  // without explicit asserts.
  //
  window.assertDeprecation = function() {
    var expecteds = EmberDev.deprecations.expecteds,
        actuals   = EmberDev.deprecations.actuals || [];
    if (!expecteds) {
      EmberDev.deprecations.actuals = null;
      return;
    }

    EmberDev.deprecations.restoreEmber();
    EmberDev.deprecations.actuals = null;
    EmberDev.deprecations.expecteds = null;

    if (expecteds === EmberDev.deprecations.NONE) {
      var actualMessages = [];
      for (var actual in actuals) {
        actualMessages.push(actual[0]);
      }
      ok(actuals.length === 0, "Expected no deprecation call, got: "+actualMessages.join(', '));
    } else {
      for (var o=0;o < expecteds.length; o++) {
        var expected = expecteds[o], match;
        for (var i=0;i < actuals.length; i++) {
          var actual = actuals[i];
          if (!actual[1]) {
            if (expected instanceof RegExp) {
              if (expected.test(actual[0])) {
                match = actual;
                break;
              }
            } else {
              if (expected === actual[0]) {
                match = actual;
                break;
              }
            }
          }
        }

        if (!actual)
          ok(false, "Recieved no deprecate calls at all, expecting: "+expected);
        else if (match && !match[1])
          ok(true, "Recieved failing deprecation with message: "+match[0]);
        else if (match && match[1])
          ok(false, "Expected failing deprecation, got succeeding with message: "+match[0]);
        else if (actual[1])
          ok(false, "Did not receive failing deprecation matching '"+expected+"', last was success with '"+actual[0]+"'");
        else if (!actual[1])
          ok(false, "Did not receive failing deprecation matching '"+expected+"', last was failure with '"+actual[0]+"'");
      }
    }
  };

})();
<commit_msg>Use polyfill for Object.create if not present.<commit_after>(function() {
  window.EmberDev = window.EmberDev || {};

  // hack qunit to not suck for Ember objects
  var originalTypeof = QUnit.jsDump.typeOf;

  QUnit.jsDump.typeOf = function(obj) {
    if (Ember && Ember.Object && Ember.Object.detectInstance(obj)) {
      return "emberObject";
    }

    return originalTypeof.call(this, obj);
  };

  QUnit.jsDump.parsers.emberObject = function(obj) {
    return obj.toString();
  };

  var originalModule = module;
  module = function(name, origOpts) {
    var opts = {};
    if (origOpts && origOpts.setup) { opts.setup = origOpts.setup; }
    opts.teardown = function() {
      if (origOpts && origOpts.teardown) { origOpts.teardown(); }

      if (Ember && Ember.run) {
        if (Ember.run.currentRunLoop) {
          ok(false, "Should not be in a run loop at end of test");
          while (Ember.run.currentRunLoop) {
            Ember.run.end();
          }
        }
        if (Ember.run.hasScheduledTimers()) {
          // Use `ok` so we get full description.
          // Gate inside of `if` so that we don't mess up `expects` counts
          ok(false, "Ember run should not have scheduled timers at end of test");
          Ember.run.cancelTimers();
        }
      }

      if (EmberDev.afterEach) {
        EmberDev.afterEach();
      }
    };
    return originalModule(name, opts);
  };

  // Tests should time out after 5 seconds
  QUnit.config.testTimeout = 5000;

  // Hide passed tests by default
  QUnit.config.hidepassed = true;

  // Handle JSHint
  QUnit.config.urlConfig.push('nojshint');

  EmberDev.jsHint = !QUnit.urlParams.nojshint;

  EmberDev.jsHintReporter = function (file, errors) {
    if (!errors) { return ''; }

    var len = errors.length,
        str = '',
        error, idx;

    if (len === 0) { return ''; }

    for (idx=0; idx<len; idx++) {
      error = errors[idx];
      str += file  + ': line ' + error.line + ', col ' +
          error.character + ', ' + error.reason + '\n';
    }

    return str + "\n" + len + ' error' + ((len === 1) ? '' : 's');
  };

  var o_create = Object.create || (function(){
    function F(){}

    return function(o) {
      if (arguments.length !== 1) {
        throw new Error('Object.create implementation only accepts one parameter.');
      }
      F.prototype = o;
      return new F();
    };
  }());

  // A light class for stubbing
  //
  function MethodCallExpectation(target, property){
    this.target = target;
    this.property = property;
  };

  MethodCallExpectation.prototype = {
    handleCall: function(){
      this.sawCall = true;
      return this.originalMethod.apply(this.target, arguments);
    },
    stubMethod: function(replacementFunc){
      var context = this,
          property = this.property;

      this.originalMethod = this.target[property];

      if (typeof replacementFunc === 'function') {
        this.target[property] = replacementFunc;
      } else {
        this.target[property] = function(){
          return context.handleCall.apply(context, arguments);
        };
      }
    },
    restoreMethod: function(){
      this.target[this.property] = this.originalMethod;
    },
    runWithStub: function(fn, replacementFunc){
      try {
        this.stubMethod(replacementFunc);
        fn();
      } finally {
        this.restoreMethod();
      }
    },
    assert: function() {
      this.runWithStub.apply(this, arguments);
      ok(this.sawCall, "Expected "+this.property+" to be called.");
    }
  };

  function AssertExpectation(message){
    MethodCallExpectation.call(this, Ember, 'assert');
    this.expectedMessage = message;
  };
  AssertExpectation.Error = function(){};
  AssertExpectation.prototype = o_create(MethodCallExpectation.prototype);
  AssertExpectation.prototype.handleCall = function(message, test){
    this.sawCall = true;
    if (test) return; // Only get message for failures
    this.actualMessage = message;
    // Halt execution
    throw new AssertExpectation.Error();
  };
  AssertExpectation.prototype.assert = function(fn){
    try {
      this.runWithStub(fn);
    } catch (e) {
      if (!(e instanceof AssertExpectation.Error))
        throw e;
    }

    // Run assertions in an order that is useful when debugging a test failure.
    //
    if (!this.sawCall) {
      ok(false, "Expected Ember.assert to be called (Not called with any value).");
    } else if (!this.actualMessage) {
      ok(false, 'Expected a failing Ember.assert (Ember.assert called, but without a failing test).');
    } else {
      if (this.expectedMessage) {
        if (this.expectedMessage instanceof RegExp) {
          ok(this.expectedMessage.test(this.actualMessage), "Expected failing Ember.assert: '" + this.expectedMessage + "', but got '" + this.actualMessage + "'.");
        } else {
          equal(this.actualMessage, this.expectedMessage, "Expected failing Ember.assert: '" + this.expectedMessage + "', but got '" + this.actualMessage + "'.");
        }
      } else {
        // Positive assertion that assert was called
        ok(true, 'Expected a failing Ember.assert.');
      }
    }
  };

  // Looks for an exception raised within the fn.
  //
  // expectAssertion(function(){
  //   Ember.assert("Homie don't roll like that");
  // } /* , optionalMessageStringOrRegex */);
  //
  window.expectAssertion = function expectAssertion(fn, message){
    (new AssertExpectation(message)).assert(fn);
  };

  window.ignoreAssertion = function ignoreAssertion(fn){
    var stubber = new MethodCallExpectation(Ember, 'assert'),
        noop = function(){};

    stubber.runWithStub(fn, noop);
  };

  EmberDev.deprecations = {
    NONE: 99, // 99 problems and a deprecation ain't one
    expecteds: null,
    actuals: null,
    stubEmber: function(){
      if (!EmberDev.deprecations.originalEmberDeprecate && Ember.deprecate !== EmberDev.deprecations.originalEmberDeprecate) {
        EmberDev.deprecations.originalEmberDeprecate = Ember.deprecate;
      }
      Ember.deprecate = function(msg, test) {
        EmberDev.deprecations.actuals = EmberDev.deprecations.actuals || [];
        EmberDev.deprecations.actuals.push([msg, test]);
      };
    },
    restoreEmber: function(){
      Ember.deprecate = EmberDev.deprecations.originalEmberDeprecate;
    }
  };

  // Expects no deprecation to happen from the time of calling until
  // the end of the test.
  //
  // expectNoDeprecation(/* optionalStringOrRegex */);
  // Ember.deprecate("Old And Busted");
  //
  window.expectNoDeprecation = function(message) {
    if (typeof EmberDev.deprecations.expecteds === 'array') {
      throw("No deprecation was expected after expectDeprecation was called!");
    }
    EmberDev.deprecations.stubEmber();
    EmberDev.deprecations.expecteds = EmberDev.deprecations.NONE;
  };

  // Expect a deprecation to happen within a function, or if no function
  // is pass, from the time of calling until the end of the test. Can be called
  // multiple times to assert deprecations with different specific messages
  // were fired.
  //
  // expectDeprecation(function(){
  //   Ember.deprecate("Old And Busted");
  // }, /* optionalStringOrRegex */);
  //
  // expectDeprecation(/* optionalStringOrRegex */);
  // Ember.deprecate("Old And Busted");
  //
  window.expectDeprecation = function(fn, message) {
    if (EmberDev.deprecations.expecteds === EmberDev.deprecations.NONE) {
      throw("A deprecation was expected after expectNoDeprecation was called!");
    }
    EmberDev.deprecations.stubEmber();
    EmberDev.deprecations.expecteds = EmberDev.deprecations.expecteds || [];
    if (fn && typeof fn !== 'function') {
      // fn is a message
      EmberDev.deprecations.expecteds.push(fn);
    } else {
      EmberDev.deprecations.expecteds.push(message || /.*/);
      if (fn) {
        fn();
        window.assertDeprecation();
      }
    }
  };

  // Forces an assert the deprecations occurred, and resets the globals
  // storing asserts for the next run.
  //
  // expectNoDeprecation(/Old/);
  // setTimeout(function(){
  //   Ember.deprecate("Old And Busted");
  //   assertDeprecation();
  // });
  //
  // assertDeprecation is called after each test run to catch any expectations
  // without explicit asserts.
  //
  window.assertDeprecation = function() {
    var expecteds = EmberDev.deprecations.expecteds,
        actuals   = EmberDev.deprecations.actuals || [];
    if (!expecteds) {
      EmberDev.deprecations.actuals = null;
      return;
    }

    EmberDev.deprecations.restoreEmber();
    EmberDev.deprecations.actuals = null;
    EmberDev.deprecations.expecteds = null;

    if (expecteds === EmberDev.deprecations.NONE) {
      var actualMessages = [];
      for (var actual in actuals) {
        actualMessages.push(actual[0]);
      }
      ok(actuals.length === 0, "Expected no deprecation call, got: "+actualMessages.join(', '));
    } else {
      for (var o=0;o < expecteds.length; o++) {
        var expected = expecteds[o], match;
        for (var i=0;i < actuals.length; i++) {
          var actual = actuals[i];
          if (!actual[1]) {
            if (expected instanceof RegExp) {
              if (expected.test(actual[0])) {
                match = actual;
                break;
              }
            } else {
              if (expected === actual[0]) {
                match = actual;
                break;
              }
            }
          }
        }

        if (!actual)
          ok(false, "Recieved no deprecate calls at all, expecting: "+expected);
        else if (match && !match[1])
          ok(true, "Recieved failing deprecation with message: "+match[0]);
        else if (match && match[1])
          ok(false, "Expected failing deprecation, got succeeding with message: "+match[0]);
        else if (actual[1])
          ok(false, "Did not receive failing deprecation matching '"+expected+"', last was success with '"+actual[0]+"'");
        else if (!actual[1])
          ok(false, "Did not receive failing deprecation matching '"+expected+"', last was failure with '"+actual[0]+"'");
      }
    }
  };

})();
<|endoftext|>


<commit_before>enchant();

//TODO: 拡張性に乏しい 取り敢えず配列で持たせておくのがベターらしい
var text = new Array(
    "HP : 1",
    "HP : 2",
    "HP : 3",
    "HP : 4",
    "HP : 5");

var BATTLE_BGM = './bgm/BATTLE_cyrf_energy.mp3';
var PLAYER_IMG = './img/player.png';

/** エフェクトの位置のバラ付き具合 */
var EFFECT_RANGE = 64;
/** 一回のタップで発生するエフェクトの数 */
var EFFECT_NUM = 5;

window.onload = function () {
    var game = new Game(800, 600);
    game.fps = 30;
    game.preload([BATTLE_BGM,PLAYER_IMG]);

    var gameOverScene = new Scene();
    var Easing = enchant.Easing;

    //Function:csvファイルをArray[][] の形に変換して出力
    //TODO:戦闘の度に逐一csvファイルを読み込んでいたら重いかもしれない．
    //ベストプラクティスがあるかも
    function csv2Array(filePath) { //csvﾌｧｲﾙﾉ相対ﾊﾟｽor絶対ﾊﾟｽ
        var csvData = new Array();
        var data = new XMLHttpRequest();
        data.open("GET", filePath, false); //true:非同期,false:同期
        data.send(null);

        var LF = String.fromCharCode(10); //改行ｺｰﾄﾞ
        var lines = data.responseText.split(LF);
        for (var i = 0; i < lines.length;++i) {
            var cells = lines[i].split(",");
            if( cells.length != 1 ) {
                csvData.push(cells);
            }
        }
        return csvData;
    }

    //Function:解答のチェック
    function isAnswer(playerAnswer,loadAnswer,hp,status) {
        var isAnswer = false;
        if (playerAnswer == loadAnswer) {
            isAnswer = true;
            return isAnswer;
        }
        else{
            hp--;
            if(hp < 0){
                gameOver();
            }else{
                status.text = text[hp];
            }
            return isAnswer;
        }
    }

    //Function:hpが0になったらゲームオーバーシーンに遷移
    function gameOver() {
        var label = new Label();
        label.x = 250;
        label.y = 200;
        label.color = 'red';
        label.font = '48px "Arial"';

        var msg = 'Game Over !!!
';
        label.text = msg;

        gameOverScene.backgroundColor = 'black';
        gameOverScene.addChild(label);
        game.pushScene(gameOverScene);
        game.stop();
    }

    /** 単体エフェクト作成 */
    function makeSingleEffect(delay) {
        var easing = Easing.SIN_EASEOUT; // イージングの種類.
        var sprite = new Sprite(100, 100);
        sprite.scaleX = 0.0;
        sprite.scaleY = 0.0;
        sprite.visible = false; // 最初は非表示.
        // エフェクトの動作設定.
        sprite.tl
            .delay(delay) // 指定時間待つ.
            .then(function() { sprite.visible = true; }) // ここで表示.
            .scaleTo(1.0, game.fps * 0.1, easing)
            .scaleTo(0.5, game.fps * 0.1, easing)
            .scaleTo(2.0, game.fps * 1, easing)
            .and().fadeOut(game.fps * 1, easing)
            .then(function() { sprite.tl.removeFromScene(); });
        return sprite;
    }

    /** ランダムな色を作成 */
    function makeRandomColor() {
        var r = 128 + Math.ceil(Math.random() * 128);
        var g = 128 + Math.ceil(Math.random() * 128);
        var b = 128 + Math.ceil(Math.random() * 128);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }

    /** 指定位置の付近に複数エフェクトを追加 */
    function addEffect(scene, x, y) {
        for (var i = 0, iNum = EFFECT_NUM; i < iNum; ++i) {
            var sprite = makeSingleEffect(i * game.fps * 0.1);
            sprite.backgroundColor = makeRandomColor();
            sprite.x = x - (sprite.width / 2) + Math.random() * EFFECT_RANGE - (EFFECT_RANGE / 2);
            sprite.y = y - (sprite.height / 2) + Math.random() * EFFECT_RANGE - (EFFECT_RANGE / 2);
            scene.addChild(sprite);
        }
    }

    function attackEffect(scene){
        addEffect(scene, 400, 300);
    }
    function damageEffect(scene){
        addEffect(scene, 400, 300);
    }

    game.onload = function () {
        var scene = new Scene();
        var backGround = new Sprite(800,600);
        game.rootScene.addChild(backGround);
        game.score = 10;

        var sound = game.assets[BATTLE_BGM].play();

        var userHp = "HP : ";
        var hp = 4;
        userHp.font = "16px Tahoma";

        var status = new Label();
        status.text = text[hp];
        scene.addChild(status);

        var player = new Sprite(100,100);
        player.image = game.assets[PLAYER_IMG];

        var question = new Sprite(500, 100);
        question.backgroundColor = "rgba(200, 255, 200, 0.5)";
        question.x = 100;
        question.y = 0;

        var enemy = new Sprite(800,400);
        enemy.backgroundColor = "rgba(200, 200, 200, 0.5)";
        enemy.y = 100;

        var selectA = new Select("A");

        var selectB = new Select("B");

        var selectC = new Select("C");

        var selectD = new Select("D");

        scene.addChild(player);
        scene.addChild(enemy);
        scene.addChild(question);
        scene.addChild(selectA);
        scene.addChild(selectB);
        scene.addChild(selectC);
        scene.addChild(selectD);
        game.pushScene(scene);

        //TODO: loadAnswerははじめにCSVファイルで読み込む．
        var loadAnswer = "A";
        selectA.addEventListener('touchstart', function() {
            var playerAnswer = "A";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });

        selectB.addEventListener('touchstart', function() {
            var playerAnswer = "B";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });
        selectC.addEventListener('touchstart', function() {
            var playerAnswer = "C";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });
        selectD.addEventListener('touchstart', function() {
            var playerAnswer = "D";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });
    };

    game.start();

    /* Class */

    var Select = Class.create(Sprite, {
        initialize:function(arg){
            if(arg == "A"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.backgroundColor = "rgba(150, 150, 150, 0.5)";
                this.x = 0;
                this.y = 500;
            }
            else if(arg == "B"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.backgroundColor = "rgba(100, 100, 100, 0.5)";
                this.x = 200;
                this.y = 500;
            }
            else if(arg == "C"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.backgroundColor = "rgba(50, 50, 50, 0.5)";
                this.x = 400;
                this.y = 500;
            }
            else if(arg == "D"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.x = 600;
                this.y = 500;
            }
            game.rootScene.addChild(this);
        }
    });
}
<commit_msg>主要な変数のクラス化<commit_after>enchant();

//TODO: 拡張性に乏しい 取り敢えず配列で持たせておくのがベターらしい
var text = new Array(
    "HP : 1",
    "HP : 2",
    "HP : 3",
    "HP : 4",
    "HP : 5");

var BATTLE_BGM = './bgm/BATTLE_cyrf_energy.mp3';
var PLAYER_IMG = './img/player.png';

/** エフェクトの位置のバラ付き具合 */
var EFFECT_RANGE = 64;
/** 一回のタップで発生するエフェクトの数 */
var EFFECT_NUM = 5;

window.onload = function () {
    var game = new Game(800, 600);
    game.fps = 30;
    game.preload([BATTLE_BGM,PLAYER_IMG]);

    var gameOverScene = new Scene();
    var Easing = enchant.Easing;

    //Function:csvファイルをArray[][] の形に変換して出力
    //TODO:戦闘の度に逐一csvファイルを読み込んでいたら重いかもしれない．
    //ベストプラクティスがあるかも
    function csv2Array(filePath) { //csvﾌｧｲﾙﾉ相対ﾊﾟｽor絶対ﾊﾟｽ
        var csvData = new Array();
        var data = new XMLHttpRequest();
        data.open("GET", filePath, false); //true:非同期,false:同期
        data.send(null);

        var LF = String.fromCharCode(10); //改行ｺｰﾄﾞ
        var lines = data.responseText.split(LF);
        for (var i = 0; i < lines.length;++i) {
            var cells = lines[i].split(",");
            if( cells.length != 1 ) {
                csvData.push(cells);
            }
        }
        return csvData;
    }

    //Function:解答のチェック
    function isAnswer(playerAnswer,loadAnswer,hp,status) {
        var isAnswer = false;
        if (playerAnswer == loadAnswer) {
            isAnswer = true;
            return isAnswer;
        }
        else{
            hp--;
            if(hp < 0){
                gameOver();
            }else{
                status.text = text[hp];
            }
            return isAnswer;
        }
    }

    //Function:hpが0になったらゲームオーバーシーンに遷移
    function gameOver() {
        var label = new Label();
        label.x = 250;
        label.y = 200;
        label.color = 'red';
        label.font = '48px "Arial"';

        var msg = 'Game Over !!!
';
        label.text = msg;

        gameOverScene.backgroundColor = 'black';
        gameOverScene.addChild(label);
        game.pushScene(gameOverScene);
        game.stop();
    }

    /** 単体エフェクト作成 */
    function makeSingleEffect(delay) {
        var easing = Easing.SIN_EASEOUT; // イージングの種類.
        var sprite = new Sprite(100, 100);
        sprite.scaleX = 0.0;
        sprite.scaleY = 0.0;
        sprite.visible = false; // 最初は非表示.
        // エフェクトの動作設定.
        sprite.tl
            .delay(delay) // 指定時間待つ.
            .then(function() { sprite.visible = true; }) // ここで表示.
            .scaleTo(1.0, game.fps * 0.1, easing)
            .scaleTo(0.5, game.fps * 0.1, easing)
            .scaleTo(2.0, game.fps * 1, easing)
            .and().fadeOut(game.fps * 1, easing)
            .then(function() { sprite.tl.removeFromScene(); });
        return sprite;
    }

    /** ランダムな色を作成 */
    function makeRandomColor() {
        var r = 128 + Math.ceil(Math.random() * 128);
        var g = 128 + Math.ceil(Math.random() * 128);
        var b = 128 + Math.ceil(Math.random() * 128);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }

    /** 指定位置の付近に複数エフェクトを追加 */
    function addEffect(scene, x, y) {
        for (var i = 0, iNum = EFFECT_NUM; i < iNum; ++i) {
            var sprite = makeSingleEffect(i * game.fps * 0.1);
            sprite.backgroundColor = makeRandomColor();
            sprite.x = x - (sprite.width / 2) + Math.random() * EFFECT_RANGE - (EFFECT_RANGE / 2);
            sprite.y = y - (sprite.height / 2) + Math.random() * EFFECT_RANGE - (EFFECT_RANGE / 2);
            scene.addChild(sprite);
        }
    }

    function attackEffect(scene){
        addEffect(scene, 400, 300);
    }
    function damageEffect(scene){
        addEffect(scene, 400, 300);
    }

    game.onload = function () {
        var scene = new Scene();
        var backGround = new Sprite(800,600);
        game.rootScene.addChild(backGround);

        var battleSound = game.assets[BATTLE_BGM].play();

        var userHp = "HP : ";
        var hp = 4;
        userHp.font = "16px Tahoma";

        var status = new Label();
        status.text = text[hp];
        scene.addChild(status);

        var player = new Player();
        var enemy = new Enemy();
        var question = new Question();
        var selectA = new Select("A");
        var selectB = new Select("B");
        var selectC = new Select("C");
        var selectD = new Select("D");

        scene.addChild(player);
        scene.addChild(enemy);
        scene.addChild(question);
        scene.addChild(selectA);
        scene.addChild(selectB);
        scene.addChild(selectC);
        scene.addChild(selectD);
        game.pushScene(scene);

        //TODO: loadAnswerははじめにCSVファイルで読み込む．
        var loadAnswer = "A";
        selectA.addEventListener('touchstart', function() {
            var playerAnswer = "A";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });

        selectB.addEventListener('touchstart', function() {
            var playerAnswer = "B";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });
        selectC.addEventListener('touchstart', function() {
            var playerAnswer = "C";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });
        selectD.addEventListener('touchstart', function() {
            var playerAnswer = "D";
            if(isAnswer(playerAnswer,loadAnswer,hp,status)){
                attackEffect(scene);
            }else{
                hp--;
                damageEffect(scene);
            }
        });
    };

    game.start();

    /* Class */
    var Player = Class.create(Sprite,{
        initialize:function(){
            Sprite.call(this,100,100);
            this.image = game.assets[PLAYER_IMG];
            this.x = 0;
            this.y = 0;
            game.rootScene.addChild(this);
        }
    });

    var Enemy = Class.create(Sprite,{
        initialize:function(){
            Sprite.call(this,800,400);
            this.backgroundColor = "rgba(200, 200, 200, 0.5)";
            this.x = 0;
            this.y = 100;
            game.rootScene.addChild(this);
        }
    });

    var Question = Class.create(Sprite, {
        initialize:function(){
            Sprite.call(this,700,100);
            this.image = game.assets[PLAYER_IMG];
            this.backgroundColor = "rgba(200, 255, 200, 0.5)";
            this.x = 100;
            this.y = 0;
            game.rootScene.addChild(this);
        }
    });

    var Select = Class.create(Sprite, {
        initialize:function(arg){
            if(arg == "A"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.backgroundColor = "rgba(150, 150, 150, 0.5)";
                this.x = 0;
                this.y = 500;
            }
            else if(arg == "B"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.backgroundColor = "rgba(100, 100, 100, 0.5)";
                this.x = 200;
                this.y = 500;
            }
            else if(arg == "C"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.backgroundColor = "rgba(50, 50, 50, 0.5)";
                this.x = 400;
                this.y = 500;
            }
            else if(arg == "D"){
                Sprite.call(this,200,100);
                this.image = game.assets[PLAYER_IMG];
                this.x = 600;
                this.y = 500;
            }
            game.rootScene.addChild(this);
        }
    });
}
<|endoftext|>


<commit_before>"use strict";

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange')
const { ExchangeError, InsufficientFunds, OrderNotFound, DDoSProtection } = require ('./base/errors')

//  ---------------------------------------------------------------------------

module.exports = class bitbay extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitbay',
            'name': 'BitBay',
            'countries': [ 'PL', 'EU' ], // Poland
            'rateLimit': 1000,
            'hasCORS': true,
            'hasWithdraw': true,
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/27766132-978a7bd8-5ece-11e7-9540-bc96d1e9bbb8.jpg',
                'www': 'https://bitbay.net',
                'api': {
                    'public': 'https://bitbay.net/API/Public',
                    'private': 'https://bitbay.net/API/Trading/tradingApi.php',
                },
                'doc': [
                    'https://bitbay.net/public-api',
                    'https://bitbay.net/account/tab-api',
                    'https://github.com/BitBayNet/API',
                ],
            },
            'api': {
                'public': {
                    'get': [
                        '{id}/all',
                        '{id}/market',
                        '{id}/orderbook',
                        '{id}/ticker',
                        '{id}/trades',
                    ],
                },
                'private': {
                    'post': [
                        'info',
                        'trade',
                        'cancel',
                        'orderbook',
                        'orders',
                        'transfer',
                        'withdraw',
                        'history',
                        'transactions',
                    ],
                },
            },
            'markets': {
                'BTC/USD': { 'id': 'BTCUSD', 'symbol': 'BTC/USD', 'base': 'BTC', 'quote': 'USD' },
                'BTC/EUR': { 'id': 'BTCEUR', 'symbol': 'BTC/EUR', 'base': 'BTC', 'quote': 'EUR' },
                'BTC/PLN': { 'id': 'BTCPLN', 'symbol': 'BTC/PLN', 'base': 'BTC', 'quote': 'PLN' },
                'LTC/USD': { 'id': 'LTCUSD', 'symbol': 'LTC/USD', 'base': 'LTC', 'quote': 'USD' },
                'LTC/EUR': { 'id': 'LTCEUR', 'symbol': 'LTC/EUR', 'base': 'LTC', 'quote': 'EUR' },
                'LTC/PLN': { 'id': 'LTCPLN', 'symbol': 'LTC/PLN', 'base': 'LTC', 'quote': 'PLN' },
                'LTC/BTC': { 'id': 'LTCBTC', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC' },
                'ETH/USD': { 'id': 'ETHUSD', 'symbol': 'ETH/USD', 'base': 'ETH', 'quote': 'USD' },
                'ETH/EUR': { 'id': 'ETHEUR', 'symbol': 'ETH/EUR', 'base': 'ETH', 'quote': 'EUR' },
                'ETH/PLN': { 'id': 'ETHPLN', 'symbol': 'ETH/PLN', 'base': 'ETH', 'quote': 'PLN' },
                'ETH/BTC': { 'id': 'ETHBTC', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC' },
                'LSK/USD': { 'id': 'LSKUSD', 'symbol': 'LSK/USD', 'base': 'LSK', 'quote': 'USD' },
                'LSK/EUR': { 'id': 'LSKEUR', 'symbol': 'LSK/EUR', 'base': 'LSK', 'quote': 'EUR' },
                'LSK/PLN': { 'id': 'LSKPLN', 'symbol': 'LSK/PLN', 'base': 'LSK', 'quote': 'PLN' },
                'LSK/BTC': { 'id': 'LSKBTC', 'symbol': 'LSK/BTC', 'base': 'LSK', 'quote': 'BTC' },
            },
        });
    }

    async fetchBalance (params = {}) {
        let response = await this.privatePostInfo ();
        if ('balances' in response) {
            let balance = response['balances'];
            let result = { 'info': balance };
            for (let c = 0; c < this.currencies.length; c++) {
                let currency = this.currencies[c];
                let account = this.account ();
                if (currency in balance) {
                    account['free'] = parseFloat (balance[currency]['available']);
                    account['used'] = parseFloat (balance[currency]['locked']);
                    account['total'] = this.sum (account['free'], account['used']);
                }
                result[currency] = account;
            }
            return this.parseBalance (result);
        }
        throw new ExchangeError (this.id + ' empty balance response ' + this.json (response));
    }

    async fetchOrderBook (symbol, params = {}) {
        let orderbook = await this.publicGetIdOrderbook (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook);
    }

    async fetchTicker (symbol, params = {}) {
        let ticker = await this.publicGetIdTicker (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        let timestamp = this.milliseconds ();
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': parseFloat (ticker['max']),
            'low': parseFloat (ticker['min']),
            'bid': parseFloat (ticker['bid']),
            'ask': parseFloat (ticker['ask']),
            'vwap': parseFloat (ticker['vwap']),
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': parseFloat (ticker['last']),
            'change': undefined,
            'percentage': undefined,
            'average': parseFloat (ticker['average']),
            'baseVolume': undefined,
            'quoteVolume': parseFloat (ticker['volume']),
            'info': ticker,
        };
    }

    parseTrade (trade, market) {
        let timestamp = trade['date'] * 1000;
        return {
            'id': trade['tid'],
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['type'],
            'price': trade['price'],
            'amount': trade['amount'],
        };
    }

    async fetchTrades (symbol, params = {}) {
        let market = this.market (symbol);
        let response = await this.publicGetIdTrades (this.extend ({
            'id': market['id'],
        }, params));
        return this.parseTrades (response, market);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        let market = this.market (symbol);
        return this.privatePostTrade (this.extend ({
            'type': side,
            'currency': market['base'],
            'amount': amount,
            'payment_currency': market['quote'],
            'rate': price,
        }, params));
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        return await this.privatePostCancel ({ 'id': id });
    }

    isFiat (currency) {
        let fiatCurrencies = {
            'USD': true,
            'EUR': true,
            'PLN': true,
        };
        if (currency in fiatCurrencies)
            return true;
        return false;
    }

    async withdraw (currency, amount, address, params = {}) {
        await this.loadMarkets ();
        let method = undefined;
        let request = {
            'currency': currency,
            'quantity': amount,
        };
        if (this.isFiat (currency)) {
            method = 'privatePostWithdraw';
            // request['account'] = params['account']; // they demand an account number
            // request['express'] = params['express']; // whatever it means, they don't explain
            // request['bic'] = '';
        } else {
            method = 'privatePostTransfer';
            request['address'] = address;
        }
        let response = await this[method] (this.extend (request, params));
        return {
            'info': response,
            'id': undefined,
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api];
        if (api == 'public') {
            url += '/' + this.implodeParams (path, params) + '.json';
        } else {
            body = this.urlencode (this.extend ({
                'method': path,
                'moment': this.nonce (),
            }, params));
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
                'API-Key': this.apiKey,
                'API-Hash': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'),
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
}<commit_msg>bitbay parseTicker() parseFloat → this.safeFloat<commit_after>"use strict";

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange')
const { ExchangeError, InsufficientFunds, OrderNotFound, DDoSProtection } = require ('./base/errors')

//  ---------------------------------------------------------------------------

module.exports = class bitbay extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitbay',
            'name': 'BitBay',
            'countries': [ 'PL', 'EU' ], // Poland
            'rateLimit': 1000,
            'hasCORS': true,
            'hasWithdraw': true,
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/27766132-978a7bd8-5ece-11e7-9540-bc96d1e9bbb8.jpg',
                'www': 'https://bitbay.net',
                'api': {
                    'public': 'https://bitbay.net/API/Public',
                    'private': 'https://bitbay.net/API/Trading/tradingApi.php',
                },
                'doc': [
                    'https://bitbay.net/public-api',
                    'https://bitbay.net/account/tab-api',
                    'https://github.com/BitBayNet/API',
                ],
            },
            'api': {
                'public': {
                    'get': [
                        '{id}/all',
                        '{id}/market',
                        '{id}/orderbook',
                        '{id}/ticker',
                        '{id}/trades',
                    ],
                },
                'private': {
                    'post': [
                        'info',
                        'trade',
                        'cancel',
                        'orderbook',
                        'orders',
                        'transfer',
                        'withdraw',
                        'history',
                        'transactions',
                    ],
                },
            },
            'markets': {
                'BTC/USD': { 'id': 'BTCUSD', 'symbol': 'BTC/USD', 'base': 'BTC', 'quote': 'USD' },
                'BTC/EUR': { 'id': 'BTCEUR', 'symbol': 'BTC/EUR', 'base': 'BTC', 'quote': 'EUR' },
                'BTC/PLN': { 'id': 'BTCPLN', 'symbol': 'BTC/PLN', 'base': 'BTC', 'quote': 'PLN' },
                'LTC/USD': { 'id': 'LTCUSD', 'symbol': 'LTC/USD', 'base': 'LTC', 'quote': 'USD' },
                'LTC/EUR': { 'id': 'LTCEUR', 'symbol': 'LTC/EUR', 'base': 'LTC', 'quote': 'EUR' },
                'LTC/PLN': { 'id': 'LTCPLN', 'symbol': 'LTC/PLN', 'base': 'LTC', 'quote': 'PLN' },
                'LTC/BTC': { 'id': 'LTCBTC', 'symbol': 'LTC/BTC', 'base': 'LTC', 'quote': 'BTC' },
                'ETH/USD': { 'id': 'ETHUSD', 'symbol': 'ETH/USD', 'base': 'ETH', 'quote': 'USD' },
                'ETH/EUR': { 'id': 'ETHEUR', 'symbol': 'ETH/EUR', 'base': 'ETH', 'quote': 'EUR' },
                'ETH/PLN': { 'id': 'ETHPLN', 'symbol': 'ETH/PLN', 'base': 'ETH', 'quote': 'PLN' },
                'ETH/BTC': { 'id': 'ETHBTC', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC' },
                'LSK/USD': { 'id': 'LSKUSD', 'symbol': 'LSK/USD', 'base': 'LSK', 'quote': 'USD' },
                'LSK/EUR': { 'id': 'LSKEUR', 'symbol': 'LSK/EUR', 'base': 'LSK', 'quote': 'EUR' },
                'LSK/PLN': { 'id': 'LSKPLN', 'symbol': 'LSK/PLN', 'base': 'LSK', 'quote': 'PLN' },
                'LSK/BTC': { 'id': 'LSKBTC', 'symbol': 'LSK/BTC', 'base': 'LSK', 'quote': 'BTC' },
            },
        });
    }

    async fetchBalance (params = {}) {
        let response = await this.privatePostInfo ();
        if ('balances' in response) {
            let balance = response['balances'];
            let result = { 'info': balance };
            for (let c = 0; c < this.currencies.length; c++) {
                let currency = this.currencies[c];
                let account = this.account ();
                if (currency in balance) {
                    account['free'] = parseFloat (balance[currency]['available']);
                    account['used'] = parseFloat (balance[currency]['locked']);
                    account['total'] = this.sum (account['free'], account['used']);
                }
                result[currency] = account;
            }
            return this.parseBalance (result);
        }
        throw new ExchangeError (this.id + ' empty balance response ' + this.json (response));
    }

    async fetchOrderBook (symbol, params = {}) {
        let orderbook = await this.publicGetIdOrderbook (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook);
    }

    async fetchTicker (symbol, params = {}) {
        let ticker = await this.publicGetIdTicker (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        let timestamp = this.milliseconds ();
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'max'),
            'low': this.safeFloat (ticker, 'min'),
            'bid': this.safeFloat (ticker, 'bid'),
            'ask': this.safeFloat (ticker, 'ask'),
            'vwap': this.safeFloat (ticker, 'vwap'),
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': this.safeFloat (ticker, 'last'),
            'change': undefined,
            'percentage': undefined,
            'average': this.safeFloat (ticker, 'average'),
            'baseVolume': undefined,
            'quoteVolume': this.safeFloat (ticker, 'volume'),
            'info': ticker,
        };
    }

    parseTrade (trade, market) {
        let timestamp = trade['date'] * 1000;
        return {
            'id': trade['tid'],
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['type'],
            'price': trade['price'],
            'amount': trade['amount'],
        };
    }

    async fetchTrades (symbol, params = {}) {
        let market = this.market (symbol);
        let response = await this.publicGetIdTrades (this.extend ({
            'id': market['id'],
        }, params));
        return this.parseTrades (response, market);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        let market = this.market (symbol);
        return this.privatePostTrade (this.extend ({
            'type': side,
            'currency': market['base'],
            'amount': amount,
            'payment_currency': market['quote'],
            'rate': price,
        }, params));
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        return await this.privatePostCancel ({ 'id': id });
    }

    isFiat (currency) {
        let fiatCurrencies = {
            'USD': true,
            'EUR': true,
            'PLN': true,
        };
        if (currency in fiatCurrencies)
            return true;
        return false;
    }

    async withdraw (currency, amount, address, params = {}) {
        await this.loadMarkets ();
        let method = undefined;
        let request = {
            'currency': currency,
            'quantity': amount,
        };
        if (this.isFiat (currency)) {
            method = 'privatePostWithdraw';
            // request['account'] = params['account']; // they demand an account number
            // request['express'] = params['express']; // whatever it means, they don't explain
            // request['bic'] = '';
        } else {
            method = 'privatePostTransfer';
            request['address'] = address;
        }
        let response = await this[method] (this.extend (request, params));
        return {
            'info': response,
            'id': undefined,
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api];
        if (api == 'public') {
            url += '/' + this.implodeParams (path, params) + '.json';
        } else {
            body = this.urlencode (this.extend ({
                'method': path,
                'moment': this.nonce (),
            }, params));
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
                'API-Key': this.apiKey,
                'API-Hash': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'),
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
}<|endoftext|>


<commit_before>(function() {
  var out$ = typeof exports != 'undefined' && exports || this;

  var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';

  function isExternal(url) {
    return url && url.lastIndexOf('http',0) == 0 && url.lastIndexOf(window.location.host) == -1;
  }

  function inlineImages(el, callback) {
    var images = el.querySelectorAll('image');
    var left = images.length;
    if (left == 0) {
      callback();
    }
    for (var i = 0; i < images.length; i++) {
      (function(image) {
        var href = image.getAttributeNS("http://www.w3.org/1999/xlink", "href");
        if (href) {
          if (isExternal(href.value)) {
            console.warn("Cannot render embedded images linking to external hosts: "+href.value);
            return;
          }
        }
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var img = new Image();
        href = href || image.getAttribute('href');
        img.src = href;
        img.onload = function() {
          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(img, 0, 0);
          image.setAttributeNS("http://www.w3.org/1999/xlink", "href", canvas.toDataURL('image/png'));
          left--;
          if (left == 0) {
            callback();
          }
        }
        img.onerror = function() {
          console.log("Could not load "+href);
          left--;
          if (left == 0) {
            callback();
          }
        }
      })(images[i]);
    }
  }

  function styles(el, selectorRemap) {
    var css = "";
    var sheets = document.styleSheets;
    for (var i = 0; i < sheets.length; i++) {
      try {
        var rules = sheets[i].cssRules;
      } catch (e) {
        console.warn("Stylesheet could not be loaded: "+sheets[i].href);
        continue;
      }

      if (rules != null) {
        for (var j = 0; j < rules.length; j++) {
          var rule = rules[j];
          if (typeof(rule.style) != "undefined") {
            var match = null;
            try {
              match = el.querySelector(rule.selectorText);
            } catch(err) {
              console.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
            }
            if (match) {
              var selector = selectorRemap ? selectorRemap(rule.selectorText) : rule.selectorText;
              css += selector + " { " + rule.style.cssText + " }\n";
            } else if(rule.cssText.match(/^@font-face/)) {
              css += rule.cssText + '\n';
            }
          }
        }
      }
    }
    return css;
  }

  function getDimension(el, clone, dim) {
    var v = (el.viewBox.baseVal && el.viewBox.baseVal[dim]) ||
      (clone.getAttribute(dim) !== null && !clone.getAttribute(dim).match(/%$/) && parseInt(clone.getAttribute(dim))) ||
      el.getBoundingClientRect()[dim] ||
      parseInt(clone.style[dim]) ||
      parseInt(window.getComputedStyle(el).getPropertyValue(dim));
    return (typeof v === 'undefined' || v === null || isNaN(parseFloat(v))) ? 0 : v;
  }

  function reEncode(data) {
    data = encodeURIComponent(data);
    data = data.replace(/%([0-9A-F]{2})/g, function(match, p1) {
      var c = String.fromCharCode('0x'+p1);
      return c === '%' ? '%25' : c;
    });
    return decodeURIComponent(data);
  }

  out$.svgAsDataUri = function(el, options, cb) {
    options = options || {};
    options.scale = options.scale || 1;
    var xmlns = "http://www.w3.org/2000/xmlns/";

    inlineImages(el, function() {
      var outer = document.createElement("div");
      var clone = el.cloneNode(true);
      var width, height;
      if(el.tagName == 'svg') {
        width = options.width || getDimension(el, clone, 'width');
        height = options.height || getDimension(el, clone, 'height');
      } else if(el.getBBox) {
        var box = el.getBBox();
        width = box.x + box.width;
        height = box.y + box.height;
        clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, ''));

        var svg = document.createElementNS('http://www.w3.org/2000/svg','svg')
        svg.appendChild(clone)
        clone = svg;
      } else {
        console.error('Attempted to render non-SVG element', el);
        return;
      }

      clone.setAttribute("version", "1.1");
      clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg");
      clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink");
      clone.setAttribute("width", width * options.scale);
      clone.setAttribute("height", height * options.scale);
      clone.setAttribute("viewBox", [
        options.left || 0,
        options.top || 0,
        width,
        height
      ].join(" "));

      outer.appendChild(clone);

      var css = styles(el, options.selectorRemap);
      var s = document.createElement('style');
      s.setAttribute('type', 'text/css');
      s.innerHTML = "<![CDATA[\n" + css + "\n]]>";
      var defs = document.createElement('defs');
      defs.appendChild(s);
      clone.insertBefore(defs, clone.firstChild);

      var svg = doctype + outer.innerHTML;
      var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(svg));
      if (cb) {
        cb(uri);
      }
    });
  }

  out$.svgAsPngUri = function(el, options, cb) {
    out$.svgAsDataUri(el, options, function(uri) {
      var image = new Image();
      image.onload = function() {
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;
        var context = canvas.getContext('2d');
        if(options && options.backgroundColor){
          context.fillStyle = options.backgroundColor;
          context.fillRect(0, 0, canvas.width, canvas.height);
        }
        context.drawImage(image, 0, 0);
        var a = document.createElement('a');
        cb(canvas.toDataURL('image/png'));
      }
      image.src = uri;
    });
  }

  out$.saveSvgAsPng = function(el, name, options) {
    options = options || {};
    out$.svgAsPngUri(el, options, function(uri) {
      var a = document.createElement('a');
      a.download = name;
      a.href = uri;
      document.body.appendChild(a);
      a.addEventListener("click", function(e) {
        a.parentNode.removeChild(a);
      });
      a.click();
    });
  }
})();
<commit_msg>Catch and abort upon SecurityError.<commit_after>(function() {
  var out$ = typeof exports != 'undefined' && exports || this;

  var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';

  function isExternal(url) {
    return url && url.lastIndexOf('http',0) == 0 && url.lastIndexOf(window.location.host) == -1;
  }

  function inlineImages(el, callback) {
    var images = el.querySelectorAll('image');
    var left = images.length;
    if (left == 0) {
      callback();
    }
    for (var i = 0; i < images.length; i++) {
      (function(image) {
        var href = image.getAttributeNS("http://www.w3.org/1999/xlink", "href");
        if (href) {
          if (isExternal(href.value)) {
            console.warn("Cannot render embedded images linking to external hosts: "+href.value);
            return;
          }
        }
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var img = new Image();
        href = href || image.getAttribute('href');
        img.src = href;
        img.onload = function() {
          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(img, 0, 0);
          image.setAttributeNS("http://www.w3.org/1999/xlink", "href", canvas.toDataURL('image/png'));
          left--;
          if (left == 0) {
            callback();
          }
        }
        img.onerror = function() {
          console.log("Could not load "+href);
          left--;
          if (left == 0) {
            callback();
          }
        }
      })(images[i]);
    }
  }

  function styles(el, selectorRemap) {
    var css = "";
    var sheets = document.styleSheets;
    for (var i = 0; i < sheets.length; i++) {
      try {
        var rules = sheets[i].cssRules;
      } catch (e) {
        console.warn("Stylesheet could not be loaded: "+sheets[i].href);
        continue;
      }

      if (rules != null) {
        for (var j = 0; j < rules.length; j++) {
          var rule = rules[j];
          if (typeof(rule.style) != "undefined") {
            var match = null;
            try {
              match = el.querySelector(rule.selectorText);
            } catch(err) {
              console.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
            }
            if (match) {
              var selector = selectorRemap ? selectorRemap(rule.selectorText) : rule.selectorText;
              css += selector + " { " + rule.style.cssText + " }\n";
            } else if(rule.cssText.match(/^@font-face/)) {
              css += rule.cssText + '\n';
            }
          }
        }
      }
    }
    return css;
  }

  function getDimension(el, clone, dim) {
    var v = (el.viewBox.baseVal && el.viewBox.baseVal[dim]) ||
      (clone.getAttribute(dim) !== null && !clone.getAttribute(dim).match(/%$/) && parseInt(clone.getAttribute(dim))) ||
      el.getBoundingClientRect()[dim] ||
      parseInt(clone.style[dim]) ||
      parseInt(window.getComputedStyle(el).getPropertyValue(dim));
    return (typeof v === 'undefined' || v === null || isNaN(parseFloat(v))) ? 0 : v;
  }

  function reEncode(data) {
    data = encodeURIComponent(data);
    data = data.replace(/%([0-9A-F]{2})/g, function(match, p1) {
      var c = String.fromCharCode('0x'+p1);
      return c === '%' ? '%25' : c;
    });
    return decodeURIComponent(data);
  }

  out$.svgAsDataUri = function(el, options, cb) {
    options = options || {};
    options.scale = options.scale || 1;
    var xmlns = "http://www.w3.org/2000/xmlns/";

    inlineImages(el, function() {
      var outer = document.createElement("div");
      var clone = el.cloneNode(true);
      var width, height;
      if(el.tagName == 'svg') {
        width = options.width || getDimension(el, clone, 'width');
        height = options.height || getDimension(el, clone, 'height');
      } else if(el.getBBox) {
        var box = el.getBBox();
        width = box.x + box.width;
        height = box.y + box.height;
        clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, ''));

        var svg = document.createElementNS('http://www.w3.org/2000/svg','svg')
        svg.appendChild(clone)
        clone = svg;
      } else {
        console.error('Attempted to render non-SVG element', el);
        return;
      }

      clone.setAttribute("version", "1.1");
      clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg");
      clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink");
      clone.setAttribute("width", width * options.scale);
      clone.setAttribute("height", height * options.scale);
      clone.setAttribute("viewBox", [
        options.left || 0,
        options.top || 0,
        width,
        height
      ].join(" "));

      outer.appendChild(clone);

      var css = styles(el, options.selectorRemap);
      var s = document.createElement('style');
      s.setAttribute('type', 'text/css');
      s.innerHTML = "<![CDATA[\n" + css + "\n]]>";
      var defs = document.createElement('defs');
      defs.appendChild(s);
      clone.insertBefore(defs, clone.firstChild);

      var svg = doctype + outer.innerHTML;
      var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(svg));
      if (cb) {
        cb(uri);
      }
    });
  }

  out$.svgAsPngUri = function(el, options, cb) {
    out$.svgAsDataUri(el, options, function(uri) {
      var image = new Image();
      image.onload = function() {
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;
        var context = canvas.getContext('2d');
        if(options && options.backgroundColor){
          context.fillStyle = options.backgroundColor;
          context.fillRect(0, 0, canvas.width, canvas.height);
        }
        context.drawImage(image, 0, 0);
        var a = document.createElement('a'), png;
        try {
          png = canvas.toDataURL('image/png');
        } catch (e if e instanceof SecurityError) {
          console.error("Rendered SVG images cannot be downloaded in this browser.");
          return;
        }
        cb(png);
      }
      image.src = uri;
    });
  }

  out$.saveSvgAsPng = function(el, name, options) {
    options = options || {};
    out$.svgAsPngUri(el, options, function(uri) {
      var a = document.createElement('a');
      a.download = name;
      a.href = uri;
      document.body.appendChild(a);
      a.addEventListener("click", function(e) {
        a.parentNode.removeChild(a);
      });
      a.click();
    });
  }
})();
<|endoftext|>


<commit_before>var Net = require("net");
var Gab = require("../gab");

var FTP_PORT = 21;

var Ftp = function (cfg) {
    Gab.apply(this, arguments);

    this.data = "";

    var port = cfg.port || FTP_PORT;
    var host = cfg.host;
    var user = this.user = cfg.user;
    var pass = this.pass = cfg.pass;

    this.commands = [
        "QUIT",
        "PWD",
    ];

    this.response = [];
    this.handler  = this.ftpHandleConnect;

    this.setTerminator("\n");
    this.setEncoding("utf8");

    this.connect(port, host);
};

Ftp.prototype = new Gab;
Ftp.prototype.constructor = Ftp;

Ftp.handleResponse = {
    "USER": function(res) {
        var code = res.substring(0, 3); // get response code
        if (code === "230") {
            return; // user accepted
        }
        else if (code === "331" || code === "332") {
            this.push("PASS " + this.pass + "\r\n");
            this.handler = Ftp.handleResponse["PASS"];
        }
        else {
            throw new Error("ftp login failed: user name not accepted");
        }
    },
    "PASS": function(res) {
        var code = res.substring(0, 3); // get response code
        if (code === "230") {
            return; // user and password accepted
        }
        else {
            throw new Error("ftp login failed: user/password not accepted");
        }
    }
};

Ftp.prototype.collectIncomingData = function(data) {
    this.data += data;
};

Ftp.prototype.foundTerminator = function() {
    var data = this.data;

    if (data.charAt(data.length - 1) === "\r")
        data = data.substring(0, data.length - 2);

    this.data = "";
    this.response.push(data);

    if (!/\d\d\d/.test(data))
        return;

    var response = this.response;
    this.response = [];

    response.forEach(function(line) {
        console.log("S:", line);
    });

    // process response
    if (this.handler) {
        // call the response handler
        handler = this.handler;
        this.handler = null;

        handler.call(this, response[response.length - 1]);

        if (this.handler)
            return; // follow-up command in progress
    }

    var command;
    if (this.commands.length) {
        command = this.commands.pop();
        console.log("C:", command);
        this.push(command + "\r\n");
    }
};

Ftp.prototype.ftpHandleConnect = function(res) {
    var code = res.substring(0, 3); // get response code
    if (code === "220") {
        this.push("USER " + this.user + "\r\n");
        this.handler = Ftp.handleResponse["USER"];
    }
    else {
        throw new Exception("ftp login failed");
    }
};

// Fire it up. For test purposes only!
var ftp = new Ftp({
    port: 2021,
    host: "localhost",
    user: "sergi",
    pass: "2x8hebsndr9"
});

<commit_msg>Updated FTP example and fixed several bugs<commit_after>var Net = require("net");
var Gab = require("../gab");

var FTP_PORT = 21;

var RE_PASV = /[-\d]+,[-\d]+,[-\d]+,[-\d]+,([-\d]+),([-\d]+)/;

var Ftp = function (cfg) {
    Gab.apply(this, arguments);

    this.data = "";

    var port = this.port = cfg.port || FTP_PORT;
    var host = this.host = cfg.host;
    var user = this.user = cfg.user;
    var pass = this.pass = cfg.pass;

    this.commands = [
        "PASV", Ftp.handleResponse.PASV,
        "LIST",
        //STAT /",
        //"NOOP",
        "PWD",
        "QUIT",
    ];

    this.response = [];
    this.handler  = this.ftpHandleConnect;

    this.setTerminator("\n");
    this.setEncoding("utf8");

    this.connect(port, host);
};

Ftp.prototype = new Gab;
Ftp.prototype.constructor = Ftp;

Ftp.handleResponse = {
    "USER": function(res) {
        var code = res.substring(0, 3); // get response code
        if (code === "230") {
            return; // user accepted
        }
        else if (code === "331" || code === "332") {
            this.push("PASS " + this.pass + "\r\n");
            this.handler = Ftp.handleResponse["PASS"];
        }
        else {
            throw new Error("ftp login failed: user name not accepted");
        }
    },
    "PASS": function(res) {
        var code = res.substring(0, 3); // get response code
        if (code === "230") {
            return; // user and password accepted
        }
        else {
            throw new Error("ftp login failed: password not accepted");
        }
    },
    "PASV": function(res) {
        var code = res.substring(0, 3); // get response code
        if (code !== "227")
            return // pasv failed

        var match = RE_PASV.exec(res);
        if (!match)
            return // bad port

        port = (parseInt(match[1]) & 255) * 256 + (parseInt(match[2]) & 255);
        // establish data connection
        new ftpDownload(this.host, port);
    }
};

Ftp.prototype.collectIncomingData = function(data) {
    this.data += data;
};

Ftp.prototype.foundTerminator = function() {
    var data = this.data;

    if (data.charAt(data.length - 1) === "\r")
        data = data.substring(0, data.length - 1);

    this.data = "";
    this.response.push(data);

    if (!/\d\d\d/.test(data))
        return;

    var response = this.response;
    this.response = [];

    response.forEach(function(line) {
        console.log("S:", line);
    });

    // process response
    if (this.handler) {
        // call the response handler
        handler = this.handler;
        this.handler = null;

        handler.call(this, response[response.length - 1]);

        if (this.handler)
            return; // follow-up command in progress
    }

    var command;
    if (this.commands.length) {
        command = this.commands.shift();
        var len = this.commands.length;

        if (len && typeof this.commands[0] === "function") {
            this.handler = this.commands.shift();
        }
        console.log("C:", "'" + command + "'");

        this.push(command + "\r\n");
    }
};

Ftp.prototype.ftpHandleConnect = function(res) {
    var code = res.substring(0, 3); // get response code
    if (code === "220") {
        this.push("USER " + this.user + "\r\n");
        this.handler = Ftp.handleResponse["USER"];
    }
    else {
        throw new Exception("ftp login failed");
    }
};

var ftpDownload = function(host, port) {
    Gab.apply(this, arguments);

    this.setTerminator("\n");

    this.socket = Net.createConnection(port, host);
    this.connect(host, port);
}

ftpDownload.prototype = new Gab;
ftpDownload.prototype.constructor = ftpDownload;

ftpDownload.prototype.writable = function() {
    return false;
};

ftpDownload.prototype.handleConnect = function(e) {console.log(e)};

ftpDownload.prototype.handleExpt = function() {
    this.close();
};

ftpDownload.prototype.handleClose = function() {
    this.close();
};

// Fire it up. For test purposes only!
var ftp = new Ftp({
    port: 21,
    host: "sergimansilla.com",
    user: "mrclash",
    pass: ""
});

<|endoftext|>


<commit_before>(function() {
  var out$ = typeof exports != 'undefined' && exports || this;

  var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';

  function isExternal(url) {
    return url && url.lastIndexOf('http',0) == 0 && url.lastIndexOf(window.location.host) == -1;
  }

  function inlineImages(el, callback) {
    var images = el.querySelectorAll('image');
    var left = images.length;
    if (left == 0) {
      callback();
    }
    for (var i = 0; i < images.length; i++) {
      (function(image) {
        var href = image.getAttribute('xlink:href');
        if (href) {
          if (isExternal(href.value)) {
            console.warn("Cannot render embedded images linking to external hosts: "+href.value);
            return;
          }
        }
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var img = new Image();
        href = href || image.getAttribute('href');
        img.src = href;
        img.onload = function() {
          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(img, 0, 0);
          image.setAttribute('xlink:href', canvas.toDataURL('image/png'));
          left--;
          if (left == 0) {
            callback();
          }
        }
        img.onerror = function() {
          console.log("Could not load "+href);
          left--;
          if (left == 0) {
            callback();
          }
        }
      })(images[i]);
    }
  }

  function styles(el, selectorRemap) {
    var css = "";
    var sheets = document.styleSheets;
    for (var i = 0; i < sheets.length; i++) {
      if (isExternal(sheets[i].href)) {
        console.warn("Cannot include styles from other hosts: "+sheets[i].href);
        continue;
      }
      var rules = sheets[i].cssRules;
      if (rules != null) {
        for (var j = 0; j < rules.length; j++) {
          var rule = rules[j];
          if (typeof(rule.style) != "undefined") {
            var match = null;
            try {
              match = el.querySelector(rule.selectorText);
            } catch(err) {
              console.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
            }
            if (match) {
              var selector = selectorRemap ? selectorRemap(rule.selectorText) : rule.selectorText;
              css += selector + " { " + rule.style.cssText + " }\n";
            } else if(rule.cssText.match(/^@font-face/)) {
              css += rule.cssText + '\n';
            }
          }
        }
      }
    }
    return css;
  }

  out$.svgAsDataUri = function(el, options, cb) {
    options = options || {};
    options.scale = options.scale || 1;
    var xmlns = "http://www.w3.org/2000/xmlns/";

    inlineImages(el, function() {
      var outer = document.createElement("div");
      var clone = el.cloneNode(true);
      var width, height;
      if(el.tagName == 'svg') {
        var box = el.getBoundingClientRect();
        width = box.width ||
          parseInt(clone.getAttribute('width') ||
          clone.style.width ||
          out$.getComputedStyle(el).getPropertyValue('width'));
        height = box.height ||
          parseInt(clone.getAttribute('height') ||
          clone.style.height ||
          out$.getComputedStyle(el).getPropertyValue('height'));
      } else {
        var box = el.getBBox();
        width = box.x + box.width;
        height = box.y + box.height;
        clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, ''));

        var svg = document.createElementNS('http://www.w3.org/2000/svg','svg')
        svg.appendChild(clone)
        clone = svg;
      }

      clone.setAttribute("version", "1.1");
      clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg");
      clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink");
      clone.setAttribute("width", width * options.scale);
      clone.setAttribute("height", height * options.scale);
      clone.setAttribute("viewBox", "0 0 " + width + " " + height);
      outer.appendChild(clone);

      var css = styles(el, options.selectorRemap);
      var s = document.createElement('style');
      s.setAttribute('type', 'text/css');
      s.innerHTML = "<![CDATA[\n" + css + "\n]]>";
      var defs = document.createElement('defs');
      defs.appendChild(s);
      clone.insertBefore(defs, clone.firstChild);

      var svg = doctype + outer.innerHTML;
      var uri = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svg)));
      if (cb) {
        cb(uri);
      }
    });
  }

  out$.saveSvgAsPng = function(el, name, options) {
    options = options || {};
    out$.svgAsDataUri(el, options, function(uri) {
      var image = new Image();
      image.src = uri;
      image.onload = function() {
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0);

        var a = document.createElement('a');
        a.download = name;
        a.href = canvas.toDataURL('image/png');
        document.body.appendChild(a);
        a.addEventListener("click", function(e) {
          a.parentNode.removeChild(a);
        });
        a.click();
      }
    });
  }
})();
<commit_msg>added namespace to href attribute to avoid duplication (fix for #22)<commit_after>(function() {
  var out$ = typeof exports != 'undefined' && exports || this;

  var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';

  function isExternal(url) {
    return url && url.lastIndexOf('http',0) == 0 && url.lastIndexOf(window.location.host) == -1;
  }

  function inlineImages(el, callback) {
    var images = el.querySelectorAll('image');
    var left = images.length;
    if (left == 0) {
      callback();
    }
    for (var i = 0; i < images.length; i++) {
      (function(image) {
        var href = image.getAttributeNS("http://www.w3.org/1999/xlink", "href");
        if (href) {
          if (isExternal(href.value)) {
            console.warn("Cannot render embedded images linking to external hosts: "+href.value);
            return;
          }
        }
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var img = new Image();
        href = href || image.getAttribute('href');
        img.src = href;
        img.onload = function() {
          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(img, 0, 0);
          image.setAttributeNS("http://www.w3.org/1999/xlink", "href", canvas.toDataURL('image/png'));
          left--;
          if (left == 0) {
            callback();
          }
        }
        img.onerror = function() {
          console.log("Could not load "+href);
          left--;
          if (left == 0) {
            callback();
          }
        }
      })(images[i]);
    }
  }

  function styles(el, selectorRemap) {
    var css = "";
    var sheets = document.styleSheets;
    for (var i = 0; i < sheets.length; i++) {
      if (isExternal(sheets[i].href)) {
        console.warn("Cannot include styles from other hosts: "+sheets[i].href);
        continue;
      }
      var rules = sheets[i].cssRules;
      if (rules != null) {
        for (var j = 0; j < rules.length; j++) {
          var rule = rules[j];
          if (typeof(rule.style) != "undefined") {
            var match = null;
            try {
              match = el.querySelector(rule.selectorText);
            } catch(err) {
              console.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
            }
            if (match) {
              var selector = selectorRemap ? selectorRemap(rule.selectorText) : rule.selectorText;
              css += selector + " { " + rule.style.cssText + " }\n";
            } else if(rule.cssText.match(/^@font-face/)) {
              css += rule.cssText + '\n';
            }
          }
        }
      }
    }
    return css;
  }

  out$.svgAsDataUri = function(el, options, cb) {
    options = options || {};
    options.scale = options.scale || 1;
    var xmlns = "http://www.w3.org/2000/xmlns/";

    inlineImages(el, function() {
      var outer = document.createElement("div");
      var clone = el.cloneNode(true);
      var width, height;
      if(el.tagName == 'svg') {
        var box = el.getBoundingClientRect();
        width = box.width ||
          parseInt(clone.getAttribute('width') ||
          clone.style.width ||
          out$.getComputedStyle(el).getPropertyValue('width'));
        height = box.height ||
          parseInt(clone.getAttribute('height') ||
          clone.style.height ||
          out$.getComputedStyle(el).getPropertyValue('height'));
      } else {
        var box = el.getBBox();
        width = box.x + box.width;
        height = box.y + box.height;
        clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, ''));

        var svg = document.createElementNS('http://www.w3.org/2000/svg','svg')
        svg.appendChild(clone)
        clone = svg;
      }

      clone.setAttribute("version", "1.1");
      clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg");
      clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink");
      clone.setAttribute("width", width * options.scale);
      clone.setAttribute("height", height * options.scale);
      clone.setAttribute("viewBox", "0 0 " + width + " " + height);
      outer.appendChild(clone);

      var css = styles(el, options.selectorRemap);
      var s = document.createElement('style');
      s.setAttribute('type', 'text/css');
      s.innerHTML = "<![CDATA[\n" + css + "\n]]>";
      var defs = document.createElement('defs');
      defs.appendChild(s);
      clone.insertBefore(defs, clone.firstChild);

      var svg = doctype + outer.innerHTML;
      var uri = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svg)));
      if (cb) {
        cb(uri);
      }
    });
  }

  out$.saveSvgAsPng = function(el, name, options) {
    options = options || {};
    out$.svgAsDataUri(el, options, function(uri) {
      var image = new Image();
      image.src = uri;
      image.onload = function() {
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0);

        var a = document.createElement('a');
        a.download = name;
        a.href = canvas.toDataURL('image/png');
        document.body.appendChild(a);
        a.addEventListener("click", function(e) {
          a.parentNode.removeChild(a);
        });
        a.click();
      }
    });
  }
})();
<|endoftext|>