<commit_before>import THREE from './Three';
import ReactDOM from 'react-dom';
let OrbitControls = require('three-orbit-controls')(THREE);

const DIRECTIONAL_LIGHT = 'directionalLight';

class Paint {
  constructor() {
    this.loader = new THREE.STLLoader();
    this.scene = new THREE.Scene();
    this.renderer = new THREE.WebGLRenderer({
      antialias: true
    });
  }

  init(context) {
    this.component = context;
    this.url = context.props.url;
    this.width = context.props.width;
    this.height = context.props.height;
    this.modelColor = context.props.modelColor;
    this.backgroundColor = context.props.backgroundColor;
    this.orbitControls = context.props.orbitControls;
    this.rotate = context.props.rotate;
    this.cameraX = context.props.cameraX;
    this.cameraY = context.props.cameraY;
    this.cameraZ = context.props.cameraZ;
    this.rotationSpeeds = context.props.rotationSpeeds;
    this.lightX = context.props.lightX;
    this.lightY = context.props.lightY;
    this.lightZ = context.props.lightZ;
    this.lightColor = context.props.lightColor;

    if (this.mesh !== undefined) {
      this.mesh.geometry.dispose();
      this.mesh.material.dispose();
      this.scene.remove(this.mesh);
      delete this.mesh;
    }
    const directionalLightObj = this.scene.getObjectByName(DIRECTIONAL_LIGHT);
    if (directionalLightObj) {
      this.scene.remove(directionalLightObj);
    }

    if (this.animationRequestId) {
      cancelAnimationFrame(this.animationRequestId);
    }

    //Detector.addGetWebGLMessage();
    this.distance = 10000;
    let directionalLight = new THREE.DirectionalLight(this.lightColor);
    directionalLight.position.x = this.lightX;
    directionalLight.position.y = this.lightY;
    directionalLight.position.z = this.lightZ;
    directionalLight.position.normalize();
    directionalLight.name = DIRECTIONAL_LIGHT;
    this.scene.add(directionalLight);

    this.addSTLToScene();
  }

  addSTLToScene() {
    this.loader.crossOrigin = '';
    this.loader.load(this.url, geometry => {
      // Calculate mesh noramls for MeshLambertMaterial.
      geometry.computeFaceNormals();
      geometry.computeVertexNormals();

      // Center the object
      geometry.center();

      this.mesh = new THREE.Mesh(
        geometry,
        new THREE.MeshLambertMaterial({
          overdraw: true,
          color: this.modelColor
        })
      );
      // Set the object's dimensions
      geometry.computeBoundingBox();
      this.xDims = geometry.boundingBox.max.x - geometry.boundingBox.min.x;
      this.yDims = geometry.boundingBox.max.y - geometry.boundingBox.min.y;
      this.zDims = geometry.boundingBox.max.z - geometry.boundingBox.min.z;

      if (this.rotate) {
        this.mesh.rotation.x = this.rotationSpeeds[0];
        this.mesh.rotation.y = this.rotationSpeeds[1];
        this.mesh.rotation.z = this.rotationSpeeds[2];
      }

      this.scene.add(this.mesh);

      this.addCamera();
      this.addInteractionControls();
      this.addToReactComponent();

      // Start the animation
      this.animate();
    });
  }

  addCamera() {
    // Add the camera
    this.camera = new THREE.PerspectiveCamera(
      30,
      this.width / this.height,
      1,
      this.distance
    );

    if (this.cameraZ === null) {
      this.cameraZ = Math.max(this.xDims * 3, this.yDims * 3, this.zDims * 3);
    }

    this.camera.position.set(this.cameraX, this.cameraY, this.cameraZ);

    this.scene.add(this.camera);

    this.camera.lookAt(this.mesh);

    this.renderer.set;
    this.renderer.setSize(this.width, this.height);
    this.renderer.setClearColor(this.backgroundColor, 1);
  }

  addInteractionControls() {
    // Add controls for mouse interaction
    if (this.orbitControls) {
      this.controls = new OrbitControls(
        this.camera,
        ReactDOM.findDOMNode(this.component)
      );
      this.controls.enableKeys = false;
      this.controls.addEventListener('change', this.orbitRender.bind(this));
    }
  }

  addToReactComponent() {
    // Add to the React Component
    ReactDOM.findDOMNode(this.component).replaceChild(
      this.renderer.domElement,
      ReactDOM.findDOMNode(this.component).firstChild
    );
  }

  /**
   * Animate the scene
   * @returns {void}
   */
  animate() {
    // note: three.js includes requestAnimationFrame shim
    if (this.rotate) {
      this.animationRequestId = requestAnimationFrame(this.animate.bind(this));
    }

    if (this.orbitControls) {
      this.controls.update();
    }
    this.render();
  }

  /**
   * Render the scene after turning off the rotation
   * @returns {void}
   */
  orbitRender() {
    if (this.rotate) {
      this.rotate = false;
    }

    this.render();
  }

  /**
   * Deallocate Mesh, renderer context.
   * @returns {void}
   */
  clean() {
    if (this.mesh !== undefined) {
      this.mesh.geometry.dispose();
      this.mesh.material.dispose();
      this.scene.remove(this.mesh);
      delete this.mesh;
    }
    const directionalLightObj = this.scene.getObjectByName(DIRECTIONAL_LIGHT);
    if (directionalLightObj) {
      this.scene.remove(directionalLightObj);
    }

    if (this.animationRequestId) {
      cancelAnimationFrame(this.animationRequestId);
    }
    this.renderer.dispose();
    this.renderer.forceContextLoss();
  }

  /**
   * Render the scene
   * @returns {void}
   */
  render() {
    if (this.mesh && this.rotate) {
      this.mesh.rotation.x += this.rotationSpeeds[0];
      this.mesh.rotation.y += this.rotationSpeeds[1];
      this.mesh.rotation.z += this.rotationSpeeds[2];
    }

    this.renderer.render(this.scene, this.camera);
  }
}

export default Paint;
<commit_msg>avoid running old stl-loader callbacks after new init calls.<commit_after>import THREE from './Three';
import ReactDOM from 'react-dom';
let OrbitControls = require('three-orbit-controls')(THREE);

const DIRECTIONAL_LIGHT = 'directionalLight';

class Paint {
  constructor() {
    this.loader = new THREE.STLLoader();
    this.scene = new THREE.Scene();
    this.renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    this.reqNumber = 0;
  }

  init(context) {
    this.component = context;
    this.url = context.props.url;
    this.width = context.props.width;
    this.height = context.props.height;
    this.modelColor = context.props.modelColor;
    this.backgroundColor = context.props.backgroundColor;
    this.orbitControls = context.props.orbitControls;
    this.rotate = context.props.rotate;
    this.cameraX = context.props.cameraX;
    this.cameraY = context.props.cameraY;
    this.cameraZ = context.props.cameraZ;
    this.rotationSpeeds = context.props.rotationSpeeds;
    this.lightX = context.props.lightX;
    this.lightY = context.props.lightY;
    this.lightZ = context.props.lightZ;
    this.lightColor = context.props.lightColor;

    if (this.mesh !== undefined) {
      this.scene.remove(this.mesh);
      this.mesh.geometry.dispose();
      this.mesh.material.dispose();
    }
    const directionalLightObj = this.scene.getObjectByName(DIRECTIONAL_LIGHT);
    if (directionalLightObj) {
      this.scene.remove(directionalLightObj);
    }

    if (this.animationRequestId) {
      cancelAnimationFrame(this.animationRequestId);
    }

    //Detector.addGetWebGLMessage();
    this.distance = 10000;
    let directionalLight = new THREE.DirectionalLight(this.lightColor);
    directionalLight.position.x = this.lightX;
    directionalLight.position.y = this.lightY;
    directionalLight.position.z = this.lightZ;
    directionalLight.position.normalize();
    directionalLight.name = DIRECTIONAL_LIGHT;
    this.scene.add(directionalLight);

    this.reqNumber += 1;
    this.addSTLToScene(this.reqNumber);
  }

  addSTLToScene(reqId) {
    this.loader.crossOrigin = '';
    this.loader.load(this.url, geometry => {
      if (this.reqNumber !== reqId) {
        return;
      }
      // Calculate mesh noramls for MeshLambertMaterial.
      geometry.computeFaceNormals();
      geometry.computeVertexNormals();

      // Center the object
      geometry.center();

      this.mesh = new THREE.Mesh(
        geometry,
        new THREE.MeshLambertMaterial({
          overdraw: true,
          color: this.modelColor
        })
      );
      // Set the object's dimensions
      geometry.computeBoundingBox();
      this.xDims = geometry.boundingBox.max.x - geometry.boundingBox.min.x;
      this.yDims = geometry.boundingBox.max.y - geometry.boundingBox.min.y;
      this.zDims = geometry.boundingBox.max.z - geometry.boundingBox.min.z;

      if (this.rotate) {
        this.mesh.rotation.x = this.rotationSpeeds[0];
        this.mesh.rotation.y = this.rotationSpeeds[1];
        this.mesh.rotation.z = this.rotationSpeeds[2];
      }

      this.scene.add(this.mesh);

      this.addCamera();
      this.addInteractionControls();
      this.addToReactComponent();

      // Start the animation
      this.animate();
    });
  }

  addCamera() {
    // Add the camera
    this.camera = new THREE.PerspectiveCamera(
      30,
      this.width / this.height,
      1,
      this.distance
    );

    if (this.cameraZ === null) {
      this.cameraZ = Math.max(this.xDims * 3, this.yDims * 3, this.zDims * 3);
    }

    this.camera.position.set(this.cameraX, this.cameraY, this.cameraZ);

    this.scene.add(this.camera);

    this.camera.lookAt(this.mesh);

    this.renderer.set;
    this.renderer.setSize(this.width, this.height);
    this.renderer.setClearColor(this.backgroundColor, 1);
  }

  addInteractionControls() {
    // Add controls for mouse interaction
    if (this.orbitControls) {
      this.controls = new OrbitControls(
        this.camera,
        ReactDOM.findDOMNode(this.component)
      );
      this.controls.enableKeys = false;
      this.controls.addEventListener('change', this.orbitRender.bind(this));
    }
  }

  addToReactComponent() {
    // Add to the React Component
    ReactDOM.findDOMNode(this.component).replaceChild(
      this.renderer.domElement,
      ReactDOM.findDOMNode(this.component).firstChild
    );
  }

