<commit_before>
/*
The structure of the emergent and non-emergent reactions is slightly different.  In the emergent reactions, a reaction is a single pair of reacting 
species.  The possible reacting pairs go in the collide handler's list for that pair.
The non-emergent reaction handler's reaction escompasses all the collision pairs that could be involved in a 2->2, 1->2, 1->1 reaction.  There are potentially many
reacting pairs for a reaction.
The non-emergent reaction will add its pairs, not itself, to the collide handler's reaction list.  
*/

function ReactionHandlerNonEmergent(collide, dotManager, rxns, tConst, activeRxns, pausedRxns) {
	this.collide = collide;
	this.dotManager = dotManager;
	this.tConst = tConst
	this.rxns = rxns;
	this.spcs = undefined; //collide calls setSpcs
	this.chanceMap = undefined;
	this.activeRxns = activeRxns;
	this.pausedRxns = pausedRxns;
	
}

_.extend(ReactionHandlerNonEmergent.prototype, ReactionFuncs, {
	setSpcs: function(spcs) {
		this.spcs = spcs;
		this.chanceMap = {};
		for (var a in this.rxns) {
			this.chanceMap[a] = {} //map of wall handles to WallPairObjs
		}
	},
	addReaction: function(attrs) {
		attrs.parent = this;
		var rxn = new ReactionHandlerNonEmergent.Reaction(attrs, this.rxns);
		rxn.init();
		this.readyHandlers(this.collide, this.rxns, rxn);
	},
	readyHandlers: function(collide, allRxns, rxn) {
		for (var i=0; i<rxn.pairs.length; i++) {
			var idStr = rxn.pairs[i].idStr
			pairRxns = allRxns[idStr];
			if (pairRxns.length == 1) {
				this.initSingleRxnPair(pairRxns[0], idStr, collide);
			} else if (pairRxns.length > 1) {
				this.initMultiRxnPair(pairRxns, idStr, collide);
			} 
		}
	},
	initSingleRxnPair: function(reactivePair, idStr, collide) {
		var idStr = reactivePair.idStr;
		collide.setHandlerByIdStr(idStr, new Listener(function(a, b, UVAB, perpAB, perpBA) {
			var wallGroup = reactivePair.rxn.wallGroupsMap[a.tag];
			var queue = wallGroup[reactivePair.queuePath];
			if (Math.random() < wallGroup[reactivePair.chancePath]) {
				queue.now--;
				if (queue.now >= 0 && this.react(a, b, reactivePair.prods)) { //prods is list of ReactionComponents
					return false;
				} else {
					return collide.impactStd(a, b, UVAB, perpAB, perpBA);
				}
				
			} else {
				return collide.impactStd(a, b, UVAB, perpAB, perpBA);
			}
		}, this));
	},
	initMultiRxnPair: function(reactivePairs, idStr, collide) {
		collide.setHandlerByIdStr(idStr, new Listener(function(a, b, UVAB, perpAB, perpBA) {
			var sumChance = 0;
			for (var i=0; i<reactivePairs.length; i++) {
			}
		}, this));
	},	
})


