<commit_before>// pick out all the pattern nodes from a patternTrace call
var nodePatternTrace = function(patternData) {
	return _.pluck(_.pluck(patternTrace(patternData), "pattern"), "this");
};

// given a pattern, trace out an array of contiguous patterns
var patternTrace = function(patternData) {

	var currPattern = patternData;
	var nextEdge = currPattern.end.edge;

	var traceEnd = patternUnidirectionalTrace(currPattern, nextEdge);

	var patternList = [{
		reverse: false,
		pattern: currPattern
	}].concat(traceEnd.patternList);

	if (!traceEnd.cycle) {
		var traceStart = patternUnidirectionalTrace(currPattern, currPattern.start.edge);
		_.map(traceStart.patternList, function(p) {
			p.reverse = !p.reverse;
		});
		patternList = traceStart.patternList.reverse().concat(patternList);
	}

	return {
		hasCycle: traceEnd.cycle,
		patternList: patternList
	};
};

// helper function in patternTrace: trace in one direction
var patternUnidirectionalTrace = function(patternData, nextEdge) {

	var currPattern = patternData;

	var patternList = [], cycle = false;

	while (nextEdge.joinedTo) {
		var selfPatternObject = _.find(nextEdge.patterns, function(p) {
			return p.pattern.this === currPattern.this;
		});

		var otherEdge = nextEdge.joinedTo.__data__;

		var otherPattern = _.min(_.filter(otherEdge.patterns, function(p) {
			return approxEq(p.proportion, 1 - selfPatternObject.proportion, config.polygonTolerance);
		}), function(p) {
			return Math.abs(p.angle - selfPatternObject.angle);
		});

		var shouldBeSelf = _.min(_.filter(nextEdge.patterns, function(p) {
			return approxEq(p.proportion, 1 - otherPattern.proportion, config.polygonTolerance);
		}), function(p) {
			return Math.abs(p.angle - otherPattern.angle);
		});

		if (shouldBeSelf === Infinity || shouldBeSelf.pattern.this !== selfPatternObject.pattern.this) {
			// unsuccessful crossing an edge
			// try bouncing instead

			var bouncePattern = _.find(nextEdge.patterns, function(p) {
				return p.pattern.this !== currPattern.this && p.proportion === selfPatternObject.proportion;
			});

			if (bouncePattern) {
				if (currPattern.start.edge.this === nextEdge.this) {
					currPattern.start.intersect = false;<commit_msg>fixes #1<commit_after>// pick out all the pattern nodes from a patternTrace call
var nodePatternTrace = function(patternData) {
	return _.pluck(_.pluck(patternTrace(patternData), "pattern"), "this");
};

// given a pattern, trace out an array of contiguous patterns
var patternTrace = function(patternData) {

	var currPattern = patternData;
	var nextEdge = currPattern.end.edge;

	var traceEnd = patternUnidirectionalTrace(currPattern, nextEdge);

	var patternList = [{
		reverse: false,
		pattern: currPattern
	}].concat(traceEnd.patternList);

	if (!traceEnd.cycle) {
		var traceStart = patternUnidirectionalTrace(currPattern, currPattern.start.edge);
		_.map(traceStart.patternList, function(p) {
			p.reverse = !p.reverse;
		});
		patternList = traceStart.patternList.reverse().concat(patternList);
	}

	return {
		hasCycle: traceEnd.cycle,
		patternList: patternList
	};
};

// helper function in patternTrace: trace in one direction
var patternUnidirectionalTrace = function(patternData, nextEdge) {

	var currPattern = patternData;

	var patternList = [], cycle = false;

	while (nextEdge.joinedTo) {
		var selfPatternObject = _.find(nextEdge.patterns, function(p) {
			return p.pattern.this === currPattern.this;
		});

		var otherEdge = nextEdge.joinedTo.__data__;

		var otherPattern = _.min(_.filter(otherEdge.patterns, function(p) {
			return approxEq(p.proportion, 1 - selfPatternObject.proportion, config.polygonTolerance);
		}), function(p) {
			return Math.abs(p.angle - selfPatternObject.angle);
		});

		var shouldBeSelf = _.min(_.filter(nextEdge.patterns, function(p) {
			return approxEq(p.proportion, 1 - otherPattern.proportion, config.polygonTolerance);
		}), function(p) {
			return Math.abs(p.angle - otherPattern.angle);
		});

		if (shouldBeSelf === Infinity || shouldBeSelf.pattern.this !== selfPatternObject.pattern.this) {
			// unsuccessful crossing an edge
			// try bouncing instead

			var bouncePattern = _.find(nextEdge.patterns, function(p) {
				return p.pattern.this !== currPattern.this && p.proportion === selfPatternObject.proportion
				// check that the pattern has not already been matched off
					&& p.pattern.this.parentNode !== null;
			});

			if (bouncePattern) {
				if (currPattern.start.edge.this === nextEdge.this) {
					currPattern.start.intersect = false;
{'fraction_non_alphanumeric': 0.12436492158162138, 'fraction_numerical': 0.001104484205875856, 'mean_word_length': 4.475211608222491, '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': '7451561', 'n_tokens_mistral': 1534, 'n_tokens_neox': 1362, 'n_words': 312}