  /**
   * Animate the scene
   * @returns {void}
   */
  animate() {
    // note: three.js includes requestAnimationFrame shim
    if (this.rotate) {
      this.animationRequestId = requestAnimationFrame(this.animate.bind(this));
    }

    if (this.orbitControls) {
      this.controls.update();
    }
    this.render();
  }

  /**
   * Render the scene after turning off the rotation
   * @returns {void}
   */
  orbitRender() {
    if (this.rotate) {
      this.rotate = false;
    }

    this.render();
  }

  /**
   * Deallocate Mesh, renderer context.
   * @returns {void}
   */
  clean() {
    if (this.mesh !== undefined) {
      this.mesh.geometry.dispose();
      this.mesh.material.dispose();
      this.scene.remove(this.mesh);
      delete this.mesh;
    }
    const directionalLightObj = this.scene.getObjectByName(DIRECTIONAL_LIGHT);
    if (directionalLightObj) {
      this.scene.remove(directionalLightObj);
    }

    if (this.animationRequestId) {
      cancelAnimationFrame(this.animationRequestId);
    }
    this.renderer.dispose();
    this.renderer.forceContextLoss();
  }

  /**
   * Render the scene
   * @returns {void}
   */
  render() {
    if (this.mesh && this.rotate) {
      this.mesh.rotation.x += this.rotationSpeeds[0];
      this.mesh.rotation.y += this.rotationSpeeds[1];
      this.mesh.rotation.z += this.rotationSpeeds[2];
    }

    this.renderer.render(this.scene, this.camera);
  }
}

export default Paint;
<|endoftext|>


<commit_before>var _ = require('lodash'),
    backpack = require('../backpack'),
    Run = require('./run'),
    Collection = require('postman-collection').Collection,
    Runner;

/**
 * @typedef {runCallback}
 * @property {Function} [done]
 * @property {Function} [error]
 * @property {Function} [success]
 */

/**
 * @constructor
 *
 * @param {Object} [options]
 */
Runner = function PostmanCollectionRunner (options) {
    this.options = _.assign({}, options);
};

_.assign(Runner.prototype, {
    /**
     * Runs a collection or a folder.
     *
     * @param {Collection} collection
     * @param {Object} [options]
     * @param {Array.<Item>} options.items
     * @param {Array.<Object>}  [options.data]
     * @param {Object} [options.globals]
     * @param {Object} [options.environment]
     * @param {Number} [options.iterationCount]
     * @param {CertificateList} [options.certificates]
     * @param {ProxyConfigList} [options.proxies]
     * @param {Array} [options.data]
     * @param {String} [options.entrypoint] Name or ID of the item-group to be run
     * @param {Object} [options.run] Run-specific options, such as options related to the host
     *
     * @param {Function} callback
     */
    run: function (collection, options, callback) {
        var self = this,
            runOptions = _.merge(_.omit(options, ['environment', 'globals', 'data']), this.options.run);

        callback = backpack.normalise(callback);
        !_.isObject(options) && (options = {});

        Runner.extractRunnableItems(collection, options.entrypoint, function (err, runnableItems) {
            if (err) { return callback(err); }
            // The condition below will probably never be satisfied
            if (!runnableItems) { return callback(new Error('Error fetching run items')); }

            // Bail out only if: abortOnError is set and the returned entrypoint is invalid
            if (options.abortOnError && !runnableItems.entrypoint) {
                return callback(new Error('A valid folder id/name is required'));
            }

            return callback(null, (new Run({
                items: runnableItems.items,
                data: Runner.normaliseIterationData(options.data, options.iterationCount),
                environment: options.environment,
                globals: _.has(options, 'globals') ? options.globals : self.options.globals,
                certificates: options.certificates,
                proxies: options.proxies
            }, runOptions)));
        });
    }
});

_.assign(Runner, {
    /**
     * Expose Run instance for testability
     *
     * @type {Run}
     */
    Run: Run,

    /**
     * @private
     *
     * @param {Array} data
     * @param {Number} length
     * @returns {Array}
     */
    normaliseIterationData: function (data, length) {
        !_.isArray(data) && (data = [{}]);
        ((length < 1) || !_.isFinite(length)) && (length = data.length);

        // if the iteration count is greater than the length of data, we repeat the last item in data. here, we are
        // using a for-loop so that we do not have excessive spatial complexity
        if (length > data.length) {
            for (var i = data.length, filler = data[i - 1]; i < length; i++) {
                data[i] = filler;
            }
        }

        // just to be sure that there are no extra items in array, we match the lengths and return the data
        data.length = length;
        return data;
    },

    /**
     * @private
     *
     * @param {?Collection} collection
     * @param {?String} groupId
     * @param {Function} callback
     * @returns {Object}
     * @todo Add support for accepting groupId as an array of ids/names
     */
    extractRunnableItems: function (collection, groupId, callback) {
        _.isFunction(groupId) && (callback = groupId, groupId = null);
        _.isFunction(collection) && (callback = collection, groupId = null, collection = null);

        if (!Collection.isCollection(collection)) {
            return callback(new Error('A valid collection SDK instance is required'));
        }

        var idMatch,
            nameMatch,
            items = [],
            group = !groupId && collection; // if a group id is unspecified, the collection is our group

        // if group id is provided, we try and check if we can find it in the collection
        if (!group) {
            collection && collection.forEachItemGroup && collection.forEachItemGroup(function (itemGroup) {
                // Matching has been done like this to avoid having to go over the collection item groups twice
                (itemGroup.id === groupId) && (idMatch = itemGroup);
                (itemGroup.name === groupId) && (nameMatch = itemGroup);
            });

            group = idMatch || nameMatch; // Prioritise id based matches over name based ones.
        }

        // accumulate all items in the collection/group in order
        // @todo: Possibly add mapItem to sdk.ItemGroup?
        group && group.forEachItem && group.forEachItem(function (item) {
            items.push(item);
        });

        callback(null, {items: items, entrypoint: group});
    }
});

module.exports = Runner;
<commit_msg>:art: Corrected invalid entrypoint copy<commit_after>var _ = require('lodash'),
    backpack = require('../backpack'),
    Run = require('./run'),
    Collection = require('postman-collection').Collection,
    Runner;

/**
 * @typedef {runCallback}
 * @property {Function} [done]
 * @property {Function} [error]
 * @property {Function} [success]
 */

/**
 * @constructor
 *
 * @param {Object} [options]
 */
Runner = function PostmanCollectionRunner (options) {
    this.options = _.assign({}, options);
};

_.assign(Runner.prototype, {
    /**
     * Runs a collection or a folder.
     *
     * @param {Collection} collection
     * @param {Object} [options]
     * @param {Array.<Item>} options.items
     * @param {Array.<Object>}  [options.data]
     * @param {Object} [options.globals]
     * @param {Object} [options.environment]
     * @param {Number} [options.iterationCount]
     * @param {CertificateList} [options.certificates]
     * @param {ProxyConfigList} [options.proxies]
     * @param {Array} [options.data]
     * @param {String} [options.entrypoint] Name or ID of the item-group to be run
     * @param {Object} [options.run] Run-specific options, such as options related to the host
     *
     * @param {Function} callback
     */
    run: function (collection, options, callback) {
        var self = this,
            runOptions = _.merge(_.omit(options, ['environment', 'globals', 'data']), this.options.run);

        callback = backpack.normalise(callback);
        !_.isObject(options) && (options = {});

        Runner.extractRunnableItems(collection, options.entrypoint, function (err, runnableItems) {
            if (err) { return callback(err); }
            // The condition below will probably never be satisfied
            if (!runnableItems) { return callback(new Error('Error fetching run items')); }

            // Bail out only if: abortOnError is set and the returned entrypoint is invalid
            if (options.abortOnError && !runnableItems.entrypoint) {
                return callback(new Error(`Unable to find a folder or request: ${options.entrypoint}`));
            }

            return callback(null, (new Run({
                items: runnableItems.items,
                data: Runner.normaliseIterationData(options.data, options.iterationCount),
                environment: options.environment,
                globals: _.has(options, 'globals') ? options.globals : self.options.globals,
                certificates: options.certificates,
                proxies: options.proxies
            }, runOptions)));
        });
    }
});

_.assign(Runner, {
    /**
     * Expose Run instance for testability
     *
     * @type {Run}
     */
    Run: Run,

    /**
     * @private
     *
     * @param {Array} data
     * @param {Number} length
     * @returns {Array}
     */
    normaliseIterationData: function (data, length) {
        !_.isArray(data) && (data = [{}]);
        ((length < 1) || !_.isFinite(length)) && (length = data.length);

        // if the iteration count is greater than the length of data, we repeat the last item in data. here, we are
        // using a for-loop so that we do not have excessive spatial complexity
        if (length > data.length) {
            for (var i = data.length, filler = data[i - 1]; i < length; i++) {
                data[i] = filler;
            }
        }

        // just to be sure that there are no extra items in array, we match the lengths and return the data
        data.length = length;
        return data;
    },

    /**
     * @private
     *
     * @param {?Collection} collection
     * @param {?String} groupId
     * @param {Function} callback
     * @returns {Object}
     * @todo Add support for accepting groupId as an array of ids/names
     */
    extractRunnableItems: function (collection, groupId, callback) {
        _.isFunction(groupId) && (callback = groupId, groupId = null);
        _.isFunction(collection) && (callback = collection, groupId = null, collection = null);

        if (!Collection.isCollection(collection)) {
            return callback(new Error('A valid collection SDK instance is required'));
        }

        var idMatch,
            nameMatch,
            items = [],
            group = !groupId && collection; // if a group id is unspecified, the collection is our group

        // if group id is provided, we try and check if we can find it in the collection
        if (!group) {
            collection && collection.forEachItemGroup && collection.forEachItemGroup(function (itemGroup) {
                // Matching has been done like this to avoid having to go over the collection item groups twice
                (itemGroup.id === groupId) && (idMatch = itemGroup);
                (itemGroup.name === groupId) && (nameMatch = itemGroup);
            });

            group = idMatch || nameMatch; // Prioritise id based matches over name based ones.
        }

        // accumulate all items in the collection/group in order
        // @todo: Possibly add mapItem to sdk.ItemGroup?
        group && group.forEachItem && group.forEachItem(function (item) {
            items.push(item);
        });

        callback(null, {items: items, entrypoint: group});
    }
});

