<commit_before>define(function (require, exports, module) {
  'use strict';

  var L20n = require('../l20n');
  var io = require('./platform/io');

  var rtlLocales = ['ar', 'fa', 'he', 'ps', 'ur'];

  var ctx = L20n.getContext();
  navigator.mozL10n = ctx;

  if (document) {
    bootstrap();
  }

  function bootstrap() {
    var localePlaceable = /\{\{\s*locale\s*\}\}/;

    var head = document.head;
    var iniLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                         '[href$=".ini"]');
    var jsonLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                          '[href$=".json"]');

    for (var i = 0; i < jsonLinks.length; i++) {
      var parts = jsonLinks[i].getAttribute('href').split(localePlaceable);
      ctx.linkResource(function(locale) {
        return parts[0] + locale + parts[1];
      });
    }

    var iniToLoad = iniLinks.length;
    if (iniToLoad === 0) {
      return requestLocales();
    }

    for (var i = 0; i < iniLinks.length; i++) {
      var url = iniLinks[i].getAttribute('href');
      io.load(url, iniLoaded.bind(null, url));
    }

    var available = [];

    function iniLoaded(url, err, text) {
      if (err) {
        throw err;
      }
      var ini = parseINI(text, url);
      available.push.apply(available, ini.locales);
      for (var i = 0; i < ini.resources.length; i++) {
        var parts = ini.resources[i].split('en-US');
        ctx.linkResource(function(locale) {
          return parts[0] + locale + parts[1];
        });
      }
      iniToLoad--;
      if (iniToLoad == 0) {
        requestLocales(available);
      }
    }

    if (document.readyState !== 'loading') {
      ctx.ready(translateDocument);
    } else {
      document.addEventListener('readystatechange', function() {
        ctx.ready(translateDocument);
      });
    }

    bindPublicAPI();
  }

  function requestLocales(available) {
    if (!available) {
      var metaLocs = headNode.querySelector('meta[name="locales"]');
      available = metaLocs.getAttribute('content').split(',').map(String.trim);
    }
    ctx.registerLocales('en-US', available);
    ctx.requestLocales(navigator.language);
  }

  var patterns = {
    ini: {
      section: /^\s*\[(.*)\]\s*$/,
      import: /^\s*@import\s+url\((.*)\)\s*$/i
    }
  };

  function parseINI(source, iniPath) {
    var entries = source.split(/[\r\n]+/);
    var locales = ['en-US'];
    var genericSection = true;
    var uris = [];

    for (var i = 0; i < entries.length; i++) {
      var line = entries[i];
      // we only care about en-US resources
      if (genericSection && patterns['ini']['import'].test(line)) {
        var match = patterns['ini']['import'].exec(line);
        var uri = relativePath(iniPath, match[1]);
        uris.push(uri);
        continue;
      }
      // but we need the list of all locales in the ini, too
      if (patterns['ini']['section'].test(line)) {
        genericSection = false;
        var match = patterns['ini']['section'].exec(line);
        locales.push(match[1]);
      }
    }
    return {
      locales: locales,
      resources: uris
    };
  }

  function relativePath(baseUrl, url) {
    if (url[0] == '/') {
      return url;
    }
    var dirs = baseUrl.split('/')
      .slice(0, -1)
      .concat(url.split('/'))
      .filter(function(elem) {
        return elem !== '.';
      });

    if (dirs[0] !== '' && dirs[0] !== '..') {
      // if the base path doesn't start with / or ..
      dirs.unshift('.');
    }

    return dirs.join('/');
  }

  function bindPublicAPI() {
    ctx.addEventListener('error', console.error.bind(console));
    ctx.addEventListener('warning', console.warn.bind(console));
    ctx.localize = function() {};
    ctx.language = {
      get code() {
        return ctx.supportedLocales[0];
      },
      set code(lang) {
        ctx.requestLocales(lang);
      },
      get direction() {
        if (rtlLocales.indexOf(ctx.supportedLocales[0]) >= 0) {
          return 'rtl';
        } else {
          return 'ltr';
        }
      }
    };
    ctx.getDictionary = getSubDictionary;
  }

  function getEntry(id, args, nested) {
    var entries = {};
    var entry = locales[curLocale].getEntry(id);
    if (!entry) {
      return {};
    }

    var entity = entry.get(args);
    entries[id] = {'_': entity.value};

    // add attributes when we have them
    if (entry.value.type === 'ComplexString') {
      entry.value.body.forEach(function (chunk) {
        if (chunk.type == 'Identifier') {
          var subentries = getEntry(chunk.name);
          for (var e in subentries) {
            entries[e] = subentries[e];
          }
        }
      });
    }
    return entries;
  }

  // return a sub-dictionary sufficient to translate a given fragment
  function getSubDictionary(fragment) {
    if (!fragment) { // by default, return a clone of the whole dictionary
      var dict = {};
      for (var id in locales[curLocale].entries) {
        dict[id] = {'_': navigator.mozL10n.get(id)};
      }
      return dict;
    }

    var dict = {};
    var elements = getTranslatableChildren(fragment);

    for (var i = 0, l = elements.length; i < l; i++) {
      var ent = getL10nAttributes(elements[i]);
      var entries = getEntry(ent.id, ent.args, true);
      if (entries) {
        for (var e in entries) {
          dict[e] = entries[e];
        }
      }
      //for (var prop in data) {
      //  var str = data[prop];

        /*if (reIndex.test(str)) { // macro index
          for (var j = 0; j < kPluralForms.length; j++) {
            var key = id + '[' + kPluralForms[j] + ']';
            if (key in gL10nData) {
              dict[key] = gL10nData[key];
              checkGlobalArguments(gL10nData[key]);
            }
          }
        }*/
      //}
    }

    return dict;
  }

  function getTranslatableChildren(element) {
    return element ? element.querySelectorAll('*[data-l10n-id]') : [];
  }

  function getL10nAttributes(element) {
    if (!element) {
      return {};
    }

    var l10nId = element.getAttribute('data-l10n-id');
    var l10nArgs = element.getAttribute('data-l10n-args');
    var args = {};
    if (l10nArgs) {
      try {
        args = JSON.parse(l10nArgs);
      } catch (e) {
        consoleWarn('could not parse arguments for #' + l10nId);
      }
    }
    return { id: l10nId, args: args };
  }

  function translateDocument() {
    var nodes = document.querySelectorAll('[data-l10n-id]');
    for (var i = 0; i < nodes.length; i++) {
      translateNode(nodes[i]);
    }
    fireLocalizedEvent();
  }

  function translateNode(node) {
    var attrs = getL10nAttributes(node);
    node.textContent = navigator.mozL10n.get(attrs.id, attrs.args);
  }

  function fireLocalizedEvent() {
    var event = document.createEvent('Event');
    event.initEvent('localized', false, false);
    event.language = ctx.supportedLocales[0];
    window.dispatchEvent(event);
  }

  return L20n;
});
<commit_msg>add mozSettings observer<commit_after>define(function (require, exports, module) {
  'use strict';

  var L20n = require('../l20n');
  var io = require('./platform/io');

  var rtlLocales = ['ar', 'fa', 'he', 'ps', 'ur'];

  var ctx = L20n.getContext();
  navigator.mozL10n = ctx;

  if (document) {
    bootstrap();
  }

  function bootstrap() {
    var localePlaceable = /\{\{\s*locale\s*\}\}/;

    var head = document.head;
    var iniLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                         '[href$=".ini"]');
    var jsonLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                          '[href$=".json"]');

    for (var i = 0; i < jsonLinks.length; i++) {
      var parts = jsonLinks[i].getAttribute('href').split(localePlaceable);
      ctx.linkResource(function(locale) {
        return parts[0] + locale + parts[1];
      });
    }

    var iniToLoad = iniLinks.length;
    if (iniToLoad === 0) {
      return requestLocales();
    }

    for (var i = 0; i < iniLinks.length; i++) {
      var url = iniLinks[i].getAttribute('href');
      io.load(url, iniLoaded.bind(null, url));
    }

    var available = [];

    function iniLoaded(url, err, text) {
      if (err) {
        throw err;
      }
      var ini = parseINI(text, url);
      available.push.apply(available, ini.locales);
      for (var i = 0; i < ini.resources.length; i++) {
        var parts = ini.resources[i].split('en-US');
        ctx.linkResource(function(locale) {
          return parts[0] + locale + parts[1];
        });
      }
      iniToLoad--;
      if (iniToLoad == 0) {
        requestLocales(available);
      }
    }

    if (document.readyState !== 'loading') {
      ctx.ready(translateDocument);
    } else {
      document.addEventListener('readystatechange', function() {
        ctx.ready(translateDocument);
      });
    }

    bindPublicAPI();
  }

  function requestLocales(available) {
    if (!available) {
      var metaLocs = headNode.querySelector('meta[name="locales"]');
      available = metaLocs.getAttribute('content').split(',').map(String.trim);
    }
    ctx.registerLocales('en-US', available);
    ctx.requestLocales(navigator.language);

    // listen to language change events
    if ('mozSettings' in navigator && navigator.mozSettings) {
      navigator.mozSettings.addObserver('language.current', function(event) {
        ctx.requestLocales(event.settingValue);
      });
    }
  }

  var patterns = {
    ini: {
      section: /^\s*\[(.*)\]\s*$/,
      import: /^\s*@import\s+url\((.*)\)\s*$/i
    }
  };

  function parseINI(source, iniPath) {
    var entries = source.split(/[\r\n]+/);
    var locales = ['en-US'];
    var genericSection = true;
    var uris = [];

    for (var i = 0; i < entries.length; i++) {
      var line = entries[i];
      // we only care about en-US resources
      if (genericSection && patterns['ini']['import'].test(line)) {
        var match = patterns['ini']['import'].exec(line);
        var uri = relativePath(iniPath, match[1]);
        uris.push(uri);
        continue;
      }
      // but we need the list of all locales in the ini, too
      if (patterns['ini']['section'].test(line)) {
        genericSection = false;
        var match = patterns['ini']['section'].exec(line);
        locales.push(match[1]);
      }
    }
    return {
      locales: locales,
      resources: uris
    };
  }

  function relativePath(baseUrl, url) {
    if (url[0] == '/') {
      return url;
    }
    var dirs = baseUrl.split('/')
      .slice(0, -1)
      .concat(url.split('/'))
      .filter(function(elem) {
        return elem !== '.';
      });

    if (dirs[0] !== '' && dirs[0] !== '..') {
      // if the base path doesn't start with / or ..
      dirs.unshift('.');
    }

    return dirs.join('/');
  }

  function bindPublicAPI() {
    ctx.addEventListener('error', console.error.bind(console));
    ctx.addEventListener('warning', console.warn.bind(console));
    ctx.localize = function() {};
    ctx.language = {
      get code() {
        return ctx.supportedLocales[0];
      },
      set code(lang) {
        ctx.requestLocales(lang);
      },
      get direction() {
        if (rtlLocales.indexOf(ctx.supportedLocales[0]) >= 0) {
          return 'rtl';
        } else {
          return 'ltr';
        }
      }
    };
    ctx.getDictionary = getSubDictionary;
  }

  function getEntry(id, args, nested) {
    var entries = {};
    var entry = locales[curLocale].getEntry(id);
    if (!entry) {
      return {};
    }

    var entity = entry.get(args);
    entries[id] = {'_': entity.value};

    // add attributes when we have them
    if (entry.value.type === 'ComplexString') {
      entry.value.body.forEach(function (chunk) {
        if (chunk.type == 'Identifier') {
          var subentries = getEntry(chunk.name);
          for (var e in subentries) {
            entries[e] = subentries[e];
          }
        }
      });
    }
    return entries;
  }

  // return a sub-dictionary sufficient to translate a given fragment
  function getSubDictionary(fragment) {
    if (!fragment) { // by default, return a clone of the whole dictionary
      var dict = {};
      for (var id in locales[curLocale].entries) {
        dict[id] = {'_': navigator.mozL10n.get(id)};
      }
      return dict;
    }

    var dict = {};
    var elements = getTranslatableChildren(fragment);

    for (var i = 0, l = elements.length; i < l; i++) {
      var ent = getL10nAttributes(elements[i]);
      var entries = getEntry(ent.id, ent.args, true);
      if (entries) {
        for (var e in entries) {
          dict[e] = entries[e];
        }
      }
      //for (var prop in data) {
      //  var str = data[prop];

        /*if (reIndex.test(str)) { // macro index
          for (var j = 0; j < kPluralForms.length; j++) {
            var key = id + '[' + kPluralForms[j] + ']';
            if (key in gL10nData) {
              dict[key] = gL10nData[key];
              checkGlobalArguments(gL10nData[key]);
            }
          }
        }*/
      //}
    }

    return dict;
  }

  function getTranslatableChildren(element) {
    return element ? element.querySelectorAll('*[data-l10n-id]') : [];
  }

  function getL10nAttributes(element) {
    if (!element) {
      return {};
    }

    var l10nId = element.getAttribute('data-l10n-id');
    var l10nArgs = element.getAttribute('data-l10n-args');
    var args = {};
    if (l10nArgs) {
      try {
        args = JSON.parse(l10nArgs);
      } catch (e) {
        consoleWarn('could not parse arguments for #' + l10nId);
      }
    }
    return { id: l10nId, args: args };
  }

  function translateDocument() {
    var nodes = document.querySelectorAll('[data-l10n-id]');
    for (var i = 0; i < nodes.length; i++) {
      translateNode(nodes[i]);
    }
    fireLocalizedEvent();
  }

  function translateNode(node) {
    var attrs = getL10nAttributes(node);
    node.textContent = navigator.mozL10n.get(attrs.id, attrs.args);
  }

  function fireLocalizedEvent() {
    var event = document.createEvent('Event');
    event.initEvent('localized', false, false);
    event.language = ctx.supportedLocales[0];
    window.dispatchEvent(event);
  }

  return L20n;
});
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var path = require('path');
var config = require('../config');
var lwip = require('lwip');
var ExifImage = require('exif').ExifImage;
var fs = require('fs');

