<commit_before>var routes = require('./routes.js');
var location = require('./location.js');
var mail = require('./mail.js');
var customerprice = require('./customerprice.js');

var segments = [];
var nodes = {};
var prices = [];
var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

/**
* @param {mail} mail being delivered
*/
var findRoute = function(mail){
  if(mail.priority.toUppercase() === "DOMESTIC AIR" || mail.priority === "DOMESTIC STANDARD"){
    return findDomesticRoute(mail);
  }
  if(mail.priority.toUppercase() === "INTERNATIONAL AIR"){
    return findInternationalAirRoute(mail);
  }
  if(mail.priority.toUppercase() === "INTERNATIONAL STANDARD"){
    return findInternationalStandardRoute(mail);
  }
}

var findDomesticRoute = function(mail){
  //TODO store how we got to each node
  //Create a set of all the unvisited nodes called the unvisited set and init node values
  var unvisited = [];
  for(var node in nodes){
    unvisited.push(node);
    node.distance =  Number.POSITIVE_INFINITY;
    node.visited = false;
    node.fromSegment = null;
  }
  this.currentNode = nodes[mail.from];
  this.currentNode.distance = 0;

  while(true){
    //For the current node consider all of its unvisited neighbors
      for(var segment in this.currentNode.segments){
        if(!segement.endNode.visited && segment.maxWeight >= mail.weight && segment.maxVolume >= mail.volume){
          //calculate time for next departure
          this.today = mail.date.getDay();
          this.waitTime = findRouteWaitTime(this.today, segment);
          //calculate tentative distance. Compare tentative distance to the current assigned value
          //assign the smaller one.
          if((this.currentNode.distance + segment.duration + this.waitTime) < segment.endNode.distance){
            segment.endNode.distance = this.currentNode.distance + segment.duration + this.waitTime;
            segment.endNode.fromSegment = segment;
          }
        }
      }
      //When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.
      this.currentNode.visited = true;
      removeItem(this.currentNode, unvisited);
      //If the destination node has been visited then stop. The algorithm has finished.
      if(nodes[mail.to].visted){
        this.cost = 0;
        while(this.currentNode != nodes[mail.from]){
          this.cost += (this.currentNode.fromSegment.weightCost * mail.weight) + (this.currentNode.fromSegment.volumeCost * mail.volume);
          this.currentNode = this.currentNode.fromSegment.startNode;
        }
        return this.cost;
      }
      //if the smallest distance in the unvisited set is infinity, the graph is not connected
      if(getSmallestDistance(unvisited) == Number.POSITIVE_INFINITY){
        return 0;
      }
      // Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.
      this.minDistance = Number.POSITIVE_INFINITY;
      for(var node in unvisted){
        if(node.distance< minDistance){
          this.currentNode = node;
        }
      }
  }

}

var findInternationalAirRoute = function(mail){
  //Create a set of all the unvisited nodes called the unvisited set and init node values
  var unvisited = [];
  for(var node in nodes){
    unvisited.push(node);
    node.distance =  Number.POSITIVE_INFINITY;
    node.visited = false;
    node.fromSegment = null;
  }
  this.currentNode = nodes[mail.from];
  this.currentNode.distance = 0;

  while(true){
    //For the current node consider all of its unvisited neighbors
      for(var segment in this.currentNode.segments){
        if(!segement.endNode.visited && segment.type === "Air" && segment.maxWeight >= mail.weight && segment.maxVolume >= mail.volume){
          //TODO check type format
          //calculate time for next departure
          this.today = mail.date.getDay();
          this.waitTime = findRouteWaitTime(this.today, segment);
          //calculate tentative distance. Compare tentative distance to the current assigned value
          //assign the smaller one.
          segment.endNode.distance = min(this.currentNode.distance + segment.duration + this.waitTime, segment.endNode.distance);
        }
      }
      //When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.
      this.currentNode.visited = true;
      removeItem(this.currentNode, unvisited);
      //If the destination node has been visited then stop. The algorithm has finished.
      if(nodes[mail.to].visted){
        this.cost = 0;
        while(this.currentNode != nodes[mail.from]){
          this.cost += (this.currentNode.fromSegment.weightCost * mail.weight) + (this.currentNode.fromSegment.volumeCost * mail.volume);
          this.currentNode = this.currentNode.fromSegment.startNode;
        }
        return this.cost;
      }
      //if the smallest distance in the unvisited set is infinity, the graph is not connected by air routes only
      if(getSmallestDistance(unvisited) == Number.POSITIVE_INFINITY){
        return 0;
      }
      // Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.
      this.minDistance = Number.POSITIVE_INFINITY;
      for(var node in unvisted){
        if(node.distance< minDistance){
          this.currentNode = node;
        }
      }
  }
}

var findInternationalStandardRoute = function(mail){
  //TODO allow use of air if no other option
  //Create a set of all the unvisited nodes called the unvisited set and init node values
  var unvisited = [];
  for(var node in nodes){
    unvisited.push(node);
    node.distance =  Number.POSITIVE_INFINITY;
    node.visited = false;
  }
  this.currentNode = nodes[mail.from];
  this.currentNode.distance = 0;

  while(true){
    //For the current node consider all of its unvisited neighbors
      for(var segment in this.currentNode.segments){
        if(!segement.endNode.visited && (segment.type === "Sea" || segment.type === "Land" ) && segment.maxWeight >= mail.weight && segment.maxVolume >= mail.volume){
          //TODO check type format
          //calculate tentative cost. Compare tentative distance to the current assigned value
          //assign the smaller one.
          this.cost = (segement.weightCost * mail.weight) + (segment.volumeCost * mail.volume);
          segment.endNode.distance = min(this.currentNode.distance + this.cost, segment.endNode.distance);
        }
      }
      //When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.
      this.currentNode.visited = true;
      removeItem(this.currentNode, unvisited);
      //If the destination node has been visited then stop. The algorithm has finished.
      if(nodes[mail.to].visted){
        //TODO add cost info to mail object
        return this.currentNode.distance;
      }
      //if the smallest distance in the unvisited set is infinity, the graph is not connected by air routes only
      if(getSmallestDistance(unvisited) == Number.POSITIVE_INFINITY){
        return 0;
      }
      // Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.
      this.minDistance = Number.POSITIVE_INFINITY;
      for(var node in unvisted){
        if(node.distance< minDistance){
          this.currentNode = node;
        }
      }
  }
}

var removeItem = function(item, array){
  this.index = array.indexOf(item);
  if(index >= 0){
    array.splice(index, 1);
  }
}

var getSmallestDistance = function(array){
  this.smallestDist = Number.POSITIVE_INFINITY;
  for(var node in array){
    if(this.smallestDist > node.distance){
      this.smallestDist = node.distance;
    }
  }
  return this.smallestDist;
}

var findRouteWaitTime = function(today, route){
  //TODO mail's day is in date form
  this.start = route.day;
  this.days;
  if(today === route){
    return 0;
  }
  if(today < start){
    this.days = 7 - start + today;
  }
  else{
    this.days = today - start;
  }
  return (route.frequency - ((24 * this.days) % route.frequency))
}

var createNodes = function(locs){
  if(typeof locs != 'undefined'){
    for(var i = 0;i < locs.length; i++){
      nodes[locs[i].name] = new node(locs[i].locationid, locs[i].name);
    }
    routes.getAllRoutes(createSegments);
  }
  else{
    console.log("Locs undefined");
  }
}

var createSegments = function(costs){
  if(typeof costs != 'undefined'){
    for(var i = 0; i < costs.length; i++){
      this.segment = new segment(nodes[costs[i].destination], nodes[costs[i].origin], costs[i].type, costs[i].weightcost, costs[i].volumecost, costs[i].maxweight, costs[i].maxvolume, costs[i].duration, costs[i].frequency, costs[i].day);
      segments.push(this.segment);
      nodes[costs[i].origin].segments.push(this.segment);
    }
    testMail();
  }
  else{
    console.log("Costs undefined: ");
  }
}

exports.loadGraph = function(){
    location.getAllLocations(createNodes);
}

var printAll = function(){
  console.log("Printing Nodes: ");
  for(var node in nodes){
    console.log(node);
  }
  console.log("Printing Segments: ");
  for(var seg in segments){
    console.log(seg);
  }
}

var testMail = function(){
  this.mailList = mail.getAllMail();
  for(var mail in this.mailList){
    console.log(findRoute(mail));
  }
}

/**
* @param {int} id Unique identifier
* @param {node} sNode Node where this segment originates
* @param {node} eNode Node where this segment terminates
* @param {string} type Type of transport, land, air or sea
* @param {int} wc weight cost
* @param {int} vc volume cost
* @param {int} mw max weightCost
* @param {int} mv max volumeCost
* @param {int} dur Time it takes this segment to transport
* @param {int} freq The frequency this segment sets out at
* @param {string} day Which day the transport cycle starts at
*/
var segment = function(id, sNode, eNode, type, wc, vc, mw, mv, dur, freq, day){
  this.id = id;
  this.startNode = sNode;
  this.endNode = eNode;
  this.type = type;
  this.weightCost = wc;
  this.volumeCost = vc;
  this.maxWeight = mw;
  this.maxVolume = mv;
  this.duration = dur;
  this.frequency = freq;
  this.day = day;

}

/**
* @param {int} id Unique identifier
* @param {string} name Name of location
*/
var node = function(id, name){
  this.id = id;
  this.name = name;
  this.segments = [];
  this.distance = Number.POSITIVE_INFINITY;
  this.visited = false;
  this.fromSegment = null;
}
<commit_msg>Fixed priority check in graph<commit_after>var routes = require('./routes.js');
var location = require('./location.js');
var mail = require('./mail.js');
var customerprice = require('./customerprice.js');

var segments = [];
var nodes = {};
var prices = [];
var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

/**
* @param {mail} mail being delivered
*/
var findRoute = function(mail){
  if(mail.priority.toUpperCase() === "DOMESTIC AIR" || mail.priority.toUpperCase() === "DOMESTIC STANDARD"){
    return findDomesticRoute(mail);
  }
  if(mail.priority.toUpperCase() === "INTERNATIONAL AIR"){
    return findInternationalAirRoute(mail);
  }
  if(mail.priority.toUpperCase() === "INTERNATIONAL STANDARD"){
    return findInternationalStandardRoute(mail);
  }
}