module.exports = Runner;
<|endoftext|>


<commit_before>"use strict";
/*jshint eqnull:true */
/*jshint node:true */

(function codenautasModuleDefinition(root, name, factory) {
    /* global define */
    /* istanbul ignore next */
    if(typeof root.globalModuleName !== 'string'){
        root.globalModuleName = name;
    }
    /* istanbul ignore next */
    if(typeof exports === 'object' && typeof module === 'object'){
        module.exports = factory();
    }else if(typeof define === 'function' && define.amd){
        define(factory);
    }else if(typeof exports === 'object'){
        exports[root.globalModuleName] = factory();
    }else{
        root[root.globalModuleName] = factory();
    }
    root.globalModuleName = null;
})(/*jshint -W040 */this, 'selfExplain', function() {
/*jshint +W040 */

/*jshint -W004 */
var selfExplain = {};
/*jshint +W004 */

var superassert = {};

/* istanbul ignore next */
if(typeof window === "undefined"){
    /*eslint global-require: 0*/
    var getSource=(function(){
        var fs = require('fs');
        return function(fileName){
            return fs.readFileSync(fileName, 'utf8');
        }
    })();
}else{
    var getSource=(function(){
        return function(fileUrl){
            var xhttp = new XMLHttpRequest();
            /*
            xhttp.onreadystatechange = function() {
                if (xhttp.readyState == 4 && xhttp.status == 200) {
                    return xhttp.responseText;
                }
            };
            */
            xhttp.open("GET", fileUrl, false);
            xhttp.send();
            return xhttp.responseText;
        }
    })();
}

var esprima = require('esprima');
var escodegen = require('escodegen');

var changing = require('best-globals').changing;

var escodegen_opts={};

function generate(AST){
    var str = escodegen.generate(AST, escodegen_opts);
    if(str[str.length-1]===';'){
        return str.substr(0,str.length-1);
    }
    return str;
}

var Precedence = {
    Sequence: 0,
    Yield: 1,
    Await: 1,
    Assignment: 1,
    Conditional: 2,
    ArrowFunction: 2,
    LogicalOR: 3,
    LogicalAND: 4,
    BitwiseOR: 5,
    BitwiseXOR: 6,
    BitwiseAND: 7,
    Equality: 8,
    Relational: 9,
    BitwiseSHIFT: 10,
    Additive: 11,
    Multiplicative: 12,
    Unary: 13,
    Postfix: 14,
    Call: 15,
    New: 16,
    TaggedTemplate: 17,
    Member: 18,
    Primary: 19
};

var BinaryPrecedence = {
    '||': Precedence.LogicalOR,
    '&&': Precedence.LogicalAND,
    '|': Precedence.BitwiseOR,
    '^': Precedence.BitwiseXOR,
    '&': Precedence.BitwiseAND,
    '==': Precedence.Equality,
    '!=': Precedence.Equality,
    '===': Precedence.Equality,
    '!==': Precedence.Equality,
    'is': Precedence.Equality,
    'isnt': Precedence.Equality,
    '<': Precedence.Relational,
    '>': Precedence.Relational,
    '<=': Precedence.Relational,
    '>=': Precedence.Relational,
    'in': Precedence.Relational,
    'instanceof': Precedence.Relational,
    '<<': Precedence.BitwiseSHIFT,
    '>>': Precedence.BitwiseSHIFT,
    '>>>': Precedence.BitwiseSHIFT,
    '+': Precedence.Additive,
    '-': Precedence.Additive,
    '*': Precedence.Multiplicative,
    '%': Precedence.Multiplicative,
    '/': Precedence.Multiplicative,
    // other:
    '!': Precedence.Unary,
    '.': Precedence.Member,
    'Call': Precedence.Call,
};

function parenthesis(list, expression, fatherOperator){
    var withParenthesis=expression.operator && BinaryPrecedence[expression.operator] < BinaryPrecedence[fatherOperator];
    if(withParenthesis){
        list.push('"("');
    }
    list.push(expression);
    if(withParenthesis){
        list.push('")"');
    }
}

function separateParts(previousResult, expressions){
    var result={changes:false};
    var newParts=[];
    var register=function(part){
        var expression = generate(part);
        if(!expressions[expression]){
            expressions[expression]=true;
        }
    }
    /*eslint no-loop-func: 0*/
    /*eslint complexity: [2, 10]*/
    previousResult.parts.forEach(function(part){
        if(part.type){
            if(part.body){
                newParts = newParts.concat(part.body);
                // register(part);
            }else if(part.arguments){
                register(part);
                if(part.callee.type=='Identifier'){
                    newParts.push(JSON.stringify(part.callee.name));
                }else if(part.callee.type==='FunctionExpression'){
                    newParts.push('"FunctionExpression"');
                }else{
                    // Not expand function expressions:
                    // parenthesis(newParts, part.callee, 'Call');
                }
                newParts.push('"("');
                newParts = newParts.concat(part.arguments);
                newParts.push('")"');
            }else if(part.expression){
                // register(part);
                newParts.push(part.expression);
            }else if(part.right){
                register(part);
                parenthesis(newParts, part.left, part.operator, true);
                newParts.push(JSON.stringify(part.operator));
                parenthesis(newParts, part.right, part.operator);
            }else if(part.name){
                register(part);
                newParts.push(part.name);
            }else if(part.raw){
                newParts.push(part.raw);
            }else if(part.argument){
                register(part);
                newParts.push(JSON.stringify(part.operator));
                parenthesis(newParts, part.argument, part.operator);
            }else if(part.key){
                newParts.push(JSON.stringify(part.key.name));
                newParts.push('":"');
                newParts.push(part.value);
                newParts.push('"}"');
            }else if(part.properties){
                register(part);
                newParts.push('"{"');
                part.properties.forEach(function(part){
                    newParts.push(part);
                });
                newParts.push('"}"');
            }else if(part.elements){
                register(part);
                newParts.push('"["');
                part.elements.forEach(function(part){
                    newParts.push(part);
                });
                newParts.push('"]"');
            }else if(part.type==='MemberExpression' && part.computed){
                register(part);
                parenthesis(newParts, part.object, '.');
                newParts.push('"["');
                parenthesis(newParts, part.property, '.');
                newParts.push('"]"');
            }else if(part.type==='MemberExpression' && part.property.name){
                register(part);
                parenthesis(newParts, part.object, '.');
                newParts.push('"."');
                newParts.push(JSON.stringify(part.property.name));
            }else{
                console.log("self-explain internal ERROR");
                console.log(part);
                throw new Error("self-explain internal ERROR");
            }
            result.changes=true;
        }else{
            newParts.push(part);
        }
    });
    result.parts = newParts;
    var exprs=result.parts.map(function(part){
        return part.type?generate(part):part;
    });
    result.show=exprs.join(',');
    return result;
}

selfExplain.assert = function assert(value){
    if(value===true){
        return '';
    }
    return (function(stack){
        var lineNum;
        var linea;
        var matches;
        if(!stack){
            try{
                throw new Error();
            }catch(error){
                stack = error.stack;
                // console.log('+++++++++++++');
                // console.log(stack);
                linea=stack.split(/\n\r?/)[3];
            }
        }else{
            linea=stack.split(/\n\r?/)[2];
        }
        matches = linea.match(/\((.*):(\d+):(\d+)\)/);
        if(!matches){
            if(window.navigator.userAgent.match(/PhantomJS\/[0-9.]+/)){
                lineNum=2;
            }else{
                lineNum=1;
            }
            linea=stack.split(/\n\r?/)[lineNum];
            matches = linea.match(/(?:.*@)?([^@]*):(\d+):(\d+)/);
            if(!matches){
                console.log('*****************1');
                console.log(stack);
            }
        }
        var fileName = matches[1];
        var fuente;
        superassert.files = superassert.files || {};
        if(!(fileName in superassert.files)){
            fuente = getSource(fileName);
            superassert.files[fileName] = fuente;
        }else{
            fuente = superassert.files[fileName];
        }
        var lines = fuente.split(/\n\r?/);
        var numLine = matches[2];
        var errorLineFromPosition = lines[numLine-1].substr(matches[3]-1);
        var errorLinePrePosition = lines[numLine-1].substr(0,matches[3]-1);
        var withEval=errorLinePrePosition.match(/eval\s*./)
        if(withEval){
            var errorLineParts=errorLineFromPosition.match(/(\w+)s*\((.*)\)\s*\)[^)]*$/);
        }else{
            var errorLineParts=errorLineFromPosition.match(/(\w+)s*\((.*)\)[^)]*$/);
        }
        var functionName=errorLineParts[1];
        var expression=errorLineParts[2];
        var then = '';
        var expressions={};
        selfExplain.assert.log('ASSERT FAILED');
        if(!withEval){
            selfExplain.assert.log(expression, '====', value);
            throw new Error("assert failed in line "+numLine);
        }
        var i=99999;
        var result={changes:true, parts:[esprima.parse(expression)]};
        var showAnt='!~';
        while(i>0 && result.changes){
            i--;
            result = separateParts(result, expressions);
            /*eslint no-loop-func: 0*/
        }
        for(var expression in expressions){
            then += functionName+'.log('+JSON.stringify(expression)+', "====", '+expression+');';
        }
        then += 'throw new Error("assert failed in line '+numLine+'");';
        return then;
    })((new Error()).stack);
};

selfExplain.assert.log = function log(){
    if(selfExplain.assert.collecting){
        selfExplain.assert.collecting.push(Array.prototype.slice.call(arguments));
    }else{
        console.log.apply(console, arguments);
    }
};

selfExplain.assert.collect = function collect(){
    selfExplain.assert.collecting=[];
};

selfExplain.assert.collected = function collected(){
    var collected = selfExplain.assert.collecting;
    selfExplain.assert.collecting = false;
    return collected;
};

selfExplain.assert.setOptions = function setOptions(opts){
    selfExplain.assert.opts = opts;
    escodegen_opts = opts.escodegen;
};

selfExplain.assert.opts = {showMode: 'expressions'};

selfExplain.assert.formatDiff = function formatDiff(diff, prefix){
    return prefix ? prefix+': '+diff : diff;
}

