From 62a0dfa4794a01614c7e2e18fa9fb13f34bd556f Mon Sep 17 00:00:00 2001
From: ezsh <ezsh.junk@gmail.com>
Date: Thu, 16 Apr 2020 02:32:21 +0200
Subject: [PATCH] Cache FS data, continue trivial simplifications

---
 devTools/FC.d.ts                    |   26 +
 js/003-data/slaveSummaryData.js     |  379 +++++++++-
 src/js/slaveSummaryHelpers.js       | 1033 +++++++--------------------
 src/js/slaveSummaryWidgets.js       |   52 +-
 src/uncategorized/fsDevelopments.tw |    2 +
 src/uncategorized/policies.tw       |    1 +
 6 files changed, 668 insertions(+), 825 deletions(-)

diff --git a/devTools/FC.d.ts b/devTools/FC.d.ts
index 4bc3727692c..c1ffd2605dd 100644
--- a/devTools/FC.d.ts
+++ b/devTools/FC.d.ts
@@ -35,6 +35,32 @@ declare namespace App {
 				noun: string;
 			}
 		}
+
+		namespace SlaveSummary{
+			class SmartPiercing{
+				setting: {
+					off: string,
+					submissive: string,
+					lesbian: string,
+					oral: string,
+					humiliation: string,
+					anal: string,
+					boobs: string,
+					sadist: string,
+					masochist: string,
+					dom: string,
+					pregnancy: string,
+					vanilla: string,
+					all: string,
+					none: string,
+					monitoring: string,
+					men: string,
+					women: string,
+					"anti-men": string,
+					"anti-women": string,
+				}
+			}
+		}
 	}
 
 	namespace Debug {}
diff --git a/js/003-data/slaveSummaryData.js b/js/003-data/slaveSummaryData.js
index 9fbb4aba84c..4e2a4f5ab0c 100644
--- a/js/003-data/slaveSummaryData.js
+++ b/js/003-data/slaveSummaryData.js
@@ -54,30 +54,30 @@ App.Data.SlaveSummary = {
 				195: {desc: "Ugly waist", style: "red"},
 				200: {desc: "Masculine waist", style: "red"}
 			},
-			genitalia:{
+			genitalia: {
 				dickBalls: { // indices [dick, balls]
 					3: {
 						3: null,
 						4: "Big balls.",
 						5: "Huge balls.",
-						8:  "Monstrous balls.",
-						99:  "Hyper balls."
+						8: "Monstrous balls.",
+						99: "Hyper balls."
 					},
 					4: {
-						3:  "Big dick.",
-						99:  "Big dick & balls."
+						3: "Big dick.",
+						99: "Big dick & balls."
 					},
 					5: {
-						4:  "Huge dick.",
-						99:  "Huge dick & balls."
+						4: "Huge dick.",
+						99: "Huge dick & balls."
 					},
 					8: {
-						5:  "Monster dong.",
-						99:  "Monster dick & balls."
+						5: "Monster dong.",
+						99: "Monster dick & balls."
 					},
 					99: {
-						8:  "Hyper dong.",
-						99:  "Hyper dick & balls."
+						8: "Hyper dong.",
+						99: "Hyper dick & balls."
 					}
 				},
 				holes: { // indices [vagina, anus]
@@ -122,12 +122,12 @@ App.Data.SlaveSummary = {
 					999: {desc: "Huge T&A.", style: "pink"}
 				},
 				11999: {
-					8:{desc: "Monstrous tits.", style: "pink"},
+					8: {desc: "Monstrous tits.", style: "pink"},
 					999: {desc: "Enormous T&A.", style: "pink"},
 				},
 				100000: {
 					9: {desc: "Immobilizing tits.", style: "pink"},
-					999: {desc:	"Hyper T&A.", style: "pink"}
+					999: {desc: "Hyper T&A.", style: "pink"}
 				}
 			},
 			weight: { // indices: [weigh + 100, FSHedonisticDecadence (0,1), hips + 2, ]
@@ -167,6 +167,26 @@ App.Data.SlaveSummary = {
 					0: {desc: "Dangerously Obese", style: "red"},
 					1: {desc: "Perfectly massive"}
 				}
+			},
+			hipsAss: {
+				0: {desc: "Disproportionately small butt.", style: "red"},
+				1: {desc: "Disproportionately big butt.", style: "red"}
+			},
+			muscles: { // indices: [muscles + 100, FSPhysicalIdealist(0,1) ]
+				4: {desc:"Frail", style:"red"},
+				69: {
+					0: {desc: "Very weak"},
+					1: {desc: "Very weak", style: "red"}
+				},
+				94: {
+					0: {desc: "Weak"},
+					1: {desc: "Weak", style: "red"}
+				},
+				105: {desc: "Soft"},
+				130: {desc: "Toned"},
+				150: {desc: "Fit"},
+				195: {desc: "Muscular"},
+				100: {desc: "Hugely muscular"}
 			}
 		},
 		mental: {
@@ -197,6 +217,22 @@ App.Data.SlaveSummary = {
 					200: {desc: "Profoundly trusting", style: ["trust", "prof-trusting"]},
 				}
 			},
+			education: { // index: intelligenceImplant + 15
+				0: ", hindered",
+				29: "",
+				44: ", educated",
+				99: ", well educated"
+			},
+			intelligence: { // index: intelligence + 100
+				4: {desc: "Moronic", style: "orangered"},
+				49: {desc: "Very slow", style: "orangered"},
+				84: {desc: "Slow", style: "orangered"},
+				115: {desc: "Average intelligence"},
+				150: {desc: "Smart", style: "deepskyblue"},
+				195: {desc: "Very smart", style: "deepskyblue"},
+				230: {desc: "Brilliant", style: "deepskyblue"},
+				999: {desc: "Genius", style: "deepskyblue"},
+			},
 			behavioralFlaw: {
 				"arrogant": "Arrogant.",
 				"bitchy": "Bitchy.",
@@ -209,7 +245,54 @@ App.Data.SlaveSummary = {
 				"liberated": "Mentally liberated.",
 			}
 		},
-
+		fetish: { // indices [fetish, fetishStrength]
+			"submissive": {
+				60: "Submissive tendencies",
+				95: "Submissive",
+				100: "Complete submissive"
+			},
+			"cumslut": {
+				60: "Prefers oral",
+				95: "Oral fixation",
+				100: "Cumslut"
+			},
+			"humiliation": {
+				60: "Interest in humiliation",
+				95: "Exhibitionist",
+				100: "Humiliation slut"
+			},
+			"buttslut": {
+				60: "Prefers anal",
+				95: "Anal fixation",
+				100: "Buttslut"
+			},
+			"boobs": {
+				60: "Loves boobs",
+				95: "Breast fixation",
+				100: "Boobslut"
+			},
+			"sadist": {
+				60: "Sadistic tendencies",
+				95: "Sadist",
+				100: "Complete sadist"
+			},
+			"masochist": {
+				60: "Masochistic tendencies",
+				95: "Masochist",
+				100: "Complete masochist"
+			},
+			"dom": {
+				60: "Dominant tendencies",
+				95: "Dominant",
+				100: "Complete dom"
+			},
+			"pregnancy": {
+				60: "Interest in impregnation",
+				95: "Pregnancy kink",
+				100: "Pregnancy fetish"
+			},
+			"none": "Sexually vanilla"
+		},
 		clothes: {
 			"Western clothing": "Chaps.",
 			"a Santa dress": "Santa dress.",
@@ -463,12 +546,101 @@ App.Data.SlaveSummary = {
 			2: {desc: "Very prestigious.", style: "green"},
 			3: {desc: "Extremely prestigious.", style: "green"},
 		},
+		pornPrestige: {
+			0: null,
+			1: {desc: "Porn amateur.", style: "green"},
+			2: {desc: "Porn slut.", style: "green"},
+			3: {desc: "Porn star.", style: "green"},
+		},
 		accent: {
 			0: null,
 			1: {desc: "Cute accent.", style: "pink"},
 			2: {desc: "Accent."},
 			3: {desc: "Bad accent.", style: "red"},
 			4: {desc: "No language skills.", style: "red"},
+		},
+		smartPiercing: {
+			setting: {
+				"off": "SP off.",
+				"submissive": "SP: submissive.",
+				"lesbian": "SP: lesbian",
+				"oral": "SP: oral.",
+				"humiliation": "SP: humiliation.",
+				"anal": "SP: anal.",
+				"boobs": "SP: breasts.",
+				"sadist": "SP: sadism.",
+				"masochist": "SP: masochism.",
+				"dom": "SP: dominance.",
+				"pregnancy": "SP: pregnancy.",
+				"vanilla": "SP: vanilla.",
+				"all": "SP: all.",
+				"none": "SP: none.",
+				"monitoring": "SP: monitoring",
+				"men": "SP: men",
+				"women": "SP: women",
+				"anti-men": "SP: anti men",
+				"anti-women": "SP: anti women",
+			}
+		},
+		skills: {
+			entertainment: {
+				10: null,
+				29: {desc: "Basic entertainer", style: "aquamarine"},
+				59: {desc: "Skilled entertainer", style: "aquamarine"},
+				99: {desc: "Expert entertainer", style: "aquamarine"},
+				999: {desc: "Masterful entertainer", style: "aquamarine"}
+			},
+			sex: { // indices: [sexSkills, hasVagina(0,1)]
+				30: {desc: "Sexually unskilled", style: "aquamarine"},
+				90: {desc: "Sexually skilled", style: "aquamarine"},
+				120: {desc: "Sexual expert", style: "aquamarine"},
+				180: {
+					0: {desc: "Masterful shemale", style: "aquamarine"},
+					1: {desc: "Sexual expert", style: "aquamarine"}
+				},
+				9999: {desc: "Sex master", style: "aquamarine"}
+			},
+			whoring: {
+				10: null,
+				29: {desc: "Basic whore", style: "aquamarine"},
+				59: {desc: "Skilled whore", style: "aquamarine"},
+				99: {desc: "Expert whore", style: "aquamarine"},
+				999: {desc: "Masterful whore", style: "aquamarine"}
+			},
+			mss: {desc: "Masterful Sex Slave.", style: "aquamarine"},
+			fighter: {desc: "Trained fighter.", style: "aquamarine"},
+		},
+		sexDrive: {
+			XX: {
+				5: {desc: "Disgusted by men", style: "red"},
+				15: {desc: "Turned off by men", style: "red"},
+				35: {desc: "Not attracted to men", style: "red"},
+				65: {desc: "Indifferent to men"},
+				85: {desc: "Attracted to men", style: "green"},
+				95: {desc: "Aroused by men", style: "green"},
+				999: {desc: "Passionate about men", style: "green"}
+			},
+			XY: {
+				5: {desc: "disgusted by women", style: "red"},
+				15: {desc: "turned off by women", style: "red"},
+				35: {desc: "not attracted to women", style: "red"},
+				65: {desc: "indifferent to women"},
+				85: {desc: "attracted to women", style: "green"},
+				95: {desc: "aroused by women", style: "green"},
+				999: {desc: "passionate about women", style: "green"}
+			},
+			energy: {
+				20: {desc: "No sex drive", style: "red"},
+				40: {desc: "Poor sex drive", style: "red"},
+				60: {desc: "Average sex drive", style: "yellow"},
+				80: {desc: "Good sex drive", style: "green"},
+				95: {desc: "Powerful sex drive", style: "green"},
+				999: {desc: "Nymphomaniac!", style: "green"}
+			},
+			synergy: {
+				omni: {desc: "Omnisexual!", style: "green"},
+				nymphomni: {desc: "Omnisexual nymphomaniac!", style: "green"}
+			}
 		}
 	},
 	short: {
@@ -631,6 +803,26 @@ App.Data.SlaveSummary = {
 					0: {desc: "W++++++", style: ["red", "strong"]},
 					1: {desc: "W++++++", style: "strong"}
 				}
+			},
+			hipsAss: {
+				0: {desc: "Disp-", style: "red"},
+				1: {desc: "Disp+", style: "red"}
+			},
+			muscles: { // indices: [muscles + 100, FSPhysicalIdealist(0,1) ]
+				4: {desc:"Weak++", style:"red"},
+				69: {
+					0: {desc: "Soft+"},
+					1: {desc: "Weak+", style: "red"}
+				},
+				94: {
+					0: {desc: "Soft"},
+					1: {desc: "Weak", style: "red"}
+				},
+				105: {desc: "Soft"},
+				130: {desc: "Toned"},
+				150: {desc: "Fit"},
+				195: {desc: "Musc+"},
+				100: {desc: "Musc++"}
 			}
 		},
 		mental: {
@@ -661,6 +853,22 @@ App.Data.SlaveSummary = {
 					200: {desc: "VTrust", style: ["trust", "prof-trusting"]},
 				}
 			},
