<commit_before>var d3 = require('d3');
// import * as d3 from 'd3';
var Labelizer = require('./labelizer.js');

var WIDTH = 1000;
var HEIGHT = 500;
var X_ORIG = 100;
var Y_ORIG = 20;
var PADDING = 20;
var CELL_W = 250;
var CELL_H = 75;
var MULTI_OFFSET = 3;
var BORDER_PADDING = 4;
var ANIM_DURATION = 0; // ms
var TOOLTIP_WIDTH = 300;

function Cell(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
}

function Xdsm(graph, svgid, config) {
  this.graph = graph;
  var container = d3.select(".xdsm");
  this.svg = container.append("svg")
                 .attr("width", WIDTH)
                 .attr("height", HEIGHT)
                 .attr("class", svgid);

  this.grid = [];
  this.nodes = [];
  this.edges = [];

  // TODO: Find better javascript way to do configuration.
  this.default_config = {
    labelizer: {
      ellipsis: 5,
      subSupScript: true,
      showLinkNbOnly: false,
    },
    layout: {
      origin: {x: X_ORIG, y: Y_ORIG},
      cellsize: {w: CELL_W, h: CELL_H},
      padding: PADDING,
    },
    titleTooltip: false,  // allow to use external tooltip mechanism
  };

  this.config = this.default_config;
  if (config && config.labelizer) {
    this.config.labelizer.ellipsis = config.labelizer.ellipsis;
    this.config.labelizer.subSupScript = config.labelizer.subSupScript;
    this.config.labelizer.showLinkNbOnly = config.labelizer.showLinkNbOnly;
  }
  if (config && config.layout) {
    this.config.layout.origin.x = config.layout.origin.x;
    this.config.layout.origin.y = config.layout.origin.y;
    this.config.layout.cellsize.w = config.layout.cellsize.w;
    this.config.layout.cellsize.h = config.layout.cellsize.h;
    this.config.layout.padding = config.layout.padding;
  }
  this.config.titleTooltip = config.titleTooltip;

  // Xdsm built-in tooltip for variable connexions
  if (!this.config.titleTooltip) {
    this.tooltip = d3.select("body").append("div").attr("class", "xdsm-tooltip")
        .style("opacity", 0);
  }
  this._initialize();
}

Xdsm.prototype.addNode = function(nodeName) {
  this.graph.addNode(nodeName);
  this.draw();
};

Xdsm.prototype.removeNode = function(index) {
  this.graph.removeNode(index);
  this.draw();
};

Xdsm.prototype.hasWorkflow = function() {
  return this.graph.chains.length !== 0;
};

Xdsm.prototype._initialize = function() {
  var self = this;

  if (self.graph.refname) {
    self._createTitle();
  }
  self.nodeGroup = self.svg.append('g').attr("class", "nodes");
  self.edgeGroup = self.svg.append('g').attr("class", "edges");
};

Xdsm.prototype.draw = function() {
  var self = this;

  self.nodes = self._createTextGroup("node", self.nodeGroup, self._customRect);
  self.edges = self._createTextGroup("edge", self.edgeGroup, self._customTrapz);

  // Workflow
  self._createWorkflow();

  // Dataflow
  self._createDataflow();

  // Border (used by animation)
  self._createBorder();

  // update size
  var w = self.config.layout.cellsize.w * (self.graph.nodes.length + 1);
  var h = self.config.layout.cellsize.h * (self.graph.nodes.length + 1);
  self.svg.attr("width", w).attr("height", h);
  self.svg.selectAll(".border")
    .attr("height", h - BORDER_PADDING)
    .attr("width", w - BORDER_PADDING);
};

