<commit_before>Calc = {};
// Default State
Calc.calcing = false;
Calc.relevantObjs = {
	attackerAbility:1,
	attackerItem:1,
	defenderAbility:1,
	defenderItem:1,
	move:1
};


Calc.calcDamageNumbers = function (attacker, defender, move, field) {
	// We are in the middle of calcing
	this.calcing = true;
	// Move
	if (typeof move === 'string') move = Data.Movedex[move]; // Calc.getMove(move)
	if (!move || move.category === 'Status') return;
	// Clone attacker, defender, and move.
	//this.attacker = attacker;
	//this.defender = defender;
	this.move = Calc.moveClone(move);
	this.attackerAbility = Calc.abilityClone(attacker.ability);
	this.attackerItem = Calc.itemClone(attacker.item);
	this.defenderAbility = Calc.abilityClone(defender.ability);
	this.defenderItem = Calc.itemClone(defender.item);
	this.args = {}; // Keep variables from Calc.get() here

	/* listed move type -> moves that call other moves use the new move instead ->
	 * Normalize changes the move to Normal -> moves now change type (Hidden Power/Judgment/Natural Gift/Techno Blast/Weather Ball) ->
	 * if the move is Normal, Aerilate/Pixilate/Refrigerate change it to Flying/Fairy/Ice
     * -> if the move is still Normal, Ion Deluge changes to Electric -> Electrify changes the move to Electric -> 
	 * Protean activates -> Gems activate if the Gem matches the move type
	*/
	// console.log(this.get('moveType'));
	this.move.type = this.get('moveType') || move.type;
	// Abilities
	//attacker.ability = Calc.getAbility();
	//defender.ability = Calc.getAbility();	
	// Items
	//attacker.item = Calc.getItem();
	//defender.item = Calc.getItem();
	
	attackStatName = (move.category === 'Physical' ? 'atk' : 'spa');
	defendStatName = (move.category === 'Physical' ? 'def' : 'spd');

	attackStat = attacker.stats[attackStatName];
	defendStat = defender.stats[defendStatName];
	
	
	// attackStat = Calc.getEffectiveStat(attackStatName, attackStat, attackBoosts, attacker);
	// defendStat
	var damage = 0;
	
	var basePower = this.get('basePower') || move.basePower;
	var bpMod = this.getMod('bpMod') || 0x1000;
	basePower = this.modify(basePower, bpMod);
	
	// Base Damage
	baseDamage = (Math.floor(Math.floor(Math.floor(2 * attacker.level / 5 + 2) * basePower * attackStat / defendStat) / 50) + 2);
	damage = baseDamage;
	
	// Spread?
	// TODO
	
	// Weather?
	// TODO
	
	// Crit?
	var critMod = this.get('critMod') || 0x1800;
	var crit = crit || false;
	if (crit) this.modify(damage, critMod);
	
	// Random Factor Begins To Apply Here
	// Store other variables for calculations in loop
	
	// STAB
	var hasSTAB = false;
	for (var i = 0; i < attacker.types.length && !hasSTAB; i++) {
		if (this.move.type === attacker.types[i]) hasSTAB = true;
	}
	var stabMod = this.get('stabMod') || 0x1800;
	
	// Type Effectiveness
	// var typeEff = 1;
	var typeEff = this.getTypeEff(this.move.type, defender.types);
	
	// Burn
	var burnEffect = false;
	if (attacker.status === 'brn') burnEffect = true;
	
	// Final Mods
	// TODO
	var finalMod = this.getMod('finalMod') || 0x1000; console.log()
	
	// Loop through damage rolls
	var damageNumbers = [];
	for (var dmgRoll = 15; damageNumbers.length < 16; dmgRoll--) {
		var rolledDamage = Math.floor(damage * (100 - dmgRoll) / 100);
		rolledDamage = this.modify(rolledDamage, (hasSTAB ? stabMod : 0x1000));
		rolledDamage = Math.floor(rolledDamage * typeEff);
		if (burnEffect) rolledDamage = Math.floor(rolledDamage/2);
		// Final Modifier
		rolledDamage = this.modify(rolledDamage, finalMod);
		if (rolledDamage < 1) rolledDamage = 1;
		damageNumbers.push(rolledDamage);
	}
	// done calcing
	this.calcing = false;
	// Clear relevantObjs
	for (var obj in this.relevantObjs) delete this[obj];
	delete this.args;
	return damageNumbers;
};

Calc.toModifier = function (value, numerator, denominator) {
	if (!denominator) denominator = 1;
	if (numerator && numerator.length) {
		denominator = numerator[1];
		numerator = numerator[0];
	}
	return Math.floor(numerator * 0x1000 / denominator);
};

Calc.modify = function (value, mod) {
	mod = mod || 0x1000;
	return Math.floor((value * mod + 0x800 - 1) / 0x1000);
};

