:: FResult [script]

// this is a port of the FResult widget
// it has been broken up into several functions, because it grew too long
// it has been wrapped in a closure so as not to pollute the global namespace
// and so that nested functions are only evaluated once

window.FResult = (function() {
	"use strict";
	// we can't initialise our global variables on load, because SugarCube.State isn't initialised
	// instead, declare them and initialise on run time
	let V, incest_bonus;
	function FResult(slave) {
		V = State.variables;
		incest_bonus = V.arcologies[0].FSEgyptianRevivalist > 20 || V.arcologies[0].FSEgyptianRevivalistIncestPolicy === 1;

		calcUseWeights(slave);
		if (!slave.fuckdoll)
			calcNotFuckdoll(slave);
		else
			V.FResult += slave.fuckdoll/10;

		V.FResult += Math.max(0, slave.aphrodisiacs) * 2;

		if (slave.inflationType === "aphrodisiac")
			V.FResult += slave.inflation*4;

		if (slave.lactation > 0)
			V.FResult += 1;

		if (slave.nipples === "fuckable")
			calcFuckableTits(slave);

		if (V.seeAge === 1)
			calcAge(slave);
		if (slave.fetish === "mindbroken")
			V.FResult = Math.trunc(V.FResult*0.4);
		else
			V.FResult = Math.trunc(V.FResult*0.7);

		if (slave.pregWeek < 0)
			V.FResult -= Math.trunc(V.FResult*slave.pregWeek/10); // reduced the most just after birth

		calcAmputation(slave);

		if (V.arcologies[0].FSHedonisticDecadence > 20)
			calcHedonismWeight(slave);
		if (V.FResult < 2) {
			if (supremeRaceP(slave) && V.arcologies[0].FSSupremacist > 20)
				V.FResult = 0;
			else
				V.FResult = 2;
		}
	}

	function calcUseWeights(slave) {
		V.FResult = (3 - slave.anus)+(slave.muscles/30);
		if (slave.muscles < -95)
			V.FResult -= 5;
		else if (slave.muscles < -30)
			V.FResult -= 2;

		const uses = V.oralUseWeight + V.vaginalUseWeight + V.analUseWeight;
		if (uses <= 0) return;

		V.FResult += (6+slave.tonguePiercing) * (V.oralUseWeight/uses) * (slave.oralSkill/30);
		if (slave.sexualFlaw === "cum addict")
			V.FResult += (V.oralUseWeight/uses) * (slave.oralSkill/30);
		if (canDoVaginal(slave)) {
			V.FResult += 6 * (V.vaginalUseWeight/uses) * (slave.vaginalSkill/30);
			V.FResult += (3 - slave.vagina);
			V.FResult += slave.vaginaLube;
		}
		if (canDoAnal(slave)) {
			V.FResult += 6 * (V.analUseWeight/uses) * (slave.analSkill/30);
			if (slave.sexualFlaw === "anal addict")
				V.FResult += (V.analUseWeight/uses) * (slave.analSkill/30);
			if (slave.inflationType === "aphrodisiac")
				V.FResult += (V.analUseWeight/uses) * (slave.inflation * 3);
		}
	}

	function calcFuckableTits(slave) {
		V.FResult += 2;
		if (slave.fetish === "boobs")
			V.FResult += Math.trunc(slave.fetishStrength/20);
	}

	function calcWorksWithRelatives(slave) {
		V.slaves.forEach(islave => {
			if (isParentP(slave, islave) && sameAssignmentP(slave, islave)) {
				V.FResult += 1;
				if (incest_bonus) V.FResult += 1;
			}
			if (areSisters(slave, islave) > 0 && sameAssignmentP(slave, islave)) {
				V.FResult += 1;
				if (incest_bonus) V.FResult += 1;
			}
		});
	}

	function calcWorksWithRelativesVanilla(slave) {
		const fre = getSlave(slave.relationTarget)
		if (fre !== undefined && sameAssignmentP(slave, fre)) {
			V.FResult += 2;
			if (incest_bonus) V.FResult += 2;
		}
	}

	function calcWorksWithRelationship(slave) {
		const fre = V.slaves.findIndex(s => {
			return haveRelationshipP(slave, s) && sameAssignmentP(slave, s);
		});
		if (fre !== -1) V.FResult += 1;
	}

	function calcWorksWithRival(slave) {
		const en = V.slaves.findIndex(s => {
			return isRivalP(slave, s) && sameAssignmentP(slave, s);
		});
		if (en !== -1) V.FResult -= 1;
	}

	function calcHInjectionsDiet(slave) {
		if (slave.drugs === "male hormone injections" || slave.drugs === "female hormone injections")
			V.FResult -= 10;
		if (slave.diet === "XXY")
			V.FResult += 2;
		else if (slave.diet === "XY" || slave.diet === "XX")
			V.FResult += 1;
		else if (slave.diet === "cum production")
			V.FResult += 1;
		else if (slave.diet === "fertility")
			V.FResult += 1;
	}
	function calcPreg(slave) {
		if (V.arcologies[0].FSRepopulationFocus > 20) {
			if (slave.preg > 10) V.FResult += 2;
			else V.FResult -= 2;
		} else if (V.arcologies[0].FSRestart > 20) {
			if (slave.bellyPreg >= 500 && slave.breedingMark === 1 && V.propOutcome === 1)
				V.FResult += 1;
			else if (slave.preg > 10)
				V.FResult -= 10;
			else
				V.FResult += 0;
		}
	}

	function calcRace(slave) {
		if (V.arcologies[0].FSSupremacist !== "unset" && supremeRaceP(slave))
			V.FResult -= (V.arcologies[0].FSSupremacist/5) + (V.arcologies[0].FSSupremacistLawME*10);
		if (V.arcologies[0].FSSubjugationist !== "unset" && inferiorRaceP(slave))
			V.FResult += (V.arcologies[0].FSSubjugationist/10) + (V.arcologies[0].FSSubjugationistLawME);
	}

	function calcSexAttributes(slave) {
		if (slave.clitPiercing > 2) V.FResult += 1;
		if (slave.fetishKnown === 1 && slave.fetishStrength > 60 && slave.fetish != "none")
			V.FResult += slave.fetishStrength/5;

		if (slave.attrKnown === 1) {
			V.FResult += Math.trunc(slave.attrXX/20);
			V.FResult += Math.trunc(slave.attrXY/20);
			if (slave.energy > 95) V.FResult += 3;
			else if (slave.energy > 80) V.FResult += 2;
			else if (slave.energy > 60) V.FResult += 1;
			else if (slave.energy <= 20) V.FResult -= 2;
			else if (slave.energy <= 40) V.FResult -= 1;
		}
		if (slave.sexualFlaw !== "none") V.FResult -= 2;
		if (slave.sexualQuirk !== "none") V.FResult += 2;
		if (slave.behavioralFlaw !== "none") V.FResult -= 2;
		if (slave.behavioralQuirk !== "none") V.FResult += 2;
	}

	function calcCareer(slave) {
		if (setup.whoreCareers.includes(slave.career))
			V.FResult += 1;
		else if (slave.oralCount + slave.analCount + slave.vaginalCount + slave.mammaryCount + slave.penetrativeCount > 1000)
			V.FResult += 1;
	}

	function calcSight(slave) {
		if (!canSee(slave)) V.FResult -= 3;
		else if (slave.eyes <= -1) {
			if (slave.eyewear !== "corrective glasses" && slave.eyewear !== "corrective contacts")
				V.FResult -= 1;
		} else if (slave.eyewear === "blurring glasses")
			V.FResult -= 1;
		else if (slave.eyewear === "blurring contacts")
			V.FResult -= 1;
	}

	function calcHearing(slave) {
		if (!canHear(slave)) V.FResult -= 2;
		else if (slave.hears <= -1) {
			if (slave.earwear !== "hearing aids")
				V.FResult -= 1;
		} else if (slave.earwear === "muffling ear plugs")
			V.FResult -= 1;
	}

	function calcEgyptianBonus(slave) {
		if (V.racialVarieties === undefined) V.racialVarieties = [];
		if (!V.racialVarieties.includes(slave.race))
			V.racialVarieties.push(slave.race);
	}

	function calcYouthBonus(slave) {
		if (slave.visualAge < 30) {
			if (slave.actualAge > 30)
				V.FResult += 5; // experienced for her apparent age
			if (slave.physicalAge > 30)
				V.FResult -= slave.physicalAge/2; // too old :(
		}
	}

	function calcMatureBonus(slave) {
		if (slave.visualAge >= 30 && slave.actualAge >= 30 && slave.physicalAge < slave.visualAge)
			V.FResult += Math.min((slave.physicalAge - slave.visualAge) * 2, 20); // looks and acts mature, but has a body that just won't quit
	}

	function calcNotFuckdoll(slave) {
		if (V.familyTesting === 1 && totalRelatives(slave) > 0)
			calcWorksWithRelatives(slave);
		else if(!V.familyTesting && slave.relation !==0)
			calcWorksWithRelativesVanilla(slave);
		if (slave.relationship > 0) calcWorksWithRelationship(slave);
		if (slave.rivalry !== 0) calcWorksWithRival(slave);
		calcHInjectionsDiet(slave);
		calcPreg(slave);
		calcRace(slave);
		calcSexAttributes(slave);
		calcCareer(slave);
		calcSight(slave);
		calcHearing(slave);
		if (V.arcologies[0].FSEgyptianRevivalist !== "unset")
			calcEgyptianBonus(slave);
		if (V.arcologies[0].FSYouthPreferentialist !== "unset")
			calcYouthBonus(slave);
		else if (V.arcologies[0].FSMaturityPreferentialist !== "unset")
			calcMatureBonus(slave);
	}

	function calcAge(slave) {
		if ((V.arcologies[0].FSRepopulationFocus !== "unset" || V.arcologies[0].FSGenderFundamentalist !== "unset") && slave.physicalAge === V.minimumSlaveAge && slave.physicalAge === V.fertilityAge && canGetPregnant(slave)) {
			V.FResult += 1;
			if (slave.birthWeek === 0) V.FResult += V.FResult;
			else if (slave.birthWeek < 4) V.FResult += 0.2*V.FResult;
		} else if (slave.physicalAge === V.minimumSlaveAge) {
			V.FResult += 1;
			if (slave.birthWeek === 0 ) V.FResult += 0.5*V.FResult;
			else if (slave.birthWeek < 4) V.FResult += 0.1*V.FResult;
		} else if (slave.physicalAge === V.fertilityAge && canGetPregnant(slave) && (V.arcologies[0].FSRepopulationFocus !== "unset" || V.arcologies[0].FSGenderFundamentalist !== "unset")) {
			V.FResult += 1;
			if (slave.birthWeek === 0)
				V.FResult += 0.5*V.FResult;
			else if (slave.birthWeek < 4)
				V.FResult += 0.1*V.FResult;
		}
	}

	function calcAmputation(slave) {
		switch(slave.amp) {
		case 0:
			break;
		case 1:
			V.FResult -= 2;
			break;
		case -2:
			break;
		case -5:
			break;
		default:
			V.FResult -= 1;
		}
	}

	function calcHedonismWeight(slave) {
		if (slave.weight < 10)
			V.FResult -= 2;
		else if (slave.weight > 190)
			V.FResult -= 5; // too fat
	}
	return FResult;
})();