var THUMB_WIDTH = 50;
var MAX_DIMENSION = 2048;

router.post('/upload', function(req, res) {
    //make sure that we have a single file and it is the correct type
    if (req.files == null || !req.files.uploadfile || req.files.uploadfile.truncated) {
        res.status(400).send();
        console.error('Invalid number or size of uploaded files ' + JSON.stringify(req.files));
        return;
    }

    if (req.files.uploadfile.mimetype != "image/jpeg" &&
        req.files.uploadfile.mimetype != "image/png") {

        res.status(400).send();
        console.error('Invalid file type ' + req.files.uploadfile.mimetype);
        return;
    }

    var inFile = req.files.uploadfile;
    var exifFunc;

    if (req.files.uploadfile.mimetype == "image/jpeg") {
        exifFunc = function(callback) {
            try {
                new ExifImage({image: inFile.path}, callback);
            } catch (e) {
                console.error(e);
                callback(e, null);
            }
        }
    } else {
        exifFunc = function(callback) {
            callback(null, null);
        }
    }

    //load the exif data and see if we need to perform a rotation
    exifFunc(function (error, exifData) {
        var rotFlag = 0;
        if (! error) {
            if (exifData && exifData.image && exifData.image.Orientation) {
                rotFlag = exifData.image.Orientation;
            }
        } else {
            console.error("Exif: " + error);
        }

        lwip.open(inFile.path, function(err, initial) {
            if (err) {
                console.error(err);
                res.status(500).send();
                return;
            }

            var batch = initial.batch();

            //first, let's cut this image down to size
            //find the largest dimension
            var largeDimension;
            if (initial.width() > initial.height()) {
                //use the width to clamp
                largeDimension = initial.width();
            } else {
                //use the height to clamp
                largeDimension = initial.height();
            }

            scale = MAX_DIMENSION / largeDimension;
            var rotDeg = 0;

            var finish = function(err, fullSized) {
                if (err) {
                    console.error(err);
                    res.status(500).send();
                    return;
                }

                //clone again before scaling for thumbnail
                fullSized.clone(function(err, fullClone) {
                    if (err) {
                        console.error(err);
                        res.status(500).send();
                        return;
                    }

                    //scale the original
                    var ratio = THUMB_WIDTH / fullClone.width();
                    fullClone.scale(ratio, function (err, timage) {
                        if (err) {
                            console.error(err);
                            res.status(500).send();
                            return;
                        }

                        var baseName = path.basename(inFile.path, path.extname(inFile.path));
                        var profilesDir
                            = path.normalize(
                                path.dirname(inFile.path) + '/../public/images/media'
                            );

                        var bigName = path.join(profilesDir, baseName + ".jpg");
                        var thumbName = path.join(profilesDir, baseName + "-t.jpg");

                        //save to the profiles directory
                        timage.writeFile(thumbName, function(err) {
                            if (err) {
                                console.error(err);
                                res.status(500).send();
                                return;
                            }

                            fullSized.writeFile(bigName, function(err) {
                                if (err) {
                                    console.error(err);
                                    res.status(500).send();
                                    return;
                                }

                                var ret = {
                                    img: '/images/media/' + baseName + ".jpg",
                                    thumb: '/images/media/' + baseName + "-t.jpg"
                                };

                                res.json(ret);

                                //delete the original
                                fs.unlink(inFile.path, function (err) {
                                    if (err) {
                                        console.error(err);
                                    }
                                });
                            });
                        });
                    });
                });
            };

            if (rotFlag != 0) {
                //we need to perform some kind of rotation
                if (rotFlag == 3) {
                    rotDeg = 180;
                } else if (rotFlag == 6) {
                    rotDeg = 90;
                } else if (rotFlag == 8) {
                    rotDeg == 270;
                }

                if (scale < 1.0) {
                    batch.scale(scale).rotate(rotDeg).exec(finish);
                } else {
                    batch.rotate(rotDeg).exec(finish);
                }

            } else {
                if (scale < 1.0) {
                    batch.scale(scale).exec(finish);
                } else {
                    finish(null, initial);
                }

            }
        });
    });

});