Calc.chainModifiers = function (mod1, mod2) {
	mod1 = mod1 || 0x1000;
	mod2 = mod2 || 0x1000;
	return ((mod1 * mod2 + 0x800) >>> 12); // M'' = ((M * M') + 0x800) >> 12
}

Calc.compareTypes = function (oType, dType, ignoreImmunities) {
	if (typeof oType === 'string') oType = [oType];
	if (typeof dType === 'string') dType = [dType];
	var eff = 1;
	for (var i = 0; i < oType.length; i++) {
		if (!Data.TypeChart[oType[i]]) return false;
		for (var j = 0; j < dType.length; j++) {
			if (!Data.TypeChart[dType[j]]) return false;
			eff *= (Data.TypeChart[dType[j]].damageTaken[oType[i]] !== 0 ? Data.TypeChart[dType[j]].damageTaken[oType[i]] : (ignoreImmunities ? 1 : 0));
		}
	}
}

/* Calc.get() - returns the highest priority value or an array of values.
 * Calc.get() is a function that checks the relevant variables in a battle
 * that could affect the part of damage calculation passed to the function.
 * Uses Calc.getFrom().
*/

Calc.get = function (handle, returnArray) {
	if (!this.calcing) return null;
	handle = handle || '';
	if (!handle) return console.log('Blank Handle') || null;
	returnValues = [];
	var sides = {
		attack: "Attack",
		defend: "Defend"
	}
	for (obj in this.relevantObjs) {
		var value = this.getFrom(handle,obj,true);
		if (typeof value !== 'undefined') returnValues.push(value);
		if (obj.substr(0,6) in sides) {
			value = this.getFrom(handle+sides[obj.substr(0,6)], obj, true);
			if (typeof value !== 'undefined') returnValues.push(value);
		}
	}
	returnValues.sort(function(a,b){
		return a.priority - b.priority;
	});
	if (returnArray) return returnValues.map(function(o){return o.value;});
	if (!returnValues.length) return false;
	return returnValues[0].value;
};

