@optolith/entity-descriptions 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/lib/creator.d.ts +32 -0
  3. package/lib/creator.js +72 -0
  4. package/lib/entities/activatable.d.ts +52 -0
  5. package/lib/entities/activatable.js +609 -0
  6. package/lib/entities/alternativeRule.d.ts +7 -0
  7. package/lib/entities/alternativeRule.js +21 -0
  8. package/lib/entities/attribute.d.ts +6 -0
  9. package/lib/entities/attribute.js +15 -0
  10. package/lib/entities/combatTechnique.d.ts +5 -7
  11. package/lib/entities/combatTechnique.js +34 -24
  12. package/lib/entities/condition.d.ts +12 -0
  13. package/lib/entities/condition.js +63 -0
  14. package/lib/entities/culture.d.ts +8 -0
  15. package/lib/entities/culture.js +309 -0
  16. package/lib/entities/curriculum.d.ts +11 -0
  17. package/lib/entities/curriculum.js +266 -0
  18. package/lib/entities/derivedCharacteristic.d.ts +9 -0
  19. package/lib/entities/derivedCharacteristic.js +91 -0
  20. package/lib/entities/disease.d.ts +9 -0
  21. package/lib/entities/disease.js +88 -0
  22. package/lib/entities/elixir.d.ts +10 -0
  23. package/lib/entities/elixir.js +76 -0
  24. package/lib/entities/equipment.d.ts +24 -0
  25. package/lib/entities/equipment.js +613 -0
  26. package/lib/entities/equipmentPackage.d.ts +8 -0
  27. package/lib/entities/equipmentPackage.js +301 -0
  28. package/lib/entities/experienceLevel.d.ts +3 -2
  29. package/lib/entities/experienceLevel.js +33 -28
  30. package/lib/entities/focusRule.d.ts +3 -4
  31. package/lib/entities/focusRule.js +13 -5
  32. package/lib/entities/influence.d.ts +7 -0
  33. package/lib/entities/influence.js +35 -0
  34. package/lib/entities/liturgicalChant.d.ts +10 -23
  35. package/lib/entities/liturgicalChant.js +169 -131
  36. package/lib/entities/optionalRule.d.ts +3 -2
  37. package/lib/entities/optionalRule.js +4 -3
  38. package/lib/entities/partial/activatableNameChunks.d.ts +58 -0
  39. package/lib/entities/partial/activatableNameChunks.js +356 -0
  40. package/lib/entities/partial/adventurePointsValue.d.ts +9 -0
  41. package/lib/entities/partial/adventurePointsValue.js +243 -0
  42. package/lib/entities/partial/animalTypes.d.ts +11 -0
  43. package/lib/entities/partial/animalTypes.js +13 -0
  44. package/lib/entities/partial/commonnessRatedAdvantagesAndDisadvantages.d.ts +16 -0
  45. package/lib/entities/partial/commonnessRatedAdvantagesAndDisadvantages.js +40 -0
  46. package/lib/entities/partial/dice.d.ts +10 -0
  47. package/lib/entities/partial/dice.js +13 -0
  48. package/lib/entities/partial/herbary.d.ts +28 -0
  49. package/lib/entities/partial/herbary.js +65 -0
  50. package/lib/entities/partial/map.d.ts +49 -0
  51. package/lib/entities/partial/map.js +43 -0
  52. package/lib/entities/partial/mathOperation.d.ts +36 -0
  53. package/lib/entities/partial/mathOperation.js +107 -0
  54. package/lib/entities/partial/prerequisites/displayOption.d.ts +7 -0
  55. package/lib/entities/partial/prerequisites/displayOption.js +19 -0
  56. package/lib/entities/partial/prerequisites/index.d.ts +67 -0
  57. package/lib/entities/partial/prerequisites/index.js +189 -0
  58. package/lib/entities/partial/prerequisites/part.d.ts +26 -0
  59. package/lib/entities/partial/prerequisites/part.js +88 -0
  60. package/lib/entities/partial/prerequisites/prerequisiteGroups.d.ts +65 -0
  61. package/lib/entities/partial/prerequisites/prerequisiteGroups.js +269 -0
  62. package/lib/entities/partial/prerequisites/single/activatable.d.ts +18 -0
  63. package/lib/entities/partial/prerequisites/single/activatable.js +40 -0
  64. package/lib/entities/partial/prerequisites/single/animistPower.d.ts +8 -0
  65. package/lib/entities/partial/prerequisites/single/animistPower.js +23 -0
  66. package/lib/entities/partial/prerequisites/single/blessedTradition.d.ts +7 -0
  67. package/lib/entities/partial/prerequisites/single/blessedTradition.js +32 -0
  68. package/lib/entities/partial/prerequisites/single/commonSuggestedByRCP.d.ts +6 -0
  69. package/lib/entities/partial/prerequisites/single/commonSuggestedByRCP.js +19 -0
  70. package/lib/entities/partial/prerequisites/single/culture.d.ts +8 -0
  71. package/lib/entities/partial/prerequisites/single/culture.js +20 -0
  72. package/lib/entities/partial/prerequisites/single/enhancement.d.ts +8 -0
  73. package/lib/entities/partial/prerequisites/single/enhancement.js +41 -0
  74. package/lib/entities/partial/prerequisites/single/influence.d.ts +8 -0
  75. package/lib/entities/partial/prerequisites/single/influence.js +17 -0
  76. package/lib/entities/partial/prerequisites/single/magicalTradition.d.ts +7 -0
  77. package/lib/entities/partial/prerequisites/single/magicalTradition.js +27 -0
  78. package/lib/entities/partial/prerequisites/single/noOtherAncestorBloodAdvantage.d.ts +6 -0
  79. package/lib/entities/partial/prerequisites/single/noOtherAncestorBloodAdvantage.js +8 -0
  80. package/lib/entities/partial/prerequisites/single/pact.d.ts +8 -0
  81. package/lib/entities/partial/prerequisites/single/pact.js +30 -0
  82. package/lib/entities/partial/prerequisites/single/personalityTrait.d.ts +8 -0
  83. package/lib/entities/partial/prerequisites/single/personalityTrait.js +28 -0
  84. package/lib/entities/partial/prerequisites/single/primaryAttribute.d.ts +7 -0
  85. package/lib/entities/partial/prerequisites/single/primaryAttribute.js +15 -0
  86. package/lib/entities/partial/prerequisites/single/publication.d.ts +8 -0
  87. package/lib/entities/partial/prerequisites/single/publication.js +19 -0
  88. package/lib/entities/partial/prerequisites/single/race.d.ts +8 -0
  89. package/lib/entities/partial/prerequisites/single/race.js +20 -0
  90. package/lib/entities/partial/prerequisites/single/rated.d.ts +8 -0
  91. package/lib/entities/partial/prerequisites/single/rated.js +41 -0
  92. package/lib/entities/partial/prerequisites/single/ratedMinimumNumber.d.ts +8 -0
  93. package/lib/entities/partial/prerequisites/single/ratedMinimumNumber.js +89 -0
  94. package/lib/entities/partial/prerequisites/single/ratedSum.d.ts +8 -0
  95. package/lib/entities/partial/prerequisites/single/ratedSum.js +21 -0
  96. package/lib/entities/partial/prerequisites/single/rule.d.ts +7 -0
  97. package/lib/entities/partial/prerequisites/single/rule.js +4 -0
  98. package/lib/entities/partial/prerequisites/single/sex.d.ts +7 -0
  99. package/lib/entities/partial/prerequisites/single/sex.js +19 -0
  100. package/lib/entities/partial/prerequisites/single/sexualCharacteristic.d.ts +7 -0
  101. package/lib/entities/partial/prerequisites/single/sexualCharacteristic.js +21 -0
  102. package/lib/entities/partial/prerequisites/single/socialStatus.d.ts +8 -0
  103. package/lib/entities/partial/prerequisites/single/socialStatus.js +21 -0
  104. package/lib/entities/partial/prerequisites/single/state.d.ts +8 -0
  105. package/lib/entities/partial/prerequisites/single/state.js +20 -0
  106. package/lib/entities/partial/prerequisites/single/text.d.ts +7 -0
  107. package/lib/entities/partial/prerequisites/single/text.js +9 -0
  108. package/lib/entities/partial/professions.d.ts +15 -0
  109. package/lib/entities/partial/professions.js +19 -0
  110. package/lib/entities/partial/rated/activatable/castingTime.d.ts +16 -7
  111. package/lib/entities/partial/rated/activatable/castingTime.js +35 -20
  112. package/lib/entities/partial/rated/activatable/checkResultBased.d.ts +18 -3
  113. package/lib/entities/partial/rated/activatable/checkResultBased.js +18 -10
  114. package/lib/entities/partial/rated/activatable/cost.d.ts +88 -8
  115. package/lib/entities/partial/rated/activatable/cost.js +183 -115
  116. package/lib/entities/partial/rated/activatable/duration.d.ts +36 -13
  117. package/lib/entities/partial/rated/activatable/duration.js +72 -61
  118. package/lib/entities/partial/rated/activatable/effect.d.ts +4 -4
  119. package/lib/entities/partial/rated/activatable/effect.js +32 -25
  120. package/lib/entities/partial/rated/activatable/index.d.ts +31 -27
  121. package/lib/entities/partial/rated/activatable/index.js +63 -28
  122. package/lib/entities/partial/rated/activatable/isMinimumMaximum.d.ts +5 -6
  123. package/lib/entities/partial/rated/activatable/isMinimumMaximum.js +8 -5
  124. package/lib/entities/partial/rated/activatable/nonModifiableSuffix.d.ts +2 -4
  125. package/lib/entities/partial/rated/activatable/nonModifiableSuffix.js +7 -42
  126. package/lib/entities/partial/rated/activatable/range.d.ts +22 -14
  127. package/lib/entities/partial/rated/activatable/range.js +54 -54
  128. package/lib/entities/partial/rated/activatable/speed.d.ts +11 -2
  129. package/lib/entities/partial/rated/activatable/speed.js +14 -1
  130. package/lib/entities/partial/rated/activatable/targetCategory.d.ts +4 -5
  131. package/lib/entities/partial/rated/activatable/targetCategory.js +19 -24
  132. package/lib/entities/partial/rated/improvementCost.d.ts +16 -4
  133. package/lib/entities/partial/rated/improvementCost.js +63 -4
  134. package/lib/entities/partial/rated/skillCheck.d.ts +20 -17
  135. package/lib/entities/partial/rated/skillCheck.js +56 -54
  136. package/lib/entities/partial/reader.d.ts +266 -0
  137. package/lib/entities/partial/reader.js +175 -0
  138. package/lib/entities/partial/responsiveText.d.ts +10 -5
  139. package/lib/entities/partial/responsiveText.js +19 -3
  140. package/lib/entities/partial/units/energy.d.ts +5 -8
  141. package/lib/entities/partial/units/energy.js +5 -23
  142. package/lib/entities/partial/units/length.d.ts +20 -2
  143. package/lib/entities/partial/units/length.js +24 -5
  144. package/lib/entities/partial/units/timeSpan.d.ts +25 -4
  145. package/lib/entities/partial/units/timeSpan.js +27 -15
  146. package/lib/entities/partial/unknown.d.ts +5 -1
  147. package/lib/entities/partial/unknown.js +5 -1
  148. package/lib/entities/personalityTrait.d.ts +7 -0
  149. package/lib/entities/personalityTrait.js +56 -0
  150. package/lib/entities/poison.d.ts +12 -0
  151. package/lib/entities/poison.js +356 -0
  152. package/lib/entities/profession.d.ts +12 -0
  153. package/lib/entities/profession.js +585 -0
  154. package/lib/entities/race.d.ts +9 -0
  155. package/lib/entities/race.js +146 -0
  156. package/lib/entities/sexPractice.d.ts +6 -0
  157. package/lib/entities/sexPractice.js +33 -0
  158. package/lib/entities/skill.d.ts +9 -9
  159. package/lib/entities/skill.js +124 -91
  160. package/lib/entities/spell.d.ts +83 -26
  161. package/lib/entities/spell.js +835 -147
  162. package/lib/entities/state.d.ts +6 -0
  163. package/lib/entities/state.js +17 -0
  164. package/lib/helpers/enums.d.ts +11 -0
  165. package/lib/helpers/enums.js +6 -0
  166. package/lib/helpers/getTypes.d.ts +12 -482
  167. package/lib/helpers/getTypes.js +1 -0
  168. package/lib/helpers/identifiers.d.ts +314 -0
  169. package/lib/helpers/identifiers.js +333 -0
  170. package/lib/helpers/locale.d.ts +21 -2
  171. package/lib/helpers/translate.d.ts +47 -5
  172. package/lib/helpers/translate.js +13 -6
  173. package/lib/index.d.ts +848 -21
  174. package/lib/index.js +182 -17
  175. package/lib/references/index.d.ts +6 -3
  176. package/lib/references/index.js +25 -33
  177. package/lib/references/page.d.ts +1 -1
  178. package/lib/references/page.js +14 -14
  179. package/lib/references/pageRange.d.ts +1 -5
  180. package/lib/references/pageRange.js +7 -16
  181. package/lib/tsconfig.tsbuildinfo +1 -0
  182. package/package.json +30 -10
  183. package/.prettierrc.yml +0 -1
  184. package/lib/entities/partial/rated/activatable/entity.d.ts +0 -11
  185. package/lib/entities/partial/rated/activatable/entity.js +0 -12
  186. package/lib/references/occurrence.d.ts +0 -4
  187. package/lib/references/occurrence.js +0 -3