var findDomesticRoute = function(mail){
  //TODO store how we got to each node
  //Create a set of all the unvisited nodes called the unvisited set and init node values
  var unvisited = [];
  for(var node in nodes){
    unvisited.push(node);
    node.distance =  Number.POSITIVE_INFINITY;
    node.visited = false;
    node.fromSegment = null;
  }
  this.currentNode = nodes[mail.from];
  this.currentNode.distance = 0;

  while(true){
    //For the current node consider all of its unvisited neighbors
      for(var segment in this.currentNode.segments){
        if(!segement.endNode.visited && segment.maxWeight >= mail.weight && segment.maxVolume >= mail.volume){
          //calculate time for next departure
          this.today = mail.date.getDay();
          this.waitTime = findRouteWaitTime(this.today, segment);
          //calculate tentative distance. Compare tentative distance to the current assigned value
          //assign the smaller one.
          if((this.currentNode.distance + segment.duration + this.waitTime) < segment.endNode.distance){
            segment.endNode.distance = this.currentNode.distance + segment.duration + this.waitTime;
            segment.endNode.fromSegment = segment;
          }
        }
      }
      //When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.
      this.currentNode.visited = true;
      removeItem(this.currentNode, unvisited);
      //If the destination node has been visited then stop. The algorithm has finished.
      if(nodes[mail.to].visted){
        this.cost = 0;
        while(this.currentNode != nodes[mail.from]){
          this.cost += (this.currentNode.fromSegment.weightCost * mail.weight) + (this.currentNode.fromSegment.volumeCost * mail.volume);
          this.currentNode = this.currentNode.fromSegment.startNode;
        }
        return this.cost;
      }
      //if the smallest distance in the unvisited set is infinity, the graph is not connected
      if(getSmallestDistance(unvisited) == Number.POSITIVE_INFINITY){
        return 0;
      }
      // Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.
      this.minDistance = Number.POSITIVE_INFINITY;
      for(var node in unvisted){
        if(node.distance< minDistance){
          this.currentNode = node;
        }
      }
  }

}

var findInternationalAirRoute = function(mail){
  //Create a set of all the unvisited nodes called the unvisited set and init node values
  var unvisited = [];
  for(var node in nodes){
    unvisited.push(node);
    node.distance =  Number.POSITIVE_INFINITY;
    node.visited = false;
    node.fromSegment = null;
  }
  this.currentNode = nodes[mail.from];
  this.currentNode.distance = 0;

  while(true){
    //For the current node consider all of its unvisited neighbors
      for(var segment in this.currentNode.segments){
        if(!segement.endNode.visited && segment.type === "Air" && segment.maxWeight >= mail.weight && segment.maxVolume >= mail.volume){
          //TODO check type format
          //calculate time for next departure
          this.today = mail.date.getDay();
          this.waitTime = findRouteWaitTime(this.today, segment);
          //calculate tentative distance. Compare tentative distance to the current assigned value
          //assign the smaller one.
          segment.endNode.distance = min(this.currentNode.distance + segment.duration + this.waitTime, segment.endNode.distance);
        }
      }
      //When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.
      this.currentNode.visited = true;
      removeItem(this.currentNode, unvisited);
      //If the destination node has been visited then stop. The algorithm has finished.
      if(nodes[mail.to].visted){
        this.cost = 0;
        while(this.currentNode != nodes[mail.from]){
          this.cost += (this.currentNode.fromSegment.weightCost * mail.weight) + (this.currentNode.fromSegment.volumeCost * mail.volume);
          this.currentNode = this.currentNode.fromSegment.startNode;
        }
        return this.cost;
      }
      //if the smallest distance in the unvisited set is infinity, the graph is not connected by air routes only
      if(getSmallestDistance(unvisited) == Number.POSITIVE_INFINITY){
        return 0;
      }
      // Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.
      this.minDistance = Number.POSITIVE_INFINITY;
      for(var node in unvisted){
        if(node.distance< minDistance){
          this.currentNode = node;
        }
      }
  }
}

var findInternationalStandardRoute = function(mail){
  //TODO allow use of air if no other option
  //Create a set of all the unvisited nodes called the unvisited set and init node values
  var unvisited = [];
  for(var node in nodes){
    unvisited.push(node);
    node.distance =  Number.POSITIVE_INFINITY;
    node.visited = false;
  }
  this.currentNode = nodes[mail.from];
  this.currentNode.distance = 0;

  while(true){
    //For the current node consider all of its unvisited neighbors
      for(var segment in this.currentNode.segments){
        if(!segement.endNode.visited && (segment.type === "Sea" || segment.type === "Land" ) && segment.maxWeight >= mail.weight && segment.maxVolume >= mail.volume){
          //TODO check type format
          //calculate tentative cost. Compare tentative distance to the current assigned value
          //assign the smaller one.
          this.cost = (segement.weightCost * mail.weight) + (segment.volumeCost * mail.volume);
          segment.endNode.distance = min(this.currentNode.distance + this.cost, segment.endNode.distance);
        }
      }
      //When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.
      this.currentNode.visited = true;
      removeItem(this.currentNode, unvisited);
      //If the destination node has been visited then stop. The algorithm has finished.
      if(nodes[mail.to].visted){
        //TODO add cost info to mail object
        return this.currentNode.distance;
      }
      //if the smallest distance in the unvisited set is infinity, the graph is not connected by air routes only
      if(getSmallestDistance(unvisited) == Number.POSITIVE_INFINITY){
        return 0;
      }
      // Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.
      this.minDistance = Number.POSITIVE_INFINITY;
      for(var node in unvisted){
        if(node.distance< minDistance){
          this.currentNode = node;
        }
      }
  }
}

var removeItem = function(item, array){
  this.index = array.indexOf(item);
  if(index >= 0){
    array.splice(index, 1);
  }
}

var getSmallestDistance = function(array){
  this.smallestDist = Number.POSITIVE_INFINITY;
  for(var node in array){
    if(this.smallestDist > node.distance){
      this.smallestDist = node.distance;
    }
  }
  return this.smallestDist;
}

var findRouteWaitTime = function(today, route){
  //TODO mail's day is in date form
  this.start = route.day;
  this.days;
  if(today === route){
    return 0;
  }
  if(today < start){
    this.days = 7 - start + today;
  }
  else{
    this.days = today - start;
  }
  return (route.frequency - ((24 * this.days) % route.frequency))
}

var createNodes = function(locs){
  if(typeof locs != 'undefined'){
    for(var i = 0;i < locs.length; i++){
      nodes[locs[i].name] = new node(locs[i].locationid, locs[i].name);
    }
    routes.getAllRoutes(createSegments);
  }
  else{
    console.log("Locs undefined");
  }
}

var createSegments = function(costs){
  if(typeof costs != 'undefined'){
    for(var i = 0; i < costs.length; i++){
      this.segment = new segment(nodes[costs[i].destination], nodes[costs[i].origin], costs[i].type, costs[i].weightcost, costs[i].volumecost, costs[i].maxweight, costs[i].maxvolume, costs[i].duration, costs[i].frequency, costs[i].day);
      segments.push(this.segment);
      nodes[costs[i].origin].segments.push(this.segment);
    }
    testMail();
  }
  else{
    console.log("Costs undefined: ");
  }
}

exports.loadGraph = function(){
    location.getAllLocations(createNodes);
}

var printAll = function(){
  console.log("Printing Nodes: ");
  for(var node in nodes){
    console.log(node);
  }
  console.log("Printing Segments: ");
  for(var seg in segments){
    console.log(seg);
  }
}

var testMail = function(){
  mail.getAllMail(mailFunction);
}

var mailFunction = function(mailList){
  for(var mail in mailList){
    //TODO mail location ids
    console.log(mailList);
    console.log(mail);
    console.log(findRoute(mailList[mail]));
  }
}

/**
* @param {int} id Unique identifier
* @param {node} sNode Node where this segment originates
* @param {node} eNode Node where this segment terminates
* @param {string} type Type of transport, land, air or sea
* @param {int} wc weight cost
* @param {int} vc volume cost
* @param {int} mw max weightCost
* @param {int} mv max volumeCost
* @param {int} dur Time it takes this segment to transport
* @param {int} freq The frequency this segment sets out at
* @param {string} day Which day the transport cycle starts at
*/
var segment = function(id, sNode, eNode, type, wc, vc, mw, mv, dur, freq, day){
  this.id = id;
  this.startNode = sNode;
  this.endNode = eNode;
  this.type = type;
  this.weightCost = wc;
  this.volumeCost = vc;
  this.maxWeight = mw;
  this.maxVolume = mv;
  this.duration = dur;
  this.frequency = freq;
  this.day = day;

}

/**
* @param {int} id Unique identifier
* @param {string} name Name of location
*/
var node = function(id, name){
  this.id = id;
  this.name = name;
  this.segments = [];
  this.distance = Number.POSITIVE_INFINITY;
  this.visited = false;
  this.fromSegment = null;
}
<|endoftext|>


<commit_before>/**
 * @fileoverview Raphael bubble chart renderer.
 * @author NHN Ent.
 *         FE Development Lab <dl_javascript@nhnent.com>
 */

'use strict';

var raphaelRenderUtil = require('./raphaelRenderUtil');
var snippet = require('tui-code-snippet');
var raphael = require('raphael');

var ANIMATION_DURATION = 700;
var CIRCLE_OPACITY = 0.8;
var STROKE_OPACITY = 1;
var EMPHASIS_OPACITY = 0.5;
var DE_EMPHASIS_OPACITY = 0.3;
var DEFAULT_LUMINANC = 0.2;
var OVERLAY_BORDER_WIDTH = 2;
var TOOLTIP_OFFSET_VALUE = 20;

/**
 * bound for circle
 * @typedef {{left: number, top: number, radius: number}} bound
 * @private
 */

/**
 * Information for rendered circle
 * @typedef {{circle: object, color: string, bound: bound}} circleInfo
 * @private
 */

/**
 * @classdesc RaphaelBubbleChart is graph renderer for bubble chart.
 * @class RaphaelBubbleChart
 * @private
 */