selfExplain.assert.differences = function differences(a, b, opts, prefix){
    opts = opts || {};
    prefix = prefix || '';
    var format = selfExplain.assert.formatDiff;
    if(a === b){
        return null;
    }
    if(opts.autoTypeCast && a == b){
        return null;
    }
    var result = [];
    var collect = function collect(diff){
        if(!opts.maxDifferences || result.length < opts.maxDifferences){
            result.push(diff);
        }else if(result.length == opts.maxDifferences){
            result.push("...");
            return false;
        }
        return true;
    }
    var compAndCollect = function compAndCollect(index, prefix){
        var diff = selfExplain.assert.differences(a[index], b[index], opts, prefix);
        if(diff){
            return collect(diff);
        }
        return true;
    }
    if(a instanceof Array && b instanceof Array){
        for(var i=0; i<Math.max(a.length, b.length); i++){
            if(!compAndCollect(i,  prefix+"[" + (i) + "]")) break;
        }
        return result.length ? result.join("\n") : null;
    }
    if(a instanceof Object && b instanceof Object){
        var result = [];
        var aKeys = Object.keys(a);
        var bKeys = Object.keys(b);
        var i=0;
        for(var name in a){
            if(!opts.unordered && bKeys[i]!==name){
                if(!collect(prefix+'{'+i+'}: .'+name+' != '+(i>=bKeys.length?'undefined':'.'+bKeys[i]))) break;
            }else{
                if(!compAndCollect(name,  prefix+"."+name)) break;
            }
            i++;
        }
        if(opts.unordered){
            for(var name in b){
                if(!(name in a)){
                    compAndCollect(name,  prefix+"."+name);
                }
            }
        }else{
            while(i<bKeys.length){
                if(!collect(prefix+'{'+i+'}: undefined != .'+bKeys[i])) break;
                i++;
            }
        }
        return result.length ? result.join("\n") : null;
    }
    if(typeof a === "string" && typeof b === "string" && (opts.split.test(a) || opts.split.test(b))){
        return selfExplain.assert.differences(a.split(opts.split), b.split(opts.split), opts, prefix+".split(" + opts.split + ")");
    }
    if(opts.autoTypeCast ? !isNaN(a) && !isNaN(b) : typeof a === "number" && typeof b === "number"){
        return format(a-b, prefix);
    }
    return format(JSON.stringify(a)+' != '+JSON.stringify(b), prefix);
}

selfExplain.assert.allDifferences = function allDifferences(a,b,opts){
    return selfExplain.assert.differences(a, b, changing(selfExplain.assert.allDifferences.opts, opts||{}));
}

selfExplain.assert.allDifferences.opts = {
    minLengthToSubstr: 16,
    substrLengthArgument: 10,
    split: /\n/,
    maxDifferences: 10,
}

selfExplain.assert.bigDifferences = function bigDifferences(a,b){
    return selfExplain.assert.differences(a, b, changing(
        selfExplain.assert.allDifferences.opts, selfExplain.assert.bigDifferences.opts
    ));
}

selfExplain.assert.bigDifferences.opts = {
    autoTypeCast:true,
    delta:0.00000001,
    split: /\r?\n/,
    unordered: true,
};

return selfExplain;

});<commit_msg>Anda en IE y PhantomJS<commit_after>"use strict";
/*jshint eqnull:true */
/*jshint node:true */

(function codenautasModuleDefinition(root, name, factory) {
    /* global define */
    /* istanbul ignore next */
    if(typeof root.globalModuleName !== 'string'){
        root.globalModuleName = name;
    }
    /* istanbul ignore next */
    if(typeof exports === 'object' && typeof module === 'object'){
        module.exports = factory();
    }else if(typeof define === 'function' && define.amd){
        define(factory);
    }else if(typeof exports === 'object'){
        exports[root.globalModuleName] = factory();
    }else{
        root[root.globalModuleName] = factory();
    }
    root.globalModuleName = null;
})(/*jshint -W040 */this, 'selfExplain', function() {
/*jshint +W040 */

/*jshint -W004 */
var selfExplain = {};
/*jshint +W004 */

var superassert = {};

/* istanbul ignore next */
if(typeof window === "undefined"){
    /*eslint global-require: 0*/
    var getSource=(function(){
        var fs = require('fs');
        return function(fileName){
            return fs.readFileSync(fileName, 'utf8');
        }
    })();
}else{
    var getSource=(function(){
        return function(fileUrl){
            var xhttp = new XMLHttpRequest();
            /*
            xhttp.onreadystatechange = function() {
                if (xhttp.readyState == 4 && xhttp.status == 200) {
                    return xhttp.responseText;
                }
            };
            */
            xhttp.open("GET", fileUrl, false);
            xhttp.send();
            return xhttp.responseText;
        }
    })();
}

var esprima = require('esprima');
var escodegen = require('escodegen');

var changing = require('best-globals').changing;

var escodegen_opts={};

function generate(AST){
    var str = escodegen.generate(AST, escodegen_opts);
    if(str[str.length-1]===';'){
        return str.substr(0,str.length-1);
    }
    return str;
}

var Precedence = {
    Sequence: 0,
    Yield: 1,
    Await: 1,
    Assignment: 1,
    Conditional: 2,
    ArrowFunction: 2,
    LogicalOR: 3,
    LogicalAND: 4,
    BitwiseOR: 5,
    BitwiseXOR: 6,
    BitwiseAND: 7,
    Equality: 8,
    Relational: 9,
    BitwiseSHIFT: 10,
    Additive: 11,
    Multiplicative: 12,
    Unary: 13,
    Postfix: 14,
    Call: 15,
    New: 16,
    TaggedTemplate: 17,
    Member: 18,
    Primary: 19
};

var BinaryPrecedence = {
    '||': Precedence.LogicalOR,
    '&&': Precedence.LogicalAND,
    '|': Precedence.BitwiseOR,
    '^': Precedence.BitwiseXOR,
    '&': Precedence.BitwiseAND,
    '==': Precedence.Equality,
    '!=': Precedence.Equality,
    '===': Precedence.Equality,
    '!==': Precedence.Equality,
    'is': Precedence.Equality,
    'isnt': Precedence.Equality,
    '<': Precedence.Relational,
    '>': Precedence.Relational,
    '<=': Precedence.Relational,
    '>=': Precedence.Relational,
    'in': Precedence.Relational,
    'instanceof': Precedence.Relational,
    '<<': Precedence.BitwiseSHIFT,
    '>>': Precedence.BitwiseSHIFT,
    '>>>': Precedence.BitwiseSHIFT,
    '+': Precedence.Additive,
    '-': Precedence.Additive,
    '*': Precedence.Multiplicative,
    '%': Precedence.Multiplicative,
    '/': Precedence.Multiplicative,
    // other:
    '!': Precedence.Unary,
    '.': Precedence.Member,
    'Call': Precedence.Call,
};

function parenthesis(list, expression, fatherOperator){
    var withParenthesis=expression.operator && BinaryPrecedence[expression.operator] < BinaryPrecedence[fatherOperator];
    if(withParenthesis){
        list.push('"("');
    }
    list.push(expression);
    if(withParenthesis){
        list.push('")"');
    }
}

function separateParts(previousResult, expressions){
    var result={changes:false};
    var newParts=[];
    var register=function(part){
        var expression = generate(part);
        if(!expressions[expression]){
            expressions[expression]=true;
        }
    }
    /*eslint no-loop-func: 0*/
    /*eslint complexity: [2, 10]*/
    previousResult.parts.forEach(function(part){
        if(part.type){
            if(part.body){
                newParts = newParts.concat(part.body);
                // register(part);
            }else if(part.arguments){
                register(part);
                if(part.callee.type=='Identifier'){
                    newParts.push(JSON.stringify(part.callee.name));
                }else if(part.callee.type==='FunctionExpression'){
                    newParts.push('"FunctionExpression"');
                }else{
                    // Not expand function expressions:
                    // parenthesis(newParts, part.callee, 'Call');
                }
                newParts.push('"("');
                newParts = newParts.concat(part.arguments);
                newParts.push('")"');
            }else if(part.expression){
                // register(part);
                newParts.push(part.expression);
            }else if(part.right){
                register(part);
                parenthesis(newParts, part.left, part.operator, true);
                newParts.push(JSON.stringify(part.operator));
                parenthesis(newParts, part.right, part.operator);
            }else if(part.name){
                register(part);
                newParts.push(part.name);
            }else if(part.raw){
                newParts.push(part.raw);
            }else if(part.argument){
                register(part);
                newParts.push(JSON.stringify(part.operator));
                parenthesis(newParts, part.argument, part.operator);
            }else if(part.key){
                newParts.push(JSON.stringify(part.key.name));
                newParts.push('":"');
                newParts.push(part.value);
                newParts.push('"}"');
            }else if(part.properties){
                register(part);
                newParts.push('"{"');
                part.properties.forEach(function(part){
                    newParts.push(part);
                });
                newParts.push('"}"');
            }else if(part.elements){
                register(part);
                newParts.push('"["');
                part.elements.forEach(function(part){
                    newParts.push(part);
                });
                newParts.push('"]"');
            }else if(part.type==='MemberExpression' && part.computed){
                register(part);
                parenthesis(newParts, part.object, '.');
                newParts.push('"["');
                parenthesis(newParts, part.property, '.');
                newParts.push('"]"');
            }else if(part.type==='MemberExpression' && part.property.name){
                register(part);
                parenthesis(newParts, part.object, '.');
                newParts.push('"."');
                newParts.push(JSON.stringify(part.property.name));
            }else{
                console.log("self-explain internal ERROR");
                console.log(part);
                throw new Error("self-explain internal ERROR");
            }
            result.changes=true;
        }else{
            newParts.push(part);
        }
    });
    result.parts = newParts;
    var exprs=result.parts.map(function(part){
        return part.type?generate(part):part;
    });
    result.show=exprs.join(',');
    return result;
}

selfExplain.assert = function assert(value){
    if(value===true){
        return '';
    }
    return (function(stack){
        var lineNum;
        var linea;
        var matches;
        if(!stack){
            try{
                throw new Error();
            }catch(error){
                stack = error.stack;
                // console.log('+++++++++++++');
                // console.log(stack);
                linea=stack.split(/\n\r?/)[3];
            }
        }else{
            linea=stack.split(/\n\r?/)[2];
        }
        matches = linea.match(/\((.*):(\d+):(\d+)\)/);
        if(!matches){
            if(window.navigator.userAgent.match(/PhantomJS\/[0-9.]+/)){
                // console.log('///////// PHANTOM');
                lineNum=2;
            }else{
                lineNum=1;
            }
            linea=stack.split(/\n\r?/)[lineNum];
            matches = linea.match(/(?:.*@)?([^@]*):(\d+):(\d+)/);
            if(!matches){
                console.log('*****************1');
                console.log(stack);
            }
        }
        var fileName = matches[1];
        var fuente;
        superassert.files = superassert.files || {};
        if(!(fileName in superassert.files)){
            fuente = getSource(fileName);
            superassert.files[fileName] = fuente;
        }else{
            fuente = superassert.files[fileName];
        }
        var lines = fuente.split(/\n\r?/);
        var numLine = matches[2];
        var errorLine = lines[numLine-1];
        var errorLineParts=errorLine.match(/^\s+(eval\s*\()?(\w+)s*\((.*)(\))\s*\)?[^)]*$/);
        // console.log('---',errorLineParts);
        var withEval=errorLineParts[1];
        var functionName=errorLineParts[2];
        var expression=errorLineParts[3];
        if(withEval){
            expression = expression.substr(0,expression.length-1);
        }
            // if(lineNum==2){
            //     console.log('%%%%%%%%%%%%%%%%');
            //     console.log(errorLine)
            //     console.log(withEval,'///',errorLineParts.join(' // '));
            // }
        var then = '';
        var expressions={};
        selfExplain.assert.log('ASSERT FAILED');
        if(!withEval){
            selfExplain.assert.log(expression, '====', value);
            throw new Error("assert failed in line "+numLine);
        }
        var i=99999;
        var result={changes:true, parts:[esprima.parse(expression)]};
        var showAnt='!~';
        while(i>0 && result.changes){
            i--;
            result = separateParts(result, expressions);
            /*eslint no-loop-func: 0*/
        }
        for(var expression in expressions){
            then += functionName+'.log('+JSON.stringify(expression)+', "====", '+expression+');';
        }
        then += 'throw new Error("assert failed in line '+numLine+'");';
        return then;
    })((new Error()).stack);
};

selfExplain.assert.log = function log(){
    if(selfExplain.assert.collecting){
        selfExplain.assert.collecting.push(Array.prototype.slice.call(arguments));
    }else{
        console.log.apply(console, arguments);
    }
};

selfExplain.assert.collect = function collect(){
    selfExplain.assert.collecting=[];
};

selfExplain.assert.collected = function collected(){
    var collected = selfExplain.assert.collecting;
    selfExplain.assert.collecting = false;
    return collected;
};

selfExplain.assert.setOptions = function setOptions(opts){
    selfExplain.assert.opts = opts;
    escodegen_opts = opts.escodegen;
};

selfExplain.assert.opts = {showMode: 'expressions'};

selfExplain.assert.formatDiff = function formatDiff(diff, prefix){
    return prefix ? prefix+': '+diff : diff;
}

selfExplain.assert.differences = function differences(a, b, opts, prefix){
    opts = opts || {};
    prefix = prefix || '';
    var format = selfExplain.assert.formatDiff;
    if(a === b){
        return null;
    }
    if(opts.autoTypeCast && a == b){
        return null;
    }
    var result = [];
    var collect = function collect(diff){
        if(!opts.maxDifferences || result.length < opts.maxDifferences){
            result.push(diff);
        }else if(result.length == opts.maxDifferences){
            result.push("...");
            return false;
        }
        return true;
    }
    var compAndCollect = function compAndCollect(index, prefix){
        var diff = selfExplain.assert.differences(a[index], b[index], opts, prefix);
        if(diff){
            return collect(diff);
        }
        return true;
    }
    if(a instanceof Array && b instanceof Array){
        for(var i=0; i<Math.max(a.length, b.length); i++){
            if(!compAndCollect(i,  prefix+"[" + (i) + "]")) break;
        }
        return result.length ? result.join("\n") : null;
    }
    if(a instanceof Object && b instanceof Object){
        var result = [];
        var aKeys = Object.keys(a);
        var bKeys = Object.keys(b);
        var i=0;
        for(var name in a){
            if(!opts.unordered && bKeys[i]!==name){
                if(!collect(prefix+'{'+i+'}: .'+name+' != '+(i>=bKeys.length?'undefined':'.'+bKeys[i]))) break;
            }else{
                if(!compAndCollect(name,  prefix+"."+name)) break;
            }
            i++;
        }
        if(opts.unordered){
            for(var name in b){
                if(!(name in a)){
                    compAndCollect(name,  prefix+"."+name);
                }
            }
        }else{
            while(i<bKeys.length){
                if(!collect(prefix+'{'+i+'}: undefined != .'+bKeys[i])) break;
                i++;
            }
        }
        return result.length ? result.join("\n") : null;
    }
    if(typeof a === "string" && typeof b === "string" && (opts.split.test(a) || opts.split.test(b))){
        return selfExplain.assert.differences(a.split(opts.split), b.split(opts.split), opts, prefix+".split(" + opts.split + ")");
    }
    if(opts.autoTypeCast ? !isNaN(a) && !isNaN(b) : typeof a === "number" && typeof b === "number"){
        return format(a-b, prefix);
    }
    return format(JSON.stringify(a)+' != '+JSON.stringify(b), prefix);
}

selfExplain.assert.allDifferences = function allDifferences(a,b,opts){
    return selfExplain.assert.differences(a, b, changing(selfExplain.assert.allDifferences.opts, opts||{}));
}

selfExplain.assert.allDifferences.opts = {
    minLengthToSubstr: 16,
    substrLengthArgument: 10,
    split: /\n/,
    maxDifferences: 10,
}

selfExplain.assert.bigDifferences = function bigDifferences(a,b){
    return selfExplain.assert.differences(a, b, changing(
        selfExplain.assert.allDifferences.opts, selfExplain.assert.bigDifferences.opts
    ));
}

selfExplain.assert.bigDifferences.opts = {
    autoTypeCast:true,
    delta:0.00000001,
    split: /\r?\n/,
    unordered: true,
};

return selfExplain;

});<|endoftext|>


