From 1764ffe39789e6dcb17e5c753d3aa81bad1b6492 Mon Sep 17 00:00:00 2001
From: Arkerthan <arkerthan@gmail.com>
Date: Wed, 5 May 2021 23:40:59 +0200
Subject: [PATCH] Add categories to encyclopedia entries

---
 src/004-base/encyclopediaMap.js               | 66 ++++++++++++++--
 src/gui/Encyclopedia/encyclopediaBody.js      | 75 +++++++++++++------
 .../Encyclopedia/encyclopediaRelatedLinks.tw  | 37 ++-------
 3 files changed, 119 insertions(+), 59 deletions(-)

diff --git a/src/004-base/encyclopediaMap.js b/src/004-base/encyclopediaMap.js
index 55a7f235620..38b23c44ead 100644
--- a/src/004-base/encyclopediaMap.js
+++ b/src/004-base/encyclopediaMap.js
@@ -1,5 +1,11 @@
+// Articles map
 /**
- * @type {Map<string, function():(HTMLElement|DocumentFragment)>}
+ * @typedef {object} article
+ * @property {function():(HTMLElement|DocumentFragment)} render
+ * @property {string} [category]
+ */
+/**
+ * @type {Map<string, article>}
  */
 App.Encyclopedia.articles = new Map();
 
@@ -8,12 +14,13 @@ App.Encyclopedia.articles = new Map();
  *
  * @param {string} key
  * @param {function():(HTMLElement|DocumentFragment)} article
+ * @param {string} [category]
  */