var RaphaelBubbleChart = snippet.defineClass(/** @lends RaphaelBubbleChart.prototype */ {
    /**
     * Render function of bubble chart
     * @param {object} paper - Raphael paper
     * @param {{
     *      dimension: {width: number, height: number},
     *      seriesDataModel: SeriesDataModel,
     *      groupBounds: Array.<Array.<bound>>,
     *      theme: object
     * }} data - data for rendering
     * @param {{showTooltip: function, hideTooltip: function}} callbacks - callbacks for toggle of tooltip.
     * @returns {object}
     */
    render: function(paper, data, callbacks) {
        var circleSet = paper.set();

        this.paper = paper;

        /**
         * theme
         * @type {object}
         */
        this.theme = data.theme;

        /**
         * seriesDataModel
         * @type {SeriesDataModel}
         */
        this.seriesDataModel = data.seriesDataModel;

        /**
         * group bounds
         * @type {Array.<Array.<bound>>}
         */
        this.groupBounds = data.groupBounds;

        /**
         * callbacks for toggle of tooltip.
         * @type {{showTooltip: Function, hideTooltip: Function}}
         */
        this.callbacks = callbacks;

        /**
         * overlay is circle object of raphael, that using for mouseover.
         * @type {object}
         */
        this.overlay = this._renderOverlay();

        /**
         * two-dimensional array by circleInfo
         * @type {Array.<Array.<circleInfo>>}
         */
        this.groupCircleInfos = this._renderCircles(circleSet);

        /**
         * previous selected circle
         * @type {?object}
         */
        this.prevCircle = null;

        /**
         * previous over circle
         * @type {?object}
         */
        this.prevOverCircle = null;

        /**
         * animation timeout id
         * @type {?number}
         */
        this.animationTimeoutId = null;

        if (this.paper.raphael.svg) {
            this.appendShadowFilterToDefs();
        }

        return circleSet;
    },

    /**
     * Render overlay.
     * @returns {object}
     * @private
     */
    _renderOverlay: function() {
        var position = {
            left: 0,
            top: 0
        };
        var attribute = {
            fill: 'none',
            stroke: '#fff',
            'stroke-opacity': STROKE_OPACITY,
            'stroke-width': 2
        };
        var circle = raphaelRenderUtil.renderCircle(this.paper, position, 0, attribute);

        return circle;
    },

    /**
     * Render circles.
     * @param {object} circleSet - circle set
     * @returns {Array.<Array.<circleInfo>>}
     * @private
     */
    _renderCircles: function(circleSet) {
        var self = this;
        var colors = this.theme.colors;

        return snippet.map(this.groupBounds, function(bounds, groupIndex) {
            return snippet.map(bounds, function(bound, index) {
                var circleInfo = null;
                var color, circle;

                if (bound) {
                    color = colors[index];
                    circle = raphaelRenderUtil.renderCircle(self.paper, bound, 0, {
                        fill: color,
                        opacity: 0,
                        stroke: 'none'
                    });

                    circleSet.push(circle);

                    circle.data('groupIndex', groupIndex);
                    circle.data('index', index);

                    circleInfo = {
                        circle: circle,
                        color: color,
                        bound: bound
                    };
                }

                return circleInfo;
            });
        });
    },

    /**
     * Animate circle
     * @param {object} circle - raphael object
     * @param {number} radius - radius of circle
     * @private
     */
    _animateCircle: function(circle, radius) {
        circle.animate({
            r: radius,
            opacity: CIRCLE_OPACITY
        }, ANIMATION_DURATION, '>');
    },

    /**
     * Animate.
     */
    animate: function() {
        var self = this;

        raphaelRenderUtil.forEach2dArray(this.groupCircleInfos, function(circleInfo) {
            if (!circleInfo) {
                return;
            }
            self._animateCircle(circleInfo.circle, circleInfo.bound.radius);
        });
    },

    /**
     * Update circle bound
     * @param {object} circle - raphael object
     * @param {{left: number, top: number}} bound - bound
     * @private
     */
    _updatePosition: function(circle, bound) {
        circle.attr({
            cx: bound.left,
            cy: bound.top,
            r: bound.radius
        });
    },

    /**
     * Resize graph of bubble type chart.
     * @param {object} params parameters
     *      @param {{width: number, height:number}} params.dimension - dimension
     *      @param {Array.<Array.<bound>>} params.groupBounds - group bounds
     */
    resize: function(params) {
        var self = this;
        var dimension = params.dimension;
        var groupBounds = params.groupBounds;

        this.groupBounds = groupBounds;
        this.paper.setSize(dimension.width, dimension.height);

        raphaelRenderUtil.forEach2dArray(this.groupCircleInfos, function(circleInfo, groupIndex, index) {
            var bound = groupBounds[groupIndex][index];
            if (circleInfo) {
                circleInfo.bound = bound;
                self._updatePosition(circleInfo.circle, bound);
            }
        });
    },

    /**
     * Find data indexes of rendered circle by position.
     * @param {{left: number, top: number}} position - mouse position
     * @returns {{index: number, groupIndex: number}}
     */
    findIndexes: function(position) {
        var circle = this.paper.getElementByPoint(position.left, position.top);
        var foundIndexes = null;

        if (circle) {
            foundIndexes = {
                index: circle.data('index'),
                groupIndex: circle.data('groupIndex')
            };
        }

        return foundIndexes;
    },

    appendShadowFilterToDefs: function() {
        var filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');
        var feOffset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');
        var feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
        var feBlend = document.createElementNS('http://www.w3.org/2000/svg', 'feBlend');

        filter.setAttributeNS(null, 'id', 'shadow');
        filter.setAttributeNS(null, 'x', '-50%');
        filter.setAttributeNS(null, 'y', '-50%');
        filter.setAttributeNS(null, 'width', '180%');
        filter.setAttributeNS(null, 'height', '180%');
        feOffset.setAttributeNS(null, 'result', 'offOut');
        feOffset.setAttributeNS(null, 'in', 'SourceAlpha');
        feOffset.setAttributeNS(null, 'dx', '0');
        feOffset.setAttributeNS(null, 'dy', '0');
        feGaussianBlur.setAttributeNS(null, 'result', 'blurOut');
        feGaussianBlur.setAttributeNS(null, 'in', 'offOut');
        feGaussianBlur.setAttributeNS(null, 'stdDeviation', '2');
        feBlend.setAttributeNS(null, 'in', 'SourceGraphic');
        feBlend.setAttributeNS(null, 'in2', 'blurOut');
        feBlend.setAttributeNS(null, 'mode', 'normal');
        filter.appendChild(feOffset);
        filter.appendChild(feGaussianBlur);
        filter.appendChild(feBlend);
        this.paper.defs.appendChild(filter);
    },

    /**
     * Whether changed or not.
     * @param {{left: number, top: number}} prevPosition - previous position
     * @param {{left: number, top: number}} position - position
     * @returns {boolean} result boolean
     * @private
     */
    _isChangedPosition: function(prevPosition, position) {
        return !prevPosition || prevPosition.left !== position.left || prevPosition.top !== position.top;
    },

    /**
     * Show overlay with animation.
     * @param {object} indexes - indexes
     *      @param {number} indexes.groupIndex - index of circles group
     *      @param {number} indexes.index - index of circles
     */
    showAnimation: function(indexes) {
        var circleInfo = this.groupCircleInfos[indexes.groupIndex][indexes.index];
        var bound = circleInfo.bound;
        this.circle = circleInfo.circle;

        this.overlay.attr({
            fill: circleInfo.color,
            cx: bound.left,
            cy: bound.top,
            r: bound.radius + OVERLAY_BORDER_WIDTH,
            stroke: '#fff',
            opacity: 1
        });

        this.circle.attr({
            opacity: 1
        });

        this.circle.toFront();
        this.overlay.node.setAttribute('filter', 'url(#shadow)');
        this.overlay.toFront();
    },

    /**
     * Hide overlay with animation.
     * @private
     */
    hideAnimation: function() {
        this.overlay.attr({
            cx: 0,
            cy: 0,
            r: 0,
            opacity: 0
        });

        this.circle.attr({
            opacity: CIRCLE_OPACITY
        });
    },

    /**
     * Find circle.
     * @param {{left: number, top: number}} position - position
     * @returns {?object}
     * @private
     */
    _findCircle: function(position) {
        var circles = [];
        var paper = this.paper;
        var foundCircle, circle;

        while (snippet.isUndefined(foundCircle)) {
            circle = paper.getElementByPoint(position.left, position.top);

            if (circle) {
                if (circle.attrs.opacity > DE_EMPHASIS_OPACITY) {
                    foundCircle = circle;
                } else {
                    circles.push(circle);
                    circle.hide();
                }
            } else {
                foundCircle = null;
            }
        }

        if (!foundCircle) {
            foundCircle = circles[0];
        }

        snippet.forEachArray(circles, function(_circle) {
            _circle.show();
        });

        return foundCircle;
    },

    /**
     * Move mouse on series.
     * @param {{left: number, top: number}} position - mouse position
     */
    moveMouseOnSeries: function(position) {
        var circle = this._findCircle(position);
        var groupIndex, index, args;

        if (circle && snippet.isExisty(circle.data('groupIndex'))) {
            groupIndex = circle.data('groupIndex');
            index = circle.data('index');
            args = [{}, groupIndex, index, {
                left: position.left - TOOLTIP_OFFSET_VALUE,
                top: position.top - TOOLTIP_OFFSET_VALUE
            }];

            if (this._isChangedPosition(this.prevPosition, position)) {
                this.callbacks.showTooltip.apply(null, args);
                this.prevOverCircle = circle;
            }
        } else if (this.prevOverCircle) {
            this.callbacks.hideTooltip();
            this.prevOverCircle = null;
        }
        this.prevPosition = position;
    },

    /**
     * Select series.
     * @param {{index: number, groupIndex: number}} indexes - index map
     */
    selectSeries: function(indexes) {
        var groupIndex = indexes.groupIndex;
        var index = indexes.index;
        var circleInfo = this.groupCircleInfos[groupIndex][index];
        var objColor = raphael.color(circleInfo.color);
        var themeColor = this.theme.selectionColor;
        var color = themeColor || raphaelRenderUtil.makeChangedLuminanceColor(objColor.hex, DEFAULT_LUMINANC);

        circleInfo.circle.attr({
            fill: color
        });
    },

    /**
     * Unselect series.
     * @param {{index: number, groupIndex: number}} indexes - index map
     */
    unselectSeries: function(indexes) {
        var groupIndex = indexes.groupIndex;
        var index = indexes.index;
        var circleInfo = this.groupCircleInfos[groupIndex][index];

        circleInfo.circle.attr({
            fill: circleInfo.color
        });
    },

    /**
     * Select legend.
     * @param {?number} legendIndex - index of legend
     */
    selectLegend: function(legendIndex) {
        var noneSelected = snippet.isNull(legendIndex);

        raphaelRenderUtil.forEach2dArray(this.groupCircleInfos, function(circleInfo, groupIndex, index) {
            var opacity;

            if (!circleInfo) {
                return;
            }

            opacity = (noneSelected || legendIndex === index) ? EMPHASIS_OPACITY : DE_EMPHASIS_OPACITY;

            circleInfo.circle.attr({opacity: opacity});
        });
    }
});