module.exports = router;
<commit_msg>Even if a jpg or a png does not have the expected extension, pass the correct type to lwip so that the image can be processed<commit_after>var express = require('express');
var router = express.Router();
var path = require('path');
var config = require('../config');
var lwip = require('lwip');
var ExifImage = require('exif').ExifImage;
var fs = require('fs');

var THUMB_WIDTH = 50;
var MAX_DIMENSION = 2048;

router.post('/upload', function(req, res) {
    //make sure that we have a single file and it is the correct type
    if (req.files == null || !req.files.uploadfile || req.files.uploadfile.truncated) {
        res.status(400).send();
        console.error('Invalid number or size of uploaded files ' + JSON.stringify(req.files));
        return;
    }

    if (req.files.uploadfile.mimetype != "image/jpeg" &&
        req.files.uploadfile.mimetype != "image/png") {

        res.status(400).send();
        console.error('Invalid file type ' + req.files.uploadfile.mimetype);
        return;
    }

    var inFile = req.files.uploadfile;
    var exifFunc;
    var shortType;

    if (req.files.uploadfile.mimetype == "image/jpeg") {
        shortType = "jpg";
    } else {
        shortType = "png";
    }

    if (req.files.uploadfile.mimetype == "image/jpeg") {
        exifFunc = function(callback) {
            try {
                new ExifImage({image: inFile.path}, callback);
            } catch (e) {
                console.error(e);
                callback(e, null);
            }
        }

    } else {
        exifFunc = function(callback) {
            callback(null, null);
        }
    }

    //load the exif data and see if we need to perform a rotation
    exifFunc(function (error, exifData) {
        var rotFlag = 0;
        if (! error) {
            if (exifData && exifData.image && exifData.image.Orientation) {
                rotFlag = exifData.image.Orientation;
            }
        } else {
            console.error("Exif: " + error);
        }

        lwip.open(inFile.path, shortType, function(err, initial) {
            if (err) {
                console.error(err);
                res.status(500).send();
                return;
            }

            var batch = initial.batch();

            //first, let's cut this image down to size
            //find the largest dimension
            var largeDimension;
            if (initial.width() > initial.height()) {
                //use the width to clamp
                largeDimension = initial.width();
            } else {
                //use the height to clamp
                largeDimension = initial.height();
            }

            scale = MAX_DIMENSION / largeDimension;
            var rotDeg = 0;

            var finish = function(err, fullSized) {
                if (err) {
                    console.error(err);
                    res.status(500).send();
                    return;
                }

                //clone again before scaling for thumbnail
                fullSized.clone(function(err, fullClone) {
                    if (err) {
                        console.error(err);
                        res.status(500).send();
                        return;
                    }

                    //scale the original
                    var ratio = THUMB_WIDTH / fullClone.width();
                    fullClone.scale(ratio, function (err, timage) {
                        if (err) {
                            console.error(err);
                            res.status(500).send();
                            return;
                        }

                        var baseName = path.basename(inFile.path, path.extname(inFile.path));
                        var profilesDir
                            = path.normalize(
                                path.dirname(inFile.path) + '/../public/images/media'
                            );

                        var bigName = path.join(profilesDir, baseName + ".jpg");
                        var thumbName = path.join(profilesDir, baseName + "-t.jpg");

                        //save to the profiles directory
                        timage.writeFile(thumbName, function(err) {
                            if (err) {
                                console.error(err);
                                res.status(500).send();
                                return;
                            }

                            fullSized.writeFile(bigName, function(err) {
                                if (err) {
                                    console.error(err);
                                    res.status(500).send();
                                    return;
                                }

                                var ret = {
                                    img: '/images/media/' + baseName + ".jpg",
                                    thumb: '/images/media/' + baseName + "-t.jpg"
                                };

                                res.json(ret);

                                //delete the original
                                fs.unlink(inFile.path, function (err) {
                                    if (err) {
                                        console.error(err);
                                    }
                                });
                            });
                        });
                    });
                });
            };

            if (rotFlag != 0) {
                //we need to perform some kind of rotation
                if (rotFlag == 3) {
                    rotDeg = 180;
                } else if (rotFlag == 6) {
                    rotDeg = 90;
                } else if (rotFlag == 8) {
                    rotDeg == 270;
                }

                if (scale < 1.0) {
                    batch.scale(scale).rotate(rotDeg).exec(finish);
                } else {
                    batch.rotate(rotDeg).exec(finish);
                }

            } else {
                if (scale < 1.0) {
                    batch.scale(scale).exec(finish);
                } else {
                    finish(null, initial);
                }

            }
        });
    });

});

module.exports = router;
<|endoftext|>


<commit_before>/*
 * LazyK-JS /lib/tokens.js
 * copyright (c) 2015 Susisu
 */

"use strict";

function endModule() {
    module.exports = Object.freeze({
        "Token"      : Token,
        "S"          : S,
        "K"          : K,
        "I"          : I,
        "Iota"       : Iota,
        "Application": Application
    });
}

var lambda = require("./lambda.js");

function Token(srcPos) {
    if (!(this instanceof Token)) {
        return new Token(srcPos);
    }
    this.srcPos = srcPos;
}

Token.prototype = Object.create(Object.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": Token
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "?";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            throw new Error("invalid token");
        }
    }
});

function S(srcPos) {
    if (!(this instanceof S)) {
        return new S(srcPos);
    }
    Token.call(this, srcPos);
}

S.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": S
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "S";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Var(this.srcPos, "S");
        }
    }
});

function K(srcPos) {
    if (!(this instanceof K)) {
        return new K(srcPos);
    }
    Token.call(this, srcPos);
}

K.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": K
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "K";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Var(this.srcPos, "K");
        }
    }
});

function I(srcPos) {
    if (!(this instanceof I)) {
        return new I(srcPos);
    }
    Token.call(this, srcPos);
}

I.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": I
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "I";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Var(this.srcPos, "I");
        }
    }
});

function Iota(srcPos) {
    if (!(this instanceof Iota)) {
        return new Iota(srcPos);
    }
    Token.call(this, srcPos);
}

Iota.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": Iota
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "i";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Var(this.srcPos, "iota");
        }
    }
});

function Application(srcPos, func, arg) {
    if (!(this instanceof Application)) {
        return new Application(srcPos, func, arg);
    }
    Token.call(this, srcPos);
    this.func = func;
    this.arg  = arg;
}

Application.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": Application
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "`" + this.func.toString() + this.arg.toString();
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Application(
                this.srcPos,
                this.func.toExpression(),
                this.arg.toExpression()
            );
        }
    }
});

endModule();
<commit_msg>Fix wrong name Var<commit_after>/*
 * LazyK-JS /lib/tokens.js
 * copyright (c) 2015 Susisu
 */

"use strict";

function endModule() {
    module.exports = Object.freeze({
        "Token"      : Token,
        "S"          : S,
        "K"          : K,
        "I"          : I,
        "Iota"       : Iota,
        "Application": Application
    });
}

var lambda = require("./lambda.js");

function Token(srcPos) {
    if (!(this instanceof Token)) {
        return new Token(srcPos);
    }
    this.srcPos = srcPos;
}

Token.prototype = Object.create(Object.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": Token
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "?";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            throw new Error("invalid token");
        }
    }
});

function S(srcPos) {
    if (!(this instanceof S)) {
        return new S(srcPos);
    }
    Token.call(this, srcPos);
}

S.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": S
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "S";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Variable(this.srcPos, "S");
        }
    }
});

function K(srcPos) {
    if (!(this instanceof K)) {
        return new K(srcPos);
    }
    Token.call(this, srcPos);
}

K.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": K
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "K";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Variable(this.srcPos, "K");
        }
    }
});

function I(srcPos) {
    if (!(this instanceof I)) {
        return new I(srcPos);
    }
    Token.call(this, srcPos);
}

I.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": I
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "I";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Variable(this.srcPos, "I");
        }
    }
});

function Iota(srcPos) {
    if (!(this instanceof Iota)) {
        return new Iota(srcPos);
    }
    Token.call(this, srcPos);
}

Iota.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": Iota
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "i";
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Variable(this.srcPos, "iota");
        }
    }
});

function Application(srcPos, func, arg) {
    if (!(this instanceof Application)) {
        return new Application(srcPos, func, arg);
    }
    Token.call(this, srcPos);
    this.func = func;
    this.arg  = arg;
}

Application.prototype = Object.create(Token.prototype, {
    "constructor": {
        "writable"    : true,
        "configurable": true,
        "value": Application
    },
    "toString": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return "`" + this.func.toString() + this.arg.toString();
        }
    },
    "toExpression": {
        "writable"    : true,
        "configurable": true,
        "value": function () {
            return new lambda.Application(
                this.srcPos,
                this.func.toExpression(),
                this.arg.toExpression()
            );
        }
    }
});

endModule();
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var async = require('async');
var winston = require('winston');

var SATOSHI_FACTOR = Math.pow(10, 8);

var Trader = module.exports = function (db) {
  if (!db) {
    throw new Error('`db` is required');
  }

  this.db = db;
  this.rates = {};
  this.logger = new (winston.Logger)({
    transports: [new (winston.transports.Console)()]
  });

  this._tradeQueue = [];
};