ReactionHandlerNonEmergent.Reaction = function(attrs, allRxns) {
	/*
	to specify non-emergent reaction, you need...
	rcts: [{spcName: 'name', count: #},]
	prods: [{spcName: 'name', count: #},]
	both must be <=2
	preExpForward: val, L^n/(mol^m sec)
	activeEForward: val, j/(mol K)
	*/
	this.parent = attrs.parent;
	this.chanceMap = this.parent.chanceMap;
	this.collide = this.parent.collide;
	this.handle = attrs.handle;
	this.enqueueListenerHandle = this.handle + 'Enqueue';<commit_msg>testing multi-pair rxns<commit_after>
/*
The structure of the emergent and non-emergent reactions is slightly different.  In the emergent reactions, a reaction is a single pair of reacting 
species.  The possible reacting pairs go in the collide handler's list for that pair.
The non-emergent reaction handler's reaction escompasses all the collision pairs that could be involved in a 2->2, 1->2, 1->1 reaction.  There are potentially many
reacting pairs for a reaction.
The non-emergent reaction will add its pairs, not itself, to the collide handler's reaction list.  
*/

function ReactionHandlerNonEmergent(collide, dotManager, rxns, tConst, activeRxns, pausedRxns) {
	this.collide = collide;
	this.dotManager = dotManager;
	this.tConst = tConst
	this.rxns = rxns;
	this.spcs = undefined; //collide calls setSpcs
	this.chanceMap = undefined;
	this.activeRxns = activeRxns;
	this.pausedRxns = pausedRxns;
	
}

_.extend(ReactionHandlerNonEmergent.prototype, ReactionFuncs, {
	setSpcs: function(spcs) {
		this.spcs = spcs;
		this.chanceMap = {};
		for (var a in this.rxns) {
			this.chanceMap[a] = {} //map of wall handles to WallPairObjs
		}
	},
	addReaction: function(attrs) {
		attrs.parent = this;
		var rxn = new ReactionHandlerNonEmergent.Reaction(attrs, this.rxns);
		rxn.init();
		this.readyHandlers(this.collide, this.rxns, rxn, this.chanceMap);
	},
	readyHandlers: function(collide, allRxns, rxn, chanceMap) {
		for (var i=0; i<rxn.pairs.length; i++) {
			var idStr = rxn.pairs[i].idStr
			pairRxns = allRxns[idStr];
			if (pairRxns.length == 1) {
				this.initSingleRxnPair(pairRxns[0], idStr, collide);
			} else if (pairRxns.length > 1) {
				this.initMultiRxnPair(pairRxns, idStr, collide, chanceMap);
			} 
		}
	},
	initSingleRxnPair: function(reactivePair, idStr, collide) {
		var pair = reactivePair;
		var idStr = pair.idStr;
		collide.setHandlerByIdStr(idStr, new Listener(function(a, b, UVAB, perpAB, perpBA) {
			var wallGroup = pair.rxn.wallGroupsMap[a.tag];
			var queue = wallGroup[pair.queuePath];
			if (Math.random() < wallGroup[pair.chancePath]) {
				queue.now--;
				if (queue.now >= 0 && this.react(a, b, pair.prods)) { //prods is list of ReactionComponents
					return false;
				} else {
					return collide.impactStd(a, b, UVAB, perpAB, perpBA);
				}
				
			} else {
				return collide.impactStd(a, b, UVAB, perpAB, perpBA);
			}
		}, this));
	},
	initMultiRxnPair: function(reactivePairs, idStr, collide, chanceMap) {
		collide.setHandlerByIdStr(idStr, new Listener(function(a, b, UVAB, perpAB, perpBA) {
			var chanceObj = chanceMap[idStr][a.tag];
			var chanceScalar = 1 / Math.max(1, chanceObj.total);
			var roll = Math.random();
			if (chanceObj.total < roll) {
				return collide.impactStd(a, b, UVAB, perpAB, perpBA);
			}
			var sum = 0;
			for (var i=0; i<reactivePairs.length; i++) {
				var pair = reactivePairs[i];
				var wallGroup = pair.rxn.wallGroupsMap[a.tag];
				sum += chanceScalar * wallGroup[pair.chancePath];
				if (sum >= roll) {
					var queue = wallGroup[pair.queuePath];
					queue.now--;
					if (queue.now >=0 && this.react(a, b, pair.prods)) {
						return false
					} else {
						return collide.impactStd(a, b, UVAB, perpAB, perpBA);
					}
				}
				
			}
		}, this));
	},	
})


ReactionHandlerNonEmergent.Reaction = function(attrs, allRxns) {
	/*
	to specify non-emergent reaction, you need...
	rcts: [{spcName: 'name', count: #},]
	prods: [{spcName: 'name', count: #},]
	both must be <=2
	preExpForward: val, L^n/(mol^m sec)
	activeEForward: val, j/(mol K)
	*/
	this.parent = attrs.parent;
	this.chanceMap = this.parent.chanceMap;
	this.collide = this.parent.collide;
	this.handle = attrs.handle;
	this.enqueueListenerHandle = this.handle + 'Enqueue';
{'fraction_non_alphanumeric': 0.12950699043414277, 'fraction_numerical': 0.004562178072111847, 'mean_word_length': 3.889208633093525, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 15, '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': '1979499', 'n_tokens_mistral': 2727, 'n_tokens_neox': 2433, 'n_words': 617}