module.exports = RaphaelBubbleChart;
<commit_msg>Fixed a bug that blinks tooltips on bubbles and scatter charts.<commit_after>/**
 * @fileoverview Raphael bubble chart renderer.
 * @author NHN Ent.
 *         FE Development Lab <dl_javascript@nhnent.com>
 */

'use strict';

var raphaelRenderUtil = require('./raphaelRenderUtil');
var snippet = require('tui-code-snippet');
var raphael = require('raphael');

var ANIMATION_DURATION = 700;
var CIRCLE_OPACITY = 0.8;
var STROKE_OPACITY = 1;
var EMPHASIS_OPACITY = 0.5;
var DE_EMPHASIS_OPACITY = 0.3;
var DEFAULT_LUMINANC = 0.2;
var OVERLAY_BORDER_WIDTH = 2;
var TOOLTIP_OFFSET_VALUE = 20;

/**
 * bound for circle
 * @typedef {{left: number, top: number, radius: number}} bound
 * @private
 */

/**
 * Information for rendered circle
 * @typedef {{circle: object, color: string, bound: bound}} circleInfo
 * @private
 */

/**
 * @classdesc RaphaelBubbleChart is graph renderer for bubble chart.
 * @class RaphaelBubbleChart
 * @private
 */
var RaphaelBubbleChart = snippet.defineClass(/** @lends RaphaelBubbleChart.prototype */ {
    /**
     * Render function of bubble chart
     * @param {object} paper - Raphael paper
     * @param {{
     *      dimension: {width: number, height: number},
     *      seriesDataModel: SeriesDataModel,
     *      groupBounds: Array.<Array.<bound>>,
     *      theme: object
     * }} data - data for rendering
     * @param {{showTooltip: function, hideTooltip: function}} callbacks - callbacks for toggle of tooltip.
     * @returns {object}
     */
    render: function(paper, data, callbacks) {
        var circleSet = paper.set();

        this.paper = paper;

        /**
         * theme
         * @type {object}
         */
        this.theme = data.theme;

        /**
         * seriesDataModel
         * @type {SeriesDataModel}
         */
        this.seriesDataModel = data.seriesDataModel;

        /**
         * group bounds
         * @type {Array.<Array.<bound>>}
         */
        this.groupBounds = data.groupBounds;

        /**
         * callbacks for toggle of tooltip.
         * @type {{showTooltip: Function, hideTooltip: Function}}
         */
        this.callbacks = callbacks;

        /**
         * overlay is circle object of raphael, that using for mouseover.
         * @type {object}
         */
        this.overlay = this._renderOverlay();

        /**
         * two-dimensional array by circleInfo
         * @type {Array.<Array.<circleInfo>>}
         */
        this.groupCircleInfos = this._renderCircles(circleSet);

        /**
         * previous selected circle
         * @type {?object}
         */
        this.prevCircle = null;

        /**
         * previous over circle
         * @type {?object}
         */
        this.prevOverCircle = null;

        /**
         * animation timeout id
         * @type {?number}
         */
        this.animationTimeoutId = null;

        if (this.paper.raphael.svg) {
            this.appendShadowFilterToDefs();
        }

        return circleSet;
    },

    /**
     * Render overlay.
     * @returns {object}
     * @private
     */
    _renderOverlay: function() {
        var position = {
            left: 0,
            top: 0
        };
        var attribute = {
            fill: 'none',
            stroke: '#fff',
            'stroke-opacity': STROKE_OPACITY,
            'stroke-width': 2
        };
        var circle = raphaelRenderUtil.renderCircle(this.paper, position, 0, attribute);

        return circle;
    },

    /**
     * Render circles.
     * @param {object} circleSet - circle set
     * @returns {Array.<Array.<circleInfo>>}
     * @private
     */
    _renderCircles: function(circleSet) {
        var self = this;
        var colors = this.theme.colors;

        return snippet.map(this.groupBounds, function(bounds, groupIndex) {
            return snippet.map(bounds, function(bound, index) {
                var circleInfo = null;
                var color, circle;

                if (bound) {
                    color = colors[index];
                    circle = raphaelRenderUtil.renderCircle(self.paper, bound, 0, {
                        fill: color,
                        opacity: 0,
                        stroke: 'none'
                    });

                    circleSet.push(circle);

                    circle.data('groupIndex', groupIndex);
                    circle.data('index', index);

                    circleInfo = {
                        circle: circle,
                        color: color,
                        bound: bound
                    };
                }

                return circleInfo;
            });
        });
    },

    /**
     * Animate circle
     * @param {object} circle - raphael object
     * @param {number} radius - radius of circle
     * @private
     */
    _animateCircle: function(circle, radius) {
        circle.animate({
            r: radius,
            opacity: CIRCLE_OPACITY
        }, ANIMATION_DURATION, '>');
    },

    /**
     * Animate.
     */
    animate: function() {
        var self = this;

        raphaelRenderUtil.forEach2dArray(this.groupCircleInfos, function(circleInfo) {
            if (!circleInfo) {
                return;
            }
            self._animateCircle(circleInfo.circle, circleInfo.bound.radius);
        });
    },

    /**
     * Update circle bound
     * @param {object} circle - raphael object
     * @param {{left: number, top: number}} bound - bound
     * @private
     */
    _updatePosition: function(circle, bound) {
        circle.attr({
            cx: bound.left,
            cy: bound.top,
            r: bound.radius
        });
    },

    /**
     * Resize graph of bubble type chart.
     * @param {object} params parameters
     *      @param {{width: number, height:number}} params.dimension - dimension
     *      @param {Array.<Array.<bound>>} params.groupBounds - group bounds
     */
    resize: function(params) {
        var self = this;
        var dimension = params.dimension;
        var groupBounds = params.groupBounds;

        this.groupBounds = groupBounds;
        this.paper.setSize(dimension.width, dimension.height);

        raphaelRenderUtil.forEach2dArray(this.groupCircleInfos, function(circleInfo, groupIndex, index) {
            var bound = groupBounds[groupIndex][index];
            if (circleInfo) {
                circleInfo.bound = bound;
                self._updatePosition(circleInfo.circle, bound);
            }
        });
    },

    /**
     * Find data indexes of rendered circle by position.
     * @param {{left: number, top: number}} position - mouse position
     * @returns {{index: number, groupIndex: number}}
     */
    findIndexes: function(position) {
        var circle = this.paper.getElementByPoint(position.left, position.top);
        var foundIndexes = null;

        if (circle) {
            foundIndexes = {
                index: circle.data('index'),
                groupIndex: circle.data('groupIndex')
            };
        }

        return foundIndexes;
    },

    appendShadowFilterToDefs: function() {
        var filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');
        var feOffset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');
        var feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
        var feBlend = document.createElementNS('http://www.w3.org/2000/svg', 'feBlend');

        filter.setAttributeNS(null, 'id', 'shadow');
        filter.setAttributeNS(null, 'x', '-50%');
        filter.setAttributeNS(null, 'y', '-50%');
        filter.setAttributeNS(null, 'width', '180%');
        filter.setAttributeNS(null, 'height', '180%');
        feOffset.setAttributeNS(null, 'result', 'offOut');
        feOffset.setAttributeNS(null, 'in', 'SourceAlpha');
        feOffset.setAttributeNS(null, 'dx', '0');
        feOffset.setAttributeNS(null, 'dy', '0');
        feGaussianBlur.setAttributeNS(null, 'result', 'blurOut');
        feGaussianBlur.setAttributeNS(null, 'in', 'offOut');
        feGaussianBlur.setAttributeNS(null, 'stdDeviation', '2');
        feBlend.setAttributeNS(null, 'in', 'SourceGraphic');
        feBlend.setAttributeNS(null, 'in2', 'blurOut');
        feBlend.setAttributeNS(null, 'mode', 'normal');
        filter.appendChild(feOffset);
        filter.appendChild(feGaussianBlur);
        filter.appendChild(feBlend);
        this.paper.defs.appendChild(filter);
    },

    /**
     * Whether changed or not.
     * @param {{left: number, top: number}} prevPosition - previous position
     * @param {{left: number, top: number}} position - position
     * @returns {boolean} result boolean
     * @private
     */
    _isChangedPosition: function(prevPosition, position) {
        return !prevPosition || prevPosition.left !== position.left || prevPosition.top !== position.top;
    },

    /**
     * Show overlay with animation.
     * @param {object} indexes - indexes
     *      @param {number} indexes.groupIndex - index of circles group
     *      @param {number} indexes.index - index of circles
     */
    showAnimation: function(indexes) {
        var circleInfo = this.groupCircleInfos[indexes.groupIndex][indexes.index];
        var bound = circleInfo.bound;
        this.circle = circleInfo.circle;

        this.overlay.attr({
            fill: circleInfo.color,
            cx: bound.left,
            cy: bound.top,
            r: bound.radius + OVERLAY_BORDER_WIDTH,
            stroke: '#fff',
            opacity: 1
        });

        this.circle.attr({
            opacity: 1
        });

        this.overlay.node.setAttribute('filter', 'url(#shadow)');
        this.overlay.toFront();
        this.circle.toFront();
    },

    /**
     * Hide overlay with animation.
     * @private
     */
    hideAnimation: function() {
        this.overlay.attr({
            cx: 0,
            cy: 0,
            r: 0,
            opacity: 0
        });

        this.circle.attr({
            opacity: CIRCLE_OPACITY
        });
    },

    /**
     * Find circle.
     * @param {{left: number, top: number}} position - position
     * @returns {?object}
     * @private
     */
    _findCircle: function(position) {
        var circles = [];
        var paper = this.paper;
        var foundCircle, circle;

        while (snippet.isUndefined(foundCircle)) {
            circle = paper.getElementByPoint(position.left, position.top);

            if (circle) {
                if (circle.attrs.opacity > DE_EMPHASIS_OPACITY) {
                    foundCircle = circle;
                } else {
                    circles.push(circle);
                    circle.hide();
                }
            } else {
                foundCircle = null;
            }
        }

        if (!foundCircle) {
            foundCircle = circles[0];
        }

        snippet.forEachArray(circles, function(_circle) {
            _circle.show();
        });

        return foundCircle;
    },

    /**
     * Move mouse on series.
     * @param {{left: number, top: number}} position - mouse position
     */
    moveMouseOnSeries: function(position) {
        var circle = this._findCircle(position);
        var groupIndex, index, args;

        if (circle && snippet.isExisty(circle.data('groupIndex'))) {
            groupIndex = circle.data('groupIndex');
            index = circle.data('index');
            args = [{}, groupIndex, index, {
                left: position.left - TOOLTIP_OFFSET_VALUE,
                top: position.top - TOOLTIP_OFFSET_VALUE
            }];

            if (this._isChangedPosition(this.prevPosition, position)) {
                this.callbacks.showTooltip.apply(null, args);
                this.prevOverCircle = circle;
            }
        } else if (this.prevOverCircle) {
            this.callbacks.hideTooltip();
            this.prevOverCircle = null;
        }
        this.prevPosition = position;
    },

    /**
     * Select series.
     * @param {{index: number, groupIndex: number}} indexes - index map
     */
    selectSeries: function(indexes) {
        var groupIndex = indexes.groupIndex;
        var index = indexes.index;
        var circleInfo = this.groupCircleInfos[groupIndex][index];
        var objColor = raphael.color(circleInfo.color);
        var themeColor = this.theme.selectionColor;
        var color = themeColor || raphaelRenderUtil.makeChangedLuminanceColor(objColor.hex, DEFAULT_LUMINANC);

        circleInfo.circle.attr({
            fill: color
        });
    },

    /**
     * Unselect series.
     * @param {{index: number, groupIndex: number}} indexes - index map
     */
    unselectSeries: function(indexes) {
        var groupIndex = indexes.groupIndex;
        var index = indexes.index;
        var circleInfo = this.groupCircleInfos[groupIndex][index];

        circleInfo.circle.attr({
            fill: circleInfo.color
        });
    },

    /**
     * Select legend.
     * @param {?number} legendIndex - index of legend
     */
    selectLegend: function(legendIndex) {
        var noneSelected = snippet.isNull(legendIndex);

        raphaelRenderUtil.forEach2dArray(this.groupCircleInfos, function(circleInfo, groupIndex, index) {
            var opacity;

            if (!circleInfo) {
                return;
            }

            opacity = (noneSelected || legendIndex === index) ? EMPHASIS_OPACITY : DE_EMPHASIS_OPACITY;

            circleInfo.circle.attr({opacity: opacity});
        });
    }
});