Trader.prototype._findExchange = function (name) {
  var exchange;

  try {
    exchange = require('lamassu-' + name);
  } catch (err) {
    if (!err.message.match(/Cannot find module/)) {
      throw err;
    }

    exchange = require(path.join(path.dirname(__dirname), 'exchanges', name));
  }

  return exchange;
};

Trader.prototype._findTicker = function (name) {
  var exchange = Trader.prototype._findExchange(name);
  return exchange.ticker || exchange;
};

Trader.prototype._findTrader = function (name) {
  var exchange = Trader.prototype._findExchange(name);
  return exchange.trader || exchange;
};

Trader.prototype._findWallet = function (name) {
  var exchange = Trader.prototype._findExchange(name);
  return exchange.wallet || exchange;
};

Trader.prototype.configure = function (config) {
  if (config.exchanges.settings.lowBalanceMargin < 1) {
    throw new Error('`settings.lowBalanceMargin` has to be >= 1');
  }

  var tickerExchangeCode = config.exchanges.plugins.current.ticker;
  var tickerExchangeConfig = config.exchanges.plugins.settings[tickerExchangeCode] || {};
  tickerExchangeConfig.currency = config.exchanges.settings.currency;
  this.tickerExchange = this._findTicker(tickerExchangeCode).factory(tickerExchangeConfig);

  var tradeExchangeCode = config.exchanges.plugins.current.trade;
  if (tradeExchangeCode) {
    var tradeExchangeConfig = config.exchanges.plugins.settings[tradeExchangeCode];
    this.tradeExchange = this._findTrader(tradeExchangeCode).factory(tradeExchangeConfig);
  }

  var transferExchangeCode = config.exchanges.plugins.current.transfer;
  var transferExchangeConfig = config.exchanges.plugins.settings[transferExchangeCode];
  this.transferExchange = this._findWallet(transferExchangeCode).factory(transferExchangeConfig);

  this.config = config;
};

/**
 * return fiat balance
 *
 * in input to this function, balance has the following parameters...
 *
 * balance.transferBalance - in satoshis
 * balance.tradeBalance    - in USD
 *
 * Have added conversion here, but this really needs to be thought through, lamassu-bitstamp should perhaps
 * return balance in satoshis
 */
Trader.prototype.fiatBalance = function (transferSatoshis, tradeFiat) {
  var rate = this.rate(this.config.exchanges.settings.currency).rate;
  var balance = this.balance;
  var commission = this.config.exchanges.settings.commission;

  if (!rate || !balance) {
    return 0;
  }

  // The rate is actually our commission times real rate.
  rate = commission * rate;

  // `lowBalanceMargin` is our safety net. It's a number > 1, and we divide
  // all our balances by it to provide a safety margin.
  var lowBalanceMargin = this.config.exchanges.settings.lowBalanceMargin;

  // `balance.transferBalance` is the balance of our transfer account (the one
  // we use to send Bitcoins to clients). `transferSatoshis` is the number
  // of satoshis we're expected to send for this transaction. By subtracting
  // them, we get `adjustedTransferBalance`, amount of satoshis we'll have
  // after the transaction.
  var adjustedTransferBalance = balance.transferBalance - transferSatoshis;

  // Since `adjustedTransferBalance` is in Satoshis, we need to turn it into
  // Bitcoins and then fiat to learn how much fiat currency we can exchange.
  //
  // Unit validity proof: [ $ ] = [ (B * 10^8) / 10^8 * $/B ]
  //                      [ $ ] = [ B * $/B ]
  //                      [ $ ] = [ $ ]
  var fiatTransferBalance = ((adjustedTransferBalance / SATOSHI_FACTOR) * rate) / lowBalanceMargin;

  return fiatTransferBalance;
};

Trader.prototype.sendBitcoins = function (deviceFingerprint, tx, cb) {
  var self = this;

  self.db.summonTransaction(deviceFingerprint, tx, function (err, isNew, txHash) {
    if (err) {
      return cb(err);
    }

    if (isNew) {
      return self.transferExchange.sendBitcoins(
        tx.toAddress,
        tx.satoshis,
        self.config.exchanges.settings.transactionFee,
        function(err, txHash) {
          if (err) {
            self.db.reportTransactionError(tx, err);
            return cb(err);
          }

          cb(null, txHash);
          self.db.completeTransaction(tx, txHash);
          self.pollRate();
        }
      );
    }

    // transaction exists, but txHash might be null,
    // in which case ATM should continue polling
    cb(null, txHash);
  });
};

Trader.prototype.trade = function (fiat, satoshis, currency, callback) {
  this._tradeQueue.push({fiat: fiat, satoshis: satoshis, currency: currency});
  callback(null);
};

Trader.prototype.tradeQueueFiatBalance = function (exchangeRate) {
  var satoshis = this._tradeQueue.reduce(function (memo, rec) {
    return memo + rec.satoshis;
  }, 0);
  return (satoshis / SATOSHI_FACTOR) * exchangeRate;
};

Trader.prototype._consolidateTrades = function () {
  var queue = this._tradeQueue;

  var tradeRec = {
    fiat: 0,
    satoshis: 0,
    currency: 'USD'
  };

  while (true) {
    var lastRec = queue.shift();
    if (!lastRec) {
      break;
    }
    tradeRec.fiat += lastRec.fiat;
    tradeRec.satoshis += lastRec.satoshis;
    tradeRec.currency = lastRec.currency;
  }
  return tradeRec;
};

Trader.prototype.startPolling = function () {
  this.pollBalance();
  this.pollRate();

  this.balanceInterval = setInterval(this.pollBalance.bind(this), 60 * 1000);
  this.rateInterval = setInterval(this.pollRate.bind(this), 60 * 1000);
};

Trader.prototype.stopPolling = function () {
  clearInterval(this.balanceInterval);
  clearInterval(this.rateInterval);
};

Trader.prototype.pollBalance = function (callback) {
  var self = this;

  self.logger.info('collecting balance');

  async.parallel({
    transferBalance: self.transferExchange.balance.bind(self.transferExchange),
    tradeBalance: function (next) {
      if (!self.tradeExchange) {
        return next(null, null);
      }

      self.tradeExchange.balance(next);
    }
  }, function (err, balance) {
    if (err) {
      return callback && callback(err);
    }

    balance.timestamp = Date.now();
    self.logger.info('Balance update:', balance);
    self.balance = balance;

    return callback && callback(null, balance);
  });
};

Trader.prototype.pollRate = function (callback) {
  var self = this;

  var currency = self.config.exchanges.settings.currency;
  self.logger.info('polling for rate...');
  self.tickerExchange.ticker(currency, function(err, rate) {
    if (err) {
      return callback && callback(err);
    }

    self.logger.info('Rate update:', rate);
    self.rates[currency] = {rate: rate, timestamp: new Date()};
    return callback && callback(null, self.rates[currency]);
  });
};

Trader.prototype.rate = function (currency) {
  return this.rates[currency];
};
<commit_msg>Default to Trader's currency<commit_after>'use strict';

var path = require('path');
var async = require('async');
var winston = require('winston');

var SATOSHI_FACTOR = Math.pow(10, 8);

var Trader = module.exports = function (db) {
  if (!db) {
    throw new Error('`db` is required');
  }

  this.db = db;
  this.rates = {};
  this.logger = new (winston.Logger)({
    transports: [new (winston.transports.Console)()]
  });

  this._tradeQueue = [];
};

Trader.prototype._findExchange = function (name) {
  var exchange;

  try {
    exchange = require('lamassu-' + name);
  } catch (err) {
    if (!err.message.match(/Cannot find module/)) {
      throw err;
    }

    exchange = require(path.join(path.dirname(__dirname), 'exchanges', name));
  }

  return exchange;
};

Trader.prototype._findTicker = function (name) {
  var exchange = Trader.prototype._findExchange(name);
  return exchange.ticker || exchange;
};

Trader.prototype._findTrader = function (name) {
  var exchange = Trader.prototype._findExchange(name);
  return exchange.trader || exchange;
};

Trader.prototype._findWallet = function (name) {
  var exchange = Trader.prototype._findExchange(name);
  return exchange.wallet || exchange;
};

Trader.prototype.configure = function (config) {
  if (config.exchanges.settings.lowBalanceMargin < 1) {
    throw new Error('`settings.lowBalanceMargin` has to be >= 1');
  }

  var tickerExchangeCode = config.exchanges.plugins.current.ticker;
  var tickerExchangeConfig = config.exchanges.plugins.settings[tickerExchangeCode] || {};
  tickerExchangeConfig.currency = config.exchanges.settings.currency;
  this.tickerExchange = this._findTicker(tickerExchangeCode).factory(tickerExchangeConfig);

  var tradeExchangeCode = config.exchanges.plugins.current.trade;
  if (tradeExchangeCode) {
    var tradeExchangeConfig = config.exchanges.plugins.settings[tradeExchangeCode];
    this.tradeExchange = this._findTrader(tradeExchangeCode).factory(tradeExchangeConfig);
  }

  var transferExchangeCode = config.exchanges.plugins.current.transfer;
  var transferExchangeConfig = config.exchanges.plugins.settings[transferExchangeCode];
  this.transferExchange = this._findWallet(transferExchangeCode).factory(transferExchangeConfig);

  this.config = config;
};

