<commit_before>/**
* Module that contains layout algorithms for data structures.
* Depends on core.js, datastructures.js
*/
(function() {
  if (typeof JSAV === "undefined") { return; }
  
  function centerArray(array, $lastItem) {
    // center the array inside its parent container
    if (array.options.hasOwnProperty("center") && !array.options.center) {
      // if options center is set to falsy value, return
      return;
    }
    // width of array expected to be last items position + its width
    var width = $lastItem.position().left + $lastItem.outerWidth(),
      containerWidth = $(array.jsav.container).width();
    array.element.css("left", (containerWidth - width)/2);
  }
  
  function verticalArray(array) {
    var $arr = $(array.element),
      // rely on browser doing the calculation, float everything to the left..
      $items = $arr.find("li").css({"float": "left", "position":"static"}),
      maxHeight = -1,
      indexed = !!array.options.indexed;
    if (indexed) {
      $arr.addClass("jsavindexed");
    }
    $items.each(function(index, item) {
      var $i = $(this),
        pos = $i.position();
      $i.css({"left": pos.left - index, "top": pos.top});
      maxHeight = Math.max(maxHeight, $i.outerHeight());
      if (indexed) {
        var $indexLabel = $i.find(".jsavindexlabel");
        if ($indexLabel.size() === 0) {
          $i.append('<span class="jsavindexlabel">' + index + '</span>');
          $indexLabel = $i.find(".jsavindexlabel");
        }
      }
    });
    // ..and return float and positioning
    $items.css({"float": "none", "position": "absolute"});
    $arr.height(maxHeight + (indexed?30:0));
    centerArray(array, $items.last());
  }
  function barArray(array) {
    var $arr = $(array.element).addClass("jsavbararray"),
      $items = $arr.find("li").css({"position":"relative", "float": "left"}), 
      maxValue = Number.MIN_VALUE,
      indexed = !!array.options.indexed,
      width = $items.first().outerWidth();
      size = array.size();
    if (indexed) {
      $arr.addClass("jsavindexed");
    }
    for (var i = 0; i < size; i++) {
      maxValue = Math.max(maxValue, array.value(i));
    }
    maxValue *= 1.15;
    $items.each(function(index, item) {
      var $i = $(this);
      var $valueBar = $i.find(".jsavvaluebar");
      if ($valueBar.size() === 0) {
        $i.prepend('<span class="jsavvaluebar" />');
        $valueBar = $i.find(".jsavvaluebar");
      }
      $valueBar.css({"height": "100%"});
      $i.find(".jsavvalue").css("height", (100.0*array.value(index) / maxValue) + 15 + "%")
        .html('<span>' + $i.find(".jsavvalue").text() + '</span>');
      if (indexed) {
        var $indexLabel = $i.find(".jsavindexlabel");
        if ($indexLabel.size() === 0) {
          $i.append('<span class="jsavindexlabel">' + index + '</span>');
          $indexLabel = $i.find(".jsavindexlabel");
        }
      }
    });
    centerArray(array, $items.last());
  }
  
  function treeLayout(tree) {
	  var NODEGAP = 40,
        results = {};
    var compactArray = function(arr) {
          return $.map(arr, function(item) { return item || null; });
        };
    var calculateLayout = function(node) {
  		var ch = compactArray(node.children());
  		for (var i = 0, l=ch.length; i < l; i++) {
  			if (ch[i]) {
  				calculateLayout(ch[i]);
  			}
  		}
  		results[node.id()] = {
  		  cachedTranslation: {width: 0, height: 0},
  		  translation: {width: 0, height: 0},
  		  node: node
  		};
      calculateContours(node);
  	},
  	calculateContours = function(node) {
  		var children = compactArray(node.children()),
  		  resnode = results[node.id()];
			var nodeWidth = node.element.outerWidth()/2.0,
			    nodeHeight = node.element.outerHeight();
  		if (children.length === 0) {
  			resnode.contours = new TreeContours(-nodeWidth, nodeWidth + (nodeWidth % 2 === 0 ? 0 : 1), 
  			                  nodeHeight, node.value());
  			translateThisNode(node, -nodeWidth, 0);
  		} else {
  			var transSum = 0;
  			var firstChild = children[0];
  			resnode.contours = results[firstChild.id()].contours;
  			results[firstChild.id()].contours = null;
  			translateNodes(firstChild, 0, NODEGAP + nodeHeight);

  			for (var i = 1, l = children.length; i < l; i++) {
  				var child = children[i];
  				if (!child) { continue; }
  				var childC = results[child.id()].contours;
  				var trans = resnode.contours.calcTranslation(childC, NODEGAP);
  				transSum += trans;

  				results[child.id()].contours = null;
  				resnode.contours.joinWith(childC, trans);

  				translateNodes(child, getXTranslation(firstChild) + trans - getXTranslation(child),
                                  	NODEGAP + nodeHeight);
  			}

  			var rootTrans = transSum / children.length;
  			resnode.contours.addOnTop(-nodeWidth, nodeWidth + (nodeWidth % 2 === 0 ? 0 : 1), 
  			          nodeHeight, NODEGAP, rootTrans);
  			translateThisNode(node, getXTranslation(firstChild) + rootTrans, 0);
  		}
  	},
  	translateThisNode = function(node, x, y) {
  	  var restrans = results[node.id()].translation;
  		restrans.width += x;
  		restrans.height += y;
  	},
  	translateNodes = function(node, x, y) {
  	  if (!node) { return; }
  	  var restrans = results[node.id()].cachedTranslation;
  		if (!restrans) {
  			restrans = {width: 0, height: 0};
  			results[node.id()].cachedTranslation = restrans;
  		}
  		restrans.width += x;
  		restrans.height += y;
  	},
  	getXTranslation = function(node) {
  	  var restrans = results[node.id()].cachedTranslation;
  		return results[node.id()].translation.width +
  			((!restrans) ? 0 : restrans.width);
  	},
  	propagateTranslations = function(node) {
  	  if (!node) { return; }
  	  var noderes = results[node.id()];
  		if (noderes.cachedTranslation) {
  			var ch = compactArray(node.children());
  			for (var i = 0, l = ch.length; i < l; i++) {
  				var child = ch[i];
  				translateNodes(child, noderes.cachedTranslation.width, noderes.cachedTranslation.height);
  				propagateTranslations(child);
  			}
  			noderes.translation.width += noderes.cachedTranslation.width;
  			noderes.translation.height += noderes.cachedTranslation.height;
  			noderes.cachedTranslation = null;
  		}
  	},
  	calculateFinalLayout = function(node, dx, dy) {
  	  var cLeftExtent = results[node.id()].contours.cLeftExtent;
  	  if (-cLeftExtent - getXTranslation(node) > 0) {
  			translateThisNode(node, -cLeftExtent - getXTranslation(node), 0);
  		}
  		translateNodes(node, dx, dy);
  		propagateTranslations(node);
  	};
  	
  	calculateLayout(tree.root());
  	calculateFinalLayout(tree.root(), 20, 10+NODEGAP);
  	$.each(results, function(key, value) {
  	  var oldPos = value.node.element.position();
  	  if (oldPos.left == 0 && oldPos.top == 0) {
    	  value.node.element.css({left: value.translation.width + "px", top: value.translation.height + "px"});
  	  } else {
    	  value.node.css({left: value.translation.width + "px", top: value.translation.height + "px"});
  	  }
  	});
  	var offset = tree.element.position();
  	$.each(results, function(key, value) {
  	  var node = value.node;
  	  if (node['edgetoparent']) {
  	    var start = {left: value.translation.width + offset.left,
  	                 top: value.translation.height + offset.top},
  	        endnode = results[node.parent().id()].translation,
  	        end = {left: endnode.width + offset.left,
  	               top: endnode.height + offset.top};
  	        
  	    edgeLayout(node.edgetoparent, start, end);
  	  }
  	});
  }
  
  var edgeLayout = function(edge, start, end) {
    var sElem = edge.startnode.element,
        eElem = edge.endnode.element,
        sWidth = sElem.outerWidth()/2.0,
        eWidth = eElem.outerWidth()/2.0,
        sHeight = sElem.outerHeight()/2.0,
        eHeight = eElem.outerHeight()/2.0,
        svgstyle = edge.jsav.getSvg().canvas.style,
        svgleft = svgstyle.left,
        svgtop = svgstyle.top,
        pi = Math.PI,
        startpos = sElem.offset(),
        endpos = eElem.offset(),<commit_msg>Tree width/height fix and enabled tree auto centering.<commit_after>/**
* Module that contains layout algorithms for data structures.
* Depends on core.js, datastructures.js
*/
(function() {
  if (typeof JSAV === "undefined") { return; }
  
  function centerArray(array, $lastItem) {
    // center the array inside its parent container
    if (array.options.hasOwnProperty("center") && !array.options.center) {
      // if options center is set to falsy value, return
      return;
    }
    // width of array expected to be last items position + its width
    var width = $lastItem.position().left + $lastItem.outerWidth(),
      containerWidth = $(array.jsav.container).width();
    array.element.css("left", (containerWidth - width)/2);
  }
  
  function verticalArray(array) {
    var $arr = $(array.element),
      // rely on browser doing the calculation, float everything to the left..
      $items = $arr.find("li").css({"float": "left", "position":"static"}),
      maxHeight = -1,
      indexed = !!array.options.indexed;
    if (indexed) {
      $arr.addClass("jsavindexed");
    }
    $items.each(function(index, item) {
      var $i = $(this),
        pos = $i.position();
      $i.css({"left": pos.left - index, "top": pos.top});
      maxHeight = Math.max(maxHeight, $i.outerHeight());
      if (indexed) {
        var $indexLabel = $i.find(".jsavindexlabel");
        if ($indexLabel.size() === 0) {
          $i.append('<span class="jsavindexlabel">' + index + '</span>');
          $indexLabel = $i.find(".jsavindexlabel");
        }
      }
    });
    // ..and return float and positioning
    $items.css({"float": "none", "position": "absolute"});
    $arr.height(maxHeight + (indexed?30:0));
    centerArray(array, $items.last());
  }
  function barArray(array) {
    var $arr = $(array.element).addClass("jsavbararray"),
      $items = $arr.find("li").css({"position":"relative", "float": "left"}), 
      maxValue = Number.MIN_VALUE,
      indexed = !!array.options.indexed,
      width = $items.first().outerWidth();
      size = array.size();
    if (indexed) {
      $arr.addClass("jsavindexed");
    }
    for (var i = 0; i < size; i++) {
      maxValue = Math.max(maxValue, array.value(i));
    }
    maxValue *= 1.15;
    $items.each(function(index, item) {
      var $i = $(this);
      var $valueBar = $i.find(".jsavvaluebar");
      if ($valueBar.size() === 0) {
        $i.prepend('<span class="jsavvaluebar" />');
        $valueBar = $i.find(".jsavvaluebar");
      }
      $valueBar.css({"height": "100%"});
      $i.find(".jsavvalue").css("height", (100.0*array.value(index) / maxValue) + 15 + "%")
        .html('<span>' + $i.find(".jsavvalue").text() + '</span>');
      if (indexed) {
        var $indexLabel = $i.find(".jsavindexlabel");
        if ($indexLabel.size() === 0) {
          $i.append('<span class="jsavindexlabel">' + index + '</span>');
          $indexLabel = $i.find(".jsavindexlabel");
        }
      }
    });
    centerArray(array, $items.last());
  }
  
  function treeLayout(tree) {
	  var NODEGAP = 40,
        results = {};
    var compactArray = function(arr) {
          return $.map(arr, function(item) { return item || null; });
        };
    var calculateLayout = function(node) {
  		var ch = compactArray(node.children());
  		for (var i = 0, l=ch.length; i < l; i++) {
  			if (ch[i]) {
  				calculateLayout(ch[i]);
  			}
  		}
  		results[node.id()] = {
  		  cachedTranslation: {width: 0, height: 0},
  		  translation: {width: 0, height: 0},
  		  node: node
  		};
      calculateContours(node);
  	},
  	calculateContours = function(node) {
  		var children = compactArray(node.children()),
  		  resnode = results[node.id()];
			var nodeWidth = node.element.outerWidth()/2.0,
			    nodeHeight = node.element.outerHeight();
  		if (children.length === 0) {
  			resnode.contours = new TreeContours(-nodeWidth, nodeWidth + (nodeWidth % 2 === 0 ? 0 : 1), 
  			                  nodeHeight, node.value());
  			translateThisNode(node, -nodeWidth, 0);
  		} else {
  			var transSum = 0;
  			var firstChild = children[0];
  			resnode.contours = results[firstChild.id()].contours;
  			results[firstChild.id()].contours = null;
  			translateNodes(firstChild, 0, NODEGAP + nodeHeight);

  			for (var i = 1, l = children.length; i < l; i++) {
  				var child = children[i];
  				if (!child) { continue; }
  				var childC = results[child.id()].contours;
  				var trans = resnode.contours.calcTranslation(childC, NODEGAP);
  				transSum += trans;

  				results[child.id()].contours = null;
  				resnode.contours.joinWith(childC, trans);

  				translateNodes(child, getXTranslation(firstChild) + trans - getXTranslation(child),
                                  	NODEGAP + nodeHeight);
  			}

  			var rootTrans = transSum / children.length;
  			resnode.contours.addOnTop(-nodeWidth, nodeWidth + (nodeWidth % 2 === 0 ? 0 : 1), 
  			          nodeHeight, NODEGAP, rootTrans);
  			translateThisNode(node, getXTranslation(firstChild) + rootTrans, 0);
  		}
  	},
  	translateThisNode = function(node, x, y) {
  	  var restrans = results[node.id()].translation;
  		restrans.width += x;
  		restrans.height += y;
  	},
  	translateNodes = function(node, x, y) {
  	  if (!node) { return; }
  	  var restrans = results[node.id()].cachedTranslation;
  		if (!restrans) {
  			restrans = {width: 0, height: 0};
  			results[node.id()].cachedTranslation = restrans;
  		}
  		restrans.width += x;
  		restrans.height += y;
  	},
  	getXTranslation = function(node) {
  	  var restrans = results[node.id()].cachedTranslation;
  		return results[node.id()].translation.width +
  			((!restrans) ? 0 : restrans.width);
  	},
  	propagateTranslations = function(node) {
  	  if (!node) { return; }
  	  var noderes = results[node.id()];
  		if (noderes.cachedTranslation) {
  			var ch = compactArray(node.children());
  			for (var i = 0, l = ch.length; i < l; i++) {
  				var child = ch[i];
  				translateNodes(child, noderes.cachedTranslation.width, noderes.cachedTranslation.height);
  				propagateTranslations(child);
  			}
  			noderes.translation.width += noderes.cachedTranslation.width;
  			noderes.translation.height += noderes.cachedTranslation.height;
  			noderes.cachedTranslation = null;
  		}
  	},
  	calculateFinalLayout = function(node, dx, dy) {
  	  var cLeftExtent = results[node.id()].contours.cLeftExtent;
  	  if (-cLeftExtent - getXTranslation(node) > 0) {
  			translateThisNode(node, -cLeftExtent - getXTranslation(node), 0);
  		}
  		translateNodes(node, dx, dy);
  		propagateTranslations(node);
  	};
  	
  	calculateLayout(tree.root());
  	calculateFinalLayout(tree.root(), 20, 10+NODEGAP);
  	var maxX = -1, maxY = -1, max = Math.max;
  	$.each(results, function(key, value) {
  	  var oldPos = value.node.element.position();
  	  if (oldPos.left == 0 && oldPos.top == 0) {
    	  value.node.element.css({left: value.translation.width + "px", top: value.translation.height + "px"});
  	  } else {
    	  value.node.css({left: value.translation.width + "px", top: value.translation.height + "px"});
  	  }
  	  maxX = max(maxX, value.translation.width + value.node.element.outerWidth());
  	  maxY = max(maxY, value.translation.height + value.node.element.outerHeight());
  	});
  	tree.element.width(maxX);
  	tree.element.height(maxY);

    // center the tree inside its parent container
    if (tree.options.hasOwnProperty("center") && tree.options.center) {
      // if options center is set to truthy value, center it
      containerWidth = $(tree.jsav.container).width();
      tree.element.css("left", (containerWidth - maxX)/2);
    }

  	var offset = tree.element.position();
  	$.each(results, function(key, value) {
  	  var node = value.node;
  	  if (node['edgetoparent']) {
  	    var start = {left: value.translation.width + offset.left,
  	                 top: value.translation.height + offset.top},
  	        endnode = results[node.parent().id()].translation,
  	        end = {left: endnode.width + offset.left,
  	               top: endnode.height + offset.top};
  	        
  	    edgeLayout(node.edgetoparent, start, end);
  	  }
  	});
  }
  
  var edgeLayout = function(edge, start, end) {
    var sElem = edge.startnode.element,
        eElem = edge.endnode.element,
        sWidth = sElem.outerWidth()/2.0,
        eWidth = eElem.outerWidth()/2.0,
        sHeight = sElem.outerHeight()/2.0,
        eHeight = eElem.outerHeight()/2.0,
        svgstyle = edge.jsav.getSvg().canvas.style,
        svgleft = svgstyle.left,
        svgtop = svgstyle.top,
        pi = Math.PI,
        startpos = sElem.offset(),
        endpos = eElem.offset(),
{'fraction_non_alphanumeric': 0.1635918562302227, 'fraction_numerical': 0.007940772583437818, 'mean_word_length': 2.680509778070754, 'pattern_counts': {'":': 18, '<': 25, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5165250', 'n_tokens_mistral': 5968, 'n_tokens_neox': 5699, 'n_words': 1112}