Xdsm.prototype._createTextGroup = function(kind, group, decorate) {
  var self = this;

  var selection =
    group.selectAll("." + kind)
      .data(this.graph[kind + "s"],        // DATA JOIN
            function(d) { return d.id; });

  var labelize = Labelizer.labelize()
                  .labelKind(kind)
                  .ellipsis(self.config.labelizer.ellipsis)
                  .subSupScript(self.config.labelizer.subSupScript)
                  .linkNbOnly(self.config.labelizer.showLinkNbOnly);
  
  var textGroups = selection
    .enter() // ENTER
      .append("g").attr("class", function(d) {
        var klass = kind === "node" ? d.type : "dataInter";
        if (klass === "dataInter" && d.isIO()) {
          klass = "dataIO";
        }
        return d.id + " " + kind + " " + klass;
      }).each(function(d, i) {
        var that = d3.select(this); // eslint-disable-line no-invalid-this
        that.call(labelize);  // eslint-disable-line no-invalid-this
      }).each(function(d, i) {
        var grid = self.grid;
        var item = d3.select(this); // eslint-disable-line no-invalid-this
        if (grid[i] === undefined) {
          grid[i] = new Array(self.graph["nodes"].length);
        }
        item.select("text").each(function(d, j) {
          var that = d3.select(this); // eslint-disable-line no-invalid-this
          var data = item.data()[0];
          var m = (data.row === undefined) ? i : data.row;
          var n = (data.col === undefined) ? i : data.col;
          var bbox = that.nodes()[j].getBBox();
          grid[m][n] = new Cell(-bbox.width / 2, 0, bbox.width, bbox.height);
          that
            .attr("width", function() { return grid[m][n].width; })
            .attr("height", function() { return grid[m][n].height; })
            .attr("x", function() { return grid[m][n].x; })
            .attr("y", function() { return grid[m][n].y; });
        })
      }).each(function(d, i) {    
        d3.select(this).call(decorate.bind(self), d, i, 0);
        if (d.isMulti) {<commit_msg>update discipline<commit_after>var d3 = require('d3');
// import * as d3 from 'd3';
var Labelizer = require('./labelizer.js');

var WIDTH = 1000;
var HEIGHT = 500;
var X_ORIG = 100;
var Y_ORIG = 20;
var PADDING = 20;
var CELL_W = 250;
var CELL_H = 75;
var MULTI_OFFSET = 3;
var BORDER_PADDING = 4;
var ANIM_DURATION = 0; // ms
var TOOLTIP_WIDTH = 300;

function Cell(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
}

function Xdsm(graph, svgid, config) {
  this.graph = graph;
  var container = d3.select(".xdsm");
  this.svg = container.append("svg")
                 .attr("width", WIDTH)
                 .attr("height", HEIGHT)
                 .attr("class", svgid);

  this.grid = [];
  this.nodes = [];
  this.edges = [];

  // TODO: Find better javascript way to do configuration.
  this.default_config = {
    labelizer: {
      ellipsis: 5,
      subSupScript: true,
      showLinkNbOnly: false,
    },
    layout: {
      origin: {x: X_ORIG, y: Y_ORIG},
      cellsize: {w: CELL_W, h: CELL_H},
      padding: PADDING,
    },
    titleTooltip: false,  // allow to use external tooltip mechanism
  };

  this.config = this.default_config;
  if (config && config.labelizer) {
    this.config.labelizer.ellipsis = config.labelizer.ellipsis;
    this.config.labelizer.subSupScript = config.labelizer.subSupScript;
    this.config.labelizer.showLinkNbOnly = config.labelizer.showLinkNbOnly;
  }
  if (config && config.layout) {
    this.config.layout.origin.x = config.layout.origin.x;
    this.config.layout.origin.y = config.layout.origin.y;
    this.config.layout.cellsize.w = config.layout.cellsize.w;
    this.config.layout.cellsize.h = config.layout.cellsize.h;
    this.config.layout.padding = config.layout.padding;
  }
  this.config.titleTooltip = config.titleTooltip;

  // Xdsm built-in tooltip for variable connexions
  if (!this.config.titleTooltip) {
    this.tooltip = d3.select("body").append("div").attr("class", "xdsm-tooltip")
        .style("opacity", 0);
  }
  this._initialize();
}

Xdsm.prototype.addNode = function(nodeName) {
  this.graph.addNode(nodeName);
  this.draw();
};

Xdsm.prototype.removeNode = function(index) {
  this.graph.removeNode(index);
  this.draw();
};

Xdsm.prototype.hasWorkflow = function() {
  return this.graph.chains.length !== 0;
};

Xdsm.prototype._initialize = function() {
  var self = this;

  if (self.graph.refname) {
    self._createTitle();
  }
  self.nodeGroup = self.svg.append('g').attr("class", "nodes");
  self.edgeGroup = self.svg.append('g').attr("class", "edges");
};

Xdsm.prototype.refreshNode = function(index) {
  var node = this.graph.nodes[index];
  var sel = d3.select(".nodes").select("."+node.id).select("text").remove();
  var labelize = Labelizer.labelize()
    .labelKind(kind)
    .ellipsis(self.config.labelizer.ellipsis)
    .subSupScript(self.config.labelizer.subSupScript)
    .linkNbOnly(self.config.labelizer.showLinkNbOnly);
  d3.select(".nodes").select(".id"+node.id).select("text").call(labelize)
}
  
Xdsm.prototype.draw = function() {
  var self = this;

  self.nodes = self._createTextGroup("node", self.nodeGroup, self._customRect);
  self.edges = self._createTextGroup("edge", self.edgeGroup, self._customTrapz);

  // Workflow
  self._createWorkflow();

  // Dataflow
  self._createDataflow();

  // Border (used by animation)
  self._createBorder();

  // update size
  var w = self.config.layout.cellsize.w * (self.graph.nodes.length + 1);
  var h = self.config.layout.cellsize.h * (self.graph.nodes.length + 1);
  self.svg.attr("width", w).attr("height", h);
  self.svg.selectAll(".border")
    .attr("height", h - BORDER_PADDING)
    .attr("width", w - BORDER_PADDING);
};

Xdsm.prototype._createTextGroup = function(kind, group, decorate) {
  var self = this;

  var selection =
    group.selectAll("." + kind)
      .data(this.graph[kind + "s"],        // DATA JOIN
            function(d) { return d.id; });

  var labelize = Labelizer.labelize()
                  .labelKind(kind)
                  .ellipsis(self.config.labelizer.ellipsis)
                  .subSupScript(self.config.labelizer.subSupScript)
                  .linkNbOnly(self.config.labelizer.showLinkNbOnly);
  
  var textGroups = selection
    .enter() // ENTER
      .append("g").attr("class", function(d) {
        var klass = kind === "node" ? d.type : "dataInter";
        if (klass === "dataInter" && d.isIO()) {
          klass = "dataIO";
        }
        return "id"+d.id + " " + kind + " " + klass;
      }).each(function(d, i) {
        var that = d3.select(this); // eslint-disable-line no-invalid-this
        that.call(labelize);  // eslint-disable-line no-invalid-this
      }).each(function(d, i) {
        var grid = self.grid;
        var item = d3.select(this); // eslint-disable-line no-invalid-this
        if (grid[i] === undefined) {
          grid[i] = new Array(self.graph["nodes"].length);
        }
        item.select("text").each(function(d, j) {
          var that = d3.select(this); // eslint-disable-line no-invalid-this
          var data = item.data()[0];
          var m = (data.row === undefined) ? i : data.row;
          var n = (data.col === undefined) ? i : data.col;
          var bbox = that.nodes()[j].getBBox();
          grid[m][n] = new Cell(-bbox.width / 2, 0, bbox.width, bbox.height);
          that
            .attr("width", function() { return grid[m][n].width; })
            .attr("height", function() { return grid[m][n].height; })
            .attr("x", function() { return grid[m][n].x; })
            .attr("y", function() { return grid[m][n].y; });
        })
      }).each(function(d, i) {    
        d3.select(this).call(decorate.bind(self), d, i, 0);
        if (d.isMulti) {
{'fraction_non_alphanumeric': 0.16711833785004518, 'fraction_numerical': 0.008130081300813009, 'mean_word_length': 2.6989642499164717, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '1139760', 'n_tokens_mistral': 3888, 'n_tokens_neox': 3791, 'n_words': 731}