/**
 * return fiat balance
 *
 * in input to this function, balance has the following parameters...
 *
 * balance.transferBalance - in satoshis
 * balance.tradeBalance    - in USD
 *
 * Have added conversion here, but this really needs to be thought through, lamassu-bitstamp should perhaps
 * return balance in satoshis
 */
Trader.prototype.fiatBalance = function (transferSatoshis, tradeFiat) {
  var rate = this.rate(this.config.exchanges.settings.currency).rate;
  var balance = this.balance;
  var commission = this.config.exchanges.settings.commission;

  if (!rate || !balance) {
    return 0;
  }

  // The rate is actually our commission times real rate.
  rate = commission * rate;

  // `lowBalanceMargin` is our safety net. It's a number > 1, and we divide
  // all our balances by it to provide a safety margin.
  var lowBalanceMargin = this.config.exchanges.settings.lowBalanceMargin;

  // `balance.transferBalance` is the balance of our transfer account (the one
  // we use to send Bitcoins to clients). `transferSatoshis` is the number
  // of satoshis we're expected to send for this transaction. By subtracting
  // them, we get `adjustedTransferBalance`, amount of satoshis we'll have
  // after the transaction.
  var adjustedTransferBalance = balance.transferBalance - transferSatoshis;

  // Since `adjustedTransferBalance` is in Satoshis, we need to turn it into
  // Bitcoins and then fiat to learn how much fiat currency we can exchange.
  //
  // Unit validity proof: [ $ ] = [ (B * 10^8) / 10^8 * $/B ]
  //                      [ $ ] = [ B * $/B ]
  //                      [ $ ] = [ $ ]
  var fiatTransferBalance = ((adjustedTransferBalance / SATOSHI_FACTOR) * rate) / lowBalanceMargin;

  return fiatTransferBalance;
};

Trader.prototype.sendBitcoins = function (deviceFingerprint, tx, cb) {
  var self = this;

  self.db.summonTransaction(deviceFingerprint, tx, function (err, isNew, txHash) {
    if (err) {
      return cb(err);
    }

    if (isNew) {
      return self.transferExchange.sendBitcoins(
        tx.toAddress,
        tx.satoshis,
        self.config.exchanges.settings.transactionFee,
        function(err, txHash) {
          if (err) {
            self.db.reportTransactionError(tx, err);
            return cb(err);
          }

          cb(null, txHash);
          self.db.completeTransaction(tx, txHash);
          self.pollRate();
        }
      );
    }

    // transaction exists, but txHash might be null,
    // in which case ATM should continue polling
    cb(null, txHash);
  });
};

Trader.prototype.trade = function (fiat, satoshis, currency, callback) {
  this._tradeQueue.push({fiat: fiat, satoshis: satoshis, currency: currency});
  callback(null);
};

Trader.prototype.tradeQueueFiatBalance = function (exchangeRate) {
  var satoshis = this._tradeQueue.reduce(function (memo, rec) {
    return memo + rec.satoshis;
  }, 0);
  return (satoshis / SATOSHI_FACTOR) * exchangeRate;
};

Trader.prototype._consolidateTrades = function () {
  var queue = this._tradeQueue;

  var tradeRec = {
    fiat: 0,
    satoshis: 0,
    currency: this.config.exchanges.settings.currency
  };

  while (true) {
    var lastRec = queue.shift();
    if (!lastRec) {
      break;
    }
    tradeRec.fiat += lastRec.fiat;
    tradeRec.satoshis += lastRec.satoshis;
    tradeRec.currency = lastRec.currency;
  }
  return tradeRec;
};

Trader.prototype.startPolling = function () {
  this.pollBalance();
  this.pollRate();

  this.balanceInterval = setInterval(this.pollBalance.bind(this), 60 * 1000);
  this.rateInterval = setInterval(this.pollRate.bind(this), 60 * 1000);
};

Trader.prototype.stopPolling = function () {
  clearInterval(this.balanceInterval);
  clearInterval(this.rateInterval);
};

Trader.prototype.pollBalance = function (callback) {
  var self = this;

  self.logger.info('collecting balance');

  async.parallel({
    transferBalance: self.transferExchange.balance.bind(self.transferExchange),
    tradeBalance: function (next) {
      if (!self.tradeExchange) {
        return next(null, null);
      }

      self.tradeExchange.balance(next);
    }
  }, function (err, balance) {
    if (err) {
      return callback && callback(err);
    }

    balance.timestamp = Date.now();
    self.logger.info('Balance update:', balance);
    self.balance = balance;

    return callback && callback(null, balance);
  });
};

Trader.prototype.pollRate = function (callback) {
  var self = this;

  var currency = self.config.exchanges.settings.currency;
  self.logger.info('polling for rate...');
  self.tickerExchange.ticker(currency, function(err, rate) {
    if (err) {
      return callback && callback(err);
    }

    self.logger.info('Rate update:', rate);
    self.rates[currency] = {rate: rate, timestamp: new Date()};
    return callback && callback(null, self.rates[currency]);
  });
};

Trader.prototype.rate = function (currency) {
  return this.rates[currency];
};
<|endoftext|>


<commit_before>'use strict'

const EventEmitter = require('events').EventEmitter
const qs = require('querystring')
const util = require('util')
const uuid = require('uuid')
const _ = require('lodash/fp')

const BN = require('./bn')

const mapValuesWithKey = _.mapValues.convert({ 'cap': false })

const _request = require('./request')

const POLL_TIMEOUT = 10000
const DISPENSE_TIMEOUT = 120000

let _t0 = null
const pid = uuid.v4()

// TODO: need to pass global options to request
const Trader = function (protocol, clientCert, connectionInfo) {
  if (!(this instanceof Trader)) return new Trader(protocol, clientCert, connectionInfo)
  EventEmitter.call(this)

  const globalOptions = {
    protocol,
    connectionInfo,
    clientCert
  }

  this.request = options => _request.request(this.configVersion, globalOptions, options)
  this.globalOptions = globalOptions
  this.balanceRetries = 0
  this.pollRetries = 0
  this.state = {state: 'initial', isIdle: false}
  this.configVersion = null
}
util.inherits(Trader, EventEmitter)

Trader.prototype.clearConfigVersion = function clearConfigVersion () {
  this.configVersion = null
}

Trader.prototype.setConfigVersion = function setConfigVersion () {
  if (!this.latestConfigVersion) throw new Error('We don\'t have a configVersion')
  this.configVersion = this.latestConfigVersion
}

Trader.prototype.verifyUser = function verifyUser (idRec, cb) {
  console.log(idRec)
  return this.request({
    path: '/verify_user',
    method: 'POST',
    body: idRec
  })
}

Trader.prototype.rates = function rates (cryptoCode) {
  if (this._rates) return this._rates[cryptoCode]
}

Trader.prototype.verifyTransaction = function verifyTransaction (idRec) {
  console.log(idRec)

  return this.request({
    path: '/verify_transaction',
    method: 'POST',
    body: idRec
  }).catch(err => console.log(err))
}

Trader.prototype.reportEvent = function reportEvent (eventType, note) {
  const rec = {
    eventType: eventType,
    note: note,
    deviceTime: Date.now()
  }

  return this.request({
    path: '/event',
    method: 'POST',
    body: rec
  }).catch(err => console.log(err.stack))
}

Trader.prototype.poll = function poll () {
  const stateRec = this.state

  const path = '/poll?state=' + stateRec.state + '&idle=' + stateRec.isIdle + '&pid=' + pid

  return this.request({
    path,
    method: 'GET',
    noRetry: true
  })
  .then(r => this.pollHandler(r.body))
  .catch(err => this.pollError(err))
}

function massage (tx) {
  if (!tx) return tx
  return _.assign(tx, {cryptoAtoms: BN(tx.cryptoAtoms), fiat: BN(tx.fiat)})
}

Trader.prototype.postTx = function postTx (tx) {
  // Don't retry because that's handled at a higher level.
  return this.request({
    path: '/tx',
    method: 'POST',
    body: tx,
    noRetry: true
  })
  .then(r => massage(r.body))
  .catch(err => {
    if (isNetworkError(err)) return
    throw err
  })
}

function isNetworkError (err) {
  switch (err.name) {
    case 'RequestError':
    case 'ReadError':
    case 'ParseError':
      return true
    default:
      return false
  }
}

Trader.prototype.stateChange = function stateChange (state, isIdle) {
  this.state = {state: state, isIdle: isIdle}

  const rec = {state: state, isIdle: isIdle, uuid: uuid.v4()}

  // Don't retry because we're only interested in the current state
  // and things could get confused.
  return this.request({
    path: '/state',
    method: 'POST',
    body: rec,
    noRetry: true
  }).catch(() => {})
}

Trader.prototype.phoneCode = function phoneCode (phone) {
  return this.request({
    path: '/phone_code',
    method: 'POST',
    body: {phone}
  })
  .then(r => r.body)
  .catch(err => {
    if (err && err.statusCode === 401) {
      const badNumberErr = new Error('Bad phone number')
      badNumberErr.name = 'BadNumberError'
      throw (badNumberErr)
    }

    throw err
  })
}