module.exports = RaphaelBubbleChart;
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Red Hat, Inc.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 */

/*
 *   Copyright (c) 2011-2013 The original author or authors
 *   ------------------------------------------------------
 *   All rights reserved. This program and the accompanying materials
 *   are made available under the terms of the Eclipse Public License v1.0
 *   and Apache License v2.0 which accompanies this distribution.
 *
 *       The Eclipse Public License is available at
 *       http://www.eclipse.org/legal/epl-v10.html
 *
 *       The Apache License v2.0 is available at
 *       http://www.opensource.org/licenses/apache2.0.php
 *
 *   You may elect to redistribute this code under either of these licenses.
 */

var vertx = vertx || {};

!function(factory) {
  if (typeof define === "function" && define.amd) {
    // Expose as an AMD module with SockJS dependency.
    // "vertxbus" and "sockjs" names are used because
    // AMD module names are derived from file names.
    define("vertxbus", ["sockjs"], factory);
  } else {
    // No AMD-compliant loader
    factory(SockJS);
  }
}(function(SockJS) {

  vertx.EventBus = function(url, options) {

    var that = this;
    var sockJSConn = new SockJS(url, undefined, options);
    var handlerMap = {};
    var replyHandlers = {};
    var state = vertx.EventBus.CONNECTING;
    var pingTimerID = null;
    var pingInterval = null;
    if (options) {
      pingInterval = options['vertxbus_ping_interval'];
    }
    if (!pingInterval) {
      pingInterval = 5000;
    }

    that.onopen = null;
    that.onclose = null;

    that.send = function(address, message, replyHandler) {
      sendOrPub("send", address, message, replyHandler)
    }

    that.publish = function(address, message) {
      sendOrPub("publish", address, message, null)
    }

    that.registerHandler = function(address, handler) {
      checkSpecified("address", 'string', address);
      checkSpecified("handler", 'function', handler);
      checkOpen();
      var handlers = handlerMap[address];
      if (!handlers) {
        handlers = [handler];
        handlerMap[address] = handlers;
        // First handler for this address so we should register the connection
        var msg = { type : "register",
                    address: address };
        sockJSConn.send(JSON.stringify(msg));
      } else {
        handlers[handlers.length] = handler;
      }
    }

    that.unregisterHandler = function(address, handler) {
      checkSpecified("address", 'string', address);
      checkSpecified("handler", 'function', handler);
      checkOpen();
      var handlers = handlerMap[address];
      if (handlers) {
        var idx = handlers.indexOf(handler);
        if (idx != -1) handlers.splice(idx, 1);
        if (handlers.length == 0) {
          // No more local handlers so we should unregister the connection

          var msg = { type : "unregister",
                      address: address};
          sockJSConn.send(JSON.stringify(msg));
          delete handlerMap[address];
        }
      }
    }

    that.close = function() {
      checkOpen();
      state = vertx.EventBus.CLOSING;
      sockJSConn.close();
    }

    that.readyState = function() {
      return state;
    }

    sockJSConn.onopen = function() {
      // Send the first ping then send a ping every pingInterval milliseconds
      sendPing();
      pingTimerID = setInterval(sendPing, pingInterval);
      state = vertx.EventBus.OPEN;
      if (that.onopen) {
        that.onopen();
      }
    };

    sockJSConn.onclose = function() {
      state = vertx.EventBus.CLOSED;
      if (pingTimerID) clearInterval(pingTimerID);
      if (that.onclose) {
        that.onclose();
      }
    };

    sockJSConn.onmessage = function(e) {
      var msg = e.data;
      var json = JSON.parse(msg);
      var type = json.type;
      if (type === 'err') {
        console.error("Error received on connection: " + json.body);
        return;
      }
      var body = json.body;
      var replyAddress = json.replyAddress;
      var address = json.address;
      var replyHandler;
      if (replyAddress) {
        replyHandler = function(reply, replyHandler) {
          // Send back reply
          that.send(replyAddress, reply, replyHandler);
        };
      }
      var handlers = handlerMap[address];
      if (handlers) {
        // We make a copy since the handler might get unregistered from within the
        // handler itself, which would screw up our iteration
        var copy = handlers.slice(0);
        for (var i  = 0; i < copy.length; i++) {
          copy[i](body, replyHandler);
        }
      } else {
        // Might be a reply message
        var handler = replyHandlers[address];
        if (handler) {
          delete replyHandlers[address];
          handler(body, replyHandler);
        }
      }
    }

    function sendPing() {
      var msg = {
        type: "ping"
      }
      sockJSConn.send(JSON.stringify(msg));
    }

    function sendOrPub(sendOrPub, address, message, replyHandler) {
      checkSpecified("address", 'string', address);
      checkSpecified("replyHandler", 'function', replyHandler, true);
      checkOpen();
      var envelope = { type : sendOrPub,
                       address: address,
                       body: message };
      if (replyHandler) {
        var replyAddress = makeUUID();
        envelope.replyAddress = replyAddress;
        replyHandlers[replyAddress] = replyHandler;
      }
      var str = JSON.stringify(envelope);
      sockJSConn.send(str);
    }

    function checkOpen() {
      if (state != vertx.EventBus.OPEN) {
        throw new Error('INVALID_STATE_ERR');
      }
    }

    function checkSpecified(paramName, paramType, param, optional) {
      if (!optional && !param) {
        throw new Error("Parameter " + paramName + " must be specified");
      }
      if (param && typeof param != paramType) {
        throw new Error("Parameter " + paramName + " must be of type " + paramType);
      }
    }

    function isFunction(obj) {
      return !!(obj && obj.constructor && obj.call && obj.apply);
    }

    function makeUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
        .replace(/[xy]/g,function(a,b){return b=Math.random()*16,(a=="y"?b&3|8:b|0).toString(16)})}

  }

  vertx.EventBus.CONNECTING = 0;
  vertx.EventBus.OPEN = 1;
  vertx.EventBus.CLOSING = 2;
  vertx.EventBus.CLOSED = 3;

  return vertx.EventBus;

});
<commit_msg>Adding optional failure handler to EventBus.send()<commit_after>/*
 * Copyright 2014 Red Hat, Inc.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 */

/*
 *   Copyright (c) 2011-2013 The original author or authors
 *   ------------------------------------------------------
 *   All rights reserved. This program and the accompanying materials
 *   are made available under the terms of the Eclipse Public License v1.0
 *   and Apache License v2.0 which accompanies this distribution.
 *
 *       The Eclipse Public License is available at
 *       http://www.eclipse.org/legal/epl-v10.html
 *
 *       The Apache License v2.0 is available at
 *       http://www.opensource.org/licenses/apache2.0.php
 *
 *   You may elect to redistribute this code under either of these licenses.
 */

var vertx = vertx || {};