<commit_before>// Upload files in static/ So any file static/file.pdf -> /file.pdf is accessible at root

export default {
  name: "@SourceAura",
  domain: "template.karngyan.com", // add without https:// , used in meta tags and share urls
  image: "/images/peach-avi.png",
  email: "mail@sourceaura.com",
  googleAnalyticsV4: {
    enabled: false,
    id: ""
  },
  plausibleAnalytics: {
    enabled: false,
    domain: "template.karngyan.com",
    trackLocalhost: false,
    // leave it empty if plausible is not self hosted
    apiHost: "https://analytics.lookatx.dev" // default: https://plausible.io
  },
  // enable if you want comments and likes on posts
  // see how it looks on karngyan.com
  firebase: {
    enabled: false,
  },
  social: {
    github: "sourceaura",
    linkedin: "sourceaura",
    facebook: "sourceaura",
    twitter: "sourceaura",
    instagram: "sourceaura",
    codestats: "sourceaura" // https://codestats.net make a profile if you dont already have one.
  },
  buyMeACoffee: {
    enabled: true,
    url: "https://www.buymeacoffee.com/sourcaura.dev"
  },
  projects: {
    enabled: true
  },
  log: {
    enabled: true
  },
  // blog: {
  //   enabled: true
  // },
  resume: {
    enabled: true,
    pdfUrl: "/RESUME_GYAN_KARN_DARK.pdf" // add files in static folder
  },
  uses: {
    enabled: true,
    meta: [
      { title: "OS", value: "macOS Big Sur - Version 11.1" },
      { title: "Memory", value: "8 GB 2133 MHz LPDDR3" },
      { title: "Mouse", value: "Logitech M570 x MX Ergo" },
      { title: "Monitor", value: "Retina Display 13.3-inch (2560 × 1600)" },
      {
        title: "Laptop",
        value: "MacBook Pro (13.3-inch, 2019) • 1.4 GHz Quad-Core Intel Core i5"
      }
    ]
  },
  pulses: {
    enabled: true,
    meta: [
      { title: "OS", value: "macOS Big Sur - Version 11.1" },
      { title: "Memory", value: "8 GB 2133 MHz LPDDR3" },
      { title: "Mouse", value: "Logitech M570 x MX Ergo" },
      { title: "Monitor", value: "Retina Display 13.3-inch (2560 × 1600)" },
      {
        title: "Laptop",
        value: "MacBook Pro (13.3-inch, 2019) • 1.4 GHz Quad-Core Intel Core i5"
      }
    ]
  },
  theStack: {
    // add logos in static and at max add 3/4
    enabled: true,
    meta: [
      {
        name: "JavaScript",
        src: "/images/sendpost.png",
        url: "https://sendpost.io"
      },
      {
        name: "Nuxt/VueJs",
        src: "/images/amazon.png",
        url: "https://amazon.in"
      },
      {
        name: "Laravel",
        src: "/images/interviewready-io.png",
        url: "https://get.interviewready.io"
      },
      { name: "Firebase", src: "/images/crio.png", url: "https://crio.do" }
    ]
  },
  workedAt: {
    // add logos in static and at max add 3/4
    enabled: false,
    meta: [
      {
        name: "SendPost",
        src: "/images/sendpost.png",
        url: "https://sendpost.io"
      },
      { name: "Amazon", src: "/images/amazon.png", url: "https://amazon.in" },
      {
        name: "InterviewReady",
        src: "/images/interviewready-io.png",
        url: "https://get.interviewready.io"
      },
      { name: "CrioDo", src: "/images/crio.png", url: "https://crio.do" }
    ]
  },
  loadingIndicator: {
    name: "pulse"
    // https://tobiasahlin.com/spinkit/
    // circle
    // cube-grid
    // fading-circle
    // folding-cube
    // chasing-dots
    // nuxt
    // pulse
    // rectangle-bounce
    // rotating-plane
    // three-bounce
    // wandering-cubes
  },
  strings: {
    en_US: {
      download: "download",
      nav: {
        home: "home",
        log: "log",
        // blog: "blog",
        projects: "projects",
        pulses: "pulses",
        // uses: "uses",
        // resume: "résumé",
        buyMeACoffee: "buy me a beer",
        signIn: "sign in",
        signOut: "sign out"
      },
      // Author Info
      hero: {
        namaste: "namasté...",
        explore: "explore a bit",
        iAm: "an 'eclectic'",
        terms: [
          "poet",
          "programmer",
          "developer",
          "designer",
          "caligraphist",
          "coder",
          "eclectic. "
        ],
        aboutMe: "weird wiz 🧙🏾 || UI/UX Designer"
      },
      // GitHub Data
      gitData: {
        header: "contributions",
        subtext: "github heatmap"
      },
      githubCalendar: {
        header: "contributions",
        subtext: "github calendar heatmap"
      },
      // Journal - Log
      log: {
        header: "log",
        subtext:
          "always been a poet at my purest. figured i'd share here sometimes. feel free to join in.."
      },
      recentLog: {
        header: "recent logs",
        subtext: "balance may all ways be the challenge."
      },
      projects: {
        header: "projects",
        subtext:
          "this page lists some of my personal and work projects. every project has some story, click on the title to read"
      },
      // Journal - Log End
      // blog: {
      //   header: "blog",
      //   subtext:
      //     "i try to write once in a while. let me know your thoughts in comments or mail@karngyan.com"
      // },

      // recentBlog: {
      //   header: "recent blogs",
      //   subtext: "it takes a lot of time to write man"
      // },
      //
      // pulses - real-time activity
      pulses: {
        header: "pulses",
        subtext:
          "a quick 👀 at what i use on a daily basis to code 💻. "
      },
      // uses: {
      //   header: "uses",
      //   subtext:
      //     "a quick summary of what I use on a daily basis to code and some codestats.net flex"
      // }
    }
  }
};
<commit_msg>Update sourceaura.config.js<commit_after>// Upload files in static/ So any file static/file.pdf -> /file.pdf is accessible at root