Calc.getFrom = function (handle, fromObj, returnObj) {
	if (!this.calcing) return null;
	handle = handle || '';
	fromObj = fromObj || '';<commit_msg>Sort returnValues by highest priority<commit_after>Calc = {};
// Default State
Calc.calcing = false;
Calc.relevantObjs = {
	attackerAbility:1,
	attackerItem:1,
	defenderAbility:1,
	defenderItem:1,
	move:1
};


Calc.calcDamageNumbers = function (attacker, defender, move, field) {
	// We are in the middle of calcing
	this.calcing = true;
	// Move
	if (typeof move === 'string') move = Data.Movedex[move]; // Calc.getMove(move)
	if (!move || move.category === 'Status') return;
	// Clone attacker, defender, and move.
	//this.attacker = attacker;
	//this.defender = defender;
	this.move = Calc.moveClone(move);
	this.attackerAbility = Calc.abilityClone(attacker.ability);
	this.attackerItem = Calc.itemClone(attacker.item);
	this.defenderAbility = Calc.abilityClone(defender.ability);
	this.defenderItem = Calc.itemClone(defender.item);
	this.args = {}; // Keep variables from Calc.get() here

	/* listed move type -> moves that call other moves use the new move instead ->
	 * Normalize changes the move to Normal -> moves now change type (Hidden Power/Judgment/Natural Gift/Techno Blast/Weather Ball) ->
	 * if the move is Normal, Aerilate/Pixilate/Refrigerate change it to Flying/Fairy/Ice
     * -> if the move is still Normal, Ion Deluge changes to Electric -> Electrify changes the move to Electric -> 
	 * Protean activates -> Gems activate if the Gem matches the move type
	*/
	// console.log(this.get('moveType'));
	this.move.type = this.get('moveType') || move.type;
	// Abilities
	//attacker.ability = Calc.getAbility();
	//defender.ability = Calc.getAbility();	
	// Items
	//attacker.item = Calc.getItem();
	//defender.item = Calc.getItem();
	
	attackStatName = (move.category === 'Physical' ? 'atk' : 'spa');
	defendStatName = (move.category === 'Physical' ? 'def' : 'spd');

	attackStat = attacker.stats[attackStatName];
	defendStat = defender.stats[defendStatName];
	
	
	// attackStat = Calc.getEffectiveStat(attackStatName, attackStat, attackBoosts, attacker);
	// defendStat
	var damage = 0;
	
	var basePower = this.get('basePower') || move.basePower;
	var bpMod = this.getMod('bpMod') || 0x1000;
	basePower = this.modify(basePower, bpMod);
	
	// Base Damage
	baseDamage = (Math.floor(Math.floor(Math.floor(2 * attacker.level / 5 + 2) * basePower * attackStat / defendStat) / 50) + 2);
	damage = baseDamage;
	
	// Spread?
	// TODO
	
	// Weather?
	// TODO
	
	// Crit?
	var critMod = this.get('critMod') || 0x1800;
	var crit = crit || false;
	if (crit) this.modify(damage, critMod);
	
	// Random Factor Begins To Apply Here
	// Store other variables for calculations in loop
	
	// STAB
	var hasSTAB = false;
	for (var i = 0; i < attacker.types.length && !hasSTAB; i++) {
		if (this.move.type === attacker.types[i]) hasSTAB = true;
	}
	var stabMod = this.get('stabMod') || 0x1800;
	
	// Type Effectiveness
	// var typeEff = 1;
	var typeEff = this.getTypeEff(this.move.type, defender.types);
	
	// Burn
	var burnEffect = false;
	if (attacker.status === 'brn') burnEffect = true;
	
	// Final Mods
	// TODO
	var finalMod = this.getMod('finalMod') || 0x1000; console.log()
	
	// Loop through damage rolls
	var damageNumbers = [];
	for (var dmgRoll = 15; damageNumbers.length < 16; dmgRoll--) {
		var rolledDamage = Math.floor(damage * (100 - dmgRoll) / 100);
		rolledDamage = this.modify(rolledDamage, (hasSTAB ? stabMod : 0x1000));
		rolledDamage = Math.floor(rolledDamage * typeEff);
		if (burnEffect) rolledDamage = Math.floor(rolledDamage/2);
		// Final Modifier
		rolledDamage = this.modify(rolledDamage, finalMod);
		if (rolledDamage < 1) rolledDamage = 1;
		damageNumbers.push(rolledDamage);
	}
	// done calcing
	this.calcing = false;
	// Clear relevantObjs
	for (var obj in this.relevantObjs) delete this[obj];
	delete this.args;
	return damageNumbers;
};

Calc.toModifier = function (value, numerator, denominator) {
	if (!denominator) denominator = 1;
	if (numerator && numerator.length) {
		denominator = numerator[1];
		numerator = numerator[0];
	}
	return Math.floor(numerator * 0x1000 / denominator);
};

Calc.modify = function (value, mod) {
	mod = mod || 0x1000;
	return Math.floor((value * mod + 0x800 - 1) / 0x1000);
};

Calc.chainModifiers = function (mod1, mod2) {
	mod1 = mod1 || 0x1000;
	mod2 = mod2 || 0x1000;
	return ((mod1 * mod2 + 0x800) >>> 12); // M'' = ((M * M') + 0x800) >> 12
}

Calc.compareTypes = function (oType, dType, ignoreImmunities) {
	if (typeof oType === 'string') oType = [oType];
	if (typeof dType === 'string') dType = [dType];
	var eff = 1;
	for (var i = 0; i < oType.length; i++) {
		if (!Data.TypeChart[oType[i]]) return false;
		for (var j = 0; j < dType.length; j++) {
			if (!Data.TypeChart[dType[j]]) return false;
			eff *= (Data.TypeChart[dType[j]].damageTaken[oType[i]] !== 0 ? Data.TypeChart[dType[j]].damageTaken[oType[i]] : (ignoreImmunities ? 1 : 0));
		}
	}
}

/* Calc.get() - returns the highest priority value or an array of values.
 * Calc.get() is a function that checks the relevant variables in a battle
 * that could affect the part of damage calculation passed to the function.
 * Uses Calc.getFrom().
*/

Calc.get = function (handle, returnArray) {
	if (!this.calcing) return null;
	handle = handle || '';
	if (!handle) return console.log('Blank Handle') || null;
	returnValues = [];
	var sides = {
		attack: "Attack",
		defend: "Defend"
	}
	for (obj in this.relevantObjs) {
		var value = this.getFrom(handle,obj,true);
		if (typeof value !== 'undefined') returnValues.push(value);
		if (obj.substr(0,6) in sides) {
			value = this.getFrom(handle+sides[obj.substr(0,6)], obj, true);
			if (typeof value !== 'undefined') returnValues.push(value);
		}
	}
	returnValues.sort(function(a,b){
		return b.priority - a.priority;
	});
	if (returnArray) return returnValues.map(function(o){return o.value;});
	if (!returnValues.length) return false;
	return returnValues[0].value;
};

Calc.getFrom = function (handle, fromObj, returnObj) {
	if (!this.calcing) return null;
	handle = handle || '';
	fromObj = fromObj || '';
{'fraction_non_alphanumeric': 0.15375606491550944, 'fraction_numerical': 0.01940772963024929, 'mean_word_length': 3.917729329494035, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 29, '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': '4161140', 'n_tokens_mistral': 4534, 'n_tokens_neox': 4157, 'n_words': 1090}