!function(factory) {
  if (typeof define === "function" && define.amd) {
    // Expose as an AMD module with SockJS dependency.
    // "vertxbus" and "sockjs" names are used because
    // AMD module names are derived from file names.
    define("vertxbus", ["sockjs"], factory);
  } else {
    // No AMD-compliant loader
    factory(SockJS);
  }
}(function(SockJS) {

  vertx.EventBus = function(url, options) {

    var that = this;
    var sockJSConn = new SockJS(url, undefined, options);
    var handlerMap = {};
    var replyHandlers = {};
    var state = vertx.EventBus.CONNECTING;
    var pingTimerID = null;
    var pingInterval = null;
    if (options) {
      pingInterval = options['vertxbus_ping_interval'];
    }
    if (!pingInterval) {
      pingInterval = 5000;
    }

    that.onopen = null;
    that.onclose = null;

    that.send = function(address, message, replyHandler, failureHandler) {
      sendOrPub("send", address, message, replyHandler, failureHandler)
    }

    that.publish = function(address, message) {
      sendOrPub("publish", address, message, null)
    }

    that.registerHandler = function(address, handler) {
      checkSpecified("address", 'string', address);
      checkSpecified("handler", 'function', handler);
      checkOpen();
      var handlers = handlerMap[address];
      if (!handlers) {
        handlers = [handler];
        handlerMap[address] = handlers;
        // First handler for this address so we should register the connection
        var msg = { type : "register",
                    address: address };
        sockJSConn.send(JSON.stringify(msg));
      } else {
        handlers[handlers.length] = handler;
      }
    }

    that.unregisterHandler = function(address, handler) {
      checkSpecified("address", 'string', address);
      checkSpecified("handler", 'function', handler);
      checkOpen();
      var handlers = handlerMap[address];
      if (handlers) {
        var idx = handlers.indexOf(handler);
        if (idx != -1) handlers.splice(idx, 1);
        if (handlers.length == 0) {
          // No more local handlers so we should unregister the connection

          var msg = { type : "unregister",
                      address: address};
          sockJSConn.send(JSON.stringify(msg));
          delete handlerMap[address];
        }
      }
    }

    that.close = function() {
      checkOpen();
      state = vertx.EventBus.CLOSING;
      sockJSConn.close();
    }

    that.readyState = function() {
      return state;
    }

    sockJSConn.onopen = function() {
      // Send the first ping then send a ping every pingInterval milliseconds
      sendPing();
      pingTimerID = setInterval(sendPing, pingInterval);
      state = vertx.EventBus.OPEN;
      if (that.onopen) {
        that.onopen();
      }
    };

    sockJSConn.onclose = function() {
      state = vertx.EventBus.CLOSED;
      if (pingTimerID) clearInterval(pingTimerID);
      if (that.onclose) {
        that.onclose();
      }
    };

    sockJSConn.onmessage = function(e) {
      var msg = e.data;
      var json = JSON.parse(msg);
      var type = json.type;
      if (type === 'err') {
        console.error("Error received on connection: " + json.body);
        return;
      }
      var body = json.body;
      var failure = null;
      if (body === undefined && json.hasOwnProperty('failureCode')) {
        failure = { failureCode: json.failureCode, failureType: json.failureType, message: json.message }
      }
      var replyAddress = json.replyAddress;
      var address = json.address;
      var replyHandler;
      if (replyAddress) {
        replyHandler = function(reply, replyHandler) {
          // Send back reply
          that.send(replyAddress, reply, replyHandler);
        };
      }
      var handlers = handlerMap[address];
      if (handlers) {
        // We make a copy since the handler might get unregistered from within the
        // handler itself, which would screw up our iteration
        var copy = handlers.slice(0);
        for (var i  = 0; i < copy.length; i++) {
          copy[i](body, replyHandler);
        }
      } else {
        // Might be a reply message
        var handlers = replyHandlers[address];
        if (handlers) {
          delete replyHandlers[address];
          var handler = handlers.replyHandler;
          if (handler) {
            handler(body, replyHandler);
          }
          var failureHandler = handlers.failureHandler;
          if (failure && failureHandler) {
            failureHandler(failure)
          }
        }
      }
    }

    function sendPing() {
      var msg = {
        type: "ping"
      }
      sockJSConn.send(JSON.stringify(msg));
    }

    function sendOrPub(sendOrPub, address, message, replyHandler, failureHandler) {
      checkSpecified("address", 'string', address);
      checkSpecified("replyHandler", 'function', replyHandler, true);
      checkSpecified("failureHandler", 'function', failureHandler, true);
      checkOpen();
      var envelope = { type : sendOrPub,
                       address: address,
                       body: message };
      if (replyHandler || failureHandler) {
        var replyAddress = makeUUID();
        envelope.replyAddress = replyAddress;
        replyHandlers[replyAddress] = { replyHandler: replyHandler, failureHandler: failureHandler };
      }
      var str = JSON.stringify(envelope);
      sockJSConn.send(str);
    }

    function checkOpen() {
      if (state != vertx.EventBus.OPEN) {
        throw new Error('INVALID_STATE_ERR');
      }
    }

    function checkSpecified(paramName, paramType, param, optional) {
      if (!optional && !param) {
        throw new Error("Parameter " + paramName + " must be specified");
      }
      if (param && typeof param != paramType) {
        throw new Error("Parameter " + paramName + " must be of type " + paramType);
      }
    }

    function isFunction(obj) {
      return !!(obj && obj.constructor && obj.call && obj.apply);
    }

    function makeUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
        .replace(/[xy]/g,function(a,b){return b=Math.random()*16,(a=="y"?b&3|8:b|0).toString(16)})}

  }

  vertx.EventBus.CONNECTING = 0;
  vertx.EventBus.OPEN = 1;
  vertx.EventBus.CLOSING = 2;
  vertx.EventBus.CLOSED = 3;

  return vertx.EventBus;

});
<|endoftext|>


