Skip to content
Snippets Groups Projects
slaveSummaryHelpers.js 49.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • // WARNING This file defines objects referenced in slaveSummaryWidgets.js.
    // Either keep this file above the slaveSummaryWidgets.js in the name ordered list
    // (tweego process them in this order), or rework the references.
    
    /* eslint-disable camelcase */
    
    App.UI.SlaveSummaryImpl = function() {
    
    	const data = App.Data.SlaveSummary;
    
    
    	const helpers = function() {
    		/**
    		 * @param {HTMLElement} element
    		 * @param {string|string[]} [classNames]
    		 */
    		function _addClassNames(element, classNames) {
    			if (classNames != undefined) { /* eslint-disable-line eqeqeq */
    				if (Array.isArray(classNames)) {
    					element.classList.add(...classNames);
    				} else {
    					element.classList.add(classNames);
    				}
    			}
    		}
    
    		/**
    		 * @param {Node} container
    		 * @param {string} text
    		 * @param {string|string[]} [classNames]
    		 * @param {boolean} [stdDecor=false]
    		 * @param {number} [value]
    		 */
    		function makeSpan(container, text, classNames, stdDecor = false, value) {
    			let r = document.createElement("span");
    			r.classList.add("ssi");
    			_addClassNames(r, classNames);
    			if (value != undefined && V.summaryStats) { /* eslint-disable-line eqeqeq */
    				text += `[${value}]`;
    			}
    			r.textContent = stdDecor ? `${capFirstChar(text)}.` : text;
    			if (container) {
    				container.appendChild(r);
    			}
    			return r;
    		}
    
    		/**
    		 * @param {Node} container
    		 * @param {string} text
    		 * @returns {Text}
    		 */
    		function addText(container, text) {
    			const r = document.createTextNode(text);
    			if (container) {
    				container.appendChild(r);
    			}
    			return r;
    		}
    
    		/**
    		 * @param {Node} [container]
    		 * @param {string|string[]} [classNames]
    		 */
    		function makeBlock(container, classNames) {
    			let r = document.createElement("span");
    			r.classList.add("ssb");
    			_addClassNames(r, classNames);
    			if (container) {
    				container.appendChild(r);
    			}
    			return r;
    		}
    
    		/**
    		 * @param {Node} container
    		 * @param {string|string[]} [classNames]
    		 * @returns {HTMLParagraphElement}
    		 */
    		function makeParagraph(container, classNames) {
    			let r = document.createElement("p");
    			r.classList.add("si");
    			_addClassNames(r, classNames);
    			if (container) {
    				container.appendChild(r);
    			}
    			return r;
    		}
    
    		/**
    		 * @param {object} dict
    		 * @param {*} value
    		 * @param {*} [defaultValue]
    		 * @returns {*|null}
    		 */
    		function getExactRating(dict, value, defaultValue = null) {
    			const res = dict[value];
    			return res ? res : defaultValue;
    		}
    
    		/**
    		 * @param {object} ratings
    		 * @param {number} value
    		 * @returns {*|null}
    		 */
    		function getNumericRating(ratings, value) {
    
    			for (const key in ratings) {
    				if (parseInt(key) >= value) {
    					return ratings[key];
    
    			return null;
    		}
    
    		/**
    		 * @param {object} ratings
    		 * @param {number[]} values
    		 * @returns {*|null}
    		 */
    		function getMultiNumericRating(ratings, values) {
    			const firstRating = getNumericRating(ratings, values[0]);
    			if (firstRating === null || typeof firstRating === "string" || firstRating.hasOwnProperty("desc")) {
    				return firstRating;
    			}
    			return getMultiNumericRating(firstRating, values.slice(1));
    
    		/**
    		 * @typedef {object} StyledDesc
    		 * @property {string} desc
    		 * @property {string|string[]} [style]
    		 */
    
    		/** @typedef {Object.<string, StyledDesc>} StyledRatings */
    		/**
    		 * @param {Node} container
    		 * @param {StyledRatings} ratings
    		 * @param {number} [value]
    		 * @param {number} [offset] value offset in the ratings dictionary (to eliminate negative values)
    		 * @param {boolean} [stdDecor=false]
    		 */
    		function makeRatedStyledSpan(container, ratings, value, offset = 0, stdDecor = false) {
    			/** @type {StyledDesc} */
    			const d = getNumericRating(ratings, value + offset);
    
    			if (d) {
    				makeSpan(container, d.desc, d.style, stdDecor, value);
    			}
    		}
    
    		/**
    		 * @param {Node} container
    		 * @param {StyledDesc} styledDesc
    		 * @param {number} [value]
    		 * @param {boolean} [stdDecor]
    		 */
    		function makeStyledSpan(container, styledDesc, value, stdDecor = false) {
    			if (styledDesc) {
    				makeSpan(container, styledDesc.desc, styledDesc.style, stdDecor, value);
    			}
    
    		}
    
    		/**
    		 * @param {Node} container
    		 * @param {StyledRatings} ratings
    		 * @param {string|number} value
    		 */
    
    		function makeMappedStyledSpan(container, ratings, value) {
    
    			const d = ratings[value];
    			if (d) {
    				makeSpan(container, d.desc, d.style);
    			}
    		}
    
    		/**
    		 * @param {Node} container
    		 * @param {Object.<string, string>} ratings
    		 * @param {string|number} value
    		 * @param {string|string[]} [classNames]
    		 */
    		function makeMappedSpan(container, ratings, value, classNames) {
    			const d = ratings[value];
    			if (d) {
    				makeSpan(container, d, classNames);
    			}
    		}
    
    		/**
    		 * Returns first three string characters with the first one uppercased (string -> Str)
    		 * @param {string} s
    		 * @returns {string}
    		 */
    		function firstThreeUc(s) {
    			return s.charAt(0).toUpperCase() + s.charAt(1) + s.charAt(2);
    		}
    
    
    		/**
    		 * @param {FC.ArcologyState} arcology
    		 */
    
    		function syncFSData(arcology) {
    			arcology = arcology || V.arcologies[0];
    			for (const fsp of App.Data.misc.FutureSocieties) {
    
    				/** @type {FC.FSPolicy} */
    
    				const policy = arcology[fsp];
    				const p = fsp.slice(2);
    				FSData.policy[p] = {
    					active: policy === "unset" ? 0 : 1,
    					strength: Math.trunc(policy === "unset" ? 0: policy / 10)
    				};
    			}
    
    			const dislikeBigButts = (FSData.policy.TransformationFetishist.strength < 2) && (FSData.policy.HedonisticDecadence.strength < 2) && (FSData.policy.AssetExpansionist.strength < 2) && (arcology.FSIntellectualDependencyLawBeauty === 0);
    			FSData.bigButts = dislikeBigButts ? -1 : 0;
    
    		/**
    		 * @typedef {Object} FSDatum
    		 * @property {number} active FS policy is active (0,1)
    		 * @property {number} strength FS decoration level divided by 10
    		 */
    		const FSData = {
    			/** @type {Object.<string, FSDatum>} */
    			policy: {},
    			bigButts: 0,
    		};
    
    		return {
    			addText: addText,
    			makeSpan: makeSpan,
    			makeBlock: makeBlock,
    			makeParagraph: makeParagraph,
    			getExactRating: getExactRating,
    
    			getNumericRating: getNumericRating,
    
    			getMultiNumericRating: getMultiNumericRating,
    
    			makeStyledSpan: makeStyledSpan,
    
    			makeRatedStyledSpan: makeRatedStyledSpan,
    			makeMappedStyledSpan: makeMappedStyledSpan,
    
    			makeMappedSpan: makeMappedSpan,
    
    			firstThreeUc: firstThreeUc,
    
    			syncFSData: syncFSData,
    			FSData: FSData,
    
    		};
    	}();
    
    	const bits = function() {
    		const addText = helpers.addText;
    		const makeSpan = helpers.makeSpan;
    		const makeBlock = helpers.makeBlock;
    
    		const makeRatedStyledSpan = helpers.makeRatedStyledSpan;
    
    
    		/**
    		 * Returns index in the hips-ass rating table
    		 * @param {App.Entity.SlaveState} slave
    		 * @returns {number} 0 if butt is considered too small, 1 is too big, -1 otherwise.
    		 */
    		function hipsAssRating(slave) {
    			const FSData = helpers.FSData;
    			if (slave.hips < -1) {
    				if (slave.butt > 2 && FSData.bigButts <= 0) {
    					return 1;
    				}
    			} else if (slave.hips < 0) {
    				if (slave.butt > 4 && FSData.bigButts <= 0) {
    					return 1;
    				}
    			} else if (slave.hips > 2) {
    				if (slave.butt <= 8) {
    					return 0;
    				}
    			} else if (slave.hips > 1) {
    				if (slave.butt <= 3 && (FSData.policy.SlimnessEnthusiast.active === 0 || (slave.boobs >= 500))) {
    					return 0;
    				}
    			} else if (slave.hips > 0) {
    				if (slave.butt > 8) {
    					if (FSData.bigButts <= 0) {
    						return 1;
    					}
    				} else if (slave.butt <= 2 && ((FSData.policy.SlimnessEnthusiast.active === 0) || (slave.boobs >= 500))) {
    					return 0;
    				}
    			} else {
    				if (slave.butt > 6) {
    					if (FSData.bigButts <= 0) {
    						return 1;
    					}
    				} else if (slave.butt <= 1 && (FSData.policy.SlimnessEnthusiast.active === 0 || (slave.boobs >= 500))) {
    					return 0;
    				}
    			}
    			return -1;
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {App.Data.SlaveSummary.SmartPiercing} spData
    		 * @returns {string}
    		 */
    		function smartFetishStr(slave, spData) {
    			if (slave.fetishKnown === 1) {
    				if (slave.clitSetting === "off") {
    					return spData.setting.off;
    				} else if ((slave.energy <= 95) && (slave.clitSetting === "all")) {
    					return spData.setting.all;
    				} else if ((slave.energy > 5) && (slave.clitSetting === "none")) {
    					return spData.setting.none;
    				} else if (((slave.fetish !== "none") && (slave.clitSetting === "vanilla"))) {
    					return spData.setting.vanilla;
    				} else if (slave.fetishStrength <= 95 || slave.fetish !== slave.clitSetting) {
    					const s = spData.setting[slave.clitSetting];
    					if (s) {
    						return s;
    					}
    				}
    				if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) {
    					return spData.setting.monitoring;
    				}
    			} else {
    
    svornost's avatar
    svornost committed
    				return spData.setting[slave.clitSetting];
    
    			}
    			return null;
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {App.Data.SlaveSummary.SmartPiercing} spData
    		 * @returns {string}
    		 */
    		function smartAttractionStr(slave, spData) {
    			const sps = spData.setting;
    			const cs = slave.clitSetting;
    			if (slave.attrKnown === 1) {
    				switch (cs) {
    					case "women":
    						if (slave.attrXX < 95) {
    							return sps.women;
    						} else {
    							return sps.monitoring;
    						}
    				case "men":
    					if (slave.attrXY < 95) {
    						return sps.men;
    					} else {
    						return sps.monitoring;
    					}
    				case "anti-women":
    					if (slave.attrXX > 0) {
    						return sps["anti-women"];
    					} else {
    						return sps.monitoring;
    					}
    				case "anti-men":
    					if (slave.attrXY > 0) {
    						return sps["anti-men"];
    					} else {
    						return sps.monitoring;
    					}
    				}
    			} else {
    				switch (cs){
    					// fall-through
    					case "women":
    					case "men":
    					case "anti-women":
    					case "anti-men":
    						return sps[cs];
    				}
    			}
    			return null;
    		}
    
    
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_health(slave, c) {
    			if (slave.health.health < -20) {
    				makeSpan(c, "H", ["red", "strong"], true, slave.health.health);
    			} else if (slave.health.health <= 20) {
    				makeSpan(c, "H", ["yellow", "strong"], true, slave.health.health);
    			} else if (slave.health.health > 20) {
    				makeSpan(c, "H", ["green", "strong"], true, slave.health.health);
    			}
    			if (passage() === "Clinic" && V.clinicUpgradeScanner) {
    				if (slave.chem > 15) {
    					makeSpan(c, `C${Math.ceil(slave.chem / 10)}`, ["cyan", "strong"]);
    				} else if (slave.chem <= 15 && slave.assignment === "get treatment in the clinic") {
    					makeSpan(c, `CSafe`, ["green", "strong"]);
    				}
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_illness(slave, c) {
    
    			if (slave.health.illness > 2) {
    
    				makeSpan(c, `Ill${slave.health.illness}`, ["red", "strong"], true, slave.health.illness);
    			} else if (slave.health.illness > 0) {
    				makeSpan(c, `Ill${slave.health.illness}`, ["yellow", "strong"], true, slave.health.illness);
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_tired(slave, c) {
    
    			helpers.makeRatedStyledSpan(c, data.short.health.tiredness, slave.health.tired, 0, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_health(slave, c) {
    
    			helpers.makeRatedStyledSpan(c, data.long.health.health, slave.health.health, 100, true);
    
    			if (passage() === "Clinic" && V.clinicUpgradeScanner) {
    				if (slave.chem > 15) {
    					makeSpan(c, `Carcinogen buildup: ${Math.ceil(slave.chem / 10)}.`, "cyan");
    				} else if (slave.chem <= 15 && slave.assignment === "get treatment in the clinic") {
    					makeSpan(c, `Safe chem levels.`, "green");
    				}
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_illness(slave, c) {
    
    			makeRatedStyledSpan(c, data.long.health.illness, slave.health.illness, 0, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_tired(slave, c) {
    
    			makeRatedStyledSpan(c, data.long.health.tiredness, slave.health.tired, 0, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_age(slave, c) {
    			let r = makeSpan(c, "", "pink");
    			if (V.showAgeDetail === 1) {
    				r.textContent += `Age ` + `${slave.actualAge}` + `.`;
    			} else {
    
    				r.textContent +=  helpers.getNumericRating(data.long.body.age, slave.actualAge);
    
    			}
    			/*
    			 ** No NCS, then do the standard, However because of the wrinkles of Incubators, as long as visual age is greater
    			 ** than or equal to physical age, we do the old physical body/Looks for fresh out of the can NCS slaves.
    			 */
    			if (((slave.geneMods.NCS === 0) || (slave.visualAge >= slave.physicalAge))) {
    				if (slave.actualAge !== slave.physicalAge) {
    					r.textContent += ` ${slave.physicalAge}` + ` year old body.`;
    				}
    				if (slave.visualAge !== slave.physicalAge) {
    					r.textContent += ` Looks ` + `${slave.visualAge}` + `.`;
    				}
    			} else {
    				/*
    				 ** Now the rub. The use of physical Age for the year old body above, basically conflicts with the changes
    				 ** that NCS introduces, so here to *distinguish* the changes, we use visual age with the 'year old body'
    				 ** and appears, for example: Slave release from incubator at age 10, Her summary would show, 'Age 0. 10
    				 ** year old body.' But if she's given NCS a few weeks after release, while she's still before her first
    				 ** birthday, it'll appear the same. But once her birthday fires, if we ran with the above code it would
    				 ** say: 'Age 1. 11 year old body.' -- this conflicts with the way NCS works though, because she hasn't
    				 ** visually aged, so our change here makes it say 'Age 1. Appears to have a 10 year old body.'
    				 */
    				r.textContent += ` Appears to have a ` + `${slave.visualAge}` + ` year old body.`;
    			}
    			if (slave.geneMods.NCS === 1) {
    				makeSpan(r, "NCS", "orange");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_face(slave, c) {
    
    			const r = helpers.getNumericRating(data.long.body.face, slave.face + 100);
    			makeSpan(c, `${r.desc} ${slave.faceShape} face`, r.style, true, slave.face);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_eyes(slave, c) {
    			if (!canSee(slave)) {
    				makeSpan(c, "Blind.", "red");
    			} else if (!canSeePerfectly(slave)) {
    				makeSpan(c, "Nearsighted.", "yellow");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_ears(slave, c) {
    			if (slave.hears <= -2) {
    				makeSpan(c, "Deaf.", "red");
    			} else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) {
    				makeSpan(c, "Hard of hearing.", "yellow");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_lips(slave, c) {
    
    			makeRatedStyledSpan(c, data.long.body.lips, slave.lips, 0, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_teeth(slave, c) {
    
    			helpers.makeMappedStyledSpan(c, data.long.body.teeth, slave.teeth);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_muscles(slave, c) {
    
    			const h = helpers;
    
    			h.makeStyledSpan(c, h.getMultiNumericRating(data.long.body.muscles, [slave.muscles + 100, h.FSData.policy.PhysicalIdealist.active]), slave.muscles);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_voice(slave, c) {
    			if (slave.voice === 0) {
    				makeSpan(c, "Mute.", "red");
    			} else {
    
    				helpers.makeMappedStyledSpan(c, data.long.accent, slave.accent);
    
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_tits_ass(slave, c) {
    
    			const h = helpers;
    			h.makeStyledSpan(c,
    				h.getMultiNumericRating(data.long.body.titsAss,
    
    					[slave.boobs, slave.butt, h.FSData.policy.AssetExpansionist.active, slave.weight + 100, slave.muscles + 100]));
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_hips(slave, c) {
    
    			const di = hipsAssRating(slave);
    			if (di >= 0) {
    				helpers.makeMappedStyledSpan(c, data.long.body.hipsAss, di);
    
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_waist(slave, c) {
    
    			makeRatedStyledSpan(c, data.long.body.waist, slave.waist, 100, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_implants(slave, c) {
    			const styles = "pink";
    			if ((slave.boobsImplant !== 0) || (slave.buttImplant !== 0) || (slave.lipsImplant !== 0) || (slave.bellyImplant !== -1)) {
    				makeSpan(c, "Implants.", styles);
    			} else if ((slave.faceImplant >= 30) || (slave.waist < -95)) {
    				makeSpan(c, "Surgery enhanced.", styles);
    			} else {
    				makeSpan(c, "All natural.", styles);
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_lactation(slave, c) {
    			if (slave.lactation === 1) {
    				makeSpan(c, "Lactating naturally.", "pink");
    			} else if (slave.lactation === 2) {
    				makeSpan(c, "Heavy lactation.", "pink");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_mods(slave, c) {
    			V.modScore = SlaveStatsChecker.modScore(slave);
    			if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) {
    				return;
    			} else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) {
    				makeSpan(c, "Extensive body mods.");
    			} else if (V.modScore > 7) {
    				makeSpan(c, "Noticeable body mods.");
    			} else {
    				makeSpan(c, "Light body mods.");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_age(slave, c) {
    			let r = makeSpan(c, "", "pink");
    			if (V.showAgeDetail === 1) {
    				r.textContent += slave.actualAge.toString();
    			} else if (slave.actualAge >= 18) {
    
    				r.textContent += helpers.getNumericRating(data.short.body.age, slave.actualAge);
    
    			if (slave.actualAge !== slave.physicalAge) {
    				r.textContent += ` w ${slave.physicalAge}y-bdy`;
    			}
    			if (slave.visualAge !== slave.physicalAge) {
    				r.textContent += ` Lks${slave.visualAge}`;
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_face(slave, c) {
    
    			makeRatedStyledSpan(c, data.short.body.face, slave.face, 100, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_eyes(slave, c) {
    			if (!canSee(slave)) {
    				makeSpan(c, "Blind", "red");
    			} else if (!canSeePerfectly(slave)) {
    				makeSpan(c, "Sight-", "yellow");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_ears(slave, c) {
    			if (slave.hears === -2) {
    				makeSpan(c, "Deaf", "red");
    			} else if ((slave.hears === -1) && (slave.earwear !== "hearing aids")) {
    				makeSpan(c, "Hearing-", "yellow");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_lips(slave, c) {
    
    			makeRatedStyledSpan(c, data.short.body.lips, slave.lips, 0, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_teeth(slave, c) {
    
    			helpers.makeMappedStyledSpan(c, data.short.body.teeth, slave.teeth);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_muscles(slave, c) {
    
    			const h = helpers;
    
    Pregmodder's avatar
    Pregmodder committed
    			h.makeStyledSpan(c, h.getMultiNumericRating(data.short.body.muscles, [slave.muscles + 100, h.FSData.policy.PhysicalIdealist.active]), slave.muscles, true);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_voice(slave, c) {
    			if (slave.voice === 0) {
    				makeSpan(c, "Mute", "red");
    			} else {
    
    				helpers.makeMappedStyledSpan(c, data.short.accent, slave.accent);
    
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_tits_ass(slave, c) {
    
    			const h = helpers;
    			h.makeStyledSpan(c,
    				h.getMultiNumericRating(data.short.body.titsAss,
    
    					[slave.boobs, slave.butt, h.FSData.policy.AssetExpansionist.active, slave.weight + 100, slave.muscles + 100]));
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_hips(slave, c) {
    
    			const di = hipsAssRating(slave);
    			if (di >= 0) {
    				helpers.makeMappedStyledSpan(c, data.short.body.hipsAss, di);
    
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_waist(slave, c) {
    
    			makeRatedStyledSpan(c, data.short.body.waist, slave.waist, 100, false);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_implants(slave, c) {
    			if ((slave.boobsImplant === 0) && (slave.buttImplant === 0) && (slave.waist >= -95) && (slave.lipsImplant === 0) && (slave.faceImplant <= 5) && (slave.bellyImplant === -1)) {
    				makeSpan(c, "Natr", "pink");
    			} else {
    				makeSpan(c, "Impl", "pink");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_lactation(slave, c) {
    			if (slave.lactation === 1) {
    				makeSpan(c, "Lact", "pink");
    			} else if (slave.lactation === 2) {
    				makeSpan(c, "Lact", "pink");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_mods(slave, c) {
    			V.modScore = SlaveStatsChecker.modScore(slave);
    			if (slave.corsetPiercing === 0 && V.piercingScore < 3 && V.tatScore < 2) {
    				return;
    			} else if (V.modScore > 15 || (V.piercingScore > 8 && V.tatScore > 5)) {
    				makeSpan(c, "Mods++");
    			} else if (V.modScore > 7) {
    				makeSpan(c, "Mods+");
    			} else {
    				makeSpan(c, "Mods");
    			}
    			if (!jQuery.isEmptyObject(slave.brand)) {
    				makeSpan(c, "Br");
    			}
    		}
    
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_intelligence(slave, c) {
    			if (slave.fetish === "mindbroken") {
    				return;
    			}
    
    			const intelligence = slave.intelligence + slave.intelligenceImplant;
    			const educationStr = helpers.getNumericRating(data.short.mental.education, slave.intelligenceImplant + 15);
    			const intelligenceRating = helpers.getNumericRating(data.short.mental.intelligence, intelligence + 100);
    			makeSpan(c, `${intelligenceRating.desc}${educationStr}`, intelligenceRating.style, true, intelligence);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_skills(slave, c) {
    
    			const sd = data.short.skills;
    			let _SSkills = (slave.skill.anal + slave.skill.oral);
    
    			if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) {
    
    				helpers.makeStyledSpan(c, sd.mss);
    
    			} else {
    				_SSkills += slave.skill.vaginal;
    
    				helpers.makeStyledSpan(c, helpers.getMultiNumericRating(sd.sex, [_SSkills, slave.vagina >= 0 ? 1 : 0]), Math.trunc(_SSkills), true);
    				helpers.makeRatedStyledSpan(c, sd.whoring, slave.skill.whoring, 0, true);
    				helpers.makeRatedStyledSpan(c, sd.entertainment, slave.skill.entertainment, 0, true);
    
    			}
    			if (slave.skill.combat > 0) {
    
    				helpers.makeStyledSpan(c, sd.fighter);
    
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_prestige(slave, c) {
    
    			helpers.makeMappedStyledSpan(c, data.short.prestige, slave.prestige);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function short_porn_prestige(slave, c) {
    
    			helpers.makeMappedStyledSpan(c, data.short.pornPrestige, slave.porn.prestige);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_intelligence(slave, c) {
    			if (slave.fetish === "mindbroken") {
    				return;
    			}
    
    			const intelligence = slave.intelligence + slave.intelligenceImplant;
    			const educationStr = helpers.getNumericRating(data.long.mental.education, slave.intelligenceImplant + 15);
    			const intelligenceRating = helpers.getNumericRating(data.long.mental.intelligence, intelligence + 100);
    			makeSpan(c, `${intelligenceRating.desc}${educationStr}`, intelligenceRating.style, true, intelligence);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_skills(slave, c) {
    
    			const sd = data.long.skills;
    
    			let _SSkills = (slave.skill.anal + slave.skill.oral);
    			if (((_SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) {
    
    				helpers.makeStyledSpan(c, sd.mss);
    
    			} else {
    				_SSkills += slave.skill.vaginal;
    
    				helpers.makeStyledSpan(c, helpers.getMultiNumericRating(sd.sex, [_SSkills, slave.vagina >= 0 ? 1 : 0]), Math.trunc(_SSkills), true);
    				helpers.makeRatedStyledSpan(c, sd.whoring, slave.skill.whoring, 0, true);
    				helpers.makeRatedStyledSpan(c, sd.entertainment, slave.skill.entertainment, 0, true);
    
    			}
    			if (slave.skill.combat > 0) {
    
    				helpers.makeStyledSpan(c, sd.fighter);
    
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_prestige(slave, c) {
    
    			helpers.makeMappedStyledSpan(c, data.long.prestige, slave.prestige);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_porn_prestige(slave, c) {
    
    			helpers.makeMappedStyledSpan(c, data.long.pornPrestige, slave.porn.prestige);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_clothes(slave, c) {
    
    			makeSpan(c, helpers.getExactRating(data.long.clothes, slave.clothes,  'Naked.'));
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_collar(slave, c) {
    
    			helpers.makeMappedSpan(c, data.long.accessory.collar, slave.collar);
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_mask(slave, c) {
    			helpers.makeMappedSpan(c, data.long.accessory.faceAccessory, slave.faceAccessory);
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_mouth(slave, c) {
    			helpers.makeMappedSpan(c, data.long.accessory.mouthAccessory, slave.mouthAccessory);
    		}
    
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_belly(slave, c) {
    
    			helpers.makeMappedSpan(c, data.long.accessory.belly, slave.bellyAccessory);
    
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_arms(slave, c) {
    			if (["hand gloves", "elbow gloves"].includes(slave.armAccessory)) {
    				makeSpan(c, slave.armAccessory, undefined, true);
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave
    		 * @param {Node} c
    		 * @returns {void}
    		 */
    		function long_legs(slave, c) {
    			if (slave.legAccessory === "short stockings") {
    				makeSpan(c, "Short stockings.");
    			} else if (slave.legAccessory === "long stockings") {
    				makeSpan(c, "Long stockings.");
    			}
    		}
    
    		/**
    		 * @param {App.Entity.SlaveState} slave