Trader.prototype.fetchPhoneTx = function fetchPhoneTx (phone) {
  return this.request({
    path: '/tx?' + qs.stringify({phone}),
    method: 'GET'
  })
  .then(r => massage(r.body))
}

Trader.prototype.waitForOneDispense = function waitForOneDispense (tx, status) {
  return this.request({
    path: `/tx/${tx.id}?status=${status}`,
    method: 'GET',
    noRetry: true
  })
  .then(r => massage(r.body))
}

Trader.prototype.waitForDispense = function waitForDispense (tx, status) {
  let processing = false
  let timedout = false
  const t0 = Date.now()

  return new Promise((resolve, reject) => {
    const intervalHandle = setInterval(() => {
      if (processing) return

      processing = true
      if (Date.now() - t0 > DISPENSE_TIMEOUT) {
        timedout = true
        clearInterval(intervalHandle)
        return reject(new Error('Dispense timeout'))
      }

      this.waitForOneDispense(tx, status)
      .then(newTx => {
        processing = false

        if (timedout) return

        clearInterval(intervalHandle)

        return resolve(newTx)
      })
      .catch(err => {
        processing = false

        if (isNetworkError(err) || err.statusCode === 304) return

        clearInterval(intervalHandle)
        return reject(err)
      })
    }, 1000)
  })
}

Trader.prototype.pollHandler = function pollHandler (res) {
  _t0 = null

  this.txLimit = BN(res.txLimit || Infinity)
  this.fiatTxLimit = BN(res.fiatTxLimit || Infinity)
  this.idVerificationLimit = res.idVerificationLimit
  this.idVerificationEnabled = res.idVerificationEnabled
  this.smsVerificationEnabled = res.smsVerificationEnabled

  this.locale = res.locale

  if (res.cassettes) {
    const mapper = (v, k) => k === 'denomination' ? BN(v) : v
    this.cassettes = _.map(mapValuesWithKey(mapper), res.cassettes.cassettes)
    this.virtualCassettes = _.map(BN, res.cassettes.virtualCassettes)
  }

  this.twoWayMode = res.twoWayMode
  this.zeroConfLimit = res.zeroConfLimit
  this._rates = _.mapValues(_.mapValues(BN), res.rates)

  this.balances = _.mapValues(BN, res.balances)
  this.coins = filterCoins(res)
  this.latestConfigVersion = res.configVersion

  if (this.coins.length === 0) {
    console.log('No responsive coins, going to Network Down.')
    return this.emit('networkDown')
  }

  this.newState = isNewState(res)

  if (res.reboot) this.emit('reboot')
  this.emit('pollUpdate')
  this.emit('networkUp')
}

Trader.prototype.networkDown = function networkDown () {
  if (_t0 === null) {
    _t0 = Date.now()
    return
  }

  if (Date.now() - _t0 > POLL_TIMEOUT) {
    _t0 = null
    this.emit('networkDown')
    return
  }
}

Trader.prototype.pollError = function pollError (err) {
  if (isNetworkError(err)) return this.networkDown()

  _t0 = null
  if (err.statusCode === 403) return this.emit('unpair')
  this.emit('networkDown')
}

let oldState = {}
function isNewState (res) {
  const pare = _.pick(['twoWayMode', 'coins', 'locale'])
  if (_.isEqual(pare(res), pare(oldState))) return false

  oldState = res
  return true
}

function filterCoins (res) {
  const coins = res.coins || ['BTC']
  return coins.filter(function (coin) {
    return !_.isNil(res.rates[coin]) && !_.isNil(res.balances[coin])
  })
}

module.exports = Trader
<commit_msg>send ping serial number<commit_after>'use strict'

const EventEmitter = require('events').EventEmitter
const qs = require('querystring')
const util = require('util')
const uuid = require('uuid')
const _ = require('lodash/fp')

const BN = require('./bn')

const mapValuesWithKey = _.mapValues.convert({ 'cap': false })

const _request = require('./request')

const POLL_TIMEOUT = 10000
const DISPENSE_TIMEOUT = 120000

let _t0 = null
let serialNumber = 0
const pid = uuid.v4()

// TODO: need to pass global options to request
const Trader = function (protocol, clientCert, connectionInfo) {
  if (!(this instanceof Trader)) return new Trader(protocol, clientCert, connectionInfo)
  EventEmitter.call(this)

  const globalOptions = {
    protocol,
    connectionInfo,
    clientCert
  }

  this.request = options => _request.request(this.configVersion, globalOptions, options)
  this.globalOptions = globalOptions
  this.balanceRetries = 0
  this.pollRetries = 0
  this.state = {state: 'initial', isIdle: false}
  this.configVersion = null
}
util.inherits(Trader, EventEmitter)

Trader.prototype.clearConfigVersion = function clearConfigVersion () {
  this.configVersion = null
}

Trader.prototype.setConfigVersion = function setConfigVersion () {
  if (!this.latestConfigVersion) throw new Error('We don\'t have a configVersion')
  this.configVersion = this.latestConfigVersion
}

Trader.prototype.verifyUser = function verifyUser (idRec, cb) {
  console.log(idRec)
  return this.request({
    path: '/verify_user',
    method: 'POST',
    body: idRec
  })
}

Trader.prototype.rates = function rates (cryptoCode) {
  if (this._rates) return this._rates[cryptoCode]
}

Trader.prototype.verifyTransaction = function verifyTransaction (idRec) {
  console.log(idRec)

  return this.request({
    path: '/verify_transaction',
    method: 'POST',
    body: idRec
  }).catch(err => console.log(err))
}

Trader.prototype.reportEvent = function reportEvent (eventType, note) {
  const rec = {
    eventType: eventType,
    note: note,
    deviceTime: Date.now()
  }

  return this.request({
    path: '/event',
    method: 'POST',
    body: rec
  }).catch(err => console.log(err.stack))
}

Trader.prototype.poll = function poll () {
  const stateRec = this.state

  const path = '/poll?state=' + stateRec.state + '&idle=' + stateRec.isIdle + '&pid=' + pid + '&sn=' + serialNumber.toString()
  serialNumber++

  return this.request({
    path,
    method: 'GET',
    noRetry: true
  })
  .then(r => this.pollHandler(r.body))
  .catch(err => this.pollError(err))
}

function massage (tx) {
  if (!tx) return tx
  return _.assign(tx, {cryptoAtoms: BN(tx.cryptoAtoms), fiat: BN(tx.fiat)})
}

Trader.prototype.postTx = function postTx (tx) {
  // Don't retry because that's handled at a higher level.
  return this.request({
    path: '/tx',
    method: 'POST',
    body: tx,
    noRetry: true
  })
  .then(r => massage(r.body))
  .catch(err => {
    if (isNetworkError(err)) return
    throw err
  })
}

function isNetworkError (err) {
  switch (err.name) {
    case 'RequestError':
    case 'ReadError':
    case 'ParseError':
      return true
    default:
      return false
  }
}

Trader.prototype.stateChange = function stateChange (state, isIdle) {
  this.state = {state: state, isIdle: isIdle}

  const rec = {state: state, isIdle: isIdle, uuid: uuid.v4()}

  // Don't retry because we're only interested in the current state
  // and things could get confused.
  return this.request({
    path: '/state',
    method: 'POST',
    body: rec,
    noRetry: true
  }).catch(() => {})
}

Trader.prototype.phoneCode = function phoneCode (phone) {
  return this.request({
    path: '/phone_code',
    method: 'POST',
    body: {phone}
  })
  .then(r => r.body)
  .catch(err => {
    if (err && err.statusCode === 401) {
      const badNumberErr = new Error('Bad phone number')
      badNumberErr.name = 'BadNumberError'
      throw (badNumberErr)
    }

    throw err
  })
}

Trader.prototype.fetchPhoneTx = function fetchPhoneTx (phone) {
  return this.request({
    path: '/tx?' + qs.stringify({phone}),
    method: 'GET'
  })
  .then(r => massage(r.body))
}

Trader.prototype.waitForOneDispense = function waitForOneDispense (tx, status) {
  return this.request({
    path: `/tx/${tx.id}?status=${status}`,
    method: 'GET',
    noRetry: true
  })
  .then(r => massage(r.body))
}

Trader.prototype.waitForDispense = function waitForDispense (tx, status) {
  let processing = false
  let timedout = false
  const t0 = Date.now()

  return new Promise((resolve, reject) => {
    const intervalHandle = setInterval(() => {
      if (processing) return

      processing = true
      if (Date.now() - t0 > DISPENSE_TIMEOUT) {
        timedout = true
        clearInterval(intervalHandle)
        return reject(new Error('Dispense timeout'))
      }

      this.waitForOneDispense(tx, status)
      .then(newTx => {
        processing = false

        if (timedout) return

        clearInterval(intervalHandle)

        return resolve(newTx)
      })
      .catch(err => {
        processing = false

        if (isNetworkError(err) || err.statusCode === 304) return

        clearInterval(intervalHandle)
        return reject(err)
      })
    }, 1000)
  })
}