<commit_before>(function (exports) {
  'use strict';
  /*jshint node:true */

  var request, fs, hub, scrape, writer, Writer, ROOT_URL, types, logger, uuid, knownEntities, Sync;

  ROOT_URL = process.env.ROOT_URL;
  request = require('request');
  hub = require('node-pubsub');
  fs = require('fs');

  console.log('Beginning scrape of', ROOT_URL);

  // Generate a UUID
  uuid = function uuid(a){
    //Function from https://gist.github.com/982883 (@jed)
    return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,uuid);
  };

  // Semaphore from https://gist.github.com/1296828
  Sync = function Sync(syncCount, callback, preventInstantCallbackExecution) {
      this.syncCount = syncCount;
      this.callback = callback;
      if(preventInstantCallbackExecution === false && this.syncCount === 0) {
        this.executeCallback();
      }
    };
    Sync.prototype.decrement = function() {
      --this.syncCount;
      if(this.syncCount === 0) {
        this.executeCallback();
      }
    };
    Sync.prototype.increment = function() {
      ++this.syncCount;
    };
    Sync.prototype.executeCallback = function() {
      if (typeof this.callback === "function") this.callback();
    };

  // Writer Singleton
  Writer = (function (){
    var instantiated, init;

    init = function () {

      var writer = {}, fileName;

      fileName = "/tcgascrape"+Date.now()+".nt";

      writer.stream = fs.createWriteStream(process.cwd()+fileName);

      writer.listen = function (msg) {
        var triples = msg.triples;
        triples = triples.split(" . ").join(" .\n");
        writer.stream.write(triples);
      };

      writer.close = function () {
        writer.stream.end();
      };

      return writer;

    };

    return {
      getInstance : function () {
        if (!instantiated) instantiated = init();
        return instantiated;
      }
    };
  })();

  types = {
    9 : "disease-study",
    10 : "center-type",
    11 : "center-domain",
    12 : "platform",
    13 : "data-type",
    14 : "archive",
    archive : "archive",
    15 : "file",
    file : "file"
  };

  knownEntities = {};

  scrape = function (options) {
    var opts, target, parent, callback, start, callCallback;

    opts = options || {};
    target = opts.target || ROOT_URL;
    parent = opts.parent || {};

    callCallback = function () {
      if (callback && typeof callback === 'function') callback();
    };
    callback = opts.callback;

    request(target, function (error, response, body) {

      if (error || response.statusCode !== 200) {
        console.log("Failed to get", target);
        if (callback && typeof callback === 'function') callback();
        else return;
      }

      else {

        var pre, rows, children = [], tcga, literal;

        tcga = function (name) { return "<http://purl.org/tcga/core#"+name+">"; };
        literal = function (value) { return '"'+value+'"'; };
        pre = body.match(/<pre>([\s\S]*)<\/pre>/)[1];
        rows = pre.split("\n");
        rows = rows.slice(1,rows.length-1); // Slice off the first and last rows

        rows.forEach(function (row) {

          var name, id, url, type, tripleString, lastModified, subject, scrapeChildren = true;

          name = row.match(/>(.*)</);
          if(!name) console.log(row, name); else name = name[1];
          id = uuid();
          url = target + row.match(/href="(.*)"/)[1];
          type = types[target.split('/').length];
          lastModified = (new Date(row.match(/\d{2}-\w{3}-\d{4}/)[0])).toISOString().slice(0,10);
          tripleString = "";

          if (process.env.TESTING && target.split("/").length >= 10) {
            scrapeChildren = false;
          }

          // Things with extensions are files (e.g. reallylong_name.tiff)
          // TODO Use MIME types to determine files.
          if (name.match(/^.*\.[^\/]+$/)) {
            type = types.file;
            scrapeChildren = false;
          }

          // TODO when should this NOT be done (e.g. files)
          if (type !== types.file) name = name.slice(0,-1); // Remove the trailing "/"

          // If a file ends in .tar.gz or .tar.gz.md5, type it as an archive
          if (type === types.file && name.match(/\.tar\.gz($|\.md5$)/)) {
            type = types.archive;
          }

          if (type !== types.file && type !== types.archive) {
            if (!knownEntities[name]) knownEntities[name] = id;
            else id = knownEntities[name];
          }

          subject = tcga(id);
          tripleString = [
            subject, "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>",  tcga(type), ".",
            subject, "<http://www.w3.org/2000/01/rdf-schema#label>", literal(name), ".",
            subject, tcga("url"), literal(url), "."
          ];

          if (type === types.file) {
            var ancestor;
            Object.keys(parent).forEach(function (ancestor) {
              tripleString.push(subject, tcga(ancestor), parent[ancestor], ".");
            });
          }

          hub.publish('/triples', [{
            triples : tripleString.join(" ") + "\n",
            type : type,
            name : name
          }]);

          if (scrapeChildren){
            parent[type] = subject;
            children.push({target:url, parent:JSON.parse(JSON.stringify(parent))});
          }

        });

        //hub.publish('/triples', [ { triples : children } ]);

        if (children.length > 0) {
          var counter = new Sync(children.length, callback);
          var nextChild = function nextChild(children){
            var child = children.pop();
            if (child){
              child.callback = function(){
                counter.decrement();
                nextChild(children);
              };
              scrape(child);
            }
          };
          nextChild(children);
        }
        else callCallback();

      }

    });
  };

  //logger = hub.subscribe('/triples', function ( msg ) {
  //  if (msg.type === 'disease-study') console.log("Completed scrape of", msg.name);
  //});

  writer = Writer.getInstance();

  hub.subscribe('/triples', writer.listen);

  scrape({
    target : ROOT_URL,
    callback : function () { writer.close(); console.log("Scrape finished"); }
  });

})( exports );
<commit_msg>Better row detection regex.<commit_after>(function (exports) {
  'use strict';
  /*jshint node:true */

  var request, fs, hub, scrape, writer, Writer, ROOT_URL, types, logger, uuid, knownEntities, Sync;

  ROOT_URL = process.env.ROOT_URL;
  request = require('request');
  hub = require('node-pubsub');
  fs = require('fs');

  console.log('Beginning scrape of', ROOT_URL);

  // Generate a UUID
  uuid = function uuid(a){
    //Function from https://gist.github.com/982883 (@jed)
    return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,uuid);
  };

  // Semaphore from https://gist.github.com/1296828
  Sync = function Sync(syncCount, callback, preventInstantCallbackExecution) {
      this.syncCount = syncCount;
      this.callback = callback;
      if(preventInstantCallbackExecution === false && this.syncCount === 0) {
        this.executeCallback();
      }
    };
    Sync.prototype.decrement = function() {
      --this.syncCount;
      if(this.syncCount === 0) {
        this.executeCallback();
      }
    };
    Sync.prototype.increment = function() {
      ++this.syncCount;
    };
    Sync.prototype.executeCallback = function() {
      if (typeof this.callback === "function") this.callback();
    };

  // Writer Singleton
  Writer = (function (){
    var instantiated, init;

    init = function () {

      var writer = {}, fileName;

      fileName = "/tcgascrape"+Date.now()+".nt";

      writer.stream = fs.createWriteStream(process.cwd()+fileName);

      writer.listen = function (msg) {
        var triples = msg.triples;
        triples = triples.split(" . ").join(" .\n");
        writer.stream.write(triples);
      };

      writer.close = function () {
        writer.stream.end();
      };

      return writer;

    };

    return {
      getInstance : function () {
        if (!instantiated) instantiated = init();
        return instantiated;
      }
    };
  })();

  types = {
    9 : "disease-study",
    10 : "center-type",
    11 : "center-domain",
    12 : "platform",
    13 : "data-type",
    14 : "archive",
    archive : "archive",
    15 : "file",
    file : "file"
  };

  knownEntities = {};

  scrape = function (options) {
    var opts, target, parent, callback, start, callCallback;

    opts = options || {};
    target = opts.target || ROOT_URL;
    parent = opts.parent || {};

    callCallback = function () {
      if (callback && typeof callback === 'function') callback();
    };
    callback = opts.callback;

    request(target, function (error, response, body) {

      if (error || response.statusCode !== 200) {
        console.log("Failed to get", target);
        if (callback && typeof callback === 'function') callback();
        else return;
      }

      else {

        var pre, rows, children = [], tcga, literal;

        tcga = function (name) { return "<http://purl.org/tcga/core#"+name+">"; };
        literal = function (value) { return '"'+value+'"'; };
        pre = body.match(/<pre>([\s\S]*)<\/pre>/)[1];
        rows = pre.match(/<a[^?P]*?<\/a>[\s\S]+?\d{2}-\w{3}-\d{4}/g);

        if (rows) rows.forEach(function (row) {

          var name, id, url, type, tripleString, lastModified, subject, scrapeChildren = true;

          name = row.match(/>(.*)</)[1];
          id = uuid();
          url = target + row.match(/href="(.*)"/)[1];
          type = types[target.split('/').length];
          lastModified = (new Date(row.match(/\d{2}-\w{3}-\d{4}/)[0])).toISOString().slice(0,10);
          tripleString = "";

          if (process.env.TESTING && target.split("/").length >= 10) {
            scrapeChildren = false;
          }

          // Things with extensions are files (e.g. reallylong_name.tiff)
          // TODO Use MIME types to determine files.
          if (name.match(/^.*\.[^\/]+$/)) {
            type = types.file;
            scrapeChildren = false;
          }

          // TODO when should this NOT be done (e.g. files)
          if (type !== types.file) name = name.slice(0,-1); // Remove the trailing "/"

          // If a file ends in .tar.gz or .tar.gz.md5, type it as an archive
          if (type === types.file && name.match(/\.tar\.gz($|\.md5$)/)) {
            type = types.archive;
          }

          if (type !== types.file && type !== types.archive) {
            if (!knownEntities[name]) knownEntities[name] = id;
            else id = knownEntities[name];
          }

          subject = tcga(id);
          tripleString = [
            subject, "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>",  tcga(type), ".",
            subject, "<http://www.w3.org/2000/01/rdf-schema#label>", literal(name), ".",
            subject, tcga("url"), literal(url), "."
          ];

          if (type === types.file) {
            var ancestor;
            Object.keys(parent).forEach(function (ancestor) {
              tripleString.push(subject, tcga(ancestor), parent[ancestor], ".");
            });
          }

          hub.publish('/triples', [{
            triples : tripleString.join(" ") + "\n",
            type : type,
            name : name
          }]);

          if (scrapeChildren){
            parent[type] = subject;
            children.push({target:url, parent:JSON.parse(JSON.stringify(parent))});
          }

        });

        //hub.publish('/triples', [ { triples : children } ]);

        if (children.length > 0) {
          var counter = new Sync(children.length, callback);
          var nextChild = function nextChild(children){
            var child = children.pop();
            if (child){
              child.callback = function(){
                counter.decrement();
                nextChild(children);
              };
              scrape(child);
            }
          };
          nextChild(children);
        }
        else callCallback();

      }

    });
  };

  //logger = hub.subscribe('/triples', function ( msg ) {
  //  console.log(msg.triples);
  //});

  writer = Writer.getInstance();

  hub.subscribe('/triples', writer.listen);

  scrape({
    target : ROOT_URL,
    callback : function () { writer.close(); console.log("Scrape finished"); }
  });

})( exports );
<|endoftext|>


<commit_before>// const fs = require('fs')
const path = require('path')
var read = require('fs-readdir-recursive')

module.exports = (req, res) => {
  try {
    let { folder } = req.params
    folder = !folder ? 'trip' : folder
    const folderImg = path.join(__dirname, '../../../../public/img/' + folder)
    console.log(folderImg)
    const files = read(folderImg)
    // let jsonFiles = {'imgs': JSON.stringify(files)}
    res.status(200).json({files})
  } catch (err) {
    res.status(500).json(err)
  }
}
// .map((element) => ({element}))
<commit_msg>Refactored api/img<commit_after>const path = require('path')
var read = require('fs-readdir-recursive')

module.exports = (req, res) => {
  try {
    let { folder } = req.params
    folder = !folder ? 'trip' : folder
    const folderImg = path.join(__base, 'public/img/' + folder)// eslint-disable-line no-undef
    console.log(folderImg)
    const files = read(folderImg)
    res.status(200).json({files})
  } catch (err) {
    res.status(500).json(err)
  }
}
<|endoftext|>


<commit_before>'use strict';

/*
* When adding names to the namespace, ensure that they are added in alphabetical order according to alias (namespace key).
*/

var ns = [];

ns.push({
	'alias': 'compose',
	'path': '@stdlib/utils/compose',
	'value': require( '@stdlib/utils/compose' ),
	'type': 'Function',
	'related': []
});

ns.push({
	'alias': 'configdir',
	'path': '@stdlib/utils/configdir',
	'value': require( '@stdlib/utils/configdir' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/homedir',
		'@stdlib/utils/tmpdir'
	]
});

ns.push({
	'alias': 'constantFunction',
	'path': '@stdlib/utils/constant-function',
	'value': require( '@stdlib/utils/constant-function' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/identity-function'
	]
});

ns.push({
	'alias': 'constructorName',
	'path': '@stdlib/utils/constructor-name',
	'value': require( '@stdlib/utils/constructor-name' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/function-name'
	]
});

ns.push({
	'alias': 'contains',
	'path': '@stdlib/utils/contains',
	'value': require( '@stdlib/utils/contains' ),
	'type': 'Function',
	'related': []
});

ns.push({
	'alias': 'copy',
	'path': '@stdlib/utils/copy',
	'value': require( '@stdlib/utils/copy' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/merge'
	]
});

ns.push({
	'alias': 'curry',
	'path': '@stdlib/utils/curry',
	'value': require( '@stdlib/utils/curry' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/curry-right',
		'@stdlib/utils/uncurry',
		'@stdlib/utils/uncurry-right'
	]
});

ns.push({
	'alias': 'curryRight',
	'path': '@stdlib/utils/curry-right',
	'value': require( '@stdlib/utils/curry-right' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/curry',
		'@stdlib/utils/uncurry',
		'@stdlib/utils/uncurry-right'
	]
});

ns.push({
	'alias': 'cwd',
	'path': '@stdlib/utils/cwd',
	'value': require( '@stdlib/utils/cwd' ),
	'type': 'Function',
	'related': []
});

// EXPORTS //

module.exports = ns;
<commit_msg>Update namespace<commit_after>'use strict';

/*
* When adding names to the namespace, ensure that they are added in alphabetical order according to alias (namespace key).
*/

var ns = [];

ns.push({
	'alias': 'capitalize',
	'path': '@stdlib/string/capitalize',
	'value': require( '@stdlib/string/capitalize' ),
	'type': 'Function',
	'related': [
		'@stdlib/string/uncapitalize',
		'@stdlib/string/uppercase'
	]
});

ns.push({
	'alias': 'compose',
	'path': '@stdlib/utils/compose',
	'value': require( '@stdlib/utils/compose' ),
	'type': 'Function',
	'related': []
});

ns.push({
	'alias': 'configdir',
	'path': '@stdlib/utils/configdir',
	'value': require( '@stdlib/utils/configdir' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/homedir',
		'@stdlib/utils/tmpdir'
	]
});

ns.push({
	'alias': 'constantFunction',
	'path': '@stdlib/utils/constant-function',
	'value': require( '@stdlib/utils/constant-function' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/identity-function'
	]
});

ns.push({
	'alias': 'constructorName',
	'path': '@stdlib/utils/constructor-name',
	'value': require( '@stdlib/utils/constructor-name' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/function-name'
	]
});

ns.push({
	'alias': 'contains',
	'path': '@stdlib/utils/contains',
	'value': require( '@stdlib/utils/contains' ),
	'type': 'Function',
	'related': []
});

ns.push({
	'alias': 'copy',
	'path': '@stdlib/utils/copy',
	'value': require( '@stdlib/utils/copy' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/merge'
	]
});

