feat(ui): add type filter toggles
This commit is contained in:
53
node_modules/dagre/lib/order/add-subgraph-constraints.js
generated
vendored
Normal file
53
node_modules/dagre/lib/order/add-subgraph-constraints.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = addSubgraphConstraints;
|
||||
|
||||
function addSubgraphConstraints(g, cg, vs) {
|
||||
var prev = {},
|
||||
rootPrev;
|
||||
|
||||
_.forEach(vs, function(v) {
|
||||
var child = g.parent(v),
|
||||
parent,
|
||||
prevChild;
|
||||
while (child) {
|
||||
parent = g.parent(child);
|
||||
if (parent) {
|
||||
prevChild = prev[parent];
|
||||
prev[parent] = child;
|
||||
} else {
|
||||
prevChild = rootPrev;
|
||||
rootPrev = child;
|
||||
}
|
||||
if (prevChild && prevChild !== child) {
|
||||
cg.setEdge(prevChild, child);
|
||||
return;
|
||||
}
|
||||
child = parent;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
function dfs(v) {
|
||||
var children = v ? g.children(v) : g.children();
|
||||
if (children.length) {
|
||||
var min = Number.POSITIVE_INFINITY,
|
||||
subgraphs = [];
|
||||
_.each(children, function(child) {
|
||||
var childMin = dfs(child);
|
||||
if (g.children(child).length) {
|
||||
subgraphs.push({ v: child, order: childMin });
|
||||
}
|
||||
min = Math.min(min, childMin);
|
||||
});
|
||||
_.reduce(_.sortBy(subgraphs, "order"), function(prev, curr) {
|
||||
cg.setEdge(prev.v, curr.v);
|
||||
return curr;
|
||||
});
|
||||
return min;
|
||||
}
|
||||
return g.node(v).order;
|
||||
}
|
||||
dfs(undefined);
|
||||
*/
|
||||
}
|
||||
28
node_modules/dagre/lib/order/barycenter.js
generated
vendored
Normal file
28
node_modules/dagre/lib/order/barycenter.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = barycenter;
|
||||
|
||||
function barycenter(g, movable) {
|
||||
return _.map(movable, function(v) {
|
||||
var inV = g.inEdges(v);
|
||||
if (!inV.length) {
|
||||
return { v: v };
|
||||
} else {
|
||||
var result = _.reduce(inV, function(acc, e) {
|
||||
var edge = g.edge(e),
|
||||
nodeU = g.node(e.v);
|
||||
return {
|
||||
sum: acc.sum + (edge.weight * nodeU.order),
|
||||
weight: acc.weight + edge.weight
|
||||
};
|
||||
}, { sum: 0, weight: 0 });
|
||||
|
||||
return {
|
||||
v: v,
|
||||
barycenter: result.sum / result.weight,
|
||||
weight: result.weight
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
73
node_modules/dagre/lib/order/build-layer-graph.js
generated
vendored
Normal file
73
node_modules/dagre/lib/order/build-layer-graph.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
var _ = require("../lodash");
|
||||
var Graph = require("../graphlib").Graph;
|
||||
|
||||
module.exports = buildLayerGraph;
|
||||
|
||||
/*
|
||||
* Constructs a graph that can be used to sort a layer of nodes. The graph will
|
||||
* contain all base and subgraph nodes from the request layer in their original
|
||||
* hierarchy and any edges that are incident on these nodes and are of the type
|
||||
* requested by the "relationship" parameter.
|
||||
*
|
||||
* Nodes from the requested rank that do not have parents are assigned a root
|
||||
* node in the output graph, which is set in the root graph attribute. This
|
||||
* makes it easy to walk the hierarchy of movable nodes during ordering.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Input graph is a DAG
|
||||
* 2. Base nodes in the input graph have a rank attribute
|
||||
* 3. Subgraph nodes in the input graph has minRank and maxRank attributes
|
||||
* 4. Edges have an assigned weight
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Output graph has all nodes in the movable rank with preserved
|
||||
* hierarchy.
|
||||
* 2. Root nodes in the movable layer are made children of the node
|
||||
* indicated by the root attribute of the graph.
|
||||
* 3. Non-movable nodes incident on movable nodes, selected by the
|
||||
* relationship parameter, are included in the graph (without hierarchy).
|
||||
* 4. Edges incident on movable nodes, selected by the relationship
|
||||
* parameter, are added to the output graph.
|
||||
* 5. The weights for copied edges are aggregated as need, since the output
|
||||
* graph is not a multi-graph.
|
||||
*/
|
||||
function buildLayerGraph(g, rank, relationship) {
|
||||
var root = createRootNode(g),
|
||||
result = new Graph({ compound: true }).setGraph({ root: root })
|
||||
.setDefaultNodeLabel(function(v) { return g.node(v); });
|
||||
|
||||
_.forEach(g.nodes(), function(v) {
|
||||
var node = g.node(v),
|
||||
parent = g.parent(v);
|
||||
|
||||
if (node.rank === rank || node.minRank <= rank && rank <= node.maxRank) {
|
||||
result.setNode(v);
|
||||
result.setParent(v, parent || root);
|
||||
|
||||
// This assumes we have only short edges!
|
||||
_.forEach(g[relationship](v), function(e) {
|
||||
var u = e.v === v ? e.w : e.v,
|
||||
edge = result.edge(u, v),
|
||||
weight = !_.isUndefined(edge) ? edge.weight : 0;
|
||||
result.setEdge(u, v, { weight: g.edge(e).weight + weight });
|
||||
});
|
||||
|
||||
if (_.has(node, "minRank")) {
|
||||
result.setNode(v, {
|
||||
borderLeft: node.borderLeft[rank],
|
||||
borderRight: node.borderRight[rank]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function createRootNode(g) {
|
||||
var v;
|
||||
while (g.hasNode((v = _.uniqueId("_root"))));
|
||||
return v;
|
||||
}
|
||||
67
node_modules/dagre/lib/order/cross-count.js
generated
vendored
Normal file
67
node_modules/dagre/lib/order/cross-count.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
"use strict";
|
||||
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = crossCount;
|
||||
|
||||
/*
|
||||
* A function that takes a layering (an array of layers, each with an array of
|
||||
* ordererd nodes) and a graph and returns a weighted crossing count.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Input graph must be simple (not a multigraph), directed, and include
|
||||
* only simple edges.
|
||||
* 2. Edges in the input graph must have assigned weights.
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. The graph and layering matrix are left unchanged.
|
||||
*
|
||||
* This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
|
||||
*/
|
||||
function crossCount(g, layering) {
|
||||
var cc = 0;
|
||||
for (var i = 1; i < layering.length; ++i) {
|
||||
cc += twoLayerCrossCount(g, layering[i-1], layering[i]);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
||||
function twoLayerCrossCount(g, northLayer, southLayer) {
|
||||
// Sort all of the edges between the north and south layers by their position
|
||||
// in the north layer and then the south. Map these edges to the position of
|
||||
// their head in the south layer.
|
||||
var southPos = _.zipObject(southLayer,
|
||||
_.map(southLayer, function (v, i) { return i; }));
|
||||
var southEntries = _.flatten(_.map(northLayer, function(v) {
|
||||
return _.sortBy(_.map(g.outEdges(v), function(e) {
|
||||
return { pos: southPos[e.w], weight: g.edge(e).weight };
|
||||
}), "pos");
|
||||
}), true);
|
||||
|
||||
// Build the accumulator tree
|
||||
var firstIndex = 1;
|
||||
while (firstIndex < southLayer.length) firstIndex <<= 1;
|
||||
var treeSize = 2 * firstIndex - 1;
|
||||
firstIndex -= 1;
|
||||
var tree = _.map(new Array(treeSize), function() { return 0; });
|
||||
|
||||
// Calculate the weighted crossings
|
||||
var cc = 0;
|
||||
_.forEach(southEntries.forEach(function(entry) {
|
||||
var index = entry.pos + firstIndex;
|
||||
tree[index] += entry.weight;
|
||||
var weightSum = 0;
|
||||
while (index > 0) {
|
||||
if (index % 2) {
|
||||
weightSum += tree[index + 1];
|
||||
}
|
||||
index = (index - 1) >> 1;
|
||||
tree[index] += entry.weight;
|
||||
}
|
||||
cc += entry.weight * weightSum;
|
||||
}));
|
||||
|
||||
return cc;
|
||||
}
|
||||
79
node_modules/dagre/lib/order/index.js
generated
vendored
Normal file
79
node_modules/dagre/lib/order/index.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
"use strict";
|
||||
|
||||
var _ = require("../lodash");
|
||||
var initOrder = require("./init-order");
|
||||
var crossCount = require("./cross-count");
|
||||
var sortSubgraph = require("./sort-subgraph");
|
||||
var buildLayerGraph = require("./build-layer-graph");
|
||||
var addSubgraphConstraints = require("./add-subgraph-constraints");
|
||||
var Graph = require("../graphlib").Graph;
|
||||
var util = require("../util");
|
||||
|
||||
module.exports = order;
|
||||
|
||||
/*
|
||||
* Applies heuristics to minimize edge crossings in the graph and sets the best
|
||||
* order solution as an order attribute on each node.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Graph must be DAG
|
||||
* 2. Graph nodes must be objects with a "rank" attribute
|
||||
* 3. Graph edges must have the "weight" attribute
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Graph nodes will have an "order" attribute based on the results of the
|
||||
* algorithm.
|
||||
*/
|
||||
function order(g) {
|
||||
var maxRank = util.maxRank(g),
|
||||
downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), "inEdges"),
|
||||
upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), "outEdges");
|
||||
|
||||
var layering = initOrder(g);
|
||||
assignOrder(g, layering);
|
||||
|
||||
var bestCC = Number.POSITIVE_INFINITY,
|
||||
best;
|
||||
|
||||
for (var i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
|
||||
sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
|
||||
|
||||
layering = util.buildLayerMatrix(g);
|
||||
var cc = crossCount(g, layering);
|
||||
if (cc < bestCC) {
|
||||
lastBest = 0;
|
||||
best = _.cloneDeep(layering);
|
||||
bestCC = cc;
|
||||
}
|
||||
}
|
||||
|
||||
assignOrder(g, best);
|
||||
}
|
||||
|
||||
function buildLayerGraphs(g, ranks, relationship) {
|
||||
return _.map(ranks, function(rank) {
|
||||
return buildLayerGraph(g, rank, relationship);
|
||||
});
|
||||
}
|
||||
|
||||
function sweepLayerGraphs(layerGraphs, biasRight) {
|
||||
var cg = new Graph();
|
||||
_.forEach(layerGraphs, function(lg) {
|
||||
var root = lg.graph().root;
|
||||
var sorted = sortSubgraph(lg, root, cg, biasRight);
|
||||
_.forEach(sorted.vs, function(v, i) {
|
||||
lg.node(v).order = i;
|
||||
});
|
||||
addSubgraphConstraints(lg, cg, sorted.vs);
|
||||
});
|
||||
}
|
||||
|
||||
function assignOrder(g, layering) {
|
||||
_.forEach(layering, function(layer) {
|
||||
_.forEach(layer, function(v, i) {
|
||||
g.node(v).order = i;
|
||||
});
|
||||
});
|
||||
}
|
||||
38
node_modules/dagre/lib/order/init-order.js
generated
vendored
Normal file
38
node_modules/dagre/lib/order/init-order.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = initOrder;
|
||||
|
||||
/*
|
||||
* Assigns an initial order value for each node by performing a DFS search
|
||||
* starting from nodes in the first rank. Nodes are assigned an order in their
|
||||
* rank as they are first visited.
|
||||
*
|
||||
* This approach comes from Gansner, et al., "A Technique for Drawing Directed
|
||||
* Graphs."
|
||||
*
|
||||
* Returns a layering matrix with an array per layer and each layer sorted by
|
||||
* the order of its nodes.
|
||||
*/
|
||||
function initOrder(g) {
|
||||
var visited = {};
|
||||
var simpleNodes = _.filter(g.nodes(), function(v) {
|
||||
return !g.children(v).length;
|
||||
});
|
||||
var maxRank = _.max(_.map(simpleNodes, function(v) { return g.node(v).rank; }));
|
||||
var layers = _.map(_.range(maxRank + 1), function() { return []; });
|
||||
|
||||
function dfs(v) {
|
||||
if (_.has(visited, v)) return;
|
||||
visited[v] = true;
|
||||
var node = g.node(v);
|
||||
layers[node.rank].push(v);
|
||||
_.forEach(g.successors(v), dfs);
|
||||
}
|
||||
|
||||
var orderedVs = _.sortBy(simpleNodes, function(v) { return g.node(v).rank; });
|
||||
_.forEach(orderedVs, dfs);
|
||||
|
||||
return layers;
|
||||
}
|
||||
122
node_modules/dagre/lib/order/resolve-conflicts.js
generated
vendored
Normal file
122
node_modules/dagre/lib/order/resolve-conflicts.js
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
"use strict";
|
||||
|
||||
var _ = require("../lodash");
|
||||
|
||||
module.exports = resolveConflicts;
|
||||
|
||||
/*
|
||||
* Given a list of entries of the form {v, barycenter, weight} and a
|
||||
* constraint graph this function will resolve any conflicts between the
|
||||
* constraint graph and the barycenters for the entries. If the barycenters for
|
||||
* an entry would violate a constraint in the constraint graph then we coalesce
|
||||
* the nodes in the conflict into a new node that respects the contraint and
|
||||
* aggregates barycenter and weight information.
|
||||
*
|
||||
* This implementation is based on the description in Forster, "A Fast and
|
||||
* Simple Hueristic for Constrained Two-Level Crossing Reduction," thought it
|
||||
* differs in some specific details.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Each entry has the form {v, barycenter, weight}, or if the node has
|
||||
* no barycenter, then {v}.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* A new list of entries of the form {vs, i, barycenter, weight}. The list
|
||||
* `vs` may either be a singleton or it may be an aggregation of nodes
|
||||
* ordered such that they do not violate constraints from the constraint
|
||||
* graph. The property `i` is the lowest original index of any of the
|
||||
* elements in `vs`.
|
||||
*/
|
||||
function resolveConflicts(entries, cg) {
|
||||
var mappedEntries = {};
|
||||
_.forEach(entries, function(entry, i) {
|
||||
var tmp = mappedEntries[entry.v] = {
|
||||
indegree: 0,
|
||||
"in": [],
|
||||
out: [],
|
||||
vs: [entry.v],
|
||||
i: i
|
||||
};
|
||||
if (!_.isUndefined(entry.barycenter)) {
|
||||
tmp.barycenter = entry.barycenter;
|
||||
tmp.weight = entry.weight;
|
||||
}
|
||||
});
|
||||
|
||||
_.forEach(cg.edges(), function(e) {
|
||||
var entryV = mappedEntries[e.v];
|
||||
var entryW = mappedEntries[e.w];
|
||||
if (!_.isUndefined(entryV) && !_.isUndefined(entryW)) {
|
||||
entryW.indegree++;
|
||||
entryV.out.push(mappedEntries[e.w]);
|
||||
}
|
||||
});
|
||||
|
||||
var sourceSet = _.filter(mappedEntries, function(entry) {
|
||||
return !entry.indegree;
|
||||
});
|
||||
|
||||
return doResolveConflicts(sourceSet);
|
||||
}
|
||||
|
||||
function doResolveConflicts(sourceSet) {
|
||||
var entries = [];
|
||||
|
||||
function handleIn(vEntry) {
|
||||
return function(uEntry) {
|
||||
if (uEntry.merged) {
|
||||
return;
|
||||
}
|
||||
if (_.isUndefined(uEntry.barycenter) ||
|
||||
_.isUndefined(vEntry.barycenter) ||
|
||||
uEntry.barycenter >= vEntry.barycenter) {
|
||||
mergeEntries(vEntry, uEntry);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function handleOut(vEntry) {
|
||||
return function(wEntry) {
|
||||
wEntry["in"].push(vEntry);
|
||||
if (--wEntry.indegree === 0) {
|
||||
sourceSet.push(wEntry);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
while (sourceSet.length) {
|
||||
var entry = sourceSet.pop();
|
||||
entries.push(entry);
|
||||
_.forEach(entry["in"].reverse(), handleIn(entry));
|
||||
_.forEach(entry.out, handleOut(entry));
|
||||
}
|
||||
|
||||
return _.map(_.filter(entries, function(entry) { return !entry.merged; }),
|
||||
function(entry) {
|
||||
return _.pick(entry, ["vs", "i", "barycenter", "weight"]);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function mergeEntries(target, source) {
|
||||
var sum = 0;
|
||||
var weight = 0;
|
||||
|
||||
if (target.weight) {
|
||||
sum += target.barycenter * target.weight;
|
||||
weight += target.weight;
|
||||
}
|
||||
|
||||
if (source.weight) {
|
||||
sum += source.barycenter * source.weight;
|
||||
weight += source.weight;
|
||||
}
|
||||
|
||||
target.vs = source.vs.concat(target.vs);
|
||||
target.barycenter = sum / weight;
|
||||
target.weight = weight;
|
||||
target.i = Math.min(source.i, target.i);
|
||||
source.merged = true;
|
||||
}
|
||||
76
node_modules/dagre/lib/order/sort-subgraph.js
generated
vendored
Normal file
76
node_modules/dagre/lib/order/sort-subgraph.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
var _ = require("../lodash");
|
||||
var barycenter = require("./barycenter");
|
||||
var resolveConflicts = require("./resolve-conflicts");
|
||||
var sort = require("./sort");
|
||||
|
||||
module.exports = sortSubgraph;
|
||||
|
||||
function sortSubgraph(g, v, cg, biasRight) {
|
||||
var movable = g.children(v);
|
||||
var node = g.node(v);
|
||||
var bl = node ? node.borderLeft : undefined;
|
||||
var br = node ? node.borderRight: undefined;
|
||||
var subgraphs = {};
|
||||
|
||||
if (bl) {
|
||||
movable = _.filter(movable, function(w) {
|
||||
return w !== bl && w !== br;
|
||||
});
|
||||
}
|
||||
|
||||
var barycenters = barycenter(g, movable);
|
||||
_.forEach(barycenters, function(entry) {
|
||||
if (g.children(entry.v).length) {
|
||||
var subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
|
||||
subgraphs[entry.v] = subgraphResult;
|
||||
if (_.has(subgraphResult, "barycenter")) {
|
||||
mergeBarycenters(entry, subgraphResult);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var entries = resolveConflicts(barycenters, cg);
|
||||
expandSubgraphs(entries, subgraphs);
|
||||
|
||||
var result = sort(entries, biasRight);
|
||||
|
||||
if (bl) {
|
||||
result.vs = _.flatten([bl, result.vs, br], true);
|
||||
if (g.predecessors(bl).length) {
|
||||
var blPred = g.node(g.predecessors(bl)[0]),
|
||||
brPred = g.node(g.predecessors(br)[0]);
|
||||
if (!_.has(result, "barycenter")) {
|
||||
result.barycenter = 0;
|
||||
result.weight = 0;
|
||||
}
|
||||
result.barycenter = (result.barycenter * result.weight +
|
||||
blPred.order + brPred.order) / (result.weight + 2);
|
||||
result.weight += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function expandSubgraphs(entries, subgraphs) {
|
||||
_.forEach(entries, function(entry) {
|
||||
entry.vs = _.flatten(entry.vs.map(function(v) {
|
||||
if (subgraphs[v]) {
|
||||
return subgraphs[v].vs;
|
||||
}
|
||||
return v;
|
||||
}), true);
|
||||
});
|
||||
}
|
||||
|
||||
function mergeBarycenters(target, other) {
|
||||
if (!_.isUndefined(target.barycenter)) {
|
||||
target.barycenter = (target.barycenter * target.weight +
|
||||
other.barycenter * other.weight) /
|
||||
(target.weight + other.weight);
|
||||
target.weight += other.weight;
|
||||
} else {
|
||||
target.barycenter = other.barycenter;
|
||||
target.weight = other.weight;
|
||||
}
|
||||
}
|
||||
57
node_modules/dagre/lib/order/sort.js
generated
vendored
Normal file
57
node_modules/dagre/lib/order/sort.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
var _ = require("../lodash");
|
||||
var util = require("../util");
|
||||
|
||||
module.exports = sort;
|
||||
|
||||
function sort(entries, biasRight) {
|
||||
var parts = util.partition(entries, function(entry) {
|
||||
return _.has(entry, "barycenter");
|
||||
});
|
||||
var sortable = parts.lhs,
|
||||
unsortable = _.sortBy(parts.rhs, function(entry) { return -entry.i; }),
|
||||
vs = [],
|
||||
sum = 0,
|
||||
weight = 0,
|
||||
vsIndex = 0;
|
||||
|
||||
sortable.sort(compareWithBias(!!biasRight));
|
||||
|
||||
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
||||
|
||||
_.forEach(sortable, function (entry) {
|
||||
vsIndex += entry.vs.length;
|
||||
vs.push(entry.vs);
|
||||
sum += entry.barycenter * entry.weight;
|
||||
weight += entry.weight;
|
||||
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
||||
});
|
||||
|
||||
var result = { vs: _.flatten(vs, true) };
|
||||
if (weight) {
|
||||
result.barycenter = sum / weight;
|
||||
result.weight = weight;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function consumeUnsortable(vs, unsortable, index) {
|
||||
var last;
|
||||
while (unsortable.length && (last = _.last(unsortable)).i <= index) {
|
||||
unsortable.pop();
|
||||
vs.push(last.vs);
|
||||
index++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
function compareWithBias(bias) {
|
||||
return function(entryV, entryW) {
|
||||
if (entryV.barycenter < entryW.barycenter) {
|
||||
return -1;
|
||||
} else if (entryV.barycenter > entryW.barycenter) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user