export default {
  name: "@SourceAura",
  domain: "sourceaura.netlify.app", // add without https:// , used in meta tags and share urls
  image: "/images/peach-avi.png",
  email: "mail@sourceaura.com",
  googleAnalyticsV4: {
    enabled: false,
    id: ""
  },
  plausibleAnalytics: {
    enabled: false,
    domain: "sourceaura.netlify.app", // add without https:// , used in meta tags and share urls
    trackLocalhost: false,
    // leave it empty if plausible is not self hosted
    apiHost: "https://analytics.lookatx.dev" // default: https://plausible.io
  },
  // enable if you want comments and likes on posts
  // see how it looks on karngyan.com
  firebase: {
    enabled: true,
  },
  social: {
    github: "sourceaura",
    linkedin: "sourceaura",
    facebook: "sourceaura",
    twitter: "sourceaura",
    instagram: "sourceaura",
    codestats: "sourceaura" // https://codestats.net make a profile if you dont already have one.
  },
  buyMeACoffee: {
    enabled: true,
    url: "https://www.buymeacoffee.com/sourcaura.dev"
  },
  projects: {
    enabled: true
  },
  log: {
    enabled: true
  },
  // blog: {
  //   enabled: true
  // },
  resume: {
    enabled: true,
    pdfUrl: "/RESUME_GYAN_KARN_DARK.pdf" // add files in static folder
  },
  uses: {
    enabled: true,
    meta: [
      { title: "OS", value: "macOS Big Sur - Version 11.1" },
      { title: "Memory", value: "8 GB 2133 MHz LPDDR3" },
      { title: "Mouse", value: "Logitech M570 x MX Ergo" },
      { title: "Monitor", value: "Retina Display 13.3-inch (2560 × 1600)" },
      {
        title: "Laptop",
        value: "MacBook Pro (13.3-inch, 2019) • 1.4 GHz Quad-Core Intel Core i5"
      }
    ]
  },
  pulses: {
    enabled: true,
    meta: [
      { title: "OS", value: "macOS Big Sur - Version 11.1" },
      { title: "Memory", value: "8 GB 2133 MHz LPDDR3" },
      { title: "Mouse", value: "Logitech M570 x MX Ergo" },
      { title: "Monitor", value: "Retina Display 13.3-inch (2560 × 1600)" },
      {
        title: "Laptop",
        value: "MacBook Pro (13.3-inch, 2019) • 1.4 GHz Quad-Core Intel Core i5"
      }
    ]
  },
  theStack: {
    // add logos in static and at max add 3/4
    enabled: true,
    meta: [
      {
        name: "JavaScript",
        src: "/images/sendpost.png",
        url: "https://sendpost.io"
      },
      {
        name: "Nuxt/VueJs",
        src: "/images/amazon.png",
        url: "https://amazon.in"
      },
      {
        name: "Laravel",
        src: "/images/interviewready-io.png",
        url: "https://get.interviewready.io"
      },
      { name: "Firebase", src: "/images/crio.png", url: "https://crio.do" }
    ]
  },
  workedAt: {
    // add logos in static and at max add 3/4
    enabled: false,
    meta: [
      {
        name: "SendPost",
        src: "/images/sendpost.png",
        url: "https://sendpost.io"
      },
      { name: "Amazon", src: "/images/amazon.png", url: "https://amazon.in" },
      {
        name: "InterviewReady",
        src: "/images/interviewready-io.png",
        url: "https://get.interviewready.io"
      },
      { name: "CrioDo", src: "/images/crio.png", url: "https://crio.do" }
    ]
  },
  loadingIndicator: {
    name: "pulse"
    // https://tobiasahlin.com/spinkit/
    // circle
    // cube-grid
    // fading-circle
    // folding-cube
    // chasing-dots
    // nuxt
    // pulse
    // rectangle-bounce
    // rotating-plane
    // three-bounce
    // wandering-cubes
  },
  strings: {
    en_US: {
      download: "download",
      nav: {
        home: "home",
        log: "log",
        // blog: "blog",
        projects: "projects",
        pulses: "pulses",
        // uses: "uses",
        // resume: "résumé",
        buyMeACoffee: "buy me a beer",
        signIn: "sign in",
        signOut: "sign out"
      },
      // Author Info
      hero: {
        namaste: "namasté...",
        explore: "explore a bit",
        iAm: "an 'eclectic'",
        terms: [
          "poet",
          "programmer",
          "developer",
          "designer",
          "caligraphist",
          "coder",
          "eclectic. "
        ],
        aboutMe: "weird wiz 🧙🏾 || UI/UX Designer"
      },
      // GitHub Data
      gitData: {
        header: "contributions",
        subtext: "github heatmap"
      },
      githubCalendar: {
        header: "contributions",
        subtext: "github calendar heatmap"
      },
      // Journal - Log
      log: {
        header: "log",
        subtext:
          "always been a poet at my purest. figured i'd share here sometimes. feel free to join in.."
      },
      recentLog: {
        header: "recent logs",
        subtext: "balance may all ways be the challenge."
      },
      projects: {
        header: "projects",
        subtext:
          "this page lists some of my personal and work projects. every project has some story, click on the title to read"
      },
      // Journal - Log End
      // blog: {
      //   header: "blog",
      //   subtext:
      //     "i try to write once in a while. let me know your thoughts in comments or mail@karngyan.com"
      // },

      // recentBlog: {
      //   header: "recent blogs",
      //   subtext: "it takes a lot of time to write man"
      // },
      //
      // pulses - real-time activity
      pulses: {
        header: "pulses",
        subtext:
          "a quick 👀 at what i use on a daily basis to code 💻. "
      },
      // uses: {
      //   header: "uses",
      //   subtext:
      //     "a quick summary of what I use on a daily basis to code and some codestats.net flex"
      // }
    }
  }
};
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

/* global chrome */

var _ = require('lodash');
var async = require('async');
var localStore = require('./core/localStore');

// for tests
if (typeof localStore === 'function') {
  localStore = localStore({});
}

var DEVICEPORTS = 'devicePorts';

var debug = require('./bows')('SerialDevice');

var moduleCounter = 1;