-App.Encyclopedia.addArticle = function(key, article) {
+App.Encyclopedia.addArticle = function(key, article, category) {
 	if (!App.Encyclopedia.articles.has(key)) {
-		App.Encyclopedia.articles.set(key, article);
+		App.Encyclopedia.articles.set(key, {render: article, category: category});
 	} else {
-		console.log(`Trying to overwrite encyclopedia article ${article}.`);
+		console.log(`Trying to overwrite encyclopedia article "${article}".`);
 	}
 };
 
@@ -25,14 +32,61 @@ App.Encyclopedia.addArticle = function(key, article) {
  */
 App.Encyclopedia.renderArticle = function(article) {
 	if (App.Encyclopedia.articles.has(article)) {
-		return App.Encyclopedia.get(article)();
+		return App.Encyclopedia.articles.get(article).render();
 	}
 
 	// TODO: turn this back on when completed.
-	// return `Encyclopedia entry "${article}" not found.`;
+	// return `Encyclopedia article "${article}" not found.`;
 	return null;
 };
 
+// Categories map
+/**
+ * @type {Map<string, function():(HTMLElement|DocumentFragment)>}
+ */
+App.Encyclopedia.categories = new Map();
+
+/**
+ * Adds an article if it does not exist yet.
+ *
+ * @param {string} key
+ * @param {function():(HTMLElement|DocumentFragment)} category
+ */
+App.Encyclopedia.addCategory = function(key, category) {
+	if (!App.Encyclopedia.categories.has(key)) {
+		App.Encyclopedia.categories.set(key, category);
+	} else {
+		console.log(`Trying to overwrite encyclopedia category "${category}".`);
+	}
+};
+
+/**
+ * Renders the specified article.
+ *
+ * @param {string} article
+ * @returns {string|HTMLElement|DocumentFragment}
+ */
+App.Encyclopedia.renderCategory = function(article) {
+	if (!App.Encyclopedia.articles.has(article)) {
+		// TODO: turn this back on when completed.
+		// return `Encyclopedia article "${article}" not found.`;
+		return null;
+	}
+
+	const category = App.Encyclopedia.articles.get(article).category;
+	if (!category) {
+		// TODO: turn this back on when completed.
+		// return `Encyclopedia article "${article}" has no category.`;
+		return null;
+	}
+
+	if (!App.Encyclopedia.categories.has(category)) {
+		return `Encyclopedia category "${category}" not found.`;
+	}
+
+	return App.Encyclopedia.categories.get(category)();
+};
+
 // Utility functions
 App.Encyclopedia.topic = function(topic) {
 	return App.UI.DOM.makeElement("span", topic, ["encyclopedia", "topic"]);
diff --git a/src/gui/Encyclopedia/encyclopediaBody.js b/src/gui/Encyclopedia/encyclopediaBody.js
index 05efeb9edc5..ff8f91b4030 100644
--- a/src/gui/Encyclopedia/encyclopediaBody.js
+++ b/src/gui/Encyclopedia/encyclopediaBody.js
@@ -3,7 +3,7 @@ App.Encyclopedia.addArticle("Body", function() {
 	App.UI.DOM.appendNewElement("p", fragment, "Future room for lore text", "note");
 	App.UI.DOM.appendNewElement("div", fragment, "Choose a more particular entry below:");
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Waist", function() {
 	const fragment = new DocumentFragment();
@@ -13,7 +13,7 @@ App.Encyclopedia.addArticle("Waist", function() {
 	r.push(`contributes to beauty. Waists can be altered permanently by corsets over time, or quickly in the surgery. (wiki: needs more technical detail)`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Anuses", function() {
 	const fragment = new DocumentFragment();
@@ -34,7 +34,7 @@ App.Encyclopedia.addArticle("Anuses", function() {
 	));
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Areolae", function() {
 	const fragment = new DocumentFragment();
@@ -44,7 +44,7 @@ App.Encyclopedia.addArticle("Areolae", function() {
 	r.push(`can be altered in size or shape through surgery. (wiki: needs more technical detail)`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Breasts", function() {
 	const fragment = new DocumentFragment();
@@ -68,7 +68,7 @@ App.Encyclopedia.addArticle("Breasts", function() {
 	r.push(`will be grateful for).`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Clits", function() {
 	const fragment = new DocumentFragment();
@@ -79,7 +79,7 @@ App.Encyclopedia.addArticle("Clits", function() {
 	// TODO: how are clits tied to dicks, vaginas, and hormones?
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Dicks", function() {
 	const fragment = new DocumentFragment();
@@ -101,7 +101,7 @@ App.Encyclopedia.addArticle("Dicks", function() {
 	fragment.append(App.Encyclopedia.Dialog.linkDOM("Clits?", "Clits"));
 	// TODO: how do dicks and clits relate, future coder?
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Ethnicity", function() {
 	const fragment = new DocumentFragment();
@@ -111,7 +111,7 @@ App.Encyclopedia.addArticle("Ethnicity", function() {
 	r.push(`affects random slave generation; the game produces bodies according to broad phenotypes. For example, black hair is almost universal among randomly generated Asian slaves. Its only other impact at game start is that white slaves enjoy a minor bonus to beauty, modeling the near-universal reach of western standards of beauty. Racially based future societies can apply ethnic bonuses or penalties to beauty, changing this landscape.`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Faces", function() {
 	const fragment = new DocumentFragment();
@@ -136,7 +136,7 @@ App.Encyclopedia.addArticle("Faces", function() {
 	r = [];
 	r.push(App.UI.DOM.makeElement("h2", `Facial shapes and beauty`));
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Height", function() {
 	const fragment = new DocumentFragment();
@@ -152,7 +152,7 @@ App.Encyclopedia.addArticle("Height", function() {
 	r.push(`though the game handles it in terms of ranges; beyond ${heightToEitherUnit(190)}, all very tall slaves will be treated almost identically. Height can be affected by surgery, and younger slaves can also see minor hormonal impacts on height. Unlike most other attributes, a slave's height cannot be changed more than one step by surgery.`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Hips", function() {
 	const fragment = new DocumentFragment();
@@ -163,7 +163,7 @@ App.Encyclopedia.addArticle("Hips", function() {
 	// TODO: how are clits tied to dicks, vaginas, and hormones?
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Lactation", function() {
 	const fragment = new DocumentFragment();
@@ -183,7 +183,7 @@ App.Encyclopedia.addArticle("Lactation", function() {
 	r.push(`enjoy a bonus to milk production. Natural lactation will dry up over time if not constantly maintained.`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Lips", function() {
 	const fragment = new DocumentFragment();
@@ -197,7 +197,7 @@ App.Encyclopedia.addArticle("Lips", function() {
 	));
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Musculature", function() {
 	const fragment = new DocumentFragment();
@@ -239,7 +239,7 @@ App.Encyclopedia.addArticle("Musculature", function() {
 	App.UI.DOM.appendNewElement("p", fragment, `Values >= 95 allows slaves with extremely hypertrophied balls (>70) to move around with effort.`);
 
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Nipples", function() {
 	const fragment = new DocumentFragment();
@@ -262,7 +262,7 @@ App.Encyclopedia.addArticle("Nipples", function() {
 
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Ovaries", function() {
 	const fragment = new DocumentFragment();
@@ -276,7 +276,7 @@ App.Encyclopedia.addArticle("Ovaries", function() {
 	));
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Pregnancy", function() {
 	return App.UI.DOM.combineNodes(
@@ -293,7 +293,7 @@ App.Encyclopedia.addArticle("Pregnancy", function() {
 		` from the fertile slave's individual menu. Otherwise, slaves with vaginas and ovaries who aren't wearing chastity belts or taking contraceptives, and have not had their tubes tied via surgery, will likely become pregnant if performing sexual jobs or if allowed to have sex with slaves with balls. Pregnancy has a number of minor physical effects and will induce `,
 		App.Encyclopedia.Dialog.linkDOM("lactation", "Lactation")
 	);
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Skin Distinctions", function() {
 	const fragment = new DocumentFragment();
@@ -326,7 +326,7 @@ App.Encyclopedia.addArticle("Skin Distinctions", function() {
 	r.push(`will improve a slave's attractiveness score if she is prestigious, and reduce it if she is not.`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Teeth", function() {
 	const fragment = new DocumentFragment();
@@ -346,7 +346,7 @@ App.Encyclopedia.addArticle("Teeth", function() {
 	}
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Testicles", function() {
 	const fragment = new DocumentFragment();
@@ -356,7 +356,7 @@ App.Encyclopedia.addArticle("Testicles", function() {
 	r.push(`are necessary for erection and provide a small amount of natural XY hormones. At game start, larger testicles reduce slave value, though this can be reduced or even reversed by some future society choices. Orchiectomy, available with extreme content enabled, will stop testicles' hormonal effects, producing a slave with no natural hormones. It also has significant mental effects.`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Vaginas", function() {
 	const fragment = new DocumentFragment();
@@ -380,7 +380,7 @@ App.Encyclopedia.addArticle("Vaginas", function() {
 	fragment.append(App.Encyclopedia.Dialog.linkDOM("Clit?", "Clits"));
 
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Weight", function() {
 	const fragment = new DocumentFragment();
@@ -424,7 +424,7 @@ App.Encyclopedia.addArticle("Weight", function() {
 	r.push(` is -10 to 30, going either way negatively impacts them.`);
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Hormones (XX)", function() {
 	const fragment = new DocumentFragment();
@@ -471,7 +471,7 @@ App.Encyclopedia.addArticle("Hormones (XX)", function() {
 
 	App.Events.addParagraph(fragment, r);
 	return fragment;
-});
+}, "body");
 
 App.Encyclopedia.addArticle("Hormones (XY)", function() {
 	const fragment = new DocumentFragment();
@@ -512,4 +512,33 @@ App.Encyclopedia.addArticle("Hormones (XY)", function() {
 
 	App.Events.addParagraph(fragment, r);
 	return fragment;
+}, "body");
+
+App.Encyclopedia.addCategory("body", function() {
+	const links = [];
+	links.push(App.Encyclopedia.Dialog.linkDOM("Anuses", "Anuses"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Areolae", "Areolae"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Breasts", "Breasts"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Butts", "Butts"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Clits", "Clits"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Dicks", "Dicks"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Ethnicity", "Ethnicity"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Faces", "Faces"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Height", "Height"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Hips", "Hips"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Lactation", "Lactation"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Lips", "Lips"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Musculature", "Musculature"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Nipples", "Nipples"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Ovaries", "Ovaries"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Pregnancy", "Pregnancy"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Skin Distinctions", "Skin Distinctions"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Teeth", "Teeth"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Testicles", "Testicles"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Vaginas", "Vaginas"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Waist", "Waist"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("Weight", "Weight"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("XX", "Hormones (XX)"));
+	links.push(App.Encyclopedia.Dialog.linkDOM("XY", "Hormones (XY)"));
+	return App.UI.DOM.generateLinksStrip(links);
 });
diff --git a/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw b/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw
index 48bf1a4d93a..1f3354bc0d0 100644
--- a/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw
+++ b/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw
@@ -5,6 +5,12 @@
 	<br><h3>Related Links</h3>
 <</if>>
 
+
+<<set _pass = App.Encyclopedia.renderCategory($encyclopedia)>>
+<<if _pass>>
+	<<includeDOM _pass>>
+<<else>>
+
 <<switch $encyclopedia>>
 
 /**********
@@ -105,36 +111,6 @@ SLAVE ASSIGNMENTS (COMMON):
 	| <<= App.Encyclopedia.Dialog.linkSC("Servitude, Sexual", "Sexual Servitude")>>
 	| <<= App.Encyclopedia.Dialog.linkSC("Servitude", "Servitude")>>
 	| <<= App.Encyclopedia.Dialog.linkSC("Whoring", "Whoring")>>
-
-/**********
-SLAVE BODY:
-**********/
-<<case "Anuses" "Areolae" "Body" "Breasts" "Butts" "Clits" "Dicks" "Ethnicity" "Faces" "Height" "Hips" "Lactation" "Lips" "Musculature" "Nipples" "Ovaries" "Skin Distinctions" "Teeth" "Testicles" "Vaginas" "Waist" "Weight" "Hormones (XX)" "Hormones (XY)">>
-	<<= App.Encyclopedia.Dialog.linkSC("Anuses", "Anuses")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Areolae", "Areolae")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Breasts", "Breasts")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Butts", "Butts")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Clits", "Clits")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Dicks", "Dicks")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Ethnicity", "Ethnicity")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Faces", "Faces")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Height", "Height")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Hips", "Hips")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Lactation", "Lactation")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Lips", "Lips")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Musculature", "Musculature")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Nipples", "Nipples")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Ovaries", "Ovaries")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Pregnancy", "Pregnancy")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Skin Distinctions", "Skin Distinctions")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Teeth", "Teeth")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Testicles", "Testicles")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Vaginas", "Vaginas")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Waist", "Waist")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("Weight", "Weight")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("XX", "Hormones (XX)")>>
-	| <<= App.Encyclopedia.Dialog.linkSC("XY", "Hormones (XY)")>>
-
 /**********
 SLAVE SKILLS
 **********/
@@ -466,3 +442,4 @@ MODS
 	| <<= App.Encyclopedia.Dialog.linkSC("Bioengineering", "Bioengineering")>>
 
 <</switch>>
+<</if>>
-- 
GitLab