Trader.prototype.pollHandler = function pollHandler (res) {
  _t0 = null

  this.txLimit = BN(res.txLimit || Infinity)
  this.fiatTxLimit = BN(res.fiatTxLimit || Infinity)
  this.idVerificationLimit = res.idVerificationLimit
  this.idVerificationEnabled = res.idVerificationEnabled
  this.smsVerificationEnabled = res.smsVerificationEnabled

  this.locale = res.locale

  if (res.cassettes) {
    const mapper = (v, k) => k === 'denomination' ? BN(v) : v
    this.cassettes = _.map(mapValuesWithKey(mapper), res.cassettes.cassettes)
    this.virtualCassettes = _.map(BN, res.cassettes.virtualCassettes)
  }

  this.twoWayMode = res.twoWayMode
  this.zeroConfLimit = res.zeroConfLimit
  this._rates = _.mapValues(_.mapValues(BN), res.rates)

  this.balances = _.mapValues(BN, res.balances)
  this.coins = filterCoins(res)
  this.latestConfigVersion = res.configVersion

  if (this.coins.length === 0) {
    console.log('No responsive coins, going to Network Down.')
    return this.emit('networkDown')
  }

  this.newState = isNewState(res)

  if (res.reboot) this.emit('reboot')
  this.emit('pollUpdate')
  this.emit('networkUp')
}

Trader.prototype.networkDown = function networkDown () {
  if (_t0 === null) {
    _t0 = Date.now()
    return
  }

  if (Date.now() - _t0 > POLL_TIMEOUT) {
    _t0 = null
    this.emit('networkDown')
    return
  }
}

Trader.prototype.pollError = function pollError (err) {
  if (isNetworkError(err)) return this.networkDown()

  _t0 = null
  if (err.statusCode === 403) return this.emit('unpair')
  this.emit('networkDown')
}

let oldState = {}
function isNewState (res) {
  const pare = _.pick(['twoWayMode', 'coins', 'locale'])
  if (_.isEqual(pare(res), pare(oldState))) return false

  oldState = res
  return true
}

function filterCoins (res) {
  const coins = res.coins || ['BTC']
  return coins.filter(function (coin) {
    return !_.isNil(res.rates[coin]) && !_.isNil(res.balances[coin])
  })
}

module.exports = Trader
<|endoftext|>


<commit_before>var config = require("./config");
var MongoClient = require("mongodb").MongoClient;
var TripleGraph = require('./graph');

/**
 * Main tripod object
 * @constructor
 */
var Tripod = function(dbName,collectionName) {
    this._config = config;
    this._connStr = config.get("databases:"+dbName+":connStr")+"/"+dbName;
    this._collectionName = collectionName;
    this._collection = null;
    this._viewsCollection = null;
};

/**
 * Describe resource r in named context c
 * @param r
 * @param c if null will default to config.defaultContext
 * @param callback
 */
Tripod.prototype.describe = function(r,c,callback) {
    c = (c==null) ? this._config.get("defaultContext") : c;
    // todo: alias c and r
    this._getCollection(function(err,collection) {
        collection.findOne({_id:{"r":r,"c":c}},function(err,doc) {
            if (err) {
                callback(err,null);
            } else {
                var graph = new TripleGraph();
                graph.addTripodDoc(doc);
                callback(null,graph);
            }
        })
    })
};

/**
 * Describe resources represented in the Array ids
 * @param ids Array containing id objects {r:.. c:..}
 * @param callback
 */
Tripod.prototype.multiDescribe = function(ids,callback) {
    var query = {_id: {'$in':ids}};
    this._getCollection(function(err,collection) {
        collection.find(query).toArray(function(err,docs) {
            if (err) {
                callback(err,null);
            } else {
                var graph = new TripleGraph();
                docs.forEach(function(doc) {
                    graph.addTripodDoc(doc);
                });
                callback(null,graph);
            }
        })
    })
};

/**
 * Get a graph containing view of type v for resource
 * @param v - view type
 * @param r - resource
 * @param c - context, if null default context used
 * @param callback
 */
Tripod.prototype.getViewForResource = function (v,r,c,callback) {
    c = (c==null) ? this._config.get("defaultContext") : c;
    this._getViewsCollection(function(err,collection) {
        collection.findOne({_id:{"r":r,"c":c,type:v}},function(err,doc) {
            if (err) {
                callback(err,null);
            } else {
                var graph = new TripleGraph();
                graph.addTripodDoc(doc);
                callback(null,graph);
            }
        });
    });
};

/**
 * Get a graph containing the views of type v for the resources represented in the Array ids
 * @param v - view type
 * @param ids Array containing id objects {r:.. c:..}
 * @param callback
 */
Tripod.prototype.getViewForResources = function (v,ids,callback) {
    var idsWithType = [];
    ids.forEach(function(id) {
        var idWithType = _.clone(id);
        idsWithType['type'] = v;
        idsWithType.push(idWithType);
    });
    var query = {_id: {'$in':idsWithType}};
    this._getViewsCollection(function(err,collection) {
        collection.find(query).toArray(function(err,docs) {
            if (err) {
                callback(err,null);
            } else {
                var graph = new TripleGraph();
                docs.forEach(function(doc) {
                    graph.addTripodDoc(doc);
                });
                callback(null,graph);
            }
        })
    });
};

/**
 * Lazy-load collection
 * @param callback
 * @private
 */
Tripod.prototype._getCollection = function(callback) {
    if (this._collection == null) {
        var self = this;
        MongoClient.connect(this._connStr,function(err,db) {
            if (err) {
                callback(err,null);
            } else {
                db.collection(self._collectionName, function(err,collection) { // todo: check if collection is in config...?
                    if (err) {
                        callback(err,null);
                    } else {
                        self._collection = collection;
                        callback(null,collection)
                    }
                });
            }
        });
    } else {
        callback(null,this._collection);
    }
};

/**
 * Lazy-load views collection
 * @param callback
 * @private
 */
Tripod.prototype._getViewsCollection = function(callback) {
    if (this._viewsCollection == null) {
        var self = this;
        MongoClient.connect(this._connStr,function(err,db) {
            if (err) {
                callback(err,null);
            } else {
                db.collection("views", function(err,collection) {
                    if (err) {
                        callback(err,null);
                    } else {
                        self._viewsCollection = collection;
                        callback(null,collection)
                    }
                });
            }
        });
    } else {
        callback(null,this._viewsCollection);
    }
};

exports = module.exports = Tripod;
<commit_msg>Adding graph() method<commit_after>var config = require("./config");
var MongoClient = require("mongodb").MongoClient;
var TripleGraph = require('./graph');

/**
 * Main tripod object
 * @constructor
 */
var Tripod = function(dbName,collectionName) {
    this._config = config;
    this._connStr = config.get("databases:"+dbName+":connStr")+"/"+dbName;
    this._collectionName = collectionName;
    this._collection = null;
    this._viewsCollection = null;
};

/**
 * Describe resource r in named context c
 * @param r
 * @param c if null will default to config.defaultContext
 * @param callback
 */
Tripod.prototype.describe = function(r,c,callback) {
    c = (c==null) ? this._config.get("defaultContext") : c;
    // todo: alias c and r
    this.graph({_id:{"r":r,"c":c}},callback);
};

/**
 * Describe resources represented in the Array ids
 * @param ids Array containing id objects {r:.. c:..}
 * @param callback
 */
Tripod.prototype.multiDescribe = function(ids,callback) {
    this.graph({_id: {'$in':ids}},callback);
};

/**
 * Get a graph containing view of type v for resource
 * @param v - view type
 * @param r - resource
 * @param c - context, if null default context used
 * @param callback
 */
Tripod.prototype.getViewForResource = function (v,r,c,callback) {
    c = (c==null) ? this._config.get("defaultContext") : c;
    this._getViewsCollection(function(err,collection) {
        collection.findOne({_id:{"r":r,"c":c,type:v}},function(err,doc) {
            if (err) {
                callback(err,null);
            } else {
                var graph = new TripleGraph();
                graph.addTripodDoc(doc);
                callback(null,graph);
            }
        });
    });
};

/**
 * Fetch a graph based on a query
 * @param query
 * @param callback
 */
Tripod.prototype.graph = function(query,callback) {
    this._getCollection(function(err,collection) {
        collection.find(query).toArray(function(err,docs) {
            if (err) {
                callback(err,null);
            } else {
                var graph = new TripleGraph();
                docs.forEach(function(doc) {
                    graph.addTripodDoc(doc);
                });
                callback(null,graph);
            }
        })
    })
}

/**
 * Get a graph containing the views of type v for the resources represented in the Array ids
 * @param v - view type
 * @param ids Array containing id objects {r:.. c:..}
 * @param callback
 */
Tripod.prototype.getViewForResources = function (v,ids,callback) {
    var idsWithType = [];
    ids.forEach(function(id) {
        var idWithType = _.clone(id);
        idsWithType['type'] = v;
        idsWithType.push(idWithType);
    });
    var query = {_id: {'$in':idsWithType}};
    this._getViewsCollection(function(err,collection) {
        collection.find(query).toArray(function(err,docs) {
            if (err) {
                callback(err,null);
            } else {
                var graph = new TripleGraph();
                docs.forEach(function(doc) {
                    graph.addTripodDoc(doc);
                });
                callback(null,graph);
            }
        })
    });
};