module.exports = function(config) {
  config = config || {};
  var connection = null;
  var connectionPort = null;
  var buffer = [];
  var packetBuffer = [];
  var packetHandler = null;
  var errorHandler = null;
  var moduleNumber = moduleCounter++;
  var portPattern = '/dev/cu.usb.+';
  var bitrate = config.bitrate || 9600;
  var log = '';
  var logcount = 0;
  var loglimit = 400;
  var doLogging = (config && config.doLogging) || false;

  if (config.silent) {
    // debug = _.noop;
  }

  function init() {
    connection = null;
    connectionPort = null;
    buffer = [];
    packetBuffer = [];
    packetHandler = null;
    log = '';
    localStore.init(DEVICEPORTS, function() {});
  }

  init();

  // This is the object that is passed to the packetHandler
  // it lets us abstract away the details of the packetHandling
  var bufobj = {
    // get(x) -- returns char at x
    get : function(n) {return buffer[n]; },
    // len() -- returns length
    len : function() { return buffer.length; },
    // discard(n) -- deletes n chars at start of buffer
    discard : function(n) { discardBytes(n); },
    // bytes() -- returns entire buffer as a Uint8Array
    bytes : function() {
      return new Uint8Array(buffer);
    }
  };

  function addlog(s) {
    if (!doLogging) {
      return;
    }

    if (logcount < loglimit) {
      if (s.indexOf('\n') !== -1) {
        ++logcount;
      }
      log += s;
    }
  }

  var logdump = _.debounce(function() {
    if (doLogging) {
      debug(log);
    }
  }, 900);

  var emitLog = function(clearLog) {
    debug(log);
    if (clearLog) {
      log = '';
      logcount = 0;
    }
  };

  function _receiveSomeBytes(bufView) {
    for (var i=0; i<bufView.byteLength; i++) {
      buffer.push(bufView[i]);
    }

    addlog('  rcv ');
    for (i in bufView) {
      addlog(('00' + bufView[i].toString(16)).substr(-2) + ' ');
    }
    addlog('\n');
    logdump();

    // we got some bytes, let's see if they make one or more packets
    if (packetHandler) {
      var pkt = packetHandler(bufobj);
      while (pkt) {
        packetBuffer.push(pkt);
        pkt = packetHandler(bufobj);
      }
    }

  }

  function portListener(info) {
    if (connection && info.connectionId == connection.connectionId && info.data) {
      var bufView=new Uint8Array(info.data);
      _receiveSomeBytes(bufView);
    }
  }

  // if an errorHandler was specified, then we call it with every error.
  // If it returns anything, it should return either a string or an array
  // containing the bytes it wants to insert into the buffer.
  // According to chrome's docs, info will contain connectionId, and an
  // error member that can be any of "disconnected", "timeout", "device_lost", or "system_error"
  function errorListener(info) {
    if (info.error && errorHandler) {
      var bytes = errorHandler(info);
      var bufView = new Uint8Array(bytes.length);
      for (var i=0; i<bytes.length; i++) {
        if (_.isString(bytes)) {
          bufView[i] = bytes.charCodeAt(i);
        } else if (_.isArray(bytes)) {
          bufView[i] = bytes[i];
        }
      }
      _receiveSomeBytes(bufView);
    }
  }

  function connect(deviceInfo, handler, probe, cb) {
    if (arguments.length != 4) {
      console.log('serial connect called with wrong number of arguments!');
    }

    // If the driver specifies a bitrate override, we have to use it
    if (!!deviceInfo.bitrate) {
      bitrate = deviceInfo.bitrate;
    }

    // add a listener for any serial traffic
    // do this first so that we don't lose anything (not that it's all that
    // likely, but it doesn't hurt)
    chrome.serial.onReceive.addListener(portListener);
    if (_.isFunction(handler)) {
      setPacketHandler(handler);
    } else if (_.isObject(handler)) {
      setPacketHandler(handler.packetHandler);
      if (handler.errorHandler) {
        setErrorHandler(handler.errorHandler);
        chrome.serial.onReceiveError.addListener(errorListener);
      }
    }
    flush();

    debug('in SerialDevice.connect, info ', deviceInfo);

    // generate a list of all the ports in the system
    chrome.serial.getDevices(function(ports) {
      // filter the list of ports if we can, using the portPattern if we have one
      if (deviceInfo.portPattern) {
        ports = _.filter(ports, function(p) {
          return p.path.match(deviceInfo.portPattern);
        });
      }

      // now sort that list based on index within the list of successful ports
      // we've used for this device
      var storedPorts = localStore.getItem(DEVICEPORTS);
      var allports = {};
      if (!_.isEmpty(storedPorts)) {
        allports = JSON.parse(storedPorts);
      }
      var successfulPorts = [];
      if (allports) {
        successfulPorts = allports[deviceInfo.driverId];
      }
      ports = _.sortBy(ports, function(port) {
        var i = _.indexOf(successfulPorts, port.path);
        if (i < 0) {
          return 1000;
        } else {
          return i;
        }
      });

      // now walk all the matching serial ports and try each one
      // debug(ports);

      async.eachSeries(ports, function(port, done) {
        debug('now trying port ', port);
        var connectopts = {
          bitrate: bitrate,
          name: port.path,
          sendTimeout: deviceInfo.sendTimeout || 1000,
          receiveTimeout: deviceInfo.receiveTimeout || 1000,
          ctsFlowControl: deviceInfo.ctsFlowControl || false
        };

        chrome.serial.connect(port.path, connectopts, function(conn) {
          if (chrome.runtime.lastError !== undefined) {
            console.log('Error attempting to connect: ', chrome.runtime.lastError);
          }
          if (conn && conn.connectionId) {
            connection = conn;
            probe(function(err) {
              if (!err) {
                return done(conn); // we found a port so abort the eachSerial
              } else {
                // it didn't work so disconnect
                chrome.serial.disconnect(conn.connectionId, function() {});  // don't care what the result is
                return done();
              }
            });
          } else {
            done();
          }
        });
      }, function(result) {
        if (result) {
          addlog(' conn\n');
          logdump();
          connection = result;
          connectionPort = connection.name;
          debug('connected to ' + connection.name);
          cb();
        } else {
          connection = null;
          clearPacketHandler();
          cb(new Error('Could not connect to a matching device port ' + deviceInfo));
        }
      });
    });
  }

  function recordPort(deviceId) {
    var ap = localStore.getItem(DEVICEPORTS);
    var allports = ap ? JSON.parse(ap) : {};
    var successfulPorts = [];
    if (allports && allports[deviceId]) {
      successfulPorts = allports[deviceId];
    } else {
      allports = {};
    }
    if (_.indexOf(successfulPorts, connection.name) == -1) {
      successfulPorts.unshift(connection.name);
    }
    allports[deviceId] = successfulPorts;
    var s = JSON.stringify(allports);
    localStore.setItem(DEVICEPORTS, s);
  }

  function disconnect(cb) {
    chrome.serial.onReceive.removeListener(portListener);
    if (connection) {
      chrome.serial.disconnect(connection.connectionId, function(result) {
        addlog(' done\n');
        logdump();
        init();
        if (cb) {
          cb(result);
        }
      });
    } else {
      if (cb) {
        cb(null);
      }
    }
  }

  // allows changing the bit rate of an existing connection -- it disconnects and
  // reconnects
  function changeBitRate(newrate, cb) {
    if (connection) {
      addlog(' change bitrate to ' + newrate + '\n');
      bitrate = newrate;
      chrome.serial.disconnect(connection.connectionId, function(result) {
        debug('reconnecting on ' + connection.name + ' at ' + bitrate);
        setTimeout(function() {
          chrome.serial.connect(connection.name, { bitrate: bitrate }, function(conn) {
            if (chrome.runtime.lastError !== undefined) {
              console.log('Error attempting to connect: ', chrome.runtime.lastError);
            }
            debug('reconnected');
            connection = conn;
            if (cb) {
              cb(true);
            }
          });
        }, 500);
      });
    } else {
      if (cb) {
        cb(false);
      }
    }
  }

  function discardBytes(discardCount) {
    addlog('discard ' + discardCount + '\n');
    logdump();
    buffer = buffer.slice(discardCount);
  }

  function readSerial(bytes, timeout, callback) {
    var packet;
    if (buffer.length >= bytes) {
      packet = buffer.slice(0,bytes);
      buffer = buffer.slice(0 - bytes);
      callback(packet);
    } else if (timeout === 0) {
      packet = buffer;
      buffer = [];
      callback(packet);
    } else {
      setTimeout(function() {
        readSerial(bytes, 0, callback);
      }, timeout);
    }
  }

  function writeSerial(bytes, callback) {
    var bufView = new Uint8Array(bytes);
    var l = bufView.length;
    var timerId = setTimeout(function() {
      sendcheck({ bytesSent: 0, error: 'timeout' });
    }, 500);
    var sendcheck = function(info) {
      clearTimeout(timerId);
      // debug('Sent ', info.bytesSent,' bytes');
      addlog(' xmit ');
      for (var i in bufView) {
        addlog(('00' + bufView[i].toString(16)).substr(-2) + ' ');
      }
      addlog('\n');
      logdump();

      if (l != info.bytesSent) {
        debug('Only ' + info.bytesSent + ' bytes sent out of ' + l);
      }
      if (info.error) {
        debug('Serial send returned ' + info.error);
      }
      callback(info.error, info);
    };
    if (bytes == null) {
      debug('just tried to send nothing!');
    } else {
      chrome.serial.send(connection.connectionId, bytes, sendcheck);
    }
  }

  // a handler should be a function that takes a parameter of a buffer
  // and tries to extract a packet from it; if it finds one, it should delete
  // the characters that make up the packet from the buffer, and return the
  // packet.
  function setPacketHandler(handler) {
    packetHandler = handler;
  }

  function clearPacketHandler() {
    packetHandler = null;
  }

  function setErrorHandler(handler) {
    errorHandler = handler;
  }

  function clearErrorHandler() {
    errorHandler = null;
  }

  function hasAvailablePacket() {
    return packetBuffer.length > 0;
  }

  function peekPacket() {
    if (hasAvailablePacket()) {
      return packetBuffer[0];
    } else {
      return null;
    }
  }

  function nextPacket() {
    if (hasAvailablePacket()) {
      return packetBuffer.shift();
    } else {
      return null;
    }
  }

  function flush() {
    addlog('flush\n');
    logdump();
    packetBuffer = [];
  }

  function setPattern(p) {
    debug('Module #' + moduleNumber + ' setting portPattern to ' + p);
    portPattern = p;
  }

  function setBitrate(br) {
    bitrate = br;
  }

  return {
    setPattern: setPattern,
    setBitrate: setBitrate,
    connect: connect,
    recordPort: recordPort,
    disconnect: disconnect,
    changeBitRate: changeBitRate,
    discardBytes: discardBytes,
    readSerial: readSerial,
    writeSerial: writeSerial,
    setPacketHandler: setPacketHandler,
    clearPacketHandler: clearPacketHandler,
    setErrorHandler: setErrorHandler,
    clearErrorHandler: clearErrorHandler,
    hasAvailablePacket: hasAvailablePacket,
    peekPacket: peekPacket,
    nextPacket: nextPacket,
    flush: flush,
    emitLog: emitLog
  };

};
<commit_msg>minor adjustment for prettier logs<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

/* global chrome */

var _ = require('lodash');
var async = require('async');
var localStore = require('./core/localStore');

// for tests
if (typeof localStore === 'function') {
  localStore = localStore({});
}

var DEVICEPORTS = 'devicePorts';

var debug = require('./bows')('SerialDevice');

var moduleCounter = 1;