ns.push({
	'alias': 'curry',
	'path': '@stdlib/utils/curry',
	'value': require( '@stdlib/utils/curry' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/curry-right',
		'@stdlib/utils/uncurry',
		'@stdlib/utils/uncurry-right'
	]
});

ns.push({
	'alias': 'curryRight',
	'path': '@stdlib/utils/curry-right',
	'value': require( '@stdlib/utils/curry-right' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/curry',
		'@stdlib/utils/uncurry',
		'@stdlib/utils/uncurry-right'
	]
});

ns.push({
	'alias': 'cwd',
	'path': '@stdlib/utils/cwd',
	'value': require( '@stdlib/utils/cwd' ),
	'type': 'Function',
	'related': []
});

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>'use strict';
var app = angular.module('com.module.files');

app.controller('UploadCtrl', function ($scope, FileUploader, CoreService) {

  // create a uploader with options
  var uploader = $scope.uploader = new FileUploader({
    scope: $scope, // to automatically update the html. Default: $rootScope
    url: CoreService.env.apiUrl + '/containers/files/upload',
    formData: [
      {
        key: 'value'
      }
    ]
  });

  // FILTERS

  uploader.filters.push({
    name: 'customFilter',
    fn: function () {
      return this.queue.length < 10;
    }
  });

  // CALLBACKS

  uploader.onWhenAddingFileFailed = function (item /*{File|FileLikeObject}*/, filter, options) {
    console.info('onWhenAddingFileFailed', item, filter, options);
  };
  uploader.onAfterAddingFile = function (fileItem) {
    console.info('onAfterAddingFile', fileItem);
  };
  uploader.onAfterAddingAll = function (addedFileItems) {
    console.info('onAfterAddingAll', addedFileItems);
  };
  uploader.onBeforeUploadItem = function (item) {
    console.info('onBeforeUploadItem', item);
  };
  uploader.onProgressItem = function (fileItem, progress) {
    console.info('onProgressItem', fileItem, progress);
  };
  uploader.onProgressAll = function (progress) {
    console.info('onProgressAll', progress);
  };
  uploader.onSuccessItem = function (fileItem, response, status, headers) {
    console.info('onSuccessItem', fileItem, response, status, headers);
  };
  uploader.onErrorItem = function (fileItem, response, status, headers) {
    console.info('onErrorItem', fileItem, response, status, headers);
  };
  uploader.onCancelItem = function (fileItem, response, status, headers) {
    console.info('onCancelItem', fileItem, response, status, headers);
  };
  uploader.onCompleteItem = function (fileItem, response, status, headers) {
    console.info('onCompleteItem', fileItem, response, status, headers);
  };
  uploader.onCompleteAll = function () {
    console.info('onCompleteAll');
  };

  console.info('uploader', uploader);

});
<commit_msg>Comment filters and callbacks<commit_after>'use strict';
var app = angular.module('com.module.files');

app.controller('UploadCtrl', function ($scope, FileUploader, CoreService) {

  // create a uploader with options
  var uploader = $scope.uploader = new FileUploader({
    scope: $scope, // to automatically update the html. Default: $rootScope
    url: CoreService.env.apiUrl + '/containers/files/upload',
    formData: [
      {
        key: 'value'
      }
    ]
  });

  // FILTERS AND CALLBACKS

  //uploader.filters.push({
  //  name: 'customFilter',
  //  fn: function () {
  //    return this.queue.length < 10;
  //  }
  //});

  // CALLBACKS

  //uploader.onWhenAddingFileFailed = function (item /*{File|FileLikeObject}*/, filter, options) {
  //  console.info('onWhenAddingFileFailed', item, filter, options);
  //};
  //uploader.onAfterAddingFile = function (fileItem) {
  //  console.info('onAfterAddingFile', fileItem);
  //};
  //uploader.onAfterAddingAll = function (addedFileItems) {
  //  console.info('onAfterAddingAll', addedFileItems);
  //};
  //uploader.onBeforeUploadItem = function (item) {
  //  console.info('onBeforeUploadItem', item);
  //};
  //uploader.onProgressItem = function (fileItem, progress) {
  //  console.info('onProgressItem', fileItem, progress);
  //};
  //uploader.onProgressAll = function (progress) {
  //  console.info('onProgressAll', progress);
  //};
  //uploader.onSuccessItem = function (fileItem, response, status, headers) {
  //  console.info('onSuccessItem', fileItem, response, status, headers);
  //};
  //uploader.onErrorItem = function (fileItem, response, status, headers) {
  //  console.info('onErrorItem', fileItem, response, status, headers);
  //};
  //uploader.onCancelItem = function (fileItem, response, status, headers) {
  //  console.info('onCancelItem', fileItem, response, status, headers);
  //};
  //uploader.onCompleteItem = function (fileItem, response, status, headers) {
  //  console.info('onCompleteItem', fileItem, response, status, headers);
  //};
  //uploader.onCompleteAll = function () {
  //  console.info('onCompleteAll');
  //};

});
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import Paper from '@material-ui/core/Paper'
import Typography from '@material-ui/core/Typography'

// TODO: use class styles

const NewsSearchItem = props => {
  const {
    item: {
      // eslint-disable-next-line no-unused-vars
      category,
      contractualRules,
      // eslint-disable-next-line no-unused-vars
      datePublished,
      description,
      image,
      name,
      url,
    },
  } = props

  // If the title or description are too long, slice them
  // and add ellipses.
  const MAX_DESC_CHARS = 125
  const MAX_TITLE_CHARS = 80
  const subtitle =
    description.length > MAX_DESC_CHARS
      ? `${description.slice(0, MAX_DESC_CHARS)} ...`
      : name
  const title =
    name.length > MAX_TITLE_CHARS
      ? `${name.slice(0, MAX_TITLE_CHARS)} ...`
      : name

  // TODO
  // const timeSincePublished = datePublished
  return (
    <Paper
      elevation={1}
      style={{
        margin: '0px 12px 0px 0px',
        minWidth: 200,
        height: 254,
        fontFamily: 'arial, sans-serif',
        display: 'flex',
        flexDirection: 'column',
      }}
    >
      {image ? (

      ) : null}

            {title}

        {// Only show the description if there is no image.
        image ? null : (

              {subtitle}

        )}
        {contractualRules.map((contractualRule, index) => {
          return (

              {contractualRule.text}

          )
        })}

    </Paper>
  )
}

NewsSearchItem.propTypes = {
  item: PropTypes.shape({
    category: PropTypes.string,
    contractualRules: PropTypes.arrayOf(
      PropTypes.shape({
        text: PropTypes.string,
      })
    ),
    datePublished: PropTypes.string,
    description: PropTypes.string,
    image: PropTypes.shape({
      thumbnail: PropTypes.shape({
        contentUrl: PropTypes.string,
        height: PropTypes.number,
        width: PropTypes.number,
      }),
    }),
    name: PropTypes.string,
    url: PropTypes.string,
  }).isRequired,
}

NewsSearchItem.defaultProps = {}

const NewsSearchResults = props => {
  const { newsItems } = props

  // Only display 3 news items. If we want to display more,
  // we need horizontal scrolling.
  const newsItemsToShow = newsItems.slice(0, 3)
  return (

      <Typography variant={'h6'} style={{ marginBottom: 8 }}>
        Top stories
      </Typography>

        {newsItemsToShow.map(newsItem => (
          <NewsSearchItem key={newsItem.url} item={newsItem} />
        ))}

  )
}

NewsSearchResults.propTypes = {
  newsItems: PropTypes.arrayOf(NewsSearchItem.propTypes.item),
}

NewsSearchResults.defaultProps = {}

export default NewsSearchResults
<commit_msg>Handle empty contractual rules in news item<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import Paper from '@material-ui/core/Paper'
import Typography from '@material-ui/core/Typography'

// TODO: use class styles

const NewsSearchItem = props => {
  const {
    item: {
      // eslint-disable-next-line no-unused-vars
      category,
      contractualRules,
      // eslint-disable-next-line no-unused-vars
      datePublished,
      description,
      image,
      name,
      url,
    },
  } = props

  // If the title or description are too long, slice them
  // and add ellipses.
  const MAX_DESC_CHARS = 125
  const MAX_TITLE_CHARS = 80
  const subtitle =
    description.length > MAX_DESC_CHARS
      ? `${description.slice(0, MAX_DESC_CHARS)} ...`
      : name
  const title =
    name.length > MAX_TITLE_CHARS
      ? `${name.slice(0, MAX_TITLE_CHARS)} ...`
      : name

  // TODO
  // const timeSincePublished = datePublished
  return (
    <Paper
      elevation={1}
      style={{
        margin: '0px 12px 0px 0px',
        minWidth: 200,
        height: 254,
        fontFamily: 'arial, sans-serif',
        display: 'flex',
        flexDirection: 'column',
      }}
    >
      {image ? (

      ) : null}

            {title}

        {// Only show the description if there is no image.
        image ? null : (

              {subtitle}

        )}
        {// TODO: show provider if no contractual text
        contractualRules
          ? contractualRules.map((contractualRule, index) => {
              return (

                  {contractualRule.text}

              )
            })
          : null}

    </Paper>
  )
}

NewsSearchItem.propTypes = {
  item: PropTypes.shape({
    category: PropTypes.string,
    contractualRules: PropTypes.arrayOf(
      PropTypes.shape({
        text: PropTypes.string,
      })
    ),
    datePublished: PropTypes.string,
    description: PropTypes.string,
    image: PropTypes.shape({
      thumbnail: PropTypes.shape({
        contentUrl: PropTypes.string,
        height: PropTypes.number,
        width: PropTypes.number,
      }),
    }),
    name: PropTypes.string,
    url: PropTypes.string,
  }).isRequired,
}

NewsSearchItem.defaultProps = {}

const NewsSearchResults = props => {
  const { newsItems } = props

  // Only display 3 news items. If we want to display more,
  // we need horizontal scrolling.
  const newsItemsToShow = newsItems.slice(0, 3)
  return (

      <Typography variant={'h6'} style={{ marginBottom: 8 }}>
        Top stories
      </Typography>

        {newsItemsToShow.map(newsItem => (
          <NewsSearchItem key={newsItem.url} item={newsItem} />
        ))}

  )
}

NewsSearchResults.propTypes = {
  newsItems: PropTypes.arrayOf(NewsSearchItem.propTypes.item),
}

NewsSearchResults.defaultProps = {}

export default NewsSearchResults
<|endoftext|>