+			education: { // index: intelligenceImplant + 15
+				0: "(e-)",
+				29: "",
+				44: "(e)",
+				99: "(e+)"
+			},
+			intelligence: { // index: intelligence + 100
+				4: {desc: "I---", style: "orangered"},
+				49: {desc: "I--", style: "orangered"},
+				84: {desc: "I-", style: "orangered"},
+				115: {desc: "I"},
+				150: {desc: "I+", style: "deepskyblue"},
+				195: {desc: "I++", style: "deepskyblue"},
+				230: {desc: "I+++", style: "deepskyblue"},
+				999: {desc: "I++++", style: "deepskyblue"},
+			},
 			behavioralFlaw: {
 				"arrogant": "Arrog",
 				"bitchy": "Bitchy",
@@ -729,6 +937,66 @@ App.Data.SlaveSummary = {
 			3: {desc: "Acc--"},
 			4: {desc: "Acc--", style: "red"},
 		},
+		fetish: { // indices [fetish, fetishStrength]
+			"submissive": {
+				60: "Sub",
+				95: "Sub+",
+				100: "Sub++"
+			},
+			"cumslut": {
+				60: "Oral",
+				95: "Oral+",
+				100: "Oral++"
+			},
+			"humiliation": {
+				60: "Humil",
+				95: "Humil+",
+				100: "Humil++"
+			},
+			"buttslut": {
+				60: "Anal",
+				95: "Anal+",
+				100: "Anal++"
+			},
+			"boobs": {
+				60: "Boobs",
+				95: "Boobs+",
+				100: "Boobs++"
+			},
+			"sadist": {
+				60: "Sadist",
+				95: "Sadist+",
+				100: "Sadist++"
+			},
+			"masochist": {
+				60: "Pain",
+				95: "Pain+",
+				100: "Pain++"
+			},
+			"dom": {
+				60: "Dom",
+				95: "Dom+",
+				100: "Dom++"
+			},
+			"pregnancy": {
+				60: "Preg",
+				95: "Preg+",
+				100: "Preg++"
+			},
+			"none" : "Vanilla"
+		},
+		prestige: {
+			0: null,
+			1: {desc: "Prest", style: "green"},
+			2: {desc: "Prest+", style: "green"},
+			3: {desc: "Prest++", style: "green"},
+		},
+		pornPrestige: {
+			0: null,
+			1: {desc: "PPrest", style: "green"},
+			2: {desc: "PPrest+", style: "green"},
+			3: {desc: "PPrest++", style: "green"},
+		},
 		diet: {
 			"restricted": "Di:W-",
 			"fattening": "Di:W+",
@@ -1048,6 +1316,89 @@ App.Data.SlaveSummary = {
 			"dark": "Dark",
 			"fair": "Fair",
 			"pale": "Pale"
+		},
+		smartPiercing: {
+			setting: {
+				"off": "SP-",
+				"submissive": "SP:sub",
+				"lesbian": "SP:les",
+				"oral": "SP:oral",
+				"humiliation": "SP:humil",
+				"anal": "SP:anal",
+				"boobs": "SP:boobs",
+				"sadist": "SP:sade",
+				"masochist": "SP:pain",
+				"dom": "SP:dom",
+				"pregnancy": "SP:pregnancy",
+				"vanilla": "SP:vanilla",
+				"all": "SP:all",
+				"none": "SP:none",
+				"monitoring": "SP:monitoring",
+				"men": "SP:men",
+				"women": "SP:women",
+				"anti-men": "SP:anti-men",
+				"anti-women": "SP:anti-women",
+			}
+		},
+		skills: {
+			entertainment: {
+				10: null,
+				29: {desc: "E", style: "aquamarine"},
+				59: {desc: "E+", style: "aquamarine"},
+				99: {desc: "E++", style: "aquamarine"},
+				999: {desc: "E+++", style: "aquamarine"}
+			},
+			sex: { // indices: [sexSkills, hasVagina(0,1)]
+				30: {desc: "S-", style: "aquamarine"},
+				90: {desc: "S+", style: "aquamarine"},
+				120: {desc: "S++", style: "aquamarine"},
+				180: {
+					0: {desc: "Sh++", style: "aquamarine"},
+					1: {desc: "S++", style: "aquamarine"}
+				},
+				9999: {desc: "S++", style: "aquamarine"}
+			},
+			whoring: {
+				10: null,
+				29: {desc: "W", style: "aquamarine"},
+				59: {desc: "W+", style: "aquamarine"},
+				99: {desc: "W++", style: "aquamarine"},
+				999: {desc: "W+++", style: "aquamarine"}
+			},
+			mss: {desc: "MSS", style: "aquamarine"},
+			fighter: {desc: "C", style: "aquamarine"},
+		},
+		sexDrive: {
+			XX: {
+				5: {desc: "XY---", style: "red"},
+				15: {desc: "XY--", style: "red"},
+				35: {desc: "XY-", style: "red"},
+				65: {desc: "XY"},
+				85: {desc: "XY+", style: "green"},
+				95: {desc: "XY++", style: "green"},
+				999: {desc: "XY+++", style: "green"}
+			},
+			XY: {
+				5: {desc: "XX---", style: "red"},
+				15: {desc: "XX--", style: "red"},
+				35: {desc: "XX-", style: "red"},
+				65: {desc: "XX"},
+				85: {desc: "XX+", style: "green"},
+				95: {desc: "XX++", style: "green"},
+				999: {desc: "XX+++", style: "green"}
+			},
+			energy: {
+				20: {desc: "SD--", style: "red"},
+				40: {desc: "SD-", style: "red"},
+				60: {desc: "SD", style: "yellow"},
+				80: {desc: "SD+", style: "green"},
+				95: {desc: "SD++", style: "green"},
+				999: {desc: "Nympho!", style: "green"}
+			},
+			synergy: {
+				omni: {desc: "Omni!", style: "green"},
+				nymphomni: {desc: "Omni+Nympho!!", style: "green"}
+			}
 		}
 	}
 };