module.exports = function(config) {
  config = config || {};
  var connection = null;
  var connectionPort = null;
  var buffer = [];
  var packetBuffer = [];
  var packetHandler = null;
  var errorHandler = null;
  var moduleNumber = moduleCounter++;
  var portPattern = '/dev/cu.usb.+';
  var bitrate = config.bitrate || 9600;
  var log = '';
  var logcount = 0;
  var loglimit = 400;
  var doLogging = (config && config.doLogging) || false;

  if (config.silent) {
    // debug = _.noop;
  }

  function init() {
    connection = null;
    connectionPort = null;
    buffer = [];
    packetBuffer = [];
    packetHandler = null;
    log = '';
    localStore.init(DEVICEPORTS, function() {});
  }

  init();

  // This is the object that is passed to the packetHandler
  // it lets us abstract away the details of the packetHandling
  var bufobj = {
    // get(x) -- returns char at x
    get : function(n) {return buffer[n]; },
    // len() -- returns length
    len : function() { return buffer.length; },
    // discard(n) -- deletes n chars at start of buffer
    discard : function(n) { discardBytes(n); },
    // bytes() -- returns entire buffer as a Uint8Array
    bytes : function() {
      return new Uint8Array(buffer);
    }
  };

  function addlog(s) {
    if (!doLogging) {
      return;
    }

    if (logcount < loglimit) {
      if (s.indexOf('\n') !== -1) {
        ++logcount;
      }
      log += s;
    }
  }

  var logdump = _.debounce(function() {
    if (doLogging) {
      debug(log);
    }
  }, 900);

  var emitLog = function(clearLog) {
    debug(log);
    if (clearLog) {
      log = '';
      logcount = 0;
    }
  };

  function _receiveSomeBytes(bufView) {
    for (var i=0; i<bufView.byteLength; i++) {
      buffer.push(bufView[i]);
    }

    addlog('  rcv ');
    for (i in bufView) {
      addlog(('00' + bufView[i].toString(16)).substr(-2) + ' ');
    }
    addlog('\n');
    logdump();

    // we got some bytes, let's see if they make one or more packets
    if (packetHandler) {
      var pkt = packetHandler(bufobj);
      while (pkt) {
        packetBuffer.push(pkt);
        pkt = packetHandler(bufobj);
      }
    }

  }

  function portListener(info) {
    if (connection && info.connectionId == connection.connectionId && info.data) {
      var bufView=new Uint8Array(info.data);
      _receiveSomeBytes(bufView);
    }
  }

  // if an errorHandler was specified, then we call it with every error.
  // If it returns anything, it should return either a string or an array
  // containing the bytes it wants to insert into the buffer.
  // According to chrome's docs, info will contain connectionId, and an
  // error member that can be any of "disconnected", "timeout", "device_lost", or "system_error"
  function errorListener(info) {
    if (info.error && errorHandler) {
      var bytes = errorHandler(info);
      var bufView = new Uint8Array(bytes.length);
      for (var i=0; i<bytes.length; i++) {
        if (_.isString(bytes)) {
          bufView[i] = bytes.charCodeAt(i);
        } else if (_.isArray(bytes)) {
          bufView[i] = bytes[i];
        }
      }
      _receiveSomeBytes(bufView);
    }
  }

  function connect(deviceInfo, handler, probe, cb) {
    if (arguments.length != 4) {
      console.log('serial connect called with wrong number of arguments!');
    }

    // If the driver specifies a bitrate override, we have to use it
    if (!!deviceInfo.bitrate) {
      bitrate = deviceInfo.bitrate;
    }

    // add a listener for any serial traffic
    // do this first so that we don't lose anything (not that it's all that
    // likely, but it doesn't hurt)
    chrome.serial.onReceive.addListener(portListener);
    if (_.isFunction(handler)) {
      setPacketHandler(handler);
    } else if (_.isObject(handler)) {
      setPacketHandler(handler.packetHandler);
      if (handler.errorHandler) {
        setErrorHandler(handler.errorHandler);
        chrome.serial.onReceiveError.addListener(errorListener);
      }
    }
    flush();

    debug('in SerialDevice.connect, info ', deviceInfo);

    // generate a list of all the ports in the system
    chrome.serial.getDevices(function(ports) {
      // filter the list of ports if we can, using the portPattern if we have one
      if (deviceInfo.portPattern) {
        ports = _.filter(ports, function(p) {
          return p.path.match(deviceInfo.portPattern);
        });
      }

      // now sort that list based on index within the list of successful ports
      // we've used for this device
      var storedPorts = localStore.getItem(DEVICEPORTS);
      var allports = {};
      if (!_.isEmpty(storedPorts)) {
        allports = JSON.parse(storedPorts);
      }
      var successfulPorts = [];
      if (allports) {
        successfulPorts = allports[deviceInfo.driverId];
      }
      ports = _.sortBy(ports, function(port) {
        var i = _.indexOf(successfulPorts, port.path);
        if (i < 0) {
          return 1000;
        } else {
          return i;
        }
      });

      // now walk all the matching serial ports and try each one
      // debug(ports);

      async.eachSeries(ports, function(port, done) {
        debug('now trying port ', port);
        var connectopts = {
          bitrate: bitrate,
          name: port.path,
          sendTimeout: deviceInfo.sendTimeout || 1000,
          receiveTimeout: deviceInfo.receiveTimeout || 1000,
          ctsFlowControl: deviceInfo.ctsFlowControl || false
        };

        chrome.serial.connect(port.path, connectopts, function(conn) {
          if (chrome.runtime.lastError !== undefined) {
            console.log('Error attempting to connect: ', chrome.runtime.lastError);
          }
          if (conn && conn.connectionId) {
            connection = conn;
            probe(function(err) {
              if (!err) {
                return done(conn); // we found a port so abort the eachSerial
              } else {
                // it didn't work so disconnect
                chrome.serial.disconnect(conn.connectionId, function() {});  // don't care what the result is
                return done();
              }
            });
          } else {
            done();
          }
        });
      }, function(result) {
        if (result) {
          addlog(' conn\n');
          logdump();
          connection = result;
          connectionPort = connection.name;
          debug('connected to ' + connection.name);
          cb();
        } else {
          connection = null;
          clearPacketHandler();
          var deviceDebugInfo = 'driverId ' + deviceInfo.driverId + ', vendorId ' + deviceInfo.vendorId +
            ', productId ' + deviceInfo.productId + ', portPattern ' + deviceInfo.portPattern +
            ', usbDevice ' + deviceInfo.usbDevice;
          cb(new Error('Could not connect to a matching device port: ' + deviceDebugInfo));
        }
      });
    });
  }

  function recordPort(deviceId) {
    var ap = localStore.getItem(DEVICEPORTS);
    var allports = ap ? JSON.parse(ap) : {};
    var successfulPorts = [];
    if (allports && allports[deviceId]) {
      successfulPorts = allports[deviceId];
    } else {
      allports = {};
    }
    if (_.indexOf(successfulPorts, connection.name) == -1) {
      successfulPorts.unshift(connection.name);
    }
    allports[deviceId] = successfulPorts;
    var s = JSON.stringify(allports);
    localStore.setItem(DEVICEPORTS, s);
  }

  function disconnect(cb) {
    chrome.serial.onReceive.removeListener(portListener);
    if (connection) {
      chrome.serial.disconnect(connection.connectionId, function(result) {
        addlog(' done\n');
        logdump();
        init();
        if (cb) {
          cb(result);
        }
      });
    } else {
      if (cb) {
        cb(null);
      }
    }
  }

  // allows changing the bit rate of an existing connection -- it disconnects and
  // reconnects
  function changeBitRate(newrate, cb) {
    if (connection) {
      addlog(' change bitrate to ' + newrate + '\n');
      bitrate = newrate;
      chrome.serial.disconnect(connection.connectionId, function(result) {
        debug('reconnecting on ' + connection.name + ' at ' + bitrate);
        setTimeout(function() {
          chrome.serial.connect(connection.name, { bitrate: bitrate }, function(conn) {
            if (chrome.runtime.lastError !== undefined) {
              console.log('Error attempting to connect: ', chrome.runtime.lastError);
            }
            debug('reconnected');
            connection = conn;
            if (cb) {
              cb(true);
            }
          });
        }, 500);
      });
    } else {
      if (cb) {
        cb(false);
      }
    }
  }

  function discardBytes(discardCount) {
    addlog('discard ' + discardCount + '\n');
    logdump();
    buffer = buffer.slice(discardCount);
  }

  function readSerial(bytes, timeout, callback) {
    var packet;
    if (buffer.length >= bytes) {
      packet = buffer.slice(0,bytes);
      buffer = buffer.slice(0 - bytes);
      callback(packet);
    } else if (timeout === 0) {
      packet = buffer;
      buffer = [];
      callback(packet);
    } else {
      setTimeout(function() {
        readSerial(bytes, 0, callback);
      }, timeout);
    }
  }

  function writeSerial(bytes, callback) {
    var bufView = new Uint8Array(bytes);
    var l = bufView.length;
    var timerId = setTimeout(function() {
      sendcheck({ bytesSent: 0, error: 'timeout' });
    }, 500);
    var sendcheck = function(info) {
      clearTimeout(timerId);
      // debug('Sent ', info.bytesSent,' bytes');
      addlog(' xmit ');
      for (var i in bufView) {
        addlog(('00' + bufView[i].toString(16)).substr(-2) + ' ');
      }
      addlog('\n');
      logdump();

      if (l != info.bytesSent) {
        debug('Only ' + info.bytesSent + ' bytes sent out of ' + l);
      }
      if (info.error) {
        debug('Serial send returned ' + info.error);
      }
      callback(info.error, info);
    };
    if (bytes == null) {
      debug('just tried to send nothing!');
    } else {
      chrome.serial.send(connection.connectionId, bytes, sendcheck);
    }
  }

  // a handler should be a function that takes a parameter of a buffer
  // and tries to extract a packet from it; if it finds one, it should delete
  // the characters that make up the packet from the buffer, and return the
  // packet.
  function setPacketHandler(handler) {
    packetHandler = handler;
  }

  function clearPacketHandler() {
    packetHandler = null;
  }

  function setErrorHandler(handler) {
    errorHandler = handler;
  }

  function clearErrorHandler() {
    errorHandler = null;
  }

  function hasAvailablePacket() {
    return packetBuffer.length > 0;
  }

  function peekPacket() {
    if (hasAvailablePacket()) {
      return packetBuffer[0];
    } else {
      return null;
    }
  }

  function nextPacket() {
    if (hasAvailablePacket()) {
      return packetBuffer.shift();
    } else {
      return null;
    }
  }

  function flush() {
    addlog('flush\n');
    logdump();
    packetBuffer = [];
  }

  function setPattern(p) {
    debug('Module #' + moduleNumber + ' setting portPattern to ' + p);
    portPattern = p;
  }

  function setBitrate(br) {
    bitrate = br;
  }

  return {
    setPattern: setPattern,
    setBitrate: setBitrate,
    connect: connect,
    recordPort: recordPort,
    disconnect: disconnect,
    changeBitRate: changeBitRate,
    discardBytes: discardBytes,
    readSerial: readSerial,
    writeSerial: writeSerial,
    setPacketHandler: setPacketHandler,
    clearPacketHandler: clearPacketHandler,
    setErrorHandler: setErrorHandler,
    clearErrorHandler: clearErrorHandler,
    hasAvailablePacket: hasAvailablePacket,
    peekPacket: peekPacket,
    nextPacket: nextPacket,
    flush: flush,
    emitLog: emitLog
  };

};
<|endoftext|>