@@ -1,15 +1,13 @@
1
- import { CloseCombatTechnique } from "optolith-database-schema/types/CombatTechnique_Close";
2
- import { RangedCombatTechnique } from "optolith-database-schema/types/CombatTechnique_Ranged";
3
- import { GetById } from "../helpers/getTypes.js";
1
+ import type { GetInstanceById } from "../helpers/getTypes.js";
4
2
  /**
5
3
  * Get a JSON representation of the rules text for a close combat technique.
6
4
  */
7
- export declare const getCloseCombatTechniqueEntityDescription: import("../index.js").EntityDescriptionCreator<CloseCombatTechnique | undefined, {
8
- getAttributeById: GetById.Static.Attribute;
5
+ export declare const getCloseCombatTechniqueEntityDescription: import("../creator.js").EntityDescriptionCreator<"CloseCombatTechnique", {
6
+ getInstanceById: GetInstanceById<"Publication" | "Attribute">;
9
7
  }, import("../index.js").EntityDescription>;
10
8
  /**
11
9
  * Get a JSON representation of the rules text for a ranged combat technique.
12
10
  */
13
- export declare const getRangedCombatTechniqueEntityDescription: import("../index.js").EntityDescriptionCreator<RangedCombatTechnique | undefined, {
14
- getAttributeById: GetById.Static.Attribute;
11
+ export declare const getRangedCombatTechniqueEntityDescription: import("../creator.js").EntityDescriptionCreator<"RangedCombatTechnique", {
12
+ getInstanceById: GetInstanceById<"Publication" | "Attribute">;
15
13
  }, import("../index.js").EntityDescription>;
@@ -1,10 +1,10 @@
1
1
  import { mapNullable } from "@optolith/helpers/nullable";
2
- import { createEntityDescriptionCreator } from "../index.js";
3
- import { createImprovementCost } from "./partial/rated/improvementCost.js";
2
+ import { createEntityDescriptionCreator } from "../creator.js";
3
+ import { renderImprovementCost } from "./partial/rated/improvementCost.js";
4
4
  /**
5
5
  * Get a JSON representation of the rules text for a close combat technique.
6
6
  */
7
- export const getCloseCombatTechniqueEntityDescription = createEntityDescriptionCreator(({ getAttributeById }, { translate, translateMap }, entry) => {
7
+ export const getCloseCombatTechniqueEntityDescription = createEntityDescriptionCreator(({ getInstanceById }, { translate, translateMap }, { content: entry }) => {
8
8
  const translation = translateMap(entry.translations);
9
9
  if (translation === undefined) {
10
10
  return undefined;
@@ -13,26 +13,31 @@ export const getCloseCombatTechniqueEntityDescription = createEntityDescriptionC
13
13
  title: translation.name,
14
14
  className: "combat-technique close-combat-technique",
15
15
  body: [
16
- mapNullable(translation.special, (value) => ({
17
- label: translate("Special"),
18
- value,
19
- })),
20
16
  {
21
- label: translate("Primary Attribute"),
22
- value: entry.primary_attribute
23
- .map((attr) => translateMap(getAttributeById(attr.id.attribute)?.translations)
24
- ?.name)
25
- .join("/"),
17
+ type: "definitionList",
18
+ items: [
19
+ mapNullable(translation.special, value => ({
20
+ label: translate("Special"),
21
+ value,
22
+ })),
23
+ {
24
+ label: translate("Primary Attribute"),
25
+ value: entry.primary_attribute
26
+ .map(attrId => translateMap(getInstanceById("Attribute", attrId)?.translations)?.name)
27
+ .join("/"),
28
+ },
29
+ renderImprovementCost(entry.improvement_cost).run({ translate }),
30
+ ],
26
31
  },
27
- createImprovementCost(translate, entry.improvement_cost),
28
32
  ],
33
+ errata: translation.errata,
29
34
  references: entry.src,
30
35
  };
31
36
  });
32
37
  /**
33
38
  * Get a JSON representation of the rules text for a ranged combat technique.
34
39
  */
35
- export const getRangedCombatTechniqueEntityDescription = createEntityDescriptionCreator(({ getAttributeById }, { translate, translateMap }, entry) => {
40
+ export const getRangedCombatTechniqueEntityDescription = createEntityDescriptionCreator(({ getInstanceById }, { translate, translateMap }, { content: entry }) => {
36
41
  const translation = translateMap(entry.translations);
37
42
  if (translation === undefined) {
38
43
  return undefined;
@@ -41,19 +46,24 @@ export const getRangedCombatTechniqueEntityDescription = createEntityDescription
41
46
  title: translation.name,
42
47
  className: "combat-technique ranged-combat-technique",
43
48
  body: [
44
- mapNullable(translation.special, (value) => ({
45
- label: translate("Special"),
46
- value,
47
- })),
48
49
  {
49
- label: translate("Primary Attribute"),
50
- value: entry.primary_attribute
51
- .map((attr) => translateMap(getAttributeById(attr.id.attribute)?.translations)
52
- ?.name)
53
- .join("/"),
50
+ type: "definitionList",
51
+ items: [
52
+ mapNullable(translation.special, value => ({
53
+ label: translate("Special"),
54
+ value,
55
+ })),
56
+ {
57
+ label: translate("Primary Attribute"),
58
+ value: entry.primary_attribute
59
+ .map(attrId => translateMap(getInstanceById("Attribute", attrId)?.translations)?.name)
60
+ .join("/"),
61
+ },
62
+ renderImprovementCost(entry.improvement_cost).run({ translate }),
63
+ ],
54
64
  },
55
- createImprovementCost(translate, entry.improvement_cost),
56
65
  ],
66
+ errata: translation.errata,
57
67
  references: entry.src,
58
68
  };
59
69
  });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Get a JSON representation of the rules text for a condition.
3
+ */
4
+ export declare const getConditionEntityDescription: import("../creator.js").EntityDescriptionCreator<"Condition", {
5
+ getInstanceById: import("../helpers/getTypes.js").GetInstanceById<"Publication">;
6
+ }, import("../index.js").EntityDescription>;
7
+ /**
8
+ * Get a JSON representation of the rules text for a meta condition.
9
+ */
10
+ export declare const getMetaConditionEntityDescription: import("../creator.js").EntityDescriptionCreator<"MetaCondition", {
11
+ getInstanceById: import("../helpers/getTypes.js").GetInstanceById<"Publication">;
12
+ }, import("../index.js").EntityDescription>;
@@ -0,0 +1,63 @@
1
+ import { createEntityDescriptionCreator } from "../creator.js";
2
+ /**
3
+ * Get a JSON representation of the rules text for a condition.
4
+ */
5
+ export const getConditionEntityDescription = createEntityDescriptionCreator((_, { translate, translateMap }, { content: entry }) => {
6
+ const translation = translateMap(entry.translations);
7
+ if (translation === undefined) {
8
+ return undefined;
9
+ }
10
+ return {
11
+ title: translation.name,
12
+ className: "condition",
13
+ body: [
14
+ translation.rules === undefined
15
+ ? undefined
16
+ : { type: "plain", text: translation.rules },
17
+ {
18
+ type: "definitionList",
19
+ items: [
20
+ ...translation.effects.map((effect, index) => ({
21
+ label: translate("Level {$level}", {
22
+ level: index + 1,
23
+ }),
24
+ value: effect,
25
+ })),
26
+ ],
27
+ },
28
+ ],
29
+ errata: translation.errata,
30
+ references: entry.src,
31
+ };
32
+ });
33
+ /**
34
+ * Get a JSON representation of the rules text for a meta condition.
35
+ */
36
+ export const getMetaConditionEntityDescription = createEntityDescriptionCreator((_, { translate, translateMap }, { content: entry }) => {
37
+ const translation = translateMap(entry.translations);
38
+ if (translation === undefined) {
39
+ return undefined;
40
+ }
41
+ return {
42
+ title: translation.name,
43
+ className: "meta-condition",
44
+ body: [
45
+ translation.rules === undefined
46
+ ? undefined
47
+ : { type: "plain", text: translation.rules },
48
+ {
49
+ type: "definitionList",
50
+ items: [
51
+ ...translation.effects.map((effect, index) => ({
52
+ label: translate("Level {$level}", {
53
+ level: index + 1,
54
+ }),
55
+ value: effect,
56
+ })),
57
+ ],
58
+ },
59
+ ],
60
+ errata: translation.errata,
61
+ references: entry.src,
62
+ };
63
+ });
@@ -0,0 +1,8 @@
1
+ import type { GetAllChildInstancesForParent, GetInstanceById } from "../helpers/getTypes.js";
2
+ /**
3
+ * Get a JSON representation of the rules text for a culture.
4
+ */
5
+ export declare const getCultureEntityDescription: import("../creator.js").EntityDescriptionCreator<"Culture", {
6
+ getInstanceById: GetInstanceById<"Publication" | "Advantage" | "Disadvantage" | "Skill" | "Language" | "LanguageSpecialization" | "Script" | "SocialStatus" | "ProfessionVariant" | "MagicalTradition" | "BlessedTradition">;
7
+ getChildInstancesForInstanceId: GetAllChildInstancesForParent<"ProfessionVersion">;
8
+ }, import("../index.js").EntityDescription>;
@@ -0,0 +1,309 @@
1
+ import { allSame } from "@elyukai/utils/array/filters";
2
+ import { ensureNonEmpty, isNotEmpty } from "@elyukai/utils/array/nonEmpty";
3
+ import { sumWith } from "@elyukai/utils/array/reductions";
4
+ import { equal } from "@elyukai/utils/equality";
5
+ import { identity, on } from "@elyukai/utils/function";
6
+ import { isNotNullish, mapNullable } from "@elyukai/utils/nullable";
7
+ import { Reader } from "@elyukai/utils/reader";
8
+ import { sign } from "@elyukai/utils/string/number";
9
+ import { assertExhaustive } from "@elyukai/utils/typeSafety";
10
+ import { createEntityDescriptionCreator } from "../creator.js";
11
+ import { renderCommonnessRatedAdvantagesOrDisadvantages, renderValueWithPossibleTranslation, } from "./partial/commonnessRatedAdvantagesAndDisadvantages.js";
12
+ import { getProfessionName } from "./partial/professions.js";
13
+ import { parensIf } from "./partial/rated/activatable/parensIf.js";
14
+ import { calculateAdventurePointsFromImprovementCost } from "./partial/rated/improvementCost.js";
15
+ import { translateR, } from "./partial/reader.js";
16
+ import { MISSING_VALUE } from "./partial/unknown.js";
17
+ const renderListOperation = (operation, list) => {
18
+ switch (operation.kind) {
19
+ case "Intersection":
20
+ return Reader.of(list.join(", "));
21
+ case "Difference":
22
+ return translateR("all but {$excludedProfessions :list type=conjunction}", { excludedProfessions: list });
23
+ default:
24
+ return assertExhaustive(operation);
25
+ }
26
+ };
27
+ const renderCommonProfessionConstraints = (constraints, renderConstraint) => Reader.asks(({ localeCompare }) => Reader.sequence(constraints.constraints.map(renderConstraint)).thenW(constraintValues => renderListOperation(constraints.operation, constraintValues.filter(isNotNullish).toSorted(localeCompare)))).thenW(identity);
28
+ const renderCommonProfessionGroup = (label, constraints, renderConstraint) => translateR(label).thenW(translatedLabel => (constraints === undefined
29
+ ? Reader.of("—")
30
+ : renderCommonProfessionConstraints(constraints, renderConstraint)).map(translatedValue => ({
31
+ label: translatedLabel,
32
+ value: translatedValue,
33
+ })));
34
+ const renderRarity = (rarity) => {
35
+ if (rarity === undefined) {
36
+ return Reader.of(undefined);
37
+ }
38
+ switch (rarity.kind) {
39
+ case "Rare":
40
+ return translateR("rare");
41
+ case "VeryRare":
42
+ return translateR("very rare");
43
+ default:
44
+ return assertExhaustive(rarity);
45
+ }
46
+ };
47
+ const renderWeighted = (weightedVariants, getName) => {
48
+ if (weightedVariants === undefined) {
49
+ return Reader.of(undefined);
50
+ }
51
+ return Reader.asks(({ translate, localeCompare }) => {
52
+ const variants = ensureNonEmpty(weightedVariants.elements
53
+ .map(getName)
54
+ .filter(isNotNullish)
55
+ .toSorted(localeCompare));
56
+ if (variants === undefined) {
57
+ return undefined;
58
+ }
59
+ switch (weightedVariants.weight.kind) {
60
+ case "Mostly":
61
+ return translate("mostly {$variants :list type=conjunction}", {
62
+ variants,
63
+ });
64
+ case "Only":
65
+ return translate("only {$variants :list type=conjunction}", {
66
+ variants,
67
+ });
68
+ default:
69
+ return assertExhaustive(weightedVariants.weight);
70
+ }
71
+ });
72
+ };
73
+ const renderProfessionConstraint = (getChildInstancesForInstanceId, constraint) => Reader.asks(({ translateMap }) => getProfessionName(translateMap, getChildInstancesForInstanceId, constraint.id)).thenW(baseName => baseName === undefined
74
+ ? Reader.of(undefined)
75
+ : Reader.sequence([
76
+ renderRarity(constraint.rarity),
77
+ Reader.asks(({ translateMap, getInstanceById, }) => renderWeighted(constraint.weighted_variants, variantId => translateMap(getInstanceById("ProfessionVariant", variantId)
78
+ ?.translations)?.name.default)).thenW(identity),
79
+ ]).map(notes => baseName +
80
+ parensIf(ensureNonEmpty(notes.filter(isNotNullish))?.join("; "))));
81
+ const renderTraditionConstraint = (getChildInstancesForInstanceId, entity, constraint) => Reader.asks(({ translateMap, getInstanceById }) => {
82
+ const translation = translateMap(getInstanceById(entity, constraint.id)?.translations);
83
+ return translation?.nameOfBlessedOnes ?? translation?.name;
84
+ }).thenW(baseName => baseName === undefined
85
+ ? Reader.of(undefined)
86
+ : Reader.sequence([
87
+ renderRarity(constraint.rarity),
88
+ Reader.asks(({ translateMap }) => renderWeighted(constraint.weighted_professions, profId => getProfessionName(translateMap, getChildInstancesForInstanceId, profId))).thenW(identity),
89
+ ]).map(notes => baseName +
90
+ parensIf(ensureNonEmpty(notes.filter(isNotNullish))?.join("; "))));
91
+ const renderCommonProfessions = (getChildInstancesForInstanceId, commonProfessions) => {
92
+ switch (commonProfessions.kind) {
93
+ case "Plain":
94
+ return renderCommonProfessionConstraints(commonProfessions.Plain, profId => Reader.asks(({ translateMap }) => getProfessionName(translateMap, getChildInstancesForInstanceId, profId)));
95
+ case "Grouped":
96
+ return renderCommonProfessionGroup("Mundane Professions", commonProfessions.Grouped.mundane, constraint =>
97
+ // switch (constraint.kind) {
98
+ // case "Profession":
99
+ renderProfessionConstraint(getChildInstancesForInstanceId, constraint.Profession)).then(mundane => renderCommonProfessionGroup("Magic Professions", commonProfessions.Grouped.magic, constraint => {
100
+ switch (constraint.kind) {
101
+ case "Profession":
102
+ return renderProfessionConstraint(getChildInstancesForInstanceId, constraint.Profession);
103
+ case "Tradition":
104
+ return renderTraditionConstraint(getChildInstancesForInstanceId, "MagicalTradition", constraint.Tradition);
105
+ case "MagicDilettante":
106
+ return translateR("Magic Dilettante");
107
+ default:
108
+ return assertExhaustive(constraint);
109
+ }
110
+ }).then(magic => renderCommonProfessionGroup("Blessed Professions", commonProfessions.Grouped.blessed, constraint => renderTraditionConstraint(getChildInstancesForInstanceId, "BlessedTradition", constraint.Tradition)).map(blessed => [
111
+ {
112
+ type: "definitionList",
113
+ style: "nested",
114
+ items: [mundane, magic, blessed],
115
+ },
116
+ ])));
117
+ default:
118
+ return assertExhaustive(commonProfessions);
119
+ }
120
+ };
121
+ const renderCommonSkills = (items) => Reader.asks(({ translate, translateMap, getInstanceById, localeCompare }) => items === undefined || !isNotEmpty(items)
122
+ ? translate("none")
123
+ : items
124
+ .map(itemId => translateMap(getInstanceById("Skill", itemId)?.translations)
125
+ ?.name)
126
+ .filter(isNotNullish)
127
+ .toSorted(localeCompare)
128
+ .join(", "));
129
+ const renderCommonNames = (commonNames) => Reader.asks(({ localeCompare }) => {
130
+ const groups = [
131
+ ...(commonNames.first_name_groups ?? []),
132
+ ...(commonNames.last_name_groups ?? []),
133
+ ].map((group) => ({
134
+ label: group.label,
135
+ value: group.names
136
+ .map(name => name.name + parensIf(name.note))
137
+ .toSorted(localeCompare)
138
+ .join(", "),
139
+ }));
140
+ const specialRules = commonNames.naming_rules;
141
+ return [
142
+ mapNullable(ensureNonEmpty(groups), renderedGroups => ({
143
+ type: "definitionList",
144
+ style: "nested",
145
+ items: renderedGroups,
146
+ })),
147
+ mapNullable(specialRules, rules => ({
148
+ type: "plain",
149
+ text: rules,
150
+ })),
151
+ ];
152
+ });
153
+ const renderCulturalPackage = (items) => Reader.asks(({ translate, translateMap, getInstanceById, localeCompare }) => {
154
+ if (!isNotEmpty(items)) {
155
+ return { text: translate("none"), apValue: 0 };
156
+ }
157
+ const processedItems = items.map((item) => {
158
+ const instance = getInstanceById("Skill", item.id);
159
+ const instanceTranslation = translateMap(instance?.translations);
160
+ if (instance === undefined || instanceTranslation === undefined) {
161
+ return [MISSING_VALUE, 0];
162
+ }
163
+ return [
164
+ `${instanceTranslation.name ?? MISSING_VALUE} ${sign(item.points)}`,
165
+ calculateAdventurePointsFromImprovementCost(instance.improvement_cost, [1, item.points]),
166
+ ];
167
+ });
168
+ return {
169
+ text: processedItems
170
+ .map(([text]) => text)
171
+ .toSorted(localeCompare)
172
+ .join(", "),
173
+ apValue: sumWith(processedItems, ([, apValue]) => apValue),
174
+ };
175
+ });
176
+ /**
177
+ * Get a JSON representation of the rules text for a culture.
178
+ */
179
+ export const getCultureEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getChildInstancesForInstanceId }, { translate, translateMap, compare: localeCompare, join: localeJoin }, { content: entry }) => {
180
+ const translation = translateMap(entry.translations);
181
+ if (translation === undefined) {
182
+ return undefined;
183
+ }
184
+ const env = {
185
+ translate,
186
+ translateMap,
187
+ localeCompare,
188
+ getInstanceById,
189
+ };
190
+ const { text: culturePackageText, apValue: culturalPackageApValue } = renderCulturalPackage(entry.cultural_package).run(env);
191
+ return {
192
+ title: translation.name,
193
+ className: "culture",
194
+ body: [
195
+ {
196
+ type: "definitionList",
197
+ items: [
198
+ {
199
+ label: translate("Language"),
200
+ value: localeJoin(entry.language
201
+ .map(lang => {
202
+ const language = getInstanceById("Language", lang.id);
203
+ const languageTranslation = translateMap(language?.translations);
204
+ if (language === undefined ||
205
+ languageTranslation === undefined) {
206
+ return MISSING_VALUE;
207
+ }
208
+ return (languageTranslation.name +
209
+ parensIf([
210
+ translateMap(language.customSpecializations?.translations)?.description,
211
+ ...(lang.specializations?.map(specId => translateMap(getInstanceById("LanguageSpecialization", specId)?.translations)?.name) ?? []),
212
+ ]
213
+ .filter(isNotNullish)
214
+ .toSorted(localeCompare)
215
+ .join(", ")));
216
+ })
217
+ .toSorted(localeCompare), "disjunction"),
218
+ },
219
+ {
220
+ label: translate("Script"),
221
+ value: entry.script === undefined
222
+ ? translate("none")
223
+ : (() => {
224
+ const processedScripts = entry.script.map((scriptId) => {
225
+ const script = getInstanceById("Script", scriptId);
226
+ const scriptTranslation = translateMap(script?.translations);
227
+ if (script === undefined ||
228
+ scriptTranslation === undefined) {
229
+ return [MISSING_VALUE, 0];
230
+ }
231
+ return [scriptTranslation.name, script.ap_value ?? 0];
232
+ });
233
+ if (!isNotEmpty(processedScripts)) {
234
+ return translate("none");
235
+ }
236
+ if (allSame(processedScripts, on(([, apValue]) => apValue, equal))) {
237
+ return (localeJoin(processedScripts
238
+ .map(([name]) => name)
239
+ .toSorted(localeCompare), "disjunction") +
240
+ parensIf(translate("{$value} AP", {
241
+ value: processedScripts[0][1],
242
+ })));
243
+ }
244
+ else {
245
+ return localeJoin(processedScripts
246
+ .map(([name, apValue]) => name +
247
+ parensIf(translate("{$value} AP", {
248
+ value: apValue,
249
+ })))
250
+ .toSorted(localeCompare), "disjunction");
251
+ }
252
+ })(),
253
+ },
254
+ {
255
+ label: translate("Area Knowledge"),
256
+ value: translation.area_knowledge.description +
257
+ (translation.area_knowledge.examples === undefined
258
+ ? ""
259
+ : parensIf(translate("for example, {$examples}", {
260
+ examples: translation.area_knowledge.examples
261
+ .map(example => example.area)
262
+ .join(", "),
263
+ }))),
264
+ },
265
+ {
266
+ label: translate("Social Status"),
267
+ value: entry.social_status
268
+ .map(status => translateMap(getInstanceById("SocialStatus", status)?.translations)?.name ?? MISSING_VALUE)
269
+ .toSorted(localeCompare)
270
+ .join(", "),
271
+ },
272
+ {
273
+ label: translate("Common Professions"),
274
+ value: renderCommonProfessions(getChildInstancesForInstanceId, entry.common_professions).run(env),
275
+ },
276
+ renderValueWithPossibleTranslation("Common Advantages", entry.common_advantages, values => renderCommonnessRatedAdvantagesOrDisadvantages("Advantage", values).run(env), translation.common_advantages).run(env),
277
+ renderValueWithPossibleTranslation("Common Disadvantages", entry.common_disadvantages, values => renderCommonnessRatedAdvantagesOrDisadvantages("Disadvantage", values).run(env), translation.common_disadvantages).run(env),
278
+ renderValueWithPossibleTranslation("Uncommon Advantages", entry.uncommon_advantages, values => renderCommonnessRatedAdvantagesOrDisadvantages("Advantage", values).run(env), translation.uncommon_advantages).run(env),
279
+ renderValueWithPossibleTranslation("Uncommon Disadvantages", entry.uncommon_disadvantages, values => renderCommonnessRatedAdvantagesOrDisadvantages("Disadvantage", values).run(env), translation.uncommon_disadvantages).run(env),
280
+ {
281
+ label: translate("Common Skills"),
282
+ value: renderCommonSkills(entry.common_skills).run(env),
283
+ },
284
+ {
285
+ label: translate("Uncommon Skills"),
286
+ value: renderCommonSkills(entry.uncommon_skills).run(env),
287
+ },
288
+ {
289
+ label: translate("Common Names"),
290
+ value: renderCommonNames(translation.common_names).run(env),
291
+ },
292
+ ],
293
+ },
294
+ {
295
+ type: "labeled",
296
+ label: translate("Cultural Package {$cultureName}", {
297
+ cultureName: translation.name,
298
+ }) +
299
+ parensIf(translate("{$value} AP", { value: culturalPackageApValue })),
300
+ value: {
301
+ type: "plain",
302
+ text: culturePackageText,
303
+ },
304
+ },
305
+ ],
306
+ errata: translation.errata,
307
+ references: entry.src,
308
+ };
309
+ });
@@ -0,0 +1,11 @@
1
+ import type { GetAllChildInstancesForParent, GetAllInstances, GetInstanceById } from "../helpers/getTypes.js";
2
+ import type { IdMap } from "../index.js";
3
+ /**
4
+ * Get a JSON representation of the rules text for a curriculum.
5
+ */
6
+ export declare const getCurriculumEntityDescription: import("../creator.js").EntityDescriptionCreator<"Curriculum", {
7
+ getInstanceById: GetInstanceById<"Publication" | "Skill" | "CloseCombatTechnique" | "RangedCombatTechnique" | "Guideline" | "Spell" | "Ritual" | "MagicalTradition" | "Property" | "Element">;
8
+ getAllInstances: GetAllInstances<"Profession">;
9
+ getChildInstancesForInstanceId: GetAllChildInstancesForParent<"LessonPackage" | "ProfessionVersion" | "ProfessionPackage">;
10
+ idMap: IdMap;
11
+ }, import("../index.js").EntityDescription>;