diff --git a/src/js/slaveSummaryHelpers.js b/src/js/slaveSummaryHelpers.js
index 2602a0f59fe..f7fd1efc792 100644
--- a/src/js/slaveSummaryHelpers.js
+++ b/src/js/slaveSummaryHelpers.js
@@ -191,9 +191,30 @@ App.UI.SlaveSummaryImpl = function() {
 			return s.charAt(0).toUpperCase() + s.charAt(1) + s.charAt(2);
 		}
 
-		function FSPolicyFlag(name) {
-			return V.arcologies[0][`FS${name}`] === "unset" ? 0 : 1;
+		function syncFSData(arcology) {
+			arcology = arcology || V.arcologies[0];
+			for (const fsp of App.Data.misc.FutureSocieties) {
+				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,
@@ -208,7 +229,8 @@ App.UI.SlaveSummaryImpl = function() {
 			makeMappedStyledSpan: makeMappedStyledSpan,
 			makeMappedSpan: makeMappedSpan,
 			firstThreeUc: firstThreeUc,
-			FSPolicyFlag: FSPolicyFlag
+			syncFSData: syncFSData,
+			FSData: FSData,
 		};
 	}();
 
@@ -217,6 +239,129 @@ App.UI.SlaveSummaryImpl = function() {
 		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 {
+				return data.smartPiercing.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
@@ -395,31 +540,8 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_muscles(slave, c) {
-			if (slave.muscles > 95) {
-				makeSpan(c, "Hugely muscular", undefined, true, slave.muscles);
-			} else if (slave.muscles > 50) {
-				makeSpan(c, "Muscular", undefined, true, slave.muscles);
-			} else if (slave.muscles > 30) {
-				makeSpan(c, "Fit", undefined, true, slave.muscles);
-			} else if (slave.muscles > 5) {
-				makeSpan(c, "Toned", undefined, true, slave.muscles);
-			} else if (slave.muscles > -6) {
-				makeSpan(c, "Soft", undefined, true, slave.muscles);
-			} else if (slave.muscles > -31) {
-				if (V.arcologies[0].FSPhysicalIdealist === "unset") {
-					makeSpan(c, "Weak", "red", true, slave.muscles);
-				} else {
-					makeSpan(c, "Weak", undefined, true, slave.muscles);
-				}
-			} else if (slave.muscles > -96) {
-				if (V.arcologies[0].FSPhysicalIdealist === "unset") {
-					makeSpan(c, "Very weak", "red", true, slave.muscles);
-				} else {
-					makeSpan(c, "Very weak", undefined, true, slave.muscles);
-				}
-			} else {
-				makeSpan(c, "Frail", "red", true, slave.muscles);
-			}
+			const h = helpers;
+			h.makeStyledSpan(c, h.getMultiNumericRating(data.long.body.muscles, [slave.muscles + 100, h.FSData.policy.PhysicalIdealist.active]));
 		}
 
 		/**
@@ -444,7 +566,7 @@ App.UI.SlaveSummaryImpl = function() {
 			const h = helpers;
 			h.makeStyledSpan(c,
 				h.getMultiNumericRating(data.long.body.titsAss,
-					[slave.boobs, slave.butt, h.FSPolicyFlag("AssetExpansionist"), slave.weight + 100, slave.muscles + 100]));
+					[slave.boobs, slave.butt, h.FSData.policy.AssetExpansionist.active, slave.weight + 100, slave.muscles + 100]));
 		}
 
 		/**
@@ -453,39 +575,9 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_hips(slave, c) {
-			const styles = "red";
-			if (slave.hips < -1) {
-				if (slave.butt > 2 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) {
-					makeSpan(c, "Disproportionately big butt.", styles);
-				}
-			} else if (slave.hips < 0) {
-				if (slave.butt > 4 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) {
-					makeSpan(c, "Disproportionately big butt.", styles);
-				}
-			} else if (slave.hips > 2) {
-				if (slave.butt <= 8) {
-					makeSpan(c, "Disproportionately small butt.", styles);
-				}
-			} else if (slave.hips > 1) {
-				if (slave.butt <= 3 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) {
-					makeSpan(c, "Disproportionately small butt.", styles);
-				}
-			} else if (slave.hips > 0) {
-				if (slave.butt > 8) {
-					if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) {
-						makeSpan(c, "Disproportionately big butt.", styles);
-					}
-				} else if (slave.butt <= 2 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) {
-					makeSpan(c, "Disproportionately small butt.", styles);
-				}
-			} else {
-				if (slave.butt > 6) {
-					if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset") && (V.arcologies[0].FSAssetExpansionist < 20 || V.arcologies[0].FSAssetExpansionist === "unset") && (V.arcologies[0].FSIntellectualDependencyLawBeauty === 0)) {
-						makeSpan(c, "Disproportionately big butt.", styles);
-					}
-				} else if (slave.butt <= 1 && ((V.arcologies[0].FSSlimnessEnthusiast === "unset") || (slave.boobs >= 500))) {
-					makeSpan(c, "Disproportionately small butt.", styles);
-				}
+			const di = hipsAssRating(slave);
+			if (di >= 0) {
+				helpers.makeMappedStyledSpan(c, data.long.body.hipsAss, di);
 			}
 		}
 
@@ -625,31 +717,8 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_muscles(slave, c) {
-			if (slave.muscles > 95) {
-				makeSpan(c, "Musc++", undefined, true, slave.muscles);
-			} else if (slave.muscles > 50) {
-				makeSpan(c, "Musc+", undefined, true, slave.muscles);
-			} else if (slave.muscles > 30) {
-				makeSpan(c, "Fit", undefined, true, slave.muscles);
-			} else if (slave.muscles > 5) {
-				makeSpan(c, "Toned", undefined, true, slave.muscles);
-			} else if (slave.muscles > -6) {
-				makeSpan(c, "Soft", undefined, true, slave.muscles);
-			} else if (slave.muscles > -31) {
-				if (V.arcologies[0].FSPhysicalIdealist === "unset") {
-					makeSpan(c, "Weak", "red", true, slave.muscles);
-				} else {
-					makeSpan(c, "Soft", undefined, true, slave.muscles);
-				}
-			} else if (slave.muscles > -96) {
-				if (V.arcologies[0].FSPhysicalIdealist === "unset") {
-					makeSpan(c, "Weak+", "red", true, slave.muscles);
-				} else {
-					makeSpan(c, "Soft+", undefined, true, slave.muscles);
-				}
-			} else {
-				makeSpan(c, "Weak++", "red", true, slave.muscles);
-			}
+			const h = helpers;
+			h.makeStyledSpan(c, h.getMultiNumericRating(data.short.body.muscles, [slave.muscles + 100, h.FSData.policy.PhysicalIdealist.active]));
 		}
 
 		/**
@@ -674,7 +743,7 @@ App.UI.SlaveSummaryImpl = function() {
 			const h = helpers;
 			h.makeStyledSpan(c,
 				h.getMultiNumericRating(data.short.body.titsAss,
-					[slave.boobs, slave.butt, h.FSPolicyFlag("AssetExpansionist"), slave.weight + 100, slave.muscles + 100]));
+					[slave.boobs, slave.butt, h.FSData.policy.AssetExpansionist.active, slave.weight + 100, slave.muscles + 100]));
 		}
 
 		/**
@@ -683,42 +752,9 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_hips(slave, c) {
-			let desc = "";
-			if (slave.hips < -1) {
-				if (slave.butt > 2 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) {
-					desc = `Disp+`;
-				}
-			} else if (slave.hips < 0) {
-				if (slave.butt > 4 && (V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) {
-					desc = `Disp+`;
-				}
-			} else if (slave.hips > 2) {
-				if (slave.butt <= 8) {
-					desc = `Disp-`;
-				}
-			} else if (slave.hips > 1) {
-				if (slave.butt <= 3 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) {
-					desc = `Disp-`;
-				}
-			} else if (slave.hips > 0) {
-				if (slave.butt > 8) {
-					if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) {
-						desc = `Disp+`;
-					}
-				} else if (slave.butt <= 2 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) {
-					desc = `Disp-`;
-				}
-			} else {
-				if (slave.butt > 6) {
-					if ((V.arcologies[0].FSTransformationFetishist < 20 || V.arcologies[0].FSTransformationFetishist === "unset") && (V.arcologies[0].FSHedonisticDecadence < 20 || V.arcologies[0].FSHedonisticDecadence === "unset")) {
-						desc = `Disp+`;
-					}
-				} else if (slave.butt <= 1 && (V.arcologies[0].FSSlimnessEnthusiast === "unset" || (slave.boobs >= 500))) {
-					desc = `Disp-`;
-				}
-			}
-			if (desc) {
-				makeSpan(c, desc, "red");
+			const di = hipsAssRating(slave);
+			if (di >= 0) {
+				helpers.makeMappedStyledSpan(c, data.short.body.hipsAss, di);
 			}
 		}
 
@@ -785,45 +821,13 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_intelligence(slave, c) {
-			const intelligence = slave.intelligence + slave.intelligenceImplant;
 			if (slave.fetish === "mindbroken") {
 				return;
 			}
-			let education = "";
-			let naturalIntelligence = "";
-			let styles = undefined;
-			if (slave.intelligenceImplant >= 30) {
-				education = "(e+)";
-			} else if (slave.intelligenceImplant >= 15) {
-				education = "(e)";
-			} else if (slave.intelligenceImplant <= -15) {
-				education = "(e-)";
-			}
-			if (intelligence >= 130) {
-				naturalIntelligence = "I++++";
-				styles = "deepskyblue";
-			} else if (intelligence > 95) {
-				naturalIntelligence = "I+++";
-				styles = "deepskyblue";
-			} else if (intelligence > 50) {
-				naturalIntelligence = "I++";
-				styles = "deepskyblue";
-			} else if (intelligence > 15) {
-				naturalIntelligence = "I+";
-				styles = "deepskyblue";
-			} else if (intelligence >= -15) {
-				naturalIntelligence = "I";
-			} else if (intelligence >= -50) {
-				naturalIntelligence = "I-";
-				styles = "orangered";
-			} else if (intelligence >= -95) {
-				naturalIntelligence = "I--";
-				styles = "orangered";
-			} else {
-				naturalIntelligence = "I---";
-				styles = "orangered";
-			}
-			makeSpan(c, `${naturalIntelligence}${education}`, styles, true, intelligence);
+			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);
 		}
 
 		/**
@@ -832,60 +836,18 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_skills(slave, c) {
-			let _SSkills = slave.skill.anal + slave.skill.oral;
-			let r = makeSpan(c, "", "aquamarine");
+			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))) {
-				r.textContent += `MSS`;
+				helpers.makeStyledSpan(c, sd.mss);
 			} else {
 				_SSkills += slave.skill.vaginal;
-				_SSkills = Math.trunc(_SSkills);
-				if (_SSkills > 180) {
-					r.textContent += `S++`;
-				} else if ((_SSkills > 120) && (slave.vagina < 0)) {
-					r.textContent += `Sh++`;
-				} else if (_SSkills > 90) {
-					r.textContent += `S+`;
-				} else if (_SSkills > 30) {
-					r.textContent += `S`;
-				} else {
-					r.textContent += `S-`;
-				}
-				if (V.summaryStats) {
-					r.textContent += `[${_SSkills}]`;
-				}
-				r.textContent += " ";
-				if (slave.skill.whoring >= 100) {
-					r.textContent += `W+++`;
-				} else if (slave.skill.whoring > 60) {
-					r.textContent += `W++`;
-				} else if (slave.skill.whoring > 30) {
-					r.textContent += `W+`;
-				} else if (slave.skill.whoring > 10) {
-					r.textContent += `W`;
-				}
-				if (slave.skill.whoring > 10) {
-					if (V.summaryStats) {
-						r.textContent += `[${slave.skill.whoring}]`;
-					}
-				}
-				r.textContent += " ";
-				if (slave.skill.entertainment >= 100) {
-					r.textContent += `E+++`;
-				} else if (slave.skill.entertainment > 60) {
-					r.textContent += `E++`;
-				} else if (slave.skill.entertainment > 30) {
-					r.textContent += `E+`;
-				} else if (slave.skill.entertainment > 10) {
-					r.textContent += `E`;
-				}
-				if (slave.skill.entertainment > 10) {
-					if (V.summaryStats) {
-						r.textContent += `[${slave.skill.entertainment}]`;
-					}
-				}
+				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) {
-				r.textContent += " C";
+				helpers.makeStyledSpan(c, sd.fighter);
 			}
 		}
 
@@ -895,16 +857,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_prestige(slave, c) {
-			if (slave.prestige > 0) {
-				const styles = "green";
-				if (slave.prestige > 2) {
-					makeSpan(c, "Prest++", styles);
-				} else if (slave.prestige === 2) {
-					makeSpan(c, "Prest+", styles);
-				} else if (slave.prestige === 1) {
-					makeSpan(c, "Prest", styles);
-				}
-			}
+			helpers.makeMappedStyledSpan(c, data.short.prestige, slave.prestige);
 		}
 
 		/**
@@ -913,16 +866,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_porn_prestige(slave, c) {
-			if (slave.porn.prestige > 0) {
-				const styles = "green";
-				if (slave.porn.prestige > 2) {
-					makeSpan(c, "PPrest++", styles);
-				} else if (slave.porn.prestige === 2) {
-					makeSpan(c, "PPrest+", styles);
-				} else if (slave.porn.prestige === 1) {
-					makeSpan(c, "PPrest", styles);
-				}
-			}
+			helpers.makeMappedStyledSpan(c, data.short.pornPrestige, slave.porn.prestige);
 		}
 
 		/**
@@ -931,45 +875,13 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_intelligence(slave, c) {
-			const intelligence = slave.intelligence + slave.intelligenceImplant;
 			if (slave.fetish === "mindbroken") {
 				return;
 			}
-			let education = "";
-			let naturalIntelligence = "";
-			let styles = undefined;
-			if (slave.intelligenceImplant >= 30) {
-				education = ", well educated";
-			} else if (slave.intelligenceImplant >= 15) {
-				education = ", educated";
-			} else if (slave.intelligenceImplant <= -15) {
-				education = ", hindered";
-			}
-			if (intelligence >= 130) {
-				naturalIntelligence = "Genius";
-				styles = "deepskyblue";
-			} else if (intelligence > 95) {
-				naturalIntelligence = "Brilliant";
-				styles = "deepskyblue";
-			} else if (intelligence > 50) {
-				naturalIntelligence = "Very smart";
-				styles = "deepskyblue";
-			} else if (intelligence > 15) {
-				naturalIntelligence = "Smart";
-				styles = "deepskyblue";
-			} else if (intelligence >= -15) {
-				naturalIntelligence = "Average intelligence";
-			} else if (intelligence >= -50) {
-				naturalIntelligence = "Slow";
-				styles = "orangered";
-			} else if (intelligence >= -95) {
-				naturalIntelligence = "Very slow";
-				styles = "orangered";
-			} else {
-				naturalIntelligence = "Moronic";
-				styles = "orangered";
-			}
-			makeSpan(c, `${naturalIntelligence}${education}`, styles, true, intelligence);
+			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);
 		}
 
 		/**
@@ -978,56 +890,18 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @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))) {
-				makeSpan(c, "Masterful Sex Slave.", "aquamarine");
+				helpers.makeStyledSpan(c, sd.mss);
 			} else {
-				let desc;
 				_SSkills += slave.skill.vaginal;
-				if (_SSkills > 180) {
-					desc = "Sex master";
-				} else if ((_SSkills > 120) && (slave.vagina < 0)) {
-					desc = "Masterful shemale";
-				} else if (_SSkills > 90) {
-					desc = "Sexual expert";
-				} else if (_SSkills > 30) {
-					desc = "Sexually skilled";
-				} else {
-					desc = "Sexually unskilled";
-				}
-				if (desc) {
-					makeSpan(c, desc, "aquamarine", true, Math.trunc(_SSkills));
-					desc = "";
-				}
-				if (slave.skill.whoring >= 100) {
-					desc = "Masterful whore";
-				} else if (slave.skill.whoring >= 60) {
-					desc = "Expert whore";
-				} else if (slave.skill.whoring >= 30) {
-					desc = "Skilled whore";
-				} else if (slave.skill.whoring >= 10) {
-					desc = "Basic whore";
-				}
-				if (desc) {
-					makeSpan(c, desc, "aquamarine", true, slave.skill.whoring);
-					desc = "";
-				}
-				if (slave.skill.entertainment >= 100) {
-					desc = "Masterful entertainer";
-				} else if (slave.skill.entertainment >= 60) {
-					desc = "Expert entertainer";
-				} else if (slave.skill.entertainment >= 30) {
-					desc = "Skilled entertainer";
-				} else if (slave.skill.entertainment >= 10) {
-					desc = "Basic entertainer";
-				}
-				if (desc) {
-					makeSpan(c, desc, "aquamarine", true, slave.skill.entertainment);
-					desc = "";
-				}
+				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) {
-				makeSpan(c, "Trained fighter.", "aquamarine");
+				helpers.makeStyledSpan(c, sd.fighter);
 			}
 		}
 
@@ -1037,16 +911,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_prestige(slave, c) {
-			if (slave.prestige > 0) {
-				const styles = "green";
-				if (slave.prestige > 2) {
-					makeSpan(c, "Extremely prestigious.", styles);
-				} else if (slave.prestige === 2) {
-					makeSpan(c, "Very prestigious.", styles);
-				} else if (slave.prestige === 1) {
-					makeSpan(c, "Prestigious.", styles);
-				}
-			}
+			helpers.makeMappedStyledSpan(c, data.long.prestige, slave.prestige);
 		}
 
 		/**
@@ -1055,16 +920,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_porn_prestige(slave, c) {
-			if (slave.porn.prestige > 0) {
-				const styles = "green";
-				if (slave.porn.prestige > 2) {
-					makeSpan(c, "Porn star.", styles);
-				} else if (slave.porn.prestige === 2) {
-					makeSpan(c, "Porn slut.", styles);
-				} else if (slave.porn.prestige === 1) {
-					makeSpan(c, "Porn amateur.", styles);
-				}
-			}
+			helpers.makeMappedStyledSpan(c, data.long.pornPrestige, slave.porn.prestige);
 		}
 
 		/**
@@ -1073,7 +929,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_clothes(slave, c) {
-			makeSpan(c, helpers.getExactRating(App.Data.SlaveSummary.long.clothes, slave.clothes,  'Naked.'));
+			makeSpan(c, helpers.getExactRating(data.long.clothes, slave.clothes,  'Naked.'));
 		}
 
 		/**
@@ -1082,10 +938,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_collar(slave, c) {
-			const s = App.Data.SlaveSummary.long.accessory.collar[slave.collar];
-			if (s) {
-				makeSpan(c, s);
-			}
+			helpers.makeMappedSpan(c, data.long.accessory.collar, slave.collar);
 		}
 
 		/**
@@ -1094,10 +947,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_belly(slave, c) {
-			const s = App.Data.SlaveSummary.long.accessory.belly[slave.bellyAccessory];
-			if (s) {
-				makeSpan(c, s);
-			}
+			helpers.makeMappedSpan(c, data.long.accessory.belly, slave.bellyAccessory);
 		}
 
 		/**
@@ -1165,10 +1015,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 */
 		function long_vaginal_acc(slave, c) {
 			if (slave.vaginalAttachment !== "vibrator") {
-				const s = App.Data.SlaveSummary.long.accessory.vaginal[slave.vaginalAccessory];
-				if (s) {
-					makeSpan(c, s);
-				}
+				helpers.makeMappedSpan(c, data.long.accessory.vaginal, slave.vaginalAccessory);
 			}
 			if (slave.vaginalAttachment !== "none") {
 				switch (slave.vaginalAttachment) {
@@ -1214,97 +1061,14 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_fetish(slave, c) {
-			let descStr = "";
-			switch (slave.fetish) {
-				case "submissive":
-					if (slave.fetishStrength > 95) {
-						descStr = `Sub++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Sub+`;
-					} else {
-						descStr = `Sub`;
-					}
-					break;
-				case "cumslut":
-					if (slave.fetishStrength > 95) {
-						descStr = `Oral++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Oral+`;
-					} else {
-						descStr = `Oral`;
-					}
-					break;
-				case "humiliation":
-					if (slave.fetishStrength > 95) {
-						descStr = `Humil++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Humil+`;
-					} else {
-						descStr = `Humil`;
-					}
-					break;
-				case "buttslut":
-					if (slave.fetishStrength > 95) {
-						descStr = `Anal++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Anal+`;
-					} else {
-						descStr = `Anal`;
-					}
-					break;
-				case "boobs":
-					if (slave.fetishStrength > 95) {
-						descStr = `Boobs++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Boobs+`;
-					} else {
-						descStr = `Boobs`;
-					}
-					break;
-				case "sadist":
-					if (slave.fetishStrength > 95) {
-						descStr = `Sadist++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Sadist+`;
-					} else {
-						descStr = `Sadist`;
-					}
-					break;
-				case "masochist":
-					if (slave.fetishStrength > 95) {
-						descStr = `Pain++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Pain+`;
-					} else {
-						descStr = `Pain`;
-					}
-					break;
-				case "dom":
-					if (slave.fetishStrength > 95) {
-						descStr = `Dom++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Dom+`;
-					} else {
-						descStr = `Dom`;
-					}
-					break;
-				case "pregnancy":
-					if (slave.fetishStrength > 95) {
-						descStr = `Preg++`;
-					} else if (slave.fetishStrength > 60) {
-						descStr = `Preg+`;
-					} else {
-						descStr = `Preg`;
-					}
-					break;
-				default:
-					descStr = `Vanilla`;
-					break;
-			}
-			if (V.summaryStats) {
-				descStr += `[${slave.fetishStrength}]`;
+			function fetishStr(slave) {
+				const tbl = data.short.fetish[slave.fetish];
+				if (!tbl || typeof tbl === 'string') {
+					return tbl;
+				}
+				return helpers.getNumericRating(tbl, slave.fetishStrength);
 			}
-			makeSpan(c, descStr, "lightcoral");
+			makeSpan(c, fetishStr(slave), "lightcoral", true, slave.fetishStrength);
 		}
 
 		/**
@@ -1313,56 +1077,16 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_attraction(slave, c) {
-			if (slave.attrXY <= 5) {
-				makeSpan(c, "XY---", "red", false, slave.attrXY);
-			} else if (slave.attrXY <= 15) {
-				makeSpan(c, "XY--", "red", false, slave.attrXY);
-			} else if (slave.attrXY <= 35) {
-				makeSpan(c, "XY---", "red", false, slave.attrXY);
-			} else if (slave.attrXY <= 65) {
-				makeSpan(c, "XY", undefined, false, slave.attrXY);
-			} else if (slave.attrXY <= 85) {
-				makeSpan(c, "XY+", "green", false, slave.attrXY);
-			} else if (slave.attrXY <= 95) {
-				makeSpan(c, "XY++", "green", false, slave.attrXY);
-			} else if (slave.attrXX > 95) {
-				if (slave.energy <= 95) {
-					makeSpan(c, "Omni!", "green");
-				} else {
-					makeSpan(c, "Omni+Nympho!!", "green");
-				}
-			} else {
-				makeSpan(c, "XY+++", "green", false, slave.attrXY);
-			}
-			if (slave.attrXX <= 5) {
-				makeSpan(c, "XX---", "red", false, slave.attrXX);
-			} else if (slave.attrXX <= 15) {
-				makeSpan(c, "XX--", "red", false, slave.attrXX);
-			} else if (slave.attrXX <= 35) {
-				makeSpan(c, "XX-", "red", false, slave.attrXX);
-			} else if (slave.attrXX <= 65) {
-				makeSpan(c, "XX", undefined, false, slave.attrXX);
-			} else if (slave.attrXX <= 85) {
-				makeSpan(c, "XX+", "green", false, slave.attrXX);
-			} else if (slave.attrXX <= 95) {
-				makeSpan(c, "XX++", "green", false, slave.attrXX);
-			} else if (slave.attrXY <= 95) {
-				makeSpan(c, "XX+++", "green", false, slave.attrXX);
-			}
-			if (slave.energy > 95) {
-				if ((slave.attrXY <= 95) || (slave.attrXX <= 95)) {
-					makeSpan(c, "Nympho!", "green");
-				}
-			} else if (slave.energy > 80) {
-				makeSpan(c, "SD++", "green", false, slave.energy);
-			} else if (slave.energy > 60) {
-				makeSpan(c, "SD+", "green", false, slave.energy);
-			} else if (slave.energy > 40) {
-				makeSpan(c, "SD", "green", false, slave.energy);
-			} else if (slave.energy > 20) {
-				makeSpan(c, "SD-", "red", false, slave.energy);
+			const sd = data.short.sexDrive;
+			// check for special cases first
+			if (slave.energy > 95 && slave.attrXX > 95 && slave.attrXY > 95) {
+				helpers.makeStyledSpan(c, sd.synergy.nymphomni);
+			} else if (slave.attrXX > 95 && slave.attrXY > 95) {
+				helpers.makeStyledSpan(c, sd.synergy.omni);
 			} else {
-				makeSpan(c, "SD--", "red", false, slave.energy);
+				helpers.makeRatedStyledSpan(c, sd.XY, slave.attrXY, 0, true);
+				helpers.makeRatedStyledSpan(c, sd.XX, slave.attrXX, 0, true);
+				helpers.makeRatedStyledSpan(c, sd.energy, slave.energy, 0, true);
 			}
 		}
 
@@ -1372,74 +1096,9 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_smart_fetish(slave, c) {
-			function settingStr() {
-				if (slave.fetishKnown === 1) {
-					if (slave.clitSetting === "off") {
-						return `SP-`;
-					} else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) {
-						return `SP:sub`;
-					} else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) {
-						return `SP:oral`;
-					} else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) {
-						return `SP:humil`;
-					} else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) {
-						return `SP:anal`;
-					} else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) {
-						return `SP:boobs`;
-					} else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) {
-						return `SP:sade`;
-					} else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) {
-						return `SP:pain`;
-					} else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) {
-						return `SP:dom`;
-					} else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) {
-						return `SP:preg`;
-					} else if (((slave.fetish !== "none") && (slave.clitSetting === "vanilla"))) {
-						return `SP:vanilla`;
-					} else if ((slave.energy <= 95) && (slave.clitSetting === "all")) {
-						return `SP:all`;
-					} else if ((slave.energy > 5) && (slave.clitSetting === "none")) {
-						return `SP:none`;
-					} else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) {
-						return `SP:monitoring`;
-					}
-				} else {
-					switch (slave.clitSetting) {
-						case "off":
-							return `SP-`;
-						case "submissive":
-							return `SP:sub`;
-						case "lesbian":
-							return `SP:les`;
-						case "oral":
-							return `SP:oral`;
-						case "humiliation":
-							return `SP:humil`;
-						case "anal":
-							return `SP:anal`;
-						case "boobs":
-							return `SP:boobs`;
-						case "sadist":
-							return `SP:sade`;
-						case "masochist":
-							return `SP:pain`;
-						case "dom":
-							return `SP:dom`;
-						case "pregnancy":
-							return `SP:pregnancy`;
-						case "vanilla":
-							return `SP:vanilla`;
-						case "all":
-							return `SP:all`;
-						case "none":
-							return `SP:none`;
-					}
-				}
-				return null;
-			}
-			const s = settingStr();
+			const s = smartFetishStr(slave, data.short.smartPiercing);
 			if (s) {
-				makeSpan(c, settingStr());
+				makeSpan(c, s);
 			}
 		}
 
@@ -1449,49 +1108,23 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function short_smart_attraction(slave, c) {
-			function settingStr() {
-				if (slave.attrKnown === 1) {
-					if (slave.clitSetting === "women") {
-						if (slave.attrXX < 95) {
-							return `SP:women`;
-						} else {
-							return `SP:monitoring`;
-						}
-					} else if (slave.clitSetting === "men") {
-						if (slave.attrXY < 95) {
-							return `SP:men`;
-						} else {
-							return `SP:monitoring`;
-						}
-					} else if (slave.clitSetting === "anti-women") {
-						if (slave.attrXX > 0) {
-							return `SP:anti-women`;
-						} else {
-							return `SP:monitoring`;
-						}
-					} else if (slave.clitSetting === "anti-men") {
-						if (slave.attrXY > 0) {
-							return `SP:anti-men`;
-						} else {
-							return `SP:monitoring`;
-						}
-					}
-				} else {
-					if (slave.clitSetting === "women") {
-						return `SP:women`;
-					} else if (slave.clitSetting === "men") {
-						return `SP:men`;
-					} else if (slave.clitSetting === "anti-women") {
-						return `SP:anti-women`;
-					} else if (slave.clitSetting === "anti-men") {
-						return `SP:anti-men`;
-					}
+			/*
+			if (slave.attrKnown === 1) {
+				if ((slave.attrXX < 100) && (slave.clitSetting === "women")) {
+					makeSpan(c, `SP: women.`);
+				} else if ((slave.attrXY < 100) && (slave.clitSetting === "men")) {
+					makeSpan(c, `SP: men.`);
 				}
-				return null;
-			}
-			const s = settingStr();
+			} else {
+				if (slave.clitSetting === "women") {
+					makeSpan(c, `SP: women.`);
+				} else if (slave.clitSetting === "men") {
+					makeSpan(c, `SP: men.`);
+				}
+			}*/
+			const s = smartAttractionStr(slave, data.short.smartPiercing);
 			if (s) {
-				makeSpan(c, settingStr());
+				makeSpan(c, s);
 			}
 		}
 
@@ -1537,85 +1170,14 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_fetish(slave, c) {
-			function fetishStr() {
-				switch (slave.fetish) {
-					case "submissive":
-						if (slave.fetishStrength > 95) {
-							return "Complete submissive";
-						} else if (slave.fetishStrength > 60) {
-							return "Submissive";
-						} else {
-							return "Submissive tendencies";
-						}
-					case "cumslut":
-						if (slave.fetishStrength > 95) {
-							return "Cumslut";
-						} else if (slave.fetishStrength > 60) {
-							return "Oral fixation";
-						} else {
-							return "Prefers oral";
-						}
-					case "humiliation":
-						if (slave.fetishStrength > 95) {
-							return "Humiliation slut";
-						} else if (slave.fetishStrength > 60) {
-							return "Exhibitionist";
-						} else {
-							return "Interest in humiliation";
-						}
-					case "buttslut":
-						if (slave.fetishStrength > 95) {
-							return "Buttslut";
-						} else if (slave.fetishStrength > 60) {
-							return "Anal fixation";
-						} else {
-							return "Prefers anal";
-						}
-					case "boobs":
-						if (slave.fetishStrength > 95) {
-							return "Boobslut";
-						} else if (slave.fetishStrength > 60) {
-							return "Breast fixation";
-						} else {
-							return "Loves boobs";
-						}
-					case "sadist":
-						if (slave.fetishStrength > 95) {
-							return "Complete sadist";
-						} else if (slave.fetishStrength > 60) {
-							return "Sadist";
-						} else {
-							return "Sadistic tendencies";
-						}
-					case "masochist":
-						if (slave.fetishStrength > 95) {
-							return "Complete masochist";
-						} else if (slave.fetishStrength > 60) {
-							return "Masochist";
-						} else {
-							return "Masochistic tendencies";
-						}
-					case "dom":
-						if (slave.fetishStrength > 95) {
-							return "Complete dom";
-						} else if (slave.fetishStrength > 60) {
-							return "Dominant";
-						} else {
-							return "Dominant tendencies";
-						}
-					case "pregnancy":
-						if (slave.fetishStrength > 95) {
-							return "Pregnancy fetish";
-						} else if (slave.fetishStrength > 60) {
-							return "Pregnancy kink";
-						} else {
-							return "Interest in impregnation";
-						}
-					default:
-						return "Sexually vanilla";
+			function fetishStr(slave) {
+				const tbl = data.long.fetish[slave.fetish];
+				if (!tbl || typeof tbl === 'string') {
+					return tbl;
 				}
+				return helpers.getNumericRating(tbl, slave.fetishStrength);
 			}
-			makeSpan(c, fetishStr(), "lightcoral", true, slave.fetishStrength);
+			makeSpan(c, fetishStr(slave), "lightcoral", true, slave.fetishStrength);
 		}
 
 		/**
@@ -1624,56 +1186,17 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_attraction(slave, c) {
-			if (slave.attrXY <= 5) {
-				makeSpan(c, "Disgusted by men", "red", true, slave.attrXY);
-			} else if (slave.attrXY <= 15) {
-				makeSpan(c, "Turned off by men", "red", true, slave.attrXY);
-			} else if (slave.attrXY <= 35) {
-				makeSpan(c, "Not attracted to men", "red", true, slave.attrXY);
-			} else if (slave.attrXY <= 65) {
-				makeSpan(c, "Indifferent to men", undefined, true, slave.attrXY);
-			} else if (slave.attrXY <= 85) {
-				makeSpan(c, "Attracted to men", "green", true, slave.attrXY);
-			} else if (slave.attrXY <= 95) {
-				makeSpan(c, "Aroused by men", "green", true, slave.attrXY);
-			} else if (slave.attrXX > 95) {
-				if (slave.energy <= 95) {
-					makeSpan(c, "Omnisexual!", "green");
-				} else {
-					makeSpan(c, "Omnisexual nymphomaniac!", "green");
-				}
-			} else {
-				makeSpan(c, "Passionate about men", "green", true, slave.attrXY);
-			}
-			if (slave.attrXX <= 5) {
-				makeSpan(c, "disgusted by women", "red", true, slave.attrXX);
-			} else if (slave.attrXX <= 15) {
-				makeSpan(c, "turned off by women", "red", true, slave.attrXX);
-			} else if (slave.attrXX <= 35) {
-				makeSpan(c, "not attracted to women", "red", true, slave.attrXX);
-			} else if (slave.attrXX <= 65) {
-				makeSpan(c, "indifferent to women", undefined, true, slave.attrXX);
-			} else if (slave.attrXX <= 85) {
-				makeSpan(c, "attracted to women", "green", true, slave.attrXX);
-			} else if (slave.attrXX <= 95) {
-				makeSpan(c, "aroused by women", "green", true, slave.attrXX);
-			} else if (slave.attrXY <= 95) {
-				makeSpan(c, "passionate about women", "green", true, slave.attrXX);
-			}
-			if (slave.energy > 95) {
-				if ((slave.attrXY <= 95) || (slave.attrXX <= 95)) {
-					makeSpan(c, "Nymphomaniac!", "green");
-				}
-			} else if (slave.energy > 80) {
-				makeSpan(c, "Powerful sex drive", "green", true, slave.energy);
-			} else if (slave.energy > 60) {
-				makeSpan(c, "Good sex drive", "green", true, slave.energy);
-			} else if (slave.energy > 40) {
-				makeSpan(c, "Average sex drive", "yellow", true, slave.energy);
-			} else if (slave.energy > 20) {
-				makeSpan(c, "Poor sex drive", "red", true, slave.energy);
+			const sd = data.long.sexDrive;
+
+			// check for special cases first
+			if (slave.energy > 95 && slave.attrXX > 95 && slave.attrXY > 95) {
+				helpers.makeStyledSpan(c, sd.synergy.nymphomni);
+			} else if (slave.attrXX > 95 && slave.attrXY > 95) {
+				helpers.makeStyledSpan(c, sd.synergy.omni);
 			} else {
-				makeSpan(c, "No sex drive", "red", true, slave.energy);
+				helpers.makeRatedStyledSpan(c, sd.XY, slave.attrXY, 0, true);
+				helpers.makeRatedStyledSpan(c, sd.XX, slave.attrXX, 0, true);
+				helpers.makeRatedStyledSpan(c, sd.energy, slave.energy, 0, true);
 			}
 		}
 
@@ -1683,70 +1206,7 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_smart_fetish(slave, c) {
-			function descStr() {
-				if (slave.fetishKnown === 1) {
-					if (slave.clitSetting === "off") {
-						return `SP off.`;
-					} else if (((slave.fetish !== "submissive") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "submissive")) {
-						return `SP: submissive.`;
-					} else if (((slave.fetish !== "cumslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "oral")) {
-						return `SP: oral.`;
-					} else if (((slave.fetish !== "humiliation") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "humiliation")) {
-						return `SP: humiliation.`;
-					} else if (((slave.fetish !== "buttslut") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "anal")) {
-						return `SP: anal.`;
-					} else if (((slave.fetish !== "boobs") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "boobs")) {
-						return `SP: breasts.`;
-					} else if (((slave.fetish !== "sadist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "sadist")) {
-						return `SP: sadism.`;
-					} else if (((slave.fetish !== "masochist") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "masochist")) {
-						return `SP: masochism.`;
-					} else if (((slave.fetish !== "dom") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "dom")) {
-						return `SP: dominance.`;
-					} else if (((slave.fetish !== "pregnancy") || (slave.fetishStrength <= 95)) && (slave.clitSetting === "pregnancy")) {
-						return `SP: pregnancy.`;
-					} else if ((slave.fetish !== "none") && (slave.clitSetting === "vanilla")) {
-						return `SP: vanilla.`;
-					} else if ((slave.energy <= 95) && (slave.clitSetting === "all")) {
-						return `SP: all.`;
-					} else if ((slave.energy > 5) && (slave.clitSetting === "none")) {
-						return `SP: none.`;
-					} else if (!["anti-men", "anti-women", "men", "women"].includes(slave.clitSetting)) {
-						return `SP: monitoring.`;
-					}
-				} else {
-					switch (slave.clitSetting) {
-						case "off":
-							return `SP off.`;
-						case "submissive":
-							return `SP: submissive.`;
-						case "oral":
-							return `SP: oral.`;
-						case "humiliation":
-							return `SP: humiliation.`;
-						case "anal":
-							return `SP: anal.`;
-						case "boobs":
-							return `SP: breasts.`;
-						case "sadist":
-							return `SP: sadism.`;
-						case "masochist":
-							return `SP: masochism.`;
-						case "dom":
-							return `SP: dominance.`;
-						case "pregnancy":
-							return `SP: pregnancy.`;
-						case "vanilla":
-							return `SP: vanilla.`;
-						case "all":
-							return `SP: all.`;
-						case "none":
-							return `SP: none.`;
-					}
-				}
-				return null;
-			}
-			const s = descStr();
+			const s = smartFetishStr(slave, data.long.smartPiercing);
 			if (s) {
 				makeSpan(c, s);
 			}
@@ -1758,18 +1218,9 @@ App.UI.SlaveSummaryImpl = function() {
 		 * @returns {void}
 		 */
 		function long_smart_attraction(slave, c) {
-			if (slave.attrKnown === 1) {
-				if ((slave.attrXX < 100) && (slave.clitSetting === "women")) {
-					makeSpan(c, `SP: women.`);
-				} else if ((slave.attrXY < 100) && (slave.clitSetting === "men")) {
-					makeSpan(c, `SP: men.`);
-				}
-			} else {
-				if (slave.clitSetting === "women") {
-					makeSpan(c, `SP: women.`);
-				} else if (slave.clitSetting === "men") {
-					makeSpan(c, `SP: men.`);
-				}
+			const s = smartAttractionStr(slave, data.long.smartPiercing);
+			if (s) {
+				makeSpan(c, s);
 			}
 		}
 
diff --git a/src/js/slaveSummaryWidgets.js b/src/js/slaveSummaryWidgets.js
index 8e9a75273c4..ad5e8a32fa9 100644
--- a/src/js/slaveSummaryWidgets.js
+++ b/src/js/slaveSummaryWidgets.js
@@ -117,7 +117,7 @@ App.UI.SlaveSummaryRenderers = function() {
 		 */
 		weight: function(slave, c) {
 			helpers.makeStyledSpan(c, helpers.getMultiNumericRating(data.short.body.weight,
-				[slave.weight + 100, helpers.FSPolicyFlag("HedonisticDecadence"), slave.hips + 2]), slave.weight, true);
+				[slave.weight + 100, helpers.FSData.policy.HedonisticDecadence.active, slave.hips + 2]), slave.weight, true);
 		},
 
 		/**
@@ -424,7 +424,7 @@ App.UI.SlaveSummaryRenderers = function() {
 		 */
 		weight: function(slave, c) {
 			helpers.makeStyledSpan(c, helpers.getMultiNumericRating(data.long.body.weight,
-				[slave.weight + 100, helpers.FSPolicyFlag("HedonisticDecadence"), slave.hips + 2]), slave.weight, true);
+				[slave.weight + 100, helpers.FSData.policy.HedonisticDecadence.active, slave.hips + 2]), slave.weight, true);
 		},
 
 		/**
@@ -829,8 +829,6 @@ App.UI.SlaveSummary = function() {
 		relations: emptyRenderer
 	};
 
-	let delegatesAreValid = false;
-
 	/**
 	 * @returns {App.UI.SlaveSummary.State}
 	 */
@@ -864,25 +862,39 @@ App.UI.SlaveSummary = function() {
 	}
 
 	function initDelegates(settingsObj) {
-		settingsObj = settingsObj || V.UI.slaveSummary;
-		/** @type {App.UI.SlaveSummary.AbbreviationState} */
-		const abbrSettings = settingsObj.abbreviation;
-		for (const setting in abbrSettings) {
-			delegates[setting] = delegateForSetting(setting, abbrSettings[setting]);
-		}
-		delegates.weight = delegateForSetting("weight", abbrSettings.diet);
-		delegates.skin = delegateForSetting("skin", abbrSettings.physicals);
-		delegates.relations = delegateForSetting("relations", abbrSettings.mental);
-		// special settings
-		if (!V.seeRace) {
-			delegates.race = emptyRenderer;
+		try {
+			settingsObj = settingsObj || V.UI.slaveSummary;
+			/** @type {App.UI.SlaveSummary.AbbreviationState} */
+			const abbrSettings = settingsObj.abbreviation;
+			for (const setting in abbrSettings) {
+				delegates[setting] = delegateForSetting(setting, abbrSettings[setting]);
+			}
+			delegates.weight = delegateForSetting("weight", abbrSettings.diet);
+			delegates.skin = delegateForSetting("skin", abbrSettings.physicals);
+			delegates.relations = delegateForSetting("relations", abbrSettings.mental);
+			// special settings
+			if (!V.seeRace) {
+				delegates.race = emptyRenderer;
+			}
+		} catch (ex){
+			console.error(ex);
 		}
 	}
 
 	function settingsChanged(newState) {
-		const newStateIsOK = newState && newState.hasOwnProperty("UI") && newState.UI.hasOwnProperty("slaveSummary");
-		const settingsObj = newStateIsOK ? newState.UI.slaveSummary : V.UI.slaveSummary;
-		initDelegates(settingsObj);
+		try {
+			const newStateIsOK = newState && newState.hasOwnProperty("UI") && newState.UI.hasOwnProperty("slaveSummary");
+			const settingsObj = newStateIsOK ? newState.UI.slaveSummary : V.UI.slaveSummary;
+
+			initDelegates(settingsObj);
+			App.UI.SlaveSummaryImpl.helpers.syncFSData(newState ? newState.arcologies[0] : V.arcologies[0]);
+		} catch (ex) {
+			console.error(ex);
+		}
+	}
+
+	function societyChanged(arcology) {
+		App.UI.SlaveSummaryImpl.helpers.syncFSData(arcology);
 	}
 
 	/**
@@ -989,7 +1001,7 @@ App.UI.SlaveSummary = function() {
 	return {
 		makeNewState: makeNewState,
 		settingsChanged: settingsChanged,
-		empty: function() { },
+		societyChanged: societyChanged,
 		render: render,
 		displayOptionsFragment: displayOptionsFragment
 	};
diff --git a/src/uncategorized/fsDevelopments.tw b/src/uncategorized/fsDevelopments.tw
index b32cd29bc31..32433250947 100644
--- a/src/uncategorized/fsDevelopments.tw
+++ b/src/uncategorized/fsDevelopments.tw
@@ -1297,3 +1297,5 @@
 		<</if>>
 	<</if>>
 <</if>>
+
+<<run App.UI.SlaveSummary.societyChanged()>>
diff --git a/src/uncategorized/policies.tw b/src/uncategorized/policies.tw
index 677cdced99d..9646d6669cf 100644
--- a/src/uncategorized/policies.tw
+++ b/src/uncategorized/policies.tw
@@ -7,6 +7,7 @@
 </style>
 
 <<set $nextButton = "Back">>
+<<set _passageSwitchHandler = App.EventHandlers.societyChanged>>
 <<if $arcologies[0].FSSupremacistLawME && $PC.race != $arcologies[0].FSSupremacistRace>>
 	<<set $nextLink = "Gameover", $gameover = "Idiot Ball 2 The Dumbassening">>
 <<elseif $arcologies[0].FSSubjugationistLawME && $PC.race == $arcologies[0].FSSubjugationistRace>>
-- 
GitLab