<commit_before>//TODO do this the "angular way"
includePaho();

(function(){
  //TODO - inject paho?
  angular.module('iibWidgets',[])
    .factory('iibSubscriber',iibSubscriber)
    .factory('iibWidgetSpec',iibWidgetSpecFactory)
    .factory('d3Util',d3UtilFactory)
    .directive('iibFlowMonitoring',['$rootScope','iibSubscriber',iibFlowMonitoringDirective])
    .directive('iibFlowStats', ['$rootScope', 'iibSubscriber','d3Util',iibFlowStatsDirective])
    .directive('iibWidget',    ['$rootScope', 'iibSubscriber','d3Util',iibWidgetDirective])
    ;

  //TODO - is there a more angular way of making the widgetRegistry available to the widgets so that they can register themselves?
  //       Could make the widgets services or factories and use dependency inject, this would even work for widgets in separate modules  
  //       How would this affect the portability of the widgets to a non angular framework
  var widgetRegistry = {
    factories:[],
    register:function(widgetFactory){
      this.factories[widgetFactory.type]=widgetFactory;      
    },
    createWidget:function(type,options){
      var factory = this.factories[type];
      if(factory){
        return new factory(options);        
      }else{
        return null;
      }      
    }    
  };

  /*
  *  Define the flow stats widget and register it.
  */
  (function(){
    var flowStatsWidget = function(options){
      return {
        iibSimulation:options.iibSimulation || false,
        aspectRatio : 1,
        renderStaticD3:function (canvas){
          
          canvas.svg
          .attr('class','iib-chart');

          this.maxY    = d3.max(this.data)|1;
          this.y         = d3.scale.linear()
                        .domain([0, this.maxY])
                        .range([canvas.height, 0]);

          this.yAxis = d3.svg.axis().scale(this.y)
                          .orient('left')
                          .ticks(5);

          //console.log("maxY=",this.maxY);
          this.x         = d3.scale.linear()
                      .domain([0, this.data.length])
                      .range([0, canvas.width]);

          this.yAxisGroup = canvas.svg.append('g')
              .attr('class', 'y axis')
              .attr('stroke','#777')
              .call(this.yAxis);

          var self=this;
          this.line    = d3.svg.line()
                          .interpolate('cardinal')
                          .x(function(d,i){return self.x(i);})
                          .y(function(d,i){return self.y(d);});
                          
          this.path    = canvas.svg.append('svg:path')
                            .attr('class','dataLine')
                            .data([this.data])
                            .attr('d', this.line)
                            .attr('fill', 'none')
                            .attr('stroke-width', '1')
                            .attr('stroke','#000');
        },
        renderDynamicD3: function (element){

          this.x.domain([0,this.data.length]);
          this.maxY    = d3.max(this.data)|1;
          this.y.domain([0, this.maxY]);

          this.yAxis.scale(this.y);
          this.yAxisGroup.call(this.yAxis);
          this.path
            .attr('d',this.line);

        }        
      }
    };
    flowStatsWidget.type="iib-flow-stats";
    widgetRegistry.register(flowStatsWidget);
  })();


  function d3UtilFactory(){
    function createCanvas(element, options) {
  	  var fullWidth = d3.select(element).node().offsetWidth;
      
      //responsive. max margins at these numbers but respond to smaller element sizes with a margin as a fraction of element size
  	  var margin = {
  		  right : Math.min(80,0.1*fullWidth),
        left : Math.min(80,0.1*fullWidth)
      };
      var width = fullWidth - margin.left - margin.right;
  	  var height;
      var fullHeight;
      
      if(options.aspectRatio) {
  		  height = width * options.aspectRatio;
        margin.bottom = Math.min(20,0.1*height);
  		  margin.top    = Math.min(10,0.05*height);
        fullHeight    = height + margin.top + margin.bottom;
  	  }else{      
        fullHeight = Math.max(200,d3.select(element).node().offsetHeight);
        margin.bottom = Math.min(20,0.1*fullHeight);
  		  margin.top    = Math.min(10,0.05*fullHeight);
        height = fullHeight - margin.top - margin.bottom;
      }

  	  var svg = d3.select(element) 
  	  .append('svg') 
  	  .style('width', fullWidth) 
  	  .style('height', fullHeight) 
  	  .attr('class', 'mathsteroids');

  	  var g = svg
  	  .append("g") 
  	  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  	  return{
  		  width : width,
  		  height : height,
  		  svg : g
  	  }
    }

    function renderWidget(widget,iElement){
      var canvasOptions = {
        aspectRatio : widget.aspectRatio
      };
      var canvas = createCanvas(iElement[0],canvasOptions);
      widget.data=[];
      widget.renderStaticD3(canvas);
      
      if (widget.iibSimulation){
        setInterval(function(){
          
          widget.data.push(15 + Math.floor((Math.random() * 10) + 1));
          if(widget.data.length>widget.iibMaxRecords) {<commit_msg>handle array of objects as data<commit_after>//TODO do this the "angular way"
includePaho();

(function(){
  //TODO - inject paho?
  angular.module('iibWidgets',[])
    .factory('iibSubscriber',iibSubscriber)
    .factory('iibWidgetSpec',iibWidgetSpecFactory)
    .factory('d3Util',d3UtilFactory)
    .directive('iibFlowMonitoring',['$rootScope','iibSubscriber',iibFlowMonitoringDirective])
    .directive('iibFlowStats', ['$rootScope', 'iibSubscriber','d3Util',iibFlowStatsDirective])
    .directive('iibWidget',    ['$rootScope', 'iibSubscriber','d3Util',iibWidgetDirective])
    ;

  //TODO - is there a more angular way of making the widgetRegistry available to the widgets so that they can register themselves?
  //       Could make the widgets services or factories and use dependency inject, this would even work for widgets in separate modules  
  //       How would this affect the portability of the widgets to a non angular framework
  var widgetRegistry = {
    factories:[],
    register:function(widgetFactory){
      this.factories[widgetFactory.type]=widgetFactory;      
    },
    createWidget:function(type,options){
      var factory = this.factories[type];
      if(factory){
        return new factory(options);        
      }else{
        return null;
      }      
    }    
  };

  /*
  *  Define the flow stats widget and register it.
  */
  (function(){
    var flowStatsWidget = function(options){
      return {
        iibSimulation:options.iibSimulation || false,
        aspectRatio : 1,
        renderStaticD3:function (canvas){
          
          canvas.svg
          .attr('class','iib-chart');

          this.maxY    = d3.max(this.data.map(function(item){return item.TotalInputMessages}))|1;
          this.y         = d3.scale.linear()
                        .domain([0, this.maxY])
                        .range([canvas.height, 0]);

          this.yAxis = d3.svg.axis().scale(this.y)
                          .orient('left')
                          .ticks(5);

          //console.log("maxY=",this.maxY);
          this.x         = d3.scale.linear()
                      .domain([0, this.data.length])
                      .range([0, canvas.width]);

          this.yAxisGroup = canvas.svg.append('g')
              .attr('class', 'y axis')
              .attr('stroke','#777')
              .call(this.yAxis);

          var self=this;
          this.line    = d3.svg.line()
                          .interpolate('cardinal')
                          .x(function(d,i){return self.x(i);})
                          .y(function(d,i){
                            return self.y(d.TotalInputMessages);});
                          
          this.path    = canvas.svg.append('svg:path')
                            .attr('class','dataLine')
                            .data([this.data])
                            .attr('d', this.line)
                            .attr('fill', 'none')
                            .attr('stroke-width', '1')
                            .attr('stroke','#000');
        },
        renderDynamicD3: function (element){

          this.x.domain([0,this.data.length]);
          this.maxY    = d3.max(this.data.map(function(item){return item.TotalInputMessages}))|1;
          this.y.domain([0, this.maxY]);

          this.yAxis.scale(this.y);
          this.yAxisGroup.call(this.yAxis);
          this.path
            .attr('d',this.line);

        }        
      }
    };
    flowStatsWidget.type="iib-flow-stats";
    widgetRegistry.register(flowStatsWidget);
  })();


  function d3UtilFactory(){
    function createCanvas(element, options) {
  	  var fullWidth = d3.select(element).node().offsetWidth;
      
      //responsive. max margins at these numbers but respond to smaller element sizes with a margin as a fraction of element size
  	  var margin = {
  		  right : Math.min(80,0.1*fullWidth),
        left : Math.min(80,0.1*fullWidth)
      };
      var width = fullWidth - margin.left - margin.right;
  	  var height;
      var fullHeight;
      
      if(options.aspectRatio) {
  		  height = width * options.aspectRatio;
        margin.bottom = Math.min(20,0.1*height);
  		  margin.top    = Math.min(10,0.05*height);
        fullHeight    = height + margin.top + margin.bottom;
  	  }else{      
        fullHeight = Math.max(200,d3.select(element).node().offsetHeight);
        margin.bottom = Math.min(20,0.1*fullHeight);
  		  margin.top    = Math.min(10,0.05*fullHeight);
        height = fullHeight - margin.top - margin.bottom;
      }

  	  var svg = d3.select(element) 
  	  .append('svg') 
  	  .style('width', fullWidth) 
  	  .style('height', fullHeight) 
  	  .attr('class', 'mathsteroids');

  	  var g = svg
  	  .append("g") 
  	  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  	  return{
  		  width : width,
  		  height : height,
  		  svg : g
  	  }
    }

    function renderWidget(widget,iElement){
      var canvasOptions = {
        aspectRatio : widget.aspectRatio
      };
      var canvas = createCanvas(iElement[0],canvasOptions);
      widget.data=[];
      widget.renderStaticD3(canvas);
      
      if (widget.iibSimulation){
        setInterval(function(){
          var timeStamp = new Date();
          timeStamp = timeStamp.toUTCString();
          widget.data.push(   
          {
            EndTime:timeStamp,
            TotalInputMessages:15 + Math.floor((Math.random() * 10) + 1)
          });
            
          if(widget.data.length>widget.iibMaxRecords) {
{'fraction_non_alphanumeric': 0.13437295732561397, 'fraction_numerical': 0.01288635726958633, 'mean_word_length': 1.871313672922252, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3207178', 'n_tokens_mistral': 3295, 'n_tokens_neox': 3188, 'n_words': 586}