/**
 * Lazy-load collection
 * @param callback
 * @private
 */
Tripod.prototype._getCollection = function(callback) {
    if (this._collection == null) {
        var self = this;
        MongoClient.connect(this._connStr,function(err,db) {
            if (err) {
                callback(err,null);
            } else {
                db.collection(self._collectionName, function(err,collection) { // todo: check if collection is in config...?
                    if (err) {
                        callback(err,null);
                    } else {
                        self._collection = collection;
                        callback(null,collection)
                    }
                });
            }
        });
    } else {
        callback(null,this._collection);
    }
};

/**
 * Lazy-load views collection
 * @param callback
 * @private
 */
Tripod.prototype._getViewsCollection = function(callback) {
    if (this._viewsCollection == null) {
        var self = this;
        MongoClient.connect(this._connStr,function(err,db) {
            if (err) {
                callback(err,null);
            } else {
                db.collection("views", function(err,collection) {
                    if (err) {
                        callback(err,null);
                    } else {
                        self._viewsCollection = collection;
                        callback(null,collection)
                    }
                });
            }
        });
    } else {
        callback(null,this._viewsCollection);
    }
};

exports = module.exports = Tripod;
<|endoftext|>


<commit_before>//
// Ported to JavaScript by Patrizio Bruno 2015
//
// desertconsulting@gmail.com, https://github.com/PeculiarVentures/idscanjs
//

//
// Copyright 2007 ZXing authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///

ZXing.PDF417.PDF417Reader = function () {
};

ZXing.PDF417.PDF417Reader.prototype.decode = function (image, hints) {
    var results = ZXing.PDF417.PDF417Reader.decode(image, hints || null, false);
    if (results.length == 0) {
        return null;
    }
    else {
        return results[0];
    }
};
ZXing.PDF417.PDF417Reader.prototype.decodeMultiple = function (image, hints) {
    return ZXing.PDF417.PDF417Reader.decode(image, hints || null, true);
};
ZXing.PDF417.PDF417Reader.decode = function (image, hints, multiple) {
    var results = [];
    var detectorResult = ZXing.PDF417.Internal.Detector.detectSingle(image, hints, multiple);
    if (detectorResult != null) {
        var pointsList = detectorResult.Points;
        for (var $i = 0, $n = pointsList.length ; $i < $n; $i++) {
            var points = pointsList[$i];
            var decoderResult = ZXing.PDF417.Internal.PDF417ScanningDecoder.decode(detectorResult.Bits, points[4], points[5], points[6], points[7], ZXing.PDF417.PDF417Reader.getMinCodewordWidth(points), ZXing.PDF417.PDF417Reader.getMaxCodewordWidth(points));
            if (decoderResult == null) {
                continue;
            }
            var result = new ZXing.Result(decoderResult.Text, decoderResult.RawBytes, points, ZXing.BarcodeFormat.PDF_417);
            //result.putMetadata(ZXing.ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel);
            result.putMetadata("ERROR_CORRECTION_LEVEL", decoderResult.ECLevel);
            var pdf417ResultMetadata = decoderResult.Other instanceof ZXing.PDF417.PDF417ResultMetadata || decoderResult.Other == null ? decoderResult.Other : (function () {
                throw new Error("InvalidCastException");
            }
            ());
            if (pdf417ResultMetadata != null) {
                //result.putMetadata(ZXing.ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata);
                result.putMetadata("PDF417_EXTRA_METADATA", pdf417ResultMetadata);
            }
            results.push(result);
        }
    }
    return results;
};
ZXing.PDF417.PDF417Reader.getMaxWidth = function (p1, p2) {
    if (p1 == null || p2 == null) {
        return 0;
    }
    return Math.abs(p1.get_X() - p2.get_X());
};
ZXing.PDF417.PDF417Reader.getMinWidth = function (p1, p2) {
    if (p1 == null || p2 == null) {
        return 2147483647;
    }
    return Math.abs(p1.get_X() - p2.get_X());
};
ZXing.PDF417.PDF417Reader.getMaxCodewordWidth = function (p) {
    return Math.max(Math.max(ZXing.PDF417.PDF417Reader.getMaxWidth(p[0], p[4]), ZXing.PDF417.PDF417Reader.getMaxWidth(p[6], p[2]) * Math.floor( ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)), Math.max(ZXing.PDF417.PDF417Reader.getMaxWidth(p[1], p[5]), ZXing.PDF417.PDF417Reader.getMaxWidth(p[7], p[3]) * Math.floor(ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)));
};
ZXing.PDF417.PDF417Reader.getMinCodewordWidth = function (p) {
    return Math.min(Math.min(ZXing.PDF417.PDF417Reader.getMinWidth(p[0], p[4]), ZXing.PDF417.PDF417Reader.getMinWidth(p[6], p[2]) * Math.floor(ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)), Math.min(ZXing.PDF417.PDF417Reader.getMinWidth(p[1], p[5]), ZXing.PDF417.PDF417Reader.getMinWidth(p[7], p[3]) * Math.floor(ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)));
};
ZXing.PDF417.PDF417Reader.prototype.reset = function () {
};

<commit_msg>avoid duplicate detection<commit_after>//
// Ported to JavaScript by Patrizio Bruno 2015
//
// desertconsulting@gmail.com, https://github.com/PeculiarVentures/idscanjs
//

//
// Copyright 2007 ZXing authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///

ZXing.PDF417.PDF417Reader = function () {
};

ZXing.PDF417.PDF417Reader.prototype.decode = function (image, hints) {
    var results = ZXing.PDF417.PDF417Reader.decode(image, hints || null, false);
    if (results.length == 0) {
        return null;
    }
    else {
        return results[0];
    }
};
ZXing.PDF417.PDF417Reader.prototype.decodeMultiple = function (image, hints) {
    return ZXing.PDF417.PDF417Reader.decode(image, hints || null, true);
};
ZXing.PDF417.PDF417Reader.decode = function (image, hints, multiple, dr) {
    var results = [];
    var detectorResult = dr || ZXing.PDF417.Internal.Detector.detectSingle(image, hints, multiple);
    if (detectorResult != null) {
        var pointsList = detectorResult.Points;
        for (var $i = 0, $n = pointsList.length ; $i < $n; $i++) {
            var points = pointsList[$i];
            var decoderResult = ZXing.PDF417.Internal.PDF417ScanningDecoder.decode(detectorResult.Bits, points[4], points[5], points[6], points[7], ZXing.PDF417.PDF417Reader.getMinCodewordWidth(points), ZXing.PDF417.PDF417Reader.getMaxCodewordWidth(points));
            if (decoderResult == null) {
                continue;
            }
            var result = new ZXing.Result(decoderResult.Text, decoderResult.RawBytes, points, ZXing.BarcodeFormat.PDF_417);
            //result.putMetadata(ZXing.ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel);
            result.putMetadata("ERROR_CORRECTION_LEVEL", decoderResult.ECLevel);
            var pdf417ResultMetadata = decoderResult.Other instanceof ZXing.PDF417.PDF417ResultMetadata || decoderResult.Other == null ? decoderResult.Other : (function () {
                throw new Error("InvalidCastException");
            }
            ());
            if (pdf417ResultMetadata != null) {
                //result.putMetadata(ZXing.ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata);
                result.putMetadata("PDF417_EXTRA_METADATA", pdf417ResultMetadata);
            }
            results.push(result);
        }
    }
    return results;
};
ZXing.PDF417.PDF417Reader.getMaxWidth = function (p1, p2) {
    if (p1 == null || p2 == null) {
        return 0;
    }
    return Math.abs(p1.get_X() - p2.get_X());
};
ZXing.PDF417.PDF417Reader.getMinWidth = function (p1, p2) {
    if (p1 == null || p2 == null) {
        return 2147483647;
    }
    return Math.abs(p1.get_X() - p2.get_X());
};
ZXing.PDF417.PDF417Reader.getMaxCodewordWidth = function (p) {
    return Math.max(Math.max(ZXing.PDF417.PDF417Reader.getMaxWidth(p[0], p[4]), ZXing.PDF417.PDF417Reader.getMaxWidth(p[6], p[2]) * Math.floor( ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)), Math.max(ZXing.PDF417.PDF417Reader.getMaxWidth(p[1], p[5]), ZXing.PDF417.PDF417Reader.getMaxWidth(p[7], p[3]) * Math.floor(ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)));
};
ZXing.PDF417.PDF417Reader.getMinCodewordWidth = function (p) {
    return Math.min(Math.min(ZXing.PDF417.PDF417Reader.getMinWidth(p[0], p[4]), ZXing.PDF417.PDF417Reader.getMinWidth(p[6], p[2]) * Math.floor(ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)), Math.min(ZXing.PDF417.PDF417Reader.getMinWidth(p[1], p[5]), ZXing.PDF417.PDF417Reader.getMinWidth(p[7], p[3]) * Math.floor(ZXing.PDF417.PDF417Common.MODULES_IN_CODEWORD / ZXing.PDF417.PDF417Common.MODULES_IN_STOP_PATTERN)));
};
ZXing.PDF417.PDF417Reader.prototype.reset = function () {
};

<|endoftext|>