refactor!: migrate codebase to TSONDB database

This commit is contained in:
Lukas Obermann
2026-02-09 14:13:33 +01:00
parent 27458ea3e1
commit e70288335e
71 changed files with 4227 additions and 5183 deletions
+1534 -1243
View File
File diff suppressed because it is too large Load Diff
+13 -12
View File
@@ -16,7 +16,7 @@
"build": "tsc -b",
"watch": "tsc -b -w",
"release": "commit-and-tag-version",
"test": "glob -c \"node --import tsx --test\" \"./test/**/*.ts\"",
"test": "node --import tsx --test",
"lint": "eslint"
},
"repository": {
@@ -30,20 +30,21 @@
},
"homepage": "https://github.com/Optolith/entity-descriptions#readme",
"dependencies": {
"@optolith/helpers": "^0.2.2"
"@optolith/helpers": "^0.2.2",
"messageformat": "^4.0.0"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/node": "^22.10.5",
"commit-and-tag-version": "^12.5.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jsdoc": "^50.6.1",
"glob": "^11.0.0",
"globals": "^15.14.0",
"optolith-database-schema": "^0.17.2",
"tsx": "^4.19.2",
"typescript": "^5.7.2",
"typescript-eslint": "^8.19.0"
"@types/node": "^25.2.1",
"commit-and-tag-version": "^12.6.1",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsdoc": "^62.5.4",
"glob": "^13.0.1",
"globals": "^17.3.0",
"optolith-database-schema": "^0.29.0",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.54.0"
},
"type": "module"
}
+6 -5
View File
@@ -1,5 +1,5 @@
import { filterNonNullable } from "@optolith/helpers/array"
import { GetById } from "./helpers/getTypes.js"
import type { GetInstanceById } from "./helpers/getTypes.js"
import { LocaleEnvironment } from "./helpers/locale.js"
import { EntityDescription, RawEntityDescription } from "./index.js"
import { getReferencesTranslation } from "./references/index.js"
@@ -12,12 +12,12 @@ export const createEntityDescriptionCreator =
<T, A extends object = object>(
fn: EntityDescriptionCreator<T, A, RawEntityDescription>,
): EntityDescriptionCreator<T | undefined, A> =>
(databaseAccessors, locale, entry) => {
(databaseAccessors, locale, entry, id) => {
if (entry === undefined) {
return undefined
}
const rawEntry = fn(databaseAccessors, locale, entry)
const rawEntry = fn(databaseAccessors, locale, entry, id)
if (rawEntry === undefined) {
return undefined
@@ -30,7 +30,7 @@ export const createEntityDescriptionCreator =
rawEntry.references === undefined
? undefined
: getReferencesTranslation(
databaseAccessors.getPublicationById,
databaseAccessors.getInstanceById,
locale,
rawEntry.references,
),
@@ -46,7 +46,8 @@ export type EntityDescriptionCreator<
A extends object = object,
R = EntityDescription,
> = (
databaseAccessors: A & { getPublicationById: GetById.Static.Publication },
databaseAccessors: A & { getInstanceById: GetInstanceById<"Publication"> },
locale: LocaleEnvironment,
entry: T,
id: string,
) => R | undefined
+13 -11
View File
@@ -1,8 +1,10 @@
import { mapNullable } from "@optolith/helpers/nullable"
import { CloseCombatTechnique } from "optolith-database-schema/types/CombatTechnique_Close"
import { RangedCombatTechnique } from "optolith-database-schema/types/CombatTechnique_Ranged"
import {
CloseCombatTechnique,
RangedCombatTechnique,
} from "optolith-database-schema/gen"
import { createEntityDescriptionCreator } from "../creator.js"
import { GetById } from "../helpers/getTypes.js"
import type { GetInstanceById } from "../helpers/getTypes.js"
import { createImprovementCost } from "./partial/rated/improvementCost.js"
/**
@@ -12,9 +14,9 @@ export const getCloseCombatTechniqueEntityDescription =
createEntityDescriptionCreator<
CloseCombatTechnique,
{
getAttributeById: GetById.Static.Attribute
getInstanceById: GetInstanceById<"Attribute">
}
>(({ getAttributeById }, { translate, translateMap }, entry) => {
>(({ getInstanceById }, { translate, translateMap }, entry) => {
const translation = translateMap(entry.translations)
if (translation === undefined) {
@@ -33,8 +35,8 @@ export const getCloseCombatTechniqueEntityDescription =
label: translate("Primary Attribute"),
value: entry.primary_attribute
.map(
attr =>
translateMap(getAttributeById(attr.id.attribute)?.translations)
attrId =>
translateMap(getInstanceById("Attribute", attrId)?.translations)
?.name,
)
.join("/"),
@@ -52,9 +54,9 @@ export const getRangedCombatTechniqueEntityDescription =
createEntityDescriptionCreator<
RangedCombatTechnique,
{
getAttributeById: GetById.Static.Attribute
getInstanceById: GetInstanceById<"Attribute">
}
>(({ getAttributeById }, { translate, translateMap }, entry) => {
>(({ getInstanceById }, { translate, translateMap }, entry) => {
const translation = translateMap(entry.translations)
if (translation === undefined) {
@@ -73,8 +75,8 @@ export const getRangedCombatTechniqueEntityDescription =
label: translate("Primary Attribute"),
value: entry.primary_attribute
.map(
attr =>
translateMap(getAttributeById(attr.id.attribute)?.translations)
attrId =>
translateMap(getInstanceById("Attribute", attrId)?.translations)
?.name,
)
.join("/"),
+1 -1
View File
@@ -1,4 +1,4 @@
import { ExperienceLevel } from "optolith-database-schema/types/ExperienceLevel"
import { ExperienceLevel } from "optolith-database-schema/gen"
import { createEntityDescriptionCreator } from "../creator.js"
/**
+9 -7
View File
@@ -1,15 +1,15 @@
import { romanize } from "@optolith/helpers/roman"
import { FocusRule } from "optolith-database-schema/types/rule/FocusRule"
import type { FocusRule } from "optolith-database-schema/gen"
import { createEntityDescriptionCreator } from "../creator.js"
import { GetById } from "../helpers/getTypes.js"
import type { GetInstanceById } from "../helpers/getTypes.js"
/**
* Get a JSON representation of the rules text for a focus rule.
*/
export const getFocusRuleEntityDescription = createEntityDescriptionCreator<
FocusRule,
{ getSubjectById: GetById.Static.Subject }
>(({ getSubjectById }, { translateMap }, entry) => {
{ getInstanceById: GetInstanceById<"Subject"> }
>(({ getInstanceById }, { translateMap }, entry) => {
const translation = translateMap(entry.translations)
if (translation === undefined) {
@@ -18,9 +18,11 @@ export const getFocusRuleEntityDescription = createEntityDescriptionCreator<
return {
title: `${translation.name} (${romanize(entry.level)})`,
subtitle: translateMap(
getSubjectById(entry.subject.id.subject)?.translations,
)?.name,
subtitle:
entry.subject !== undefined
? translateMap(getInstanceById("Subject", entry.subject)?.translations)
?.name
: undefined,
className: "focus-rule",
body: [{ value: translation.description }],
references: entry.src,
+157 -189
View File
@@ -1,14 +1,15 @@
import { Compare } from "@optolith/helpers/compare"
import { isNotNullish } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { Blessing } from "optolith-database-schema/types/Blessing"
import { Ceremony } from "optolith-database-schema/types/Ceremony"
import { DerivedCharacteristic } from "optolith-database-schema/types/DerivedCharacteristic"
import { LiturgicalChant } from "optolith-database-schema/types/LiturgicalChant"
import { SkillTradition } from "optolith-database-schema/types/_Blessed"
import { AspectReference } from "optolith-database-schema/types/_SimpleReferences"
import {
Blessing,
type Ceremony,
type DerivedCharacteristic,
type LiturgicalChant,
type LiturgyTradition,
} from "optolith-database-schema/gen"
import { createEntityDescriptionCreator } from "../creator.js"
import { GetById } from "../helpers/getTypes.js"
import type { GetInstanceById } from "../helpers/getTypes.js"
import { Translate, TranslateMap } from "../helpers/translate.js"
import { EntityDescriptionSection } from "../index.js"
import { getDurationTranslationForBlessing } from "./partial/rated/activatable/duration.js"
@@ -31,24 +32,23 @@ const getTextForTraditions = (
translate: Translate
translateMap: TranslateMap
localeCompare: Compare<string>
getBlessedTraditionById: GetById.Static.BlessedTradition
getAspectById: GetById.Static.Aspect
getInstanceById: GetInstanceById<"BlessedTradition" | "Aspect">
},
values: SkillTradition[],
values: LiturgyTradition[],
): EntityDescriptionSection => {
const getAspectName = (ref: AspectReference) =>
deps.translateMap(deps.getAspectById(ref.id.aspect)?.translations)?.name
const getAspectName = (aspectId: string) =>
deps.translateMap(deps.getInstanceById("Aspect", aspectId)?.translations)
?.name
const text = values
.map(trad => {
switch (trad.tag) {
switch (trad.kind) {
case "GeneralAspect":
return getAspectName(trad.general_aspect)
return getAspectName(trad.GeneralAspect)
case "Tradition": {
const traditionTranslation = deps.translateMap(
deps.getBlessedTraditionById(
trad.tradition.tradition.id.blessed_tradition,
)?.translations,
deps.getInstanceById("BlessedTradition", trad.Tradition.tradition)
?.translations,
)
const name =
traditionTranslation?.name_compressed ?? traditionTranslation?.name
@@ -58,7 +58,7 @@ const getTextForTraditions = (
}
const aspects =
trad.tradition.aspects
trad.Tradition.aspects
?.map(getAspectName)
.filter(isNotNullish)
.sort(deps.localeCompare) ?? []
@@ -88,9 +88,9 @@ const getTextForTraditions = (
export const getBlessingEntityDescription = createEntityDescriptionCreator<
Blessing,
{
getTargetCategoryById: GetById.Static.TargetCategory
getInstanceById: GetInstanceById<"TargetCategory">
}
>(({ getTargetCategoryById }, locale, entry) => {
>(({ getInstanceById }, locale, entry) => {
const { translate, translateMap } = locale
const translation = translateMap(entry.translations)
@@ -132,7 +132,7 @@ export const getBlessingEntityDescription = createEntityDescriptionCreator<
? `***${duration}*** (${translation.duration})`
: duration,
},
getTargetCategoryTranslation(getTargetCategoryById, locale, entry.target),
getTargetCategoryTranslation(getInstanceById, locale, entry.target),
],
references: entry.src,
}
@@ -145,153 +145,17 @@ export const getLiturgicalChantEntityDescription =
createEntityDescriptionCreator<
LiturgicalChant,
{
getAttributeById: GetById.Static.Attribute
getInstanceById: GetInstanceById<
| "Attribute"
| "SkillModificationLevel"
| "TargetCategory"
| "Aspect"
| "BlessedTradition"
>
getSpirit: () => DerivedCharacteristic | undefined
getToughness: () => DerivedCharacteristic | undefined
getSkillModificationLevelById: GetById.Static.SkillModificationLevel
getTargetCategoryById: GetById.Static.TargetCategory
getBlessedTraditionById: GetById.Static.BlessedTradition
getAspectById: GetById.Static.Aspect
}
>(
(
{
getAttributeById,
getSpirit,
getToughness,
getSkillModificationLevelById,
getTargetCategoryById,
getBlessedTraditionById,
getAspectById,
},
locale,
entry,
) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
if (translation === undefined) {
return undefined
}
const { castingTime, cost, range, duration } = (() => {
switch (entry.parameters.tag) {
case "OneTime":
return getFastOneTimePerformanceParametersTranslations(
getSkillModificationLevelById,
locale,
Entity.LiturgicalChant,
ResponsiveTextSize.Full,
entry.parameters.one_time,
)
case "Sustained":
return getFastSustainedPerformanceParametersTranslations(
getSkillModificationLevelById,
locale,
Entity.LiturgicalChant,
ResponsiveTextSize.Full,
entry.parameters.sustained,
)
default:
return assertExhaustive(entry.parameters)
}
})()
return {
title: translation.name,
className: "liturgical-chant",
body: [
getTextForCheck(
{ translate, translateMap, getAttributeById },
entry.check,
{
value: entry.check_penalty,
responsiveText: ResponsiveTextSize.Full,
getSpirit,
getToughness,
},
),
...getTextForEffect(locale, translation.effect),
{
label: translate("Liturgical Time"),
value:
castingTime !== translation.casting_time.full
? `***${castingTime}*** (${translation.casting_time.full})`
: castingTime,
},
{
label: translate("KP Cost"),
value:
cost !== translation.cost.full
? `***${cost}*** (${translation.cost.full})`
: cost,
},
{
label: translate("Range"),
value:
range !== translation.range.full
? `***${range}*** (${translation.range.full})`
: range,
},
{
label: translate("Duration"),
value:
duration !== translation.duration.full
? `***${duration}*** (${translation.duration.full})`
: duration,
},
getTargetCategoryTranslation(
getTargetCategoryById,
locale,
entry.target,
),
getTextForTraditions(
{
translate,
translateMap,
localeCompare,
getBlessedTraditionById,
getAspectById,
},
entry.traditions,
),
createImprovementCost(translate, entry.improvement_cost),
],
references: entry.src,
}
},
)
/**
* Get a JSON representation of the rules text for a ceremony.
*/
export const getCeremonyEntityDescription = createEntityDescriptionCreator<
Ceremony,
{
getAttributeById: GetById.Static.Attribute
getSpirit: () => DerivedCharacteristic | undefined
getToughness: () => DerivedCharacteristic | undefined
getSkillModificationLevelById: GetById.Static.SkillModificationLevel
getTargetCategoryById: GetById.Static.TargetCategory
getBlessedTraditionById: GetById.Static.BlessedTradition
getAspectById: GetById.Static.Aspect
}
>(
(
{
getAttributeById,
getSpirit,
getToughness,
getSkillModificationLevelById,
getTargetCategoryById,
getBlessedTraditionById,
getAspectById,
},
locale,
entry,
) => {
>(({ getInstanceById, getSpirit, getToughness }, locale, entry) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
@@ -300,23 +164,23 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator<
}
const { castingTime, cost, range, duration } = (() => {
switch (entry.parameters.tag) {
switch (entry.parameters.kind) {
case "OneTime":
return getSlowOneTimePerformanceParametersTranslations(
getSkillModificationLevelById,
return getFastOneTimePerformanceParametersTranslations(
getInstanceById,
locale,
Entity.Ritual,
Entity.LiturgicalChant,
ResponsiveTextSize.Full,
entry.parameters.one_time,
entry.parameters.OneTime,
)
case "Sustained":
return getSlowSustainedPerformanceParametersTranslations(
getSkillModificationLevelById,
return getFastSustainedPerformanceParametersTranslations(
getInstanceById,
locale,
Entity.Ceremony,
Entity.LiturgicalChant,
ResponsiveTextSize.Full,
entry.parameters.sustained,
entry.parameters.Sustained,
)
default:
@@ -326,10 +190,10 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator<
return {
title: translation.name,
className: "ceremony",
className: "liturgical-chant",
body: [
getTextForCheck(
{ translate, translateMap, getAttributeById },
{ translate, translateMap, getInstanceById },
entry.check,
{
value: entry.check_penalty,
@@ -340,8 +204,9 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator<
),
...getTextForEffect(locale, translation.effect),
{
label: translate("Ceremonial Time"),
label: translate("Liturgical Time"),
value:
translation.casting_time &&
castingTime !== translation.casting_time.full
? `***${castingTime}*** (${translation.casting_time.full})`
: castingTime,
@@ -349,36 +214,31 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator<
{
label: translate("KP Cost"),
value:
cost !== translation.cost.full
translation.cost && cost !== translation.cost.full
? `***${cost}*** (${translation.cost.full})`
: cost,
},
{
label: translate("Range"),
value:
range !== translation.range.full
translation.range && range !== translation.range.full
? `***${range}*** (${translation.range.full})`
: range,
},
{
label: translate("Duration"),
value:
duration !== translation.duration.full
translation.duration && duration !== translation.duration.full
? `***${duration}*** (${translation.duration.full})`
: duration,
},
getTargetCategoryTranslation(
getTargetCategoryById,
locale,
entry.target,
),
getTargetCategoryTranslation(getInstanceById, locale, entry.target),
getTextForTraditions(
{
translate,
translateMap,
localeCompare,
getBlessedTraditionById,
getAspectById,
getInstanceById,
},
entry.traditions,
),
@@ -386,5 +246,113 @@ export const getCeremonyEntityDescription = createEntityDescriptionCreator<
],
references: entry.src,
}
},
)
})
/**
* Get a JSON representation of the rules text for a ceremony.
*/
export const getCeremonyEntityDescription = createEntityDescriptionCreator<
Ceremony,
{
getInstanceById: GetInstanceById<
| "Attribute"
| "SkillModificationLevel"
| "TargetCategory"
| "Aspect"
| "BlessedTradition"
>
getSpirit: () => DerivedCharacteristic | undefined
getToughness: () => DerivedCharacteristic | undefined
}
>(({ getInstanceById, getSpirit, getToughness }, locale, entry) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
if (translation === undefined) {
return undefined
}
const { castingTime, cost, range, duration } = (() => {
switch (entry.parameters.kind) {
case "OneTime":
return getSlowOneTimePerformanceParametersTranslations(
getInstanceById,
locale,
Entity.Ritual,
ResponsiveTextSize.Full,
entry.parameters.OneTime,
)
case "Sustained":
return getSlowSustainedPerformanceParametersTranslations(
getInstanceById,
locale,
Entity.Ceremony,
ResponsiveTextSize.Full,
entry.parameters.Sustained,
)
default:
return assertExhaustive(entry.parameters)
}
})()
return {
title: translation.name,
className: "ceremony",
body: [
getTextForCheck(
{ translate, translateMap, getInstanceById },
entry.check,
{
value: entry.check_penalty,
responsiveText: ResponsiveTextSize.Full,
getSpirit,
getToughness,
},
),
...getTextForEffect(locale, translation.effect),
{
label: translate("Ceremonial Time"),
value:
translation.casting_time &&
castingTime !== translation.casting_time.full
? `***${castingTime}*** (${translation.casting_time.full})`
: castingTime,
},
{
label: translate("KP Cost"),
value:
translation.cost && cost !== translation.cost.full
? `***${cost}*** (${translation.cost.full})`
: cost,
},
{
label: translate("Range"),
value:
translation.range && range !== translation.range.full
? `***${range}*** (${translation.range.full})`
: range,
},
{
label: translate("Duration"),
value:
translation.duration && duration !== translation.duration.full
? `***${duration}*** (${translation.duration.full})`
: duration,
},
getTargetCategoryTranslation(getInstanceById, locale, entry.target),
getTextForTraditions(
{
translate,
translateMap,
localeCompare,
getInstanceById,
},
entry.traditions,
),
createImprovementCost(translate, entry.improvement_cost),
],
references: entry.src,
}
})
+1 -1
View File
@@ -1,4 +1,4 @@
import { OptionalRule } from "optolith-database-schema/types/rule/OptionalRule"
import { OptionalRule } from "optolith-database-schema/gen"
import { createEntityDescriptionCreator } from "../creator.js"
/**
+26 -22
View File
@@ -1,19 +1,19 @@
import { mapObject } from "@optolith/helpers/object"
import { romanize } from "@optolith/helpers/roman"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { ResolvedSelectOption } from "optolith-database-schema/cache/activatableSelectOptions"
import {
import type { ResolvedSelectOption } from "optolith-database-schema/cache"
import type {
ActivatableIdentifier,
SelectOptionIdentifier,
} from "optolith-database-schema/types/_IdentifierGroup"
import { LocaleMap } from "optolith-database-schema/types/_LocaleMap"
import { GetById } from "../../helpers/getTypes.js"
RequirableSelectOptionIdentifier,
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../helpers/getTypes.js"
import {
AdvantageIdentifier,
DisadvantageIdentifier,
KarmaSpecialAbilityIdentifier,
} from "../../helpers/identifiers.js"
import { LocaleEnvironment } from "../../helpers/locale.js"
import type { LocaleMap } from "../../helpers/translate.js"
import { MISSING_VALUE } from "./unknown.js"
/**
@@ -172,17 +172,17 @@ const combineBaseName = (
}
const getEntrySpecificFullName = (
getAspectById: GetById.Static.Aspect,
getInstanceById: GetInstanceById<"Aspect">,
locale: LocaleEnvironment,
id: ActivatableIdentifier,
base: ActivatableNameChunk,
level: number | undefined,
options: SelectOptionIdentifier[] | undefined,
options: RequirableSelectOptionIdentifier[] | undefined,
printedOptions: ActivatableNameComponents["options"],
): Pick<ActivatableNameComponents, "full" | "fullWithoutLevel"> | undefined => {
switch (id.tag) {
switch (id.kind) {
case "Advantage":
switch (id.advantage) {
switch (id.Advantage) {
case AdvantageIdentifier.HatredOf: {
const [firstOption, ...rest] = printedOptions
@@ -205,7 +205,7 @@ const getEntrySpecificFullName = (
return undefined
}
case "Disadvantage":
switch (id.disadvantage) {
switch (id.Disadvantage) {
case DisadvantageIdentifier.PersonalityFlaw: {
const [selection, optionalText, ...rest] = printedOptions
@@ -239,7 +239,7 @@ const getEntrySpecificFullName = (
case "AdvancedMagicalSpecialAbility":
return undefined
case "AdvancedSkillSpecialAbility":
switch (id.advanced_skill_special_ability) {
switch (id.AdvancedSkillSpecialAbility) {
// case AdvancedSkillSpecialAbilityIdentifier.Fachwissen: {
// const [skillId, firstApplicationId, secondApplicationId] = options ?? []
// const aspect =
@@ -299,6 +299,7 @@ const getEntrySpecificFullName = (
case "AncestorGlyph":
case "ArcaneOrbEnchantment":
case "AttireEnchantment":
case "Beutelzauber":
case "BlessedTradition":
case "BowlEnchantment":
case "BrawlingSpecialAbility":
@@ -315,7 +316,7 @@ const getEntrySpecificFullName = (
case "FoolsHatEnchantment":
return undefined
case "GeneralSpecialAbility":
switch (id.general_special_ability) {
switch (id.GeneralSpecialAbility) {
// case GeneralSpecialAbilityIdentifier.LanguageSpecialization: {
// const [languageId, specializationId] = options ?? []
@@ -374,15 +375,16 @@ const getEntrySpecificFullName = (
default:
return undefined
}
case "Haubenzauber":
case "InstrumentEnchantment":
return undefined
case "KarmaSpecialAbility":
switch (id.karma_special_ability) {
switch (id.KarmaSpecialAbility) {
case KarmaSpecialAbilityIdentifier.MasterOfAspect: {
const [aspectId] = options ?? []
const aspect =
aspectId?.tag === "Aspect"
? getAspectById(aspectId.aspect)
aspectId?.kind === "Aspect"
? getInstanceById("Aspect", aspectId.Aspect)
: undefined
const aspectTranslations = locale.translateMap(aspect?.translations)
@@ -406,6 +408,7 @@ const getEntrySpecificFullName = (
return undefined
}
case "Krallenkettenzauber":
case "Kristallkugelzauber":
case "LiturgicalStyleSpecialAbility":
case "LycantropicGift":
case "MagicalSign":
@@ -439,15 +442,15 @@ const getEntrySpecificFullName = (
* Gets the name components for an activatable entry.
*/
export const getNameComponents = <T>(
getAspectById: GetById.Static.Aspect,
getInstanceById: GetInstanceById<"Aspect">,
locale: LocaleEnvironment,
id: ActivatableIdentifier,
options: SelectOptionIdentifier[] | undefined,
options: RequirableSelectOptionIdentifier[] | undefined,
level: number | undefined,
translations: LocaleMap<T>,
getBaseName: (translation: T) => string,
getSelectOptionById: (
id: SelectOptionIdentifier,
id: RequirableSelectOptionIdentifier,
) => ResolvedSelectOption | undefined,
displayedInProfession: boolean,
): ActivatableNameComponents => {
@@ -455,12 +458,13 @@ export const getNameComponents = <T>(
const nameOptions: ActivatableNameComponents["options"] = (() => {
const arr =
options?.map(optionId => {
const optTranslations = getSelectOptionById(optionId)?.translations
const optTranslations =
getSelectOptionById(optionId)?.content.translations
return optTranslations === undefined
? MISSING_VALUE
: mapObject(optTranslations, t10n =>
displayedInProfession
? t10n.name_in_profession ?? t10n.name
? (t10n.name_in_profession ?? t10n.name)
: t10n.name,
)
}) ?? []
@@ -475,7 +479,7 @@ export const getNameComponents = <T>(
return {
...(getEntrySpecificFullName(
getAspectById,
getInstanceById,
locale,
id,
base,
@@ -1,5 +1,5 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { DisplayOption } from "optolith-database-schema/types/prerequisites/DisplayOption"
import { DisplayOption } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../helpers/locale.js"
import { MISSING_VALUE } from "../unknown.js"
import { PrerequisitePart } from "./part.js"
@@ -11,15 +11,15 @@ export const printDisplayOption = (
locale: LocaleEnvironment,
displayOption: DisplayOption,
): PrerequisitePart | undefined => {
switch (displayOption.tag) {
switch (displayOption.kind) {
case "Hide":
return undefined
case "ReplaceWith":
return {
value:
locale.translateMap(displayOption.replace_with.translations) ??
MISSING_VALUE,
sentenceType: displayOption.replace_with.sentence_type,
locale.translateMap(displayOption.ReplaceWith.translations)
?.replacement ?? MISSING_VALUE,
sentenceType: displayOption.ReplaceWith.sentence_type,
isMeta: false,
}
default:
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,5 +1,5 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { SentenceType } from "optolith-database-schema/types/prerequisites/single/TextPrerequisite"
import { SentenceType } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../helpers/locale.js"
/**
@@ -28,7 +28,7 @@ export const joinPrerequisiteParts = (
return text
}
switch (part.sentenceType) {
switch (part.sentenceType?.kind) {
case "Standalone":
return `${
/[.;]$/u.test(acc) ? `${acc.slice(0, -1)}. ` : `${acc}. `
File diff suppressed because it is too large Load Diff
@@ -1,13 +1,13 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { ResolvedSelectOption } from "optolith-database-schema/cache/activatableSelectOptions"
import {
import type { ResolvedSelectOption } from "optolith-database-schema/cache"
import type {
ActivatableIdentifier,
SelectOptionIdentifier,
} from "optolith-database-schema/types/_IdentifierGroup"
import { LocaleMap } from "optolith-database-schema/types/_LocaleMap"
import { ActivatablePrerequisite } from "optolith-database-schema/types/prerequisites/single/ActivatablePrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
ActivatablePrerequisite,
RequirableSelectOptionIdentifier,
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import type { LocaleMap } from "../../../../helpers/translate.js"
import {
getNameComponents,
printActivatableNameChunk,
@@ -16,177 +16,215 @@ import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
const getTranslationsForActivatable = (
getAdvantageById: GetById.Static.Advantage,
getDisadvantageById: GetById.Static.Disadvantage,
getAdvancedCombatSpecialAbilityById: GetById.Static.AdvancedCombatSpecialAbility,
getAdvancedKarmaSpecialAbilityById: GetById.Static.AdvancedKarmaSpecialAbility,
getAdvancedMagicalSpecialAbilityById: GetById.Static.AdvancedMagicalSpecialAbility,
getAdvancedSkillSpecialAbilityById: GetById.Static.AdvancedSkillSpecialAbility,
getAncestorGlyphById: GetById.Static.AncestorGlyph,
getArcaneOrbEnchantmentById: GetById.Static.ArcaneOrbEnchantment,
getAttireEnchantmentById: GetById.Static.AttireEnchantment,
getBlessedTraditionById: GetById.Static.BlessedTradition,
getBowlEnchantmentById: GetById.Static.BowlEnchantment,
getBrawlingSpecialAbilityById: GetById.Static.BrawlingSpecialAbility,
getCauldronEnchantmentById: GetById.Static.CauldronEnchantment,
getCeremonialItemSpecialAbilityById: GetById.Static.CeremonialItemSpecialAbility,
getChronicleEnchantmentById: GetById.Static.ChronicleEnchantment,
getCombatSpecialAbilityById: GetById.Static.CombatSpecialAbility,
getCombatStyleSpecialAbilityById: GetById.Static.CombatStyleSpecialAbility,
getCommandSpecialAbilityById: GetById.Static.CommandSpecialAbility,
getDaggerRitualById: GetById.Static.DaggerRitual,
getFamiliarSpecialAbilityById: GetById.Static.FamiliarSpecialAbility,
getFatePointSexSpecialAbilityById: GetById.Static.FatePointSexSpecialAbility,
getFatePointSpecialAbilityById: GetById.Static.FatePointSpecialAbility,
getFoolsHatEnchantmentById: GetById.Static.FoolsHatEnchantment,
getGeneralSpecialAbilityById: GetById.Static.GeneralSpecialAbility,
getInstrumentEnchantmentById: GetById.Static.InstrumentEnchantment,
getKarmaSpecialAbilityById: GetById.Static.KarmaSpecialAbility,
getKrallenkettenzauberById: GetById.Static.Krallenkettenzauber,
getLiturgicalStyleSpecialAbilityById: GetById.Static.LiturgicalStyleSpecialAbility,
getLycantropicGiftById: GetById.Static.LycantropicGift,
getMagicalSignById: GetById.Static.MagicalSign,
getMagicalSpecialAbilityById: GetById.Static.MagicalSpecialAbility,
getMagicalTraditionById: GetById.Static.MagicalTradition,
getMagicStyleSpecialAbilityById: GetById.Static.MagicStyleSpecialAbility,
getOrbEnchantmentById: GetById.Static.OrbEnchantment,
getPactGiftById: GetById.Static.PactGift,
getProtectiveWardingCircleSpecialAbilityById: GetById.Static.ProtectiveWardingCircleSpecialAbility,
getRingEnchantmentById: GetById.Static.RingEnchantment,
getSermonById: GetById.Static.Sermon,
getSexSpecialAbilityById: GetById.Static.SexSpecialAbility,
getSickleRitualById: GetById.Static.SickleRitual,
getSikaryanDrainSpecialAbilityById: GetById.Static.SikaryanDrainSpecialAbility,
getSkillStyleSpecialAbilityById: GetById.Static.SkillStyleSpecialAbility,
getSpellSwordEnchantmentById: GetById.Static.SpellSwordEnchantment,
getStaffEnchantmentById: GetById.Static.StaffEnchantment,
getToyEnchantmentById: GetById.Static.ToyEnchantment,
getTrinkhornzauberById: GetById.Static.Trinkhornzauber,
getVampiricGiftById: GetById.Static.VampiricGift,
getVisionById: GetById.Static.Vision,
getWandEnchantmentById: GetById.Static.WandEnchantment,
getWeaponEnchantmentById: GetById.Static.WeaponEnchantment,
getInstanceById: GetInstanceById<
| "AdvancedCombatSpecialAbility"
| "AdvancedKarmaSpecialAbility"
| "AdvancedMagicalSpecialAbility"
| "AdvancedSkillSpecialAbility"
| "Advantage"
| "AncestorGlyph"
| "ArcaneOrbEnchantment"
| "AttireEnchantment"
| "Beutelzauber"
| "BlessedTradition"
| "BowlEnchantment"
| "BrawlingSpecialAbility"
| "CauldronEnchantment"
| "CeremonialItemSpecialAbility"
| "ChronicleEnchantment"
| "CombatSpecialAbility"
| "CombatStyleSpecialAbility"
| "CommandSpecialAbility"
| "DaggerRitual"
| "Disadvantage"
| "FamiliarSpecialAbility"
| "FatePointSexSpecialAbility"
| "FatePointSpecialAbility"
| "FoolsHatEnchantment"
| "GeneralSpecialAbility"
| "Haubenzauber"
| "InstrumentEnchantment"
| "KarmaSpecialAbility"
| "Krallenkettenzauber"
| "Kristallkugelzauber"
| "LiturgicalStyleSpecialAbility"
| "LycantropicGift"
| "MagicalSign"
| "MagicalSpecialAbility"
| "MagicalTradition"
| "MagicStyleSpecialAbility"
| "OrbEnchantment"
| "PactGift"
| "ProtectiveWardingCircleSpecialAbility"
| "RingEnchantment"
| "Sermon"
| "SexSpecialAbility"
| "SickleRitual"
| "SikaryanDrainSpecialAbility"
| "SkillStyleSpecialAbility"
| "SpellSwordEnchantment"
| "StaffEnchantment"
| "ToyEnchantment"
| "Trinkhornzauber"
| "VampiricGift"
| "Vision"
| "WandEnchantment"
| "WeaponEnchantment"
>,
id: ActivatableIdentifier,
): { translations: LocaleMap<{ name: string }> } | undefined => {
switch (id.tag) {
switch (id.kind) {
case "Advantage":
return getAdvantageById(id.advantage)
return getInstanceById("Advantage", id.Advantage)
case "Disadvantage":
return getDisadvantageById(id.disadvantage)
return getInstanceById("Disadvantage", id.Disadvantage)
case "AdvancedCombatSpecialAbility":
return getAdvancedCombatSpecialAbilityById(
id.advanced_combat_special_ability,
return getInstanceById(
"AdvancedCombatSpecialAbility",
id.AdvancedCombatSpecialAbility,
)
case "AdvancedKarmaSpecialAbility":
return getAdvancedKarmaSpecialAbilityById(
id.advanced_karma_special_ability,
return getInstanceById(
"AdvancedKarmaSpecialAbility",
id.AdvancedKarmaSpecialAbility,
)
case "AdvancedMagicalSpecialAbility":
return getAdvancedMagicalSpecialAbilityById(
id.advanced_magical_special_ability,
return getInstanceById(
"AdvancedMagicalSpecialAbility",
id.AdvancedMagicalSpecialAbility,
)
case "AdvancedSkillSpecialAbility":
return getAdvancedSkillSpecialAbilityById(
id.advanced_skill_special_ability,
return getInstanceById(
"AdvancedSkillSpecialAbility",
id.AdvancedSkillSpecialAbility,
)
case "AncestorGlyph":
return getAncestorGlyphById(id.ancestor_glyph)
return getInstanceById("AncestorGlyph", id.AncestorGlyph)
case "ArcaneOrbEnchantment":
return getArcaneOrbEnchantmentById(id.arcane_orb_enchantment)
return getInstanceById("ArcaneOrbEnchantment", id.ArcaneOrbEnchantment)
case "AttireEnchantment":
return getAttireEnchantmentById(id.attire_enchantment)
return getInstanceById("AttireEnchantment", id.AttireEnchantment)
case "BlessedTradition":
return getBlessedTraditionById(id.blessed_tradition)
return getInstanceById("BlessedTradition", id.BlessedTradition)
case "Beutelzauber":
return getInstanceById("Beutelzauber", id.Beutelzauber)
case "Haubenzauber":
return getInstanceById("Haubenzauber", id.Haubenzauber)
case "Kristallkugelzauber":
return getInstanceById("Kristallkugelzauber", id.Kristallkugelzauber)
case "BowlEnchantment":
return getBowlEnchantmentById(id.bowl_enchantment)
return getInstanceById("BowlEnchantment", id.BowlEnchantment)
case "BrawlingSpecialAbility":
return getBrawlingSpecialAbilityById(id.brawling_special_ability)
return getInstanceById(
"BrawlingSpecialAbility",
id.BrawlingSpecialAbility,
)
case "CauldronEnchantment":
return getCauldronEnchantmentById(id.cauldron_enchantment)
return getInstanceById("CauldronEnchantment", id.CauldronEnchantment)
case "CeremonialItemSpecialAbility":
return getCeremonialItemSpecialAbilityById(
id.ceremonial_item_special_ability,
return getInstanceById(
"CeremonialItemSpecialAbility",
id.CeremonialItemSpecialAbility,
)
case "ChronicleEnchantment":
return getChronicleEnchantmentById(id.chronicle_enchantment)
return getInstanceById("ChronicleEnchantment", id.ChronicleEnchantment)
case "CombatSpecialAbility":
return getCombatSpecialAbilityById(id.combat_special_ability)
return getInstanceById("CombatSpecialAbility", id.CombatSpecialAbility)
case "CombatStyleSpecialAbility":
return getCombatStyleSpecialAbilityById(id.combat_style_special_ability)
return getInstanceById(
"CombatStyleSpecialAbility",
id.CombatStyleSpecialAbility,
)
case "CommandSpecialAbility":
return getCommandSpecialAbilityById(id.command_special_ability)
return getInstanceById("CommandSpecialAbility", id.CommandSpecialAbility)
case "DaggerRitual":
return getDaggerRitualById(id.dagger_ritual)
return getInstanceById("DaggerRitual", id.DaggerRitual)
case "FamiliarSpecialAbility":
return getFamiliarSpecialAbilityById(id.familiar_special_ability)
return getInstanceById(
"FamiliarSpecialAbility",
id.FamiliarSpecialAbility,
)
case "FatePointSexSpecialAbility":
return getFatePointSexSpecialAbilityById(
id.fate_point_sex_special_ability,
return getInstanceById(
"FatePointSexSpecialAbility",
id.FatePointSexSpecialAbility,
)
case "FatePointSpecialAbility":
return getFatePointSpecialAbilityById(id.fate_point_special_ability)
return getInstanceById(
"FatePointSpecialAbility",
id.FatePointSpecialAbility,
)
case "FoolsHatEnchantment":
return getFoolsHatEnchantmentById(id.fools_hat_enchantment)
return getInstanceById("FoolsHatEnchantment", id.FoolsHatEnchantment)
case "GeneralSpecialAbility":
return getGeneralSpecialAbilityById(id.general_special_ability)
return getInstanceById("GeneralSpecialAbility", id.GeneralSpecialAbility)
case "InstrumentEnchantment":
return getInstrumentEnchantmentById(id.instrument_enchantment)
return getInstanceById("InstrumentEnchantment", id.InstrumentEnchantment)
case "KarmaSpecialAbility":
return getKarmaSpecialAbilityById(id.karma_special_ability)
return getInstanceById("KarmaSpecialAbility", id.KarmaSpecialAbility)
case "Krallenkettenzauber":
return getKrallenkettenzauberById(id.krallenkettenzauber)
return getInstanceById("Krallenkettenzauber", id.Krallenkettenzauber)
case "LiturgicalStyleSpecialAbility":
return getLiturgicalStyleSpecialAbilityById(
id.liturgical_style_special_ability,
return getInstanceById(
"LiturgicalStyleSpecialAbility",
id.LiturgicalStyleSpecialAbility,
)
case "LycantropicGift":
return getLycantropicGiftById(id.lycantropic_gift)
return getInstanceById("LycantropicGift", id.LycantropicGift)
case "MagicalSign":
return getMagicalSignById(id.magical_sign)
return getInstanceById("MagicalSign", id.MagicalSign)
case "MagicalSpecialAbility":
return getMagicalSpecialAbilityById(id.magical_special_ability)
return getInstanceById("MagicalSpecialAbility", id.MagicalSpecialAbility)
case "MagicalTradition":
return getMagicalTraditionById(id.magical_tradition)
return getInstanceById("MagicalTradition", id.MagicalTradition)
case "MagicStyleSpecialAbility":
return getMagicStyleSpecialAbilityById(id.magic_style_special_ability)
return getInstanceById(
"MagicStyleSpecialAbility",
id.MagicStyleSpecialAbility,
)
case "OrbEnchantment":
return getOrbEnchantmentById(id.orb_enchantment)
return getInstanceById("OrbEnchantment", id.OrbEnchantment)
case "PactGift":
return getPactGiftById(id.pact_gift)
return getInstanceById("PactGift", id.PactGift)
case "ProtectiveWardingCircleSpecialAbility":
return getProtectiveWardingCircleSpecialAbilityById(
id.protective_warding_circle_special_ability,
return getInstanceById(
"ProtectiveWardingCircleSpecialAbility",
id.ProtectiveWardingCircleSpecialAbility,
)
case "RingEnchantment":
return getRingEnchantmentById(id.ring_enchantment)
return getInstanceById("RingEnchantment", id.RingEnchantment)
case "Sermon":
return getSermonById(id.sermon)
return getInstanceById("Sermon", id.Sermon)
case "SexSpecialAbility":
return getSexSpecialAbilityById(id.sex_special_ability)
return getInstanceById("SexSpecialAbility", id.SexSpecialAbility)
case "SickleRitual":
return getSickleRitualById(id.sickle_ritual)
return getInstanceById("SickleRitual", id.SickleRitual)
case "SikaryanDrainSpecialAbility":
return getSikaryanDrainSpecialAbilityById(
id.sikaryan_drain_special_ability,
return getInstanceById(
"SikaryanDrainSpecialAbility",
id.SikaryanDrainSpecialAbility,
)
case "SkillStyleSpecialAbility":
return getSkillStyleSpecialAbilityById(id.skill_style_special_ability)
return getInstanceById(
"SkillStyleSpecialAbility",
id.SkillStyleSpecialAbility,
)
case "SpellSwordEnchantment":
return getSpellSwordEnchantmentById(id.spell_sword_enchantment)
return getInstanceById("SpellSwordEnchantment", id.SpellSwordEnchantment)
case "StaffEnchantment":
return getStaffEnchantmentById(id.staff_enchantment)
return getInstanceById("StaffEnchantment", id.StaffEnchantment)
case "ToyEnchantment":
return getToyEnchantmentById(id.toy_enchantment)
return getInstanceById("ToyEnchantment", id.ToyEnchantment)
case "Trinkhornzauber":
return getTrinkhornzauberById(id.trinkhornzauber)
return getInstanceById("Trinkhornzauber", id.Trinkhornzauber)
case "VampiricGift":
return getVampiricGiftById(id.vampiric_gift)
return getInstanceById("VampiricGift", id.VampiricGift)
case "Vision":
return getVisionById(id.vision)
return getInstanceById("Vision", id.Vision)
case "WandEnchantment":
return getWandEnchantmentById(id.wand_enchantment)
return getInstanceById("WandEnchantment", id.WandEnchantment)
case "WeaponEnchantment":
return getWeaponEnchantmentById(id.weapon_enchantment)
return getInstanceById("WeaponEnchantment", id.WeaponEnchantment)
default:
return assertExhaustive(id)
}
@@ -196,127 +234,77 @@ const getTranslationsForActivatable = (
*/
export type GetResolvedSelectOptionById = (
id: ActivatableIdentifier,
selectOptionId: SelectOptionIdentifier,
selectOptionId: RequirableSelectOptionIdentifier,
) => ResolvedSelectOption | undefined
const printActivatableName = (
getAdvantageById: GetById.Static.Advantage,
getDisadvantageById: GetById.Static.Disadvantage,
getAdvancedCombatSpecialAbilityById: GetById.Static.AdvancedCombatSpecialAbility,
getAdvancedKarmaSpecialAbilityById: GetById.Static.AdvancedKarmaSpecialAbility,
getAdvancedMagicalSpecialAbilityById: GetById.Static.AdvancedMagicalSpecialAbility,
getAdvancedSkillSpecialAbilityById: GetById.Static.AdvancedSkillSpecialAbility,
getAncestorGlyphById: GetById.Static.AncestorGlyph,
getArcaneOrbEnchantmentById: GetById.Static.ArcaneOrbEnchantment,
getAttireEnchantmentById: GetById.Static.AttireEnchantment,
getBlessedTraditionById: GetById.Static.BlessedTradition,
getBowlEnchantmentById: GetById.Static.BowlEnchantment,
getBrawlingSpecialAbilityById: GetById.Static.BrawlingSpecialAbility,
getCauldronEnchantmentById: GetById.Static.CauldronEnchantment,
getCeremonialItemSpecialAbilityById: GetById.Static.CeremonialItemSpecialAbility,
getChronicleEnchantmentById: GetById.Static.ChronicleEnchantment,
getCombatSpecialAbilityById: GetById.Static.CombatSpecialAbility,
getCombatStyleSpecialAbilityById: GetById.Static.CombatStyleSpecialAbility,
getCommandSpecialAbilityById: GetById.Static.CommandSpecialAbility,
getDaggerRitualById: GetById.Static.DaggerRitual,
getFamiliarSpecialAbilityById: GetById.Static.FamiliarSpecialAbility,
getFatePointSexSpecialAbilityById: GetById.Static.FatePointSexSpecialAbility,
getFatePointSpecialAbilityById: GetById.Static.FatePointSpecialAbility,
getFoolsHatEnchantmentById: GetById.Static.FoolsHatEnchantment,
getGeneralSpecialAbilityById: GetById.Static.GeneralSpecialAbility,
getInstrumentEnchantmentById: GetById.Static.InstrumentEnchantment,
getKarmaSpecialAbilityById: GetById.Static.KarmaSpecialAbility,
getKrallenkettenzauberById: GetById.Static.Krallenkettenzauber,
getLiturgicalStyleSpecialAbilityById: GetById.Static.LiturgicalStyleSpecialAbility,
getLycantropicGiftById: GetById.Static.LycantropicGift,
getMagicalSignById: GetById.Static.MagicalSign,
getMagicalSpecialAbilityById: GetById.Static.MagicalSpecialAbility,
getMagicalTraditionById: GetById.Static.MagicalTradition,
getMagicStyleSpecialAbilityById: GetById.Static.MagicStyleSpecialAbility,
getOrbEnchantmentById: GetById.Static.OrbEnchantment,
getPactGiftById: GetById.Static.PactGift,
getProtectiveWardingCircleSpecialAbilityById: GetById.Static.ProtectiveWardingCircleSpecialAbility,
getRingEnchantmentById: GetById.Static.RingEnchantment,
getSermonById: GetById.Static.Sermon,
getSexSpecialAbilityById: GetById.Static.SexSpecialAbility,
getSickleRitualById: GetById.Static.SickleRitual,
getSikaryanDrainSpecialAbilityById: GetById.Static.SikaryanDrainSpecialAbility,
getSkillStyleSpecialAbilityById: GetById.Static.SkillStyleSpecialAbility,
getSpellSwordEnchantmentById: GetById.Static.SpellSwordEnchantment,
getStaffEnchantmentById: GetById.Static.StaffEnchantment,
getToyEnchantmentById: GetById.Static.ToyEnchantment,
getTrinkhornzauberById: GetById.Static.Trinkhornzauber,
getVampiricGiftById: GetById.Static.VampiricGift,
getVisionById: GetById.Static.Vision,
getWandEnchantmentById: GetById.Static.WandEnchantment,
getWeaponEnchantmentById: GetById.Static.WeaponEnchantment,
getAspectById: GetById.Static.Aspect,
getInstanceById: GetInstanceById<
| "Advantage"
| "Disadvantage"
| "AdvancedCombatSpecialAbility"
| "AdvancedKarmaSpecialAbility"
| "AdvancedMagicalSpecialAbility"
| "AdvancedSkillSpecialAbility"
| "AncestorGlyph"
| "ArcaneOrbEnchantment"
| "AttireEnchantment"
| "BlessedTradition"
| "BowlEnchantment"
| "BrawlingSpecialAbility"
| "CauldronEnchantment"
| "CeremonialItemSpecialAbility"
| "ChronicleEnchantment"
| "CombatSpecialAbility"
| "CombatStyleSpecialAbility"
| "CommandSpecialAbility"
| "DaggerRitual"
| "FamiliarSpecialAbility"
| "FatePointSexSpecialAbility"
| "FatePointSpecialAbility"
| "FoolsHatEnchantment"
| "GeneralSpecialAbility"
| "InstrumentEnchantment"
| "KarmaSpecialAbility"
| "Krallenkettenzauber"
| "LiturgicalStyleSpecialAbility"
| "LycantropicGift"
| "MagicalSign"
| "MagicalSpecialAbility"
| "MagicalTradition"
| "MagicStyleSpecialAbility"
| "OrbEnchantment"
| "PactGift"
| "ProtectiveWardingCircleSpecialAbility"
| "RingEnchantment"
| "Sermon"
| "SexSpecialAbility"
| "SickleRitual"
| "SikaryanDrainSpecialAbility"
| "SkillStyleSpecialAbility"
| "SpellSwordEnchantment"
| "StaffEnchantment"
| "ToyEnchantment"
| "Trinkhornzauber"
| "VampiricGift"
| "Vision"
| "WandEnchantment"
| "WeaponEnchantment"
| "Aspect"
>,
locale: LocaleEnvironment,
id: ActivatableIdentifier,
options: SelectOptionIdentifier[] | undefined,
options: RequirableSelectOptionIdentifier[] | undefined,
level: number | undefined,
getResolvedSelectOptionById: GetResolvedSelectOptionById,
) => {
const entry = getTranslationsForActivatable(
getAdvantageById,
getDisadvantageById,
getAdvancedCombatSpecialAbilityById,
getAdvancedKarmaSpecialAbilityById,
getAdvancedMagicalSpecialAbilityById,
getAdvancedSkillSpecialAbilityById,
getAncestorGlyphById,
getArcaneOrbEnchantmentById,
getAttireEnchantmentById,
getBlessedTraditionById,
getBowlEnchantmentById,
getBrawlingSpecialAbilityById,
getCauldronEnchantmentById,
getCeremonialItemSpecialAbilityById,
getChronicleEnchantmentById,
getCombatSpecialAbilityById,
getCombatStyleSpecialAbilityById,
getCommandSpecialAbilityById,
getDaggerRitualById,
getFamiliarSpecialAbilityById,
getFatePointSexSpecialAbilityById,
getFatePointSpecialAbilityById,
getFoolsHatEnchantmentById,
getGeneralSpecialAbilityById,
getInstrumentEnchantmentById,
getKarmaSpecialAbilityById,
getKrallenkettenzauberById,
getLiturgicalStyleSpecialAbilityById,
getLycantropicGiftById,
getMagicalSignById,
getMagicalSpecialAbilityById,
getMagicalTraditionById,
getMagicStyleSpecialAbilityById,
getOrbEnchantmentById,
getPactGiftById,
getProtectiveWardingCircleSpecialAbilityById,
getRingEnchantmentById,
getSermonById,
getSexSpecialAbilityById,
getSickleRitualById,
getSikaryanDrainSpecialAbilityById,
getSkillStyleSpecialAbilityById,
getSpellSwordEnchantmentById,
getStaffEnchantmentById,
getToyEnchantmentById,
getTrinkhornzauberById,
getVampiricGiftById,
getVisionById,
getWandEnchantmentById,
getWeaponEnchantmentById,
id,
)
const entry = getTranslationsForActivatable(getInstanceById, id)
if (entry === undefined) {
return undefined
}
return getNameComponents(
getAspectById,
getInstanceById,
locale,
id,
options,
@@ -332,57 +320,59 @@ const printActivatableName = (
* Get the translation of a blessed tradition prerequisite.
*/
export const printActivatablePrerequisite = (
getAdvantageById: GetById.Static.Advantage,
getDisadvantageById: GetById.Static.Disadvantage,
getAdvancedCombatSpecialAbilityById: GetById.Static.AdvancedCombatSpecialAbility,
getAdvancedKarmaSpecialAbilityById: GetById.Static.AdvancedKarmaSpecialAbility,
getAdvancedMagicalSpecialAbilityById: GetById.Static.AdvancedMagicalSpecialAbility,
getAdvancedSkillSpecialAbilityById: GetById.Static.AdvancedSkillSpecialAbility,
getAncestorGlyphById: GetById.Static.AncestorGlyph,
getArcaneOrbEnchantmentById: GetById.Static.ArcaneOrbEnchantment,
getAttireEnchantmentById: GetById.Static.AttireEnchantment,
getBlessedTraditionById: GetById.Static.BlessedTradition,
getBowlEnchantmentById: GetById.Static.BowlEnchantment,
getBrawlingSpecialAbilityById: GetById.Static.BrawlingSpecialAbility,
getCauldronEnchantmentById: GetById.Static.CauldronEnchantment,
getCeremonialItemSpecialAbilityById: GetById.Static.CeremonialItemSpecialAbility,
getChronicleEnchantmentById: GetById.Static.ChronicleEnchantment,
getCombatSpecialAbilityById: GetById.Static.CombatSpecialAbility,
getCombatStyleSpecialAbilityById: GetById.Static.CombatStyleSpecialAbility,
getCommandSpecialAbilityById: GetById.Static.CommandSpecialAbility,
getDaggerRitualById: GetById.Static.DaggerRitual,
getFamiliarSpecialAbilityById: GetById.Static.FamiliarSpecialAbility,
getFatePointSexSpecialAbilityById: GetById.Static.FatePointSexSpecialAbility,
getFatePointSpecialAbilityById: GetById.Static.FatePointSpecialAbility,
getFoolsHatEnchantmentById: GetById.Static.FoolsHatEnchantment,
getGeneralSpecialAbilityById: GetById.Static.GeneralSpecialAbility,
getInstrumentEnchantmentById: GetById.Static.InstrumentEnchantment,
getKarmaSpecialAbilityById: GetById.Static.KarmaSpecialAbility,
getKrallenkettenzauberById: GetById.Static.Krallenkettenzauber,
getLiturgicalStyleSpecialAbilityById: GetById.Static.LiturgicalStyleSpecialAbility,
getLycantropicGiftById: GetById.Static.LycantropicGift,
getMagicalSignById: GetById.Static.MagicalSign,
getMagicalSpecialAbilityById: GetById.Static.MagicalSpecialAbility,
getMagicalTraditionById: GetById.Static.MagicalTradition,
getMagicStyleSpecialAbilityById: GetById.Static.MagicStyleSpecialAbility,
getOrbEnchantmentById: GetById.Static.OrbEnchantment,
getPactGiftById: GetById.Static.PactGift,
getProtectiveWardingCircleSpecialAbilityById: GetById.Static.ProtectiveWardingCircleSpecialAbility,
getRingEnchantmentById: GetById.Static.RingEnchantment,
getSermonById: GetById.Static.Sermon,
getSexSpecialAbilityById: GetById.Static.SexSpecialAbility,
getSickleRitualById: GetById.Static.SickleRitual,
getSikaryanDrainSpecialAbilityById: GetById.Static.SikaryanDrainSpecialAbility,
getSkillStyleSpecialAbilityById: GetById.Static.SkillStyleSpecialAbility,
getSpellSwordEnchantmentById: GetById.Static.SpellSwordEnchantment,
getStaffEnchantmentById: GetById.Static.StaffEnchantment,
getToyEnchantmentById: GetById.Static.ToyEnchantment,
getTrinkhornzauberById: GetById.Static.Trinkhornzauber,
getVampiricGiftById: GetById.Static.VampiricGift,
getVisionById: GetById.Static.Vision,
getWandEnchantmentById: GetById.Static.WandEnchantment,
getWeaponEnchantmentById: GetById.Static.WeaponEnchantment,
getAspectById: GetById.Static.Aspect,
getInstanceById: GetInstanceById<
| "Advantage"
| "Disadvantage"
| "AdvancedCombatSpecialAbility"
| "AdvancedKarmaSpecialAbility"
| "AdvancedMagicalSpecialAbility"
| "AdvancedSkillSpecialAbility"
| "AncestorGlyph"
| "ArcaneOrbEnchantment"
| "AttireEnchantment"
| "BlessedTradition"
| "BowlEnchantment"
| "BrawlingSpecialAbility"
| "CauldronEnchantment"
| "CeremonialItemSpecialAbility"
| "ChronicleEnchantment"
| "CombatSpecialAbility"
| "CombatStyleSpecialAbility"
| "CommandSpecialAbility"
| "DaggerRitual"
| "FamiliarSpecialAbility"
| "FatePointSexSpecialAbility"
| "FatePointSpecialAbility"
| "FoolsHatEnchantment"
| "GeneralSpecialAbility"
| "InstrumentEnchantment"
| "KarmaSpecialAbility"
| "Krallenkettenzauber"
| "LiturgicalStyleSpecialAbility"
| "LycantropicGift"
| "MagicalSign"
| "MagicalSpecialAbility"
| "MagicalTradition"
| "MagicStyleSpecialAbility"
| "OrbEnchantment"
| "PactGift"
| "ProtectiveWardingCircleSpecialAbility"
| "RingEnchantment"
| "Sermon"
| "SexSpecialAbility"
| "SickleRitual"
| "SikaryanDrainSpecialAbility"
| "SkillStyleSpecialAbility"
| "SpellSwordEnchantment"
| "StaffEnchantment"
| "ToyEnchantment"
| "Trinkhornzauber"
| "VampiricGift"
| "Vision"
| "WandEnchantment"
| "WeaponEnchantment"
| "Aspect"
>,
getResolvedSelectOptionById: GetResolvedSelectOptionById,
locale: LocaleEnvironment,
prerequisite: ActivatablePrerequisite,
@@ -392,57 +382,7 @@ export const printActivatablePrerequisite = (
}
const nameComponents = printActivatableName(
getAdvantageById,
getDisadvantageById,
getAdvancedCombatSpecialAbilityById,
getAdvancedKarmaSpecialAbilityById,
getAdvancedMagicalSpecialAbilityById,
getAdvancedSkillSpecialAbilityById,
getAncestorGlyphById,
getArcaneOrbEnchantmentById,
getAttireEnchantmentById,
getBlessedTraditionById,
getBowlEnchantmentById,
getBrawlingSpecialAbilityById,
getCauldronEnchantmentById,
getCeremonialItemSpecialAbilityById,
getChronicleEnchantmentById,
getCombatSpecialAbilityById,
getCombatStyleSpecialAbilityById,
getCommandSpecialAbilityById,
getDaggerRitualById,
getFamiliarSpecialAbilityById,
getFatePointSexSpecialAbilityById,
getFatePointSpecialAbilityById,
getFoolsHatEnchantmentById,
getGeneralSpecialAbilityById,
getInstrumentEnchantmentById,
getKarmaSpecialAbilityById,
getKrallenkettenzauberById,
getLiturgicalStyleSpecialAbilityById,
getLycantropicGiftById,
getMagicalSignById,
getMagicalSpecialAbilityById,
getMagicalTraditionById,
getMagicStyleSpecialAbilityById,
getOrbEnchantmentById,
getPactGiftById,
getProtectiveWardingCircleSpecialAbilityById,
getRingEnchantmentById,
getSermonById,
getSexSpecialAbilityById,
getSickleRitualById,
getSikaryanDrainSpecialAbilityById,
getSkillStyleSpecialAbilityById,
getSpellSwordEnchantmentById,
getStaffEnchantmentById,
getToyEnchantmentById,
getTrinkhornzauberById,
getVampiricGiftById,
getVisionById,
getWandEnchantmentById,
getWeaponEnchantmentById,
getAspectById,
getInstanceById,
locale,
prerequisite.id,
prerequisite.options,
@@ -1,7 +1,7 @@
import { isNotNullish } from "@optolith/helpers/nullable"
import { romanize } from "@optolith/helpers/roman"
import { AnimistPowerPrerequisite } from "optolith-database-schema/types/prerequisites/single/AnimistPowerPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import type { AnimistPowerPrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -10,7 +10,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a culture prerequisite.
*/
export const printAnimistPowerPrerequisite = (
getAnimistPowerById: GetById.Static.AnimistPower,
getInstanceById: GetInstanceById<"AnimistPower">,
locale: LocaleEnvironment,
prerequisite: AnimistPowerPrerequisite,
): PrerequisitePart | undefined => {
@@ -18,7 +18,7 @@ export const printAnimistPowerPrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
const animistPower = getAnimistPowerById(prerequisite.id.animist_power)
const animistPower = getInstanceById("AnimistPower", prerequisite.id)
return {
value: [
@@ -1,8 +1,8 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
import type {
BlessedTraditionPrerequisite,
BlessedTraditionPrerequisiteRestriction,
} from "optolith-database-schema/types/prerequisites/single/TraditionPrerequisite"
} from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -11,11 +11,15 @@ const printValue = (
locale: LocaleEnvironment,
restriction: BlessedTraditionPrerequisiteRestriction | undefined,
) => {
switch (restriction) {
switch (restriction?.kind) {
case "Church":
return locale.translate("Tradition ({0})", locale.translate("Church"))
return locale.translate("Tradition ({$tradition})", {
tradition: locale.translate("Church"),
})
case "Shamanistic":
return locale.translate("Tradition ({0})", locale.translate("Shaman"))
return locale.translate("Tradition ({$tradition})", {
tradition: locale.translate("Shaman"),
})
case undefined:
return locale.translate("Tradition")
default:
@@ -21,14 +21,12 @@ const printType = (
*/
export const printCommonSuggestedByRCPPrerequisite = (
locale: LocaleEnvironment,
_prerequisite: Record<string, never>,
name: string,
type: "advantage" | "disadvantage",
): PrerequisitePart | undefined => ({
value: locale.translate(
"Race, culture, or profession must have {0} as an automatic or suggested {1}",
name,
printType(locale, type),
"Race, culture, or profession must have {$entry} as an automatic or suggested {$itemOfCategory}",
{ entry: name, itemOfCategory: printType(locale, type) },
),
sentenceType: undefined,
isMeta: false,
@@ -1,5 +1,5 @@
import { CulturePrerequisite } from "optolith-database-schema/types/prerequisites/single/CulturePrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import { CulturePrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -8,7 +8,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a culture prerequisite.
*/
export const printCulturePrerequisite = (
getCultureById: GetById.Static.Culture,
getInstanceById: GetInstanceById<"Culture">,
locale: LocaleEnvironment,
prerequisite: CulturePrerequisite,
): PrerequisitePart | undefined => {
@@ -16,7 +16,7 @@ export const printCulturePrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
const culture = getCultureById(prerequisite.id.culture)
const culture = getInstanceById("Culture", prerequisite.id)
const cultureTranslation = locale.translateMap(culture?.translations)
if (cultureTranslation === undefined) {
@@ -1,21 +1,19 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { Enhancements } from "optolith-database-schema/types/_Enhancements"
import { SkillWithEnhancementsIdentifier } from "optolith-database-schema/types/_IdentifierGroup"
import { LocaleMap } from "optolith-database-schema/types/_LocaleMap"
import {
ExternalEnhancementPrerequisite,
InternalEnhancementPrerequisite,
} from "optolith-database-schema/types/prerequisites/single/EnhancementPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
type EnhancementPrerequisite,
type SkillWithEnhancementsIdentifier,
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import type { LocaleMap } from "../../../../helpers/translate.js"
import { MISSING_VALUE } from "../../unknown.js"
import { PrerequisitePart } from "../part.js"
const printLabel = (
locale: LocaleEnvironment,
skillId: SkillWithEnhancementsIdentifier,
): string => {
switch (skillId.tag) {
switch (skillId.kind) {
case "Spell":
case "Ritual":
return locale.translate("spell enhancement")
@@ -28,23 +26,20 @@ const printLabel = (
}
const getSkill = (
getSpellById: GetById.Static.Spell,
getRitualById: GetById.Static.Ritual,
getLiturgicalChantById: GetById.Static.LiturgicalChant,
getCeremonyById: GetById.Static.Ceremony,
getInstanceById: GetInstanceById<
"Spell" | "Ritual" | "LiturgicalChant" | "Ceremony"
>,
parentId: SkillWithEnhancementsIdentifier,
):
| { translations: LocaleMap<{ name: string }>; enhancements?: Enhancements }
| undefined => {
switch (parentId.tag) {
): { translations: LocaleMap<{ name: string }> } | undefined => {
switch (parentId.kind) {
case "Spell":
return getSpellById(parentId.spell)
return getInstanceById("Spell", parentId.Spell)
case "Ritual":
return getRitualById(parentId.ritual)
return getInstanceById("Ritual", parentId.Ritual)
case "LiturgicalChant":
return getLiturgicalChantById(parentId.liturgical_chant)
return getInstanceById("LiturgicalChant", parentId.LiturgicalChant)
case "Ceremony":
return getCeremonyById(parentId.ceremony)
return getInstanceById("Ceremony", parentId.Ceremony)
default:
return assertExhaustive(parentId)
}
@@ -53,68 +48,27 @@ const getSkill = (
/**
* Get the translation of an external enhancement prerequisite.
*/
export const printExternalEnhancementPrerequisite = (
getSpellById: GetById.Static.Spell,
getRitualById: GetById.Static.Ritual,
getLiturgicalChantById: GetById.Static.LiturgicalChant,
getCeremonyById: GetById.Static.Ceremony,
export const printEnhancementPrerequisite = (
getInstanceById: GetInstanceById<
"Spell" | "Ritual" | "LiturgicalChant" | "Ceremony" | "Enhancement"
>,
locale: LocaleEnvironment,
prerequisite: ExternalEnhancementPrerequisite,
prerequisite: EnhancementPrerequisite,
): PrerequisitePart | undefined => {
if (prerequisite.display_option !== undefined) {
return printDisplayOption(locale, prerequisite.display_option)
}
const enhancement = getInstanceById("Enhancement", prerequisite.id)
const skill = getSkill(
getSpellById,
getRitualById,
getLiturgicalChantById,
getCeremonyById,
prerequisite.skill.id,
)
const enhancement = skill?.enhancements?.find(
e => e.id === prerequisite.enhancement.id,
)
const skill = enhancement && getSkill(getInstanceById, enhancement.parent)
return {
label: `${printLabel(locale, prerequisite.skill.id)} `,
label: `${
enhancement ? printLabel(locale, enhancement.parent) : MISSING_VALUE
} `,
value: `*${
locale.translateMap(enhancement?.translations)?.name
locale.translateMap(enhancement?.translations)?.name ?? MISSING_VALUE
}* ${locale.translate("for")} ${
locale.translateMap(skill?.translations)?.name
locale.translateMap(skill?.translations)?.name ?? MISSING_VALUE
}`,
sentenceType: undefined,
isMeta: false,
}
}
/**
* Get the translation of an internal enhancement prerequisite.
*/
export const printInternalEnhancementPrerequisite = (
getSpellById: GetById.Static.Spell,
getRitualById: GetById.Static.Ritual,
getLiturgicalChantById: GetById.Static.LiturgicalChant,
getCeremonyById: GetById.Static.Ceremony,
locale: LocaleEnvironment,
prerequisite: InternalEnhancementPrerequisite,
parentId: SkillWithEnhancementsIdentifier,
): PrerequisitePart | undefined => {
const skill = getSkill(
getSpellById,
getRitualById,
getLiturgicalChantById,
getCeremonyById,
parentId,
)
const enhancement = skill?.enhancements?.find(e => e.id === prerequisite.id)
return {
label: `${printLabel(locale, parentId)} `,
value: `*${locale.translateMap(enhancement?.translations)?.name}*`,
sentenceType: undefined,
isMeta: false,
}
}
@@ -1,4 +1,4 @@
import { InfluencePrerequisite } from "optolith-database-schema/types/prerequisites/single/InfluencePrerequisite"
import { InfluencePrerequisite } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { MISSING_VALUE } from "../../unknown.js"
import { printDisplayOption } from "../displayOption.js"
@@ -1,8 +1,8 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
import type {
MagicalTraditionPrerequisite,
MagicalTraditionPrerequisiteRestriction,
} from "optolith-database-schema/types/prerequisites/single/TraditionPrerequisite"
} from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -11,17 +11,11 @@ const printValue = (
locale: LocaleEnvironment,
restriction: MagicalTraditionPrerequisiteRestriction | undefined,
) => {
switch (restriction) {
switch (restriction?.kind) {
case "CanLearnRituals":
return locale.translate(
"Tradition must be able to use rituals",
locale.translate("Church"),
)
return locale.translate("Tradition must be able to use rituals")
case "CanBindFamiliars":
return locale.translate(
"Tradition must be able to bind familiars",
locale.translate("Shaman"),
)
return locale.translate("Tradition must be able to bind familiars")
case undefined:
return locale.translate("Tradition")
default:
@@ -6,7 +6,6 @@ import { PrerequisitePart } from "../part.js"
*/
export const printNoOtherAncestorBloodAdvantagePrerequisite = (
locale: LocaleEnvironment,
_prerequisite: Record<string, never>,
): PrerequisitePart | undefined => ({
value: locale.translate("no other ancestor blood advantage"),
sentenceType: undefined,
@@ -1,7 +1,7 @@
import { isNotNullish } from "@optolith/helpers/nullable"
import { romanize } from "@optolith/helpers/roman"
import { PactPrerequisite } from "optolith-database-schema/types/prerequisites/single/PactPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import type { PactPrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { MISSING_VALUE } from "../../unknown.js"
import { printDisplayOption } from "../displayOption.js"
@@ -11,7 +11,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a culture prerequisite.
*/
export const printPactPrerequisite = (
getPactCategoryById: GetById.Static.PactCategory,
getInstanceById: GetInstanceById<"PactCategory" | "PactDomain">,
locale: LocaleEnvironment,
prerequisite: PactPrerequisite,
): PrerequisitePart | undefined => {
@@ -19,31 +19,26 @@ export const printPactPrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
const pactCategory = getPactCategoryById(
prerequisite.category.id.pact_category,
)
const pactCategory = getInstanceById("PactCategory", prerequisite.category)
const parts = [
prerequisite.domain_id === undefined
prerequisite.domain === undefined
? undefined
: locale.translate(
"domain {0}",
locale.joinDisjunctionList(
prerequisite.domain_id.map(
ref =>
: locale.translate("domain {$domain}", {
domain: locale.joinDisjunctionList(
prerequisite.domain.map(
id =>
locale.translateMap(
pactCategory?.domains.find(
domain => domain.id === ref.id.pact_domain,
)?.translations,
getInstanceById("PactDomain", id)?.translations,
)?.name ?? MISSING_VALUE,
),
),
),
locale.translate(
"{0} level {1}",
locale.translateMap(pactCategory?.translations)?.name ?? MISSING_VALUE,
romanize(prerequisite.level ?? 1),
),
}),
locale.translate("{$pact} level {$pactLevel}", {
pact:
locale.translateMap(pactCategory?.translations)?.name ?? MISSING_VALUE,
pactLevel: romanize(prerequisite.level ?? 1),
}),
].filter(isNotNullish)
return {
@@ -0,0 +1,47 @@
import { type PersonalityTraitPrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
/**
* Get the translation of a personality trait prerequisite.
*/
export const printPersonalityTraitPrerequisite = (
getInstanceById: GetInstanceById<"PersonalityTrait">,
locale: LocaleEnvironment,
prerequisite: PersonalityTraitPrerequisite,
): PrerequisitePart | undefined => {
if (prerequisite.display_option !== undefined) {
return printDisplayOption(locale, prerequisite.display_option)
}
const personalityTrait = getInstanceById("PersonalityTrait", prerequisite.id)
const personalityTraitTranslation = locale.translateMap(
personalityTrait?.translations,
)
if (
personalityTrait === undefined ||
personalityTraitTranslation === undefined
) {
return undefined
}
const name = `${personalityTraitTranslation.name} (${locale.translate(
".input {$level :number} {{Level {$level}}}",
{ level: personalityTrait.level },
)})`
return {
value: prerequisite.active
? locale.translate("cannot be chosen at the same time as {$trait}", {
trait: name,
})
: locale.translate("must have {$trait}", {
trait: name,
}),
sentenceType: undefined,
isMeta: false,
}
}
@@ -1,4 +1,4 @@
import { PrimaryAttributePrerequisite } from "optolith-database-schema/types/prerequisites/single/PrimaryAttributePrerequisite"
import { PrimaryAttributePrerequisite } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -1,5 +1,5 @@
import { PublicationPrerequisite } from "optolith-database-schema/types/prerequisites/single/PublicationPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import { PublicationPrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -8,7 +8,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a state prerequisite.
*/
export const printPublicationPrerequisite = (
getPublicationById: GetById.Static.Publication,
getInstanceById: GetInstanceById<"Publication">,
locale: LocaleEnvironment,
prerequisite: PublicationPrerequisite,
): PrerequisitePart | undefined => {
@@ -16,7 +16,7 @@ export const printPublicationPrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
const publication = getPublicationById(prerequisite.id.publication)
const publication = getInstanceById("Publication", prerequisite.id)
const publicationTranslation = locale.translateMap(publication?.translations)
if (publicationTranslation === undefined) {
@@ -1,5 +1,5 @@
import { RacePrerequisite } from "optolith-database-schema/types/prerequisites/single/RacePrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import { RacePrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -8,7 +8,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a race prerequisite.
*/
export const printRacePrerequisite = (
getRaceById: GetById.Static.Race,
getInstanceById: GetInstanceById<"Race">,
locale: LocaleEnvironment,
prerequisite: RacePrerequisite,
): PrerequisitePart | undefined => {
@@ -16,7 +16,7 @@ export const printRacePrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
const race = getRaceById(prerequisite.id.race)
const race = getInstanceById("Race", prerequisite.id)
const raceTranslation = locale.translateMap(race?.translations)
if (raceTranslation === undefined) {
@@ -1,68 +1,75 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { RatedIdentifier } from "optolith-database-schema/types/_IdentifierGroup"
import { RatedPrerequisite } from "optolith-database-schema/types/prerequisites/single/RatedPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import type {
RatedIdentifier,
RatedPrerequisite,
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { MISSING_VALUE } from "../../unknown.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
const printRatedName = (
getAttributeById: GetById.Static.Attribute,
getSkillById: GetById.Static.Skill,
getCloseCombatTechniqueById: GetById.Static.CloseCombatTechnique,
getRangedCombatTechniqueById: GetById.Static.RangedCombatTechnique,
getSpellById: GetById.Static.Spell,
getRitualById: GetById.Static.Ritual,
getLiturgicalChantById: GetById.Static.LiturgicalChant,
getCeremonyById: GetById.Static.Ceremony,
getInstanceById: GetInstanceById<
| "Attribute"
| "Skill"
| "CloseCombatTechnique"
| "RangedCombatTechnique"
| "Spell"
| "Ritual"
| "LiturgicalChant"
| "Ceremony"
>,
locale: LocaleEnvironment,
id: RatedIdentifier,
) => {
switch (id.tag) {
switch (id.kind) {
case "Attribute":
return (
locale.translateMap(getAttributeById(id.attribute)?.translations)
?.name ?? MISSING_VALUE
locale.translateMap(
getInstanceById("Attribute", id.Attribute)?.translations,
)?.name ?? MISSING_VALUE
)
case "Skill":
return (
locale.translateMap(getSkillById(id.skill)?.translations)?.name ??
MISSING_VALUE
locale.translateMap(getInstanceById("Skill", id.Skill)?.translations)
?.name ?? MISSING_VALUE
)
case "CloseCombatTechnique":
return (
locale.translateMap(
getCloseCombatTechniqueById(id.close_combat_technique)?.translations,
getInstanceById("CloseCombatTechnique", id.CloseCombatTechnique)
?.translations,
)?.name ?? MISSING_VALUE
)
case "RangedCombatTechnique":
return (
locale.translateMap(
getRangedCombatTechniqueById(id.ranged_combat_technique)
getInstanceById("RangedCombatTechnique", id.RangedCombatTechnique)
?.translations,
)?.name ?? MISSING_VALUE
)
case "Spell":
return (
locale.translateMap(getSpellById(id.spell)?.translations)?.name ??
MISSING_VALUE
locale.translateMap(getInstanceById("Spell", id.Spell)?.translations)
?.name ?? MISSING_VALUE
)
case "Ritual":
return (
locale.translateMap(getRitualById(id.ritual)?.translations)?.name ??
MISSING_VALUE
locale.translateMap(getInstanceById("Ritual", id.Ritual)?.translations)
?.name ?? MISSING_VALUE
)
case "LiturgicalChant":
return (
locale.translateMap(
getLiturgicalChantById(id.liturgical_chant)?.translations,
getInstanceById("LiturgicalChant", id.LiturgicalChant)?.translations,
)?.name ?? MISSING_VALUE
)
case "Ceremony":
return (
locale.translateMap(getCeremonyById(id.ceremony)?.translations)?.name ??
MISSING_VALUE
locale.translateMap(
getInstanceById("Ceremony", id.Ceremony)?.translations,
)?.name ?? MISSING_VALUE
)
default:
return assertExhaustive(id)
@@ -73,14 +80,16 @@ const printRatedName = (
* Get the translation of a blessed tradition prerequisite.
*/
export const printRatedPrerequisite = (
getAttributeById: GetById.Static.Attribute,
getSkillById: GetById.Static.Skill,
getCloseCombatTechniqueById: GetById.Static.CloseCombatTechnique,
getRangedCombatTechniqueById: GetById.Static.RangedCombatTechnique,
getSpellById: GetById.Static.Spell,
getRitualById: GetById.Static.Ritual,
getLiturgicalChantById: GetById.Static.LiturgicalChant,
getCeremonyById: GetById.Static.Ceremony,
getInstanceById: GetInstanceById<
| "Attribute"
| "Skill"
| "CloseCombatTechnique"
| "RangedCombatTechnique"
| "Spell"
| "Ritual"
| "LiturgicalChant"
| "Ceremony"
>,
locale: LocaleEnvironment,
prerequisite: RatedPrerequisite,
): PrerequisitePart | undefined => {
@@ -89,18 +98,9 @@ export const printRatedPrerequisite = (
}
return {
value: `${printRatedName(
getAttributeById,
getSkillById,
getCloseCombatTechniqueById,
getRangedCombatTechniqueById,
getSpellById,
getRitualById,
getLiturgicalChantById,
getCeremonyById,
locale,
prerequisite.id,
)} ${prerequisite.value}`,
value: `${printRatedName(getInstanceById, locale, prerequisite.id)} ${
prerequisite.value
}`,
sentenceType: undefined,
isMeta: false,
}
@@ -1,10 +1,10 @@
import { isNotNullish } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
CombatTechniquesTargetGroup,
import type {
RatedMinimumNumberPrerequisite,
} from "optolith-database-schema/types/prerequisites/single/RatedMinimumNumberPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
RatedMinimumNumberPrerequisiteCombatTechniquesTargetGroup,
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { MISSING_VALUE } from "../../unknown.js"
import { printDisplayOption } from "../displayOption.js"
@@ -13,121 +13,44 @@ import { PrerequisitePart } from "../part.js"
const printNumberOfTheFollowingSkills = (
locale: LocaleEnvironment,
number: number,
): string => {
switch (number) {
case 1:
return locale.translate("one of the following skills")
case 2:
return locale.translate("two of the following skills")
case 3:
return locale.translate("three of the following skills")
case 4:
return locale.translate("four of the following skills")
case 5:
return locale.translate("five of the following skills")
case 6:
return locale.translate("six of the following skills")
case 7:
return locale.translate("seven of the following skills")
case 8:
return locale.translate("eight of the following skills")
case 9:
return locale.translate("nine of the following skills")
default:
return locale.translate("{0} of the following skills")
}
}
): string =>
locale.translate(
".input {$count :number} {{{$count} of the following skills}}",
{ count: number },
)
const printNumberOfAllCombatTechniques = (
locale: LocaleEnvironment,
number: number,
): string => {
switch (number) {
case 1:
return locale.translate("one combat technique")
case 2:
return locale.translate("two combat techniques")
case 3:
return locale.translate("three combat techniques")
case 4:
return locale.translate("four combat techniques")
case 5:
return locale.translate("five combat techniques")
case 6:
return locale.translate("six combat techniques")
case 7:
return locale.translate("seven combat techniques")
case 8:
return locale.translate("eight combat techniques")
case 9:
return locale.translate("nine combat techniques")
default:
return locale.translate("{0} combat techniques")
}
}
): string =>
locale.translate(".input {$count :number} {{{$count} combat techniques}}", {
count: number,
})
const printNumberOfCloseCombatTechniques = (
locale: LocaleEnvironment,
number: number,
): string => {
switch (number) {
case 1:
return locale.translate("one close combat technique")
case 2:
return locale.translate("two close combat techniques")
case 3:
return locale.translate("three close combat techniques")
case 4:
return locale.translate("four close combat techniques")
case 5:
return locale.translate("five close combat techniques")
case 6:
return locale.translate("six close combat techniques")
case 7:
return locale.translate("seven close combat techniques")
case 8:
return locale.translate("eight close combat techniques")
case 9:
return locale.translate("nine close combat techniques")
default:
return locale.translate("{0} close combat techniques")
}
}
): string =>
locale.translate(
".input {$count :number} {{{$count} close combat techniques}}",
{ count: number },
)
const printNumberOfRangedCombatTechniques = (
locale: LocaleEnvironment,
number: number,
): string => {
switch (number) {
case 1:
return locale.translate("one ranged combat technique")
case 2:
return locale.translate("two ranged combat techniques")
case 3:
return locale.translate("three ranged combat techniques")
case 4:
return locale.translate("four ranged combat techniques")
case 5:
return locale.translate("five ranged combat techniques")
case 6:
return locale.translate("six ranged combat techniques")
case 7:
return locale.translate("seven ranged combat techniques")
case 8:
return locale.translate("eight ranged combat techniques")
case 9:
return locale.translate("nine ranged combat techniques")
default:
return locale.translate("{0} ranged combat techniques")
}
}
): string =>
locale.translate(
".input {$count :number} {{{$count} ranged combat techniques}}",
{ count: number },
)
const printNumberOfCombatTechniques = (
locale: LocaleEnvironment,
category: CombatTechniquesTargetGroup,
category: RatedMinimumNumberPrerequisiteCombatTechniquesTargetGroup,
number: number,
): string => {
switch (category) {
switch (category.kind) {
case "All":
return printNumberOfAllCombatTechniques(locale, number)
case "Close":
@@ -143,9 +66,7 @@ const printNumberOfCombatTechniques = (
* Get the translation of a rated minimum number prerequisite.
*/
export const printRatedMinimumNumberPrerequisite = (
getSkillById: GetById.Static.Skill,
getPropertyById: GetById.Static.Property,
getAspectById: GetById.Static.Aspect,
getInstanceById: GetInstanceById<"Skill" | "Property" | "Aspect">,
locale: LocaleEnvironment,
prerequisite: RatedMinimumNumberPrerequisite,
): PrerequisitePart | undefined => {
@@ -153,21 +74,24 @@ export const printRatedMinimumNumberPrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
switch (prerequisite.targets.tag) {
switch (prerequisite.targets.kind) {
case "Skills": {
const skills = prerequisite.targets.skills.list
const skills = prerequisite.targets.Skills.targets
.map(
ref =>
locale.translateMap(getSkillById(ref.id.skill)?.translations)?.name,
id =>
locale.translateMap(getInstanceById("Skill", id)?.translations)
?.name,
)
.filter(isNotNullish)
return {
value: locale.translate(
"{0} on at least SR {1}: {2}", // zwei der folgenden Talente mindestens FW 10:
printNumberOfTheFollowingSkills(locale, prerequisite.number),
prerequisite.value,
locale.joinConjunctionList(skills),
".input {$minRating :number} {{{$count} on at least SR {$minRating}: {$list}}}", // zwei der folgenden Talente mindestens FW 10:
{
count: printNumberOfTheFollowingSkills(locale, prerequisite.number),
minRating: prerequisite.value,
list: locale.joinConjunctionList(skills),
},
),
sentenceType: undefined,
isMeta: false,
@@ -184,7 +108,7 @@ export const printRatedMinimumNumberPrerequisite = (
return {
value: `${printNumberOfCombatTechniques(
locale,
prerequisite.targets.combat_techniques.group,
prerequisite.targets.CombatTechniques.group,
prerequisite.number,
)} ${prerequisite.value}`,
sentenceType: undefined,
@@ -195,13 +119,18 @@ export const printRatedMinimumNumberPrerequisite = (
case "Spellworks": {
return {
value: locale.translate(
"{0} arcane works with the property {1} at SR {2} or higher",
prerequisite.number,
locale.translateMap(
getPropertyById(prerequisite.targets.spellworks.id.property)
?.translations,
)?.name ?? MISSING_VALUE,
prerequisite.value,
".input {$count :number} .input {$minRating :number} {{{$count} arcane works with the property {$property} at SR {$minRating} or higher}}",
{
count: prerequisite.number,
property:
locale.translateMap(
getInstanceById(
"Property",
prerequisite.targets.Spellworks.property,
)?.translations,
)?.name ?? MISSING_VALUE,
minRating: prerequisite.value,
},
),
sentenceType: undefined,
isMeta: false,
@@ -211,13 +140,16 @@ export const printRatedMinimumNumberPrerequisite = (
case "Liturgies": {
return {
value: locale.translate(
"{0} liturgical chants and ceremonies with the aspect {1} at SR {2} or higher",
prerequisite.number,
locale.translateMap(
getAspectById(prerequisite.targets.liturgies.id.aspect)
?.translations,
)?.name ?? MISSING_VALUE,
prerequisite.value,
".input {$count :number} .input {$minRating :number} {{{$count} liturgical chants and ceremonies with the aspect {$aspect} at SR {$minRating} or higher}}",
{
count: prerequisite.number,
aspect:
locale.translateMap(
getInstanceById("Aspect", prerequisite.targets.Liturgies.aspect)
?.translations,
)?.name ?? MISSING_VALUE,
minRating: prerequisite.value,
},
),
sentenceType: undefined,
isMeta: false,
@@ -1,6 +1,6 @@
import { isNotNullish } from "@optolith/helpers/nullable"
import { RatedSumPrerequisite } from "optolith-database-schema/types/prerequisites/single/RatedSumPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import { RatedSumPrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -9,7 +9,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a rated sum prerequisite.
*/
export const printRatedSumPrerequisite = (
getSkillById: GetById.Static.Skill,
getInstanceById: GetInstanceById<"Skill">,
locale: LocaleEnvironment,
prerequisite: RatedSumPrerequisite,
): PrerequisitePart | undefined => {
@@ -19,16 +19,19 @@ export const printRatedSumPrerequisite = (
const skills = prerequisite.targets
.map(
target =>
locale.translateMap(getSkillById(target.skill)?.translations)?.name,
skillId =>
locale.translateMap(getInstanceById("Skill", skillId)?.translations)
?.name,
)
.filter(isNotNullish)
return {
value: locale.translate(
"the SR for {0} combined must add up to at least {1}",
locale.joinConjunctionList(skills),
prerequisite.sum,
"the SR for {$skill} combined must add up to at least {$minRating}",
{
skill: locale.joinConjunctionList(skills),
minRating: prerequisite.sum,
},
),
sentenceType: undefined,
isMeta: false,
@@ -1,4 +1,4 @@
import { RulePrerequisite } from "optolith-database-schema/types/prerequisites/single/RulePrerequisite"
import { RulePrerequisite } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { PrerequisitePart } from "../part.js"
@@ -1,11 +1,10 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { BinarySex } from "optolith-database-schema/types/_Sex"
import { SexPrerequisite } from "optolith-database-schema/types/prerequisites/single/SexPrerequisite"
import type { BinarySex, SexPrerequisite } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { PrerequisitePart } from "../part.js"
const printId = (locale: LocaleEnvironment, id: BinarySex): string => {
switch (id) {
switch (id.kind) {
case "Male":
return locale.translate("Male")
case "Female":
@@ -2,7 +2,7 @@ import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
SexualCharacteristic,
SexualCharacteristicPrerequisite,
} from "optolith-database-schema/types/prerequisites/single/SexualCharacteristicPrerequisite"
} from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { PrerequisitePart } from "../part.js"
@@ -10,7 +10,7 @@ const printId = (
locale: LocaleEnvironment,
id: SexualCharacteristic,
): string => {
switch (id) {
switch (id.kind) {
case "Penis":
return locale.translate("Penis")
case "Vagina":
@@ -27,7 +27,9 @@ export const printSexualCharacteristicPrerequisite = (
locale: LocaleEnvironment,
prerequisite: SexualCharacteristicPrerequisite,
): PrerequisitePart | undefined => ({
value: locale.translate("Person with {0}", printId(locale, prerequisite.id)),
value: locale.translate("Person with {$sexualCharacteristic}", {
sexualCharacteristic: printId(locale, prerequisite.id),
}),
sentenceType: undefined,
isMeta: false,
})
@@ -1,5 +1,5 @@
import { SocialStatusPrerequisite } from "optolith-database-schema/types/prerequisites/single/SocialStatusPrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import type { SocialStatusPrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -8,7 +8,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a social status prerequisite.
*/
export const printSocialStatusPrerequisite = (
getSocialStatusById: GetById.Static.SocialStatus,
getInstanceById: GetInstanceById<"SocialStatus">,
locale: LocaleEnvironment,
prerequisite: SocialStatusPrerequisite,
): PrerequisitePart | undefined => {
@@ -16,7 +16,7 @@ export const printSocialStatusPrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
const socialStatus = getSocialStatusById(prerequisite.id.social_status)
const socialStatus = getInstanceById("SocialStatus", prerequisite.id)
const socialStatusTranslation = locale.translateMap(
socialStatus?.translations,
)
@@ -26,8 +26,9 @@ export const printSocialStatusPrerequisite = (
}
return {
label: `${locale.translate("Social Status {0} or higher")} `,
value: `*${socialStatusTranslation.name}*`,
value: `${locale.translate("Social Status {$minStatus} or higher", {
minStatus: `*${socialStatusTranslation.name}*`,
})} `,
sentenceType: undefined,
isMeta: false,
}
@@ -1,5 +1,5 @@
import { StatePrerequisite } from "optolith-database-schema/types/prerequisites/single/StatePrerequisite"
import { GetById } from "../../../../helpers/getTypes.js"
import { StatePrerequisite } from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { printDisplayOption } from "../displayOption.js"
import { PrerequisitePart } from "../part.js"
@@ -8,7 +8,7 @@ import { PrerequisitePart } from "../part.js"
* Get the translation of a state prerequisite.
*/
export const printStatePrerequisite = (
getStateById: GetById.Static.State,
getInstanceById: GetInstanceById<"State">,
locale: LocaleEnvironment,
prerequisite: StatePrerequisite,
): PrerequisitePart | undefined => {
@@ -16,7 +16,7 @@ export const printStatePrerequisite = (
return printDisplayOption(locale, prerequisite.display_option)
}
const state = getStateById(prerequisite.id.state)
const state = getInstanceById("State", prerequisite.id)
const stateTranslation = locale.translateMap(state?.translations)
if (stateTranslation === undefined) {
@@ -1,4 +1,4 @@
import { TextPrerequisite } from "optolith-database-schema/types/prerequisites/single/TextPrerequisite"
import { TextPrerequisite } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { MISSING_VALUE } from "../../unknown.js"
import { PrerequisitePart } from "../part.js"
@@ -10,7 +10,7 @@ export const printTextPrerequisite = (
locale: LocaleEnvironment,
prerequisite: TextPrerequisite,
): PrerequisitePart => ({
value: locale.translateMap(prerequisite.translations) ?? MISSING_VALUE,
value: locale.translateMap(prerequisite.translations)?.text ?? MISSING_VALUE,
sentenceType: prerequisite.sentence_type,
isMeta: prerequisite.is_meta ?? false,
})
@@ -9,8 +9,9 @@ import {
ModifiableCastingTime,
SlowCastingTime,
SlowSkillNonModifiableCastingTime,
} from "optolith-database-schema/types/_ActivatableSkillCastingTime"
import { GetById } from "../../../../helpers/getTypes.js"
} from "optolith-database-schema/gen"
import { Case } from "../../../../helpers/enums.js"
import type { GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { ResponsiveTextSize } from "../../responsiveText.js"
import { formatTimeSpan } from "../../units/timeSpan.js"
@@ -23,21 +24,21 @@ import {
import { getModifiableBySpeed, Speed } from "./speed.js"
const getModifiableCastingTimeTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
responsiveTextSize: ResponsiveTextSize,
value: ModifiableCastingTime,
): string =>
mapNullable(
getSkillModificationLevelById(value.initial_modification_level),
getInstanceById("SkillModificationLevel", value.initial_modification_level),
modificationLevel =>
getModifiableBySpeed(
config =>
formatTimeSpan(
locale,
responsiveTextSize,
"Actions",
Case("Actions"),
config.casting_time,
),
config =>
@@ -57,7 +58,7 @@ const getFastSkillNonModifiableCastingTimeTranslation = (
responsiveTextSize: ResponsiveTextSize,
value: FastSkillNonModifiableCastingTime,
): string =>
formatTimeSpan(locale, responsiveTextSize, "Actions", value.actions)
formatTimeSpan(locale, responsiveTextSize, Case("Actions"), value.actions)
const getSlowSkillNonModifiableCastingTimeTranslation = (
locale: LocaleEnvironment,
@@ -67,25 +68,25 @@ const getSlowSkillNonModifiableCastingTimeTranslation = (
const getCastingTimeTranslation = <NonModifiable extends object>(
getNonModifiableCastingTimeTranslation: (value: NonModifiable) => string,
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
value: CastingTime<NonModifiable>,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Modifiable":
return getModifiableCastingTimeTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
responsiveTextSize,
value.modifiable,
value.Modifiable,
)
case "NonModifiable":
return (
getNonModifiableCastingTimeTranslation(value.non_modifiable) +
getNonModifiableCastingTimeTranslation(value.NonModifiable) +
getNonModifiableSuffixTranslation(
locale,
entity,
@@ -108,7 +109,7 @@ const getCastingTimeIncludingLovemakingTranslation = <
NonModifiable extends object,
>(
getNonModifiableCastingTimeTranslation: (value: NonModifiable) => string,
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
entity: Entity,
@@ -119,7 +120,7 @@ const getCastingTimeIncludingLovemakingTranslation = <
mapNullable(value.default, def =>
getCastingTimeTranslation(
getNonModifiableCastingTimeTranslation,
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
entity,
@@ -142,7 +143,7 @@ const getCastingTimeIncludingLovemakingTranslation = <
* Get the text for the casting time of a fast activatable skill.
*/
export const getFastCastingTimeTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
@@ -155,7 +156,7 @@ export const getFastCastingTimeTranslation = (
responsiveTextSize,
nonModifiableValue,
),
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Fast,
entity,
@@ -167,7 +168,7 @@ export const getFastCastingTimeTranslation = (
* Get the text for the casting time of a slow activatable skill.
*/
export const getSlowCastingTimeTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
@@ -180,7 +181,7 @@ export const getSlowCastingTimeTranslation = (
responsiveTextSize,
nonModifiableValue,
),
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Slow,
entity,
@@ -1,17 +1,17 @@
import { mapNullableDefault } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
import type {
CheckResultArithmetic,
CheckResultBased,
CheckResultBasedModifier,
CheckResultValue,
} from "optolith-database-schema/types/_ActivatableSkillCheckResultBased"
} from "optolith-database-schema/gen"
import { Translate } from "../../../../helpers/translate.js"
const getCheckResultBaseValueTranslation = (
translate: Translate,
baseValue: CheckResultValue,
) => {
switch (baseValue) {
switch (baseValue.kind) {
case "QualityLevels":
return translate("QL")
case "SkillPoints":
@@ -22,7 +22,7 @@ const getCheckResultBaseValueTranslation = (
}
const getArithmeticSymbol = (arithmetic: CheckResultArithmetic) => {
switch (arithmetic) {
switch (arithmetic.kind) {
case "Divide":
return ` / `
case "Multiply":
@@ -32,6 +32,18 @@ const getArithmeticSymbol = (arithmetic: CheckResultArithmetic) => {
}
}
interface CheckResultBased {
/**
* The base value that is derived from the check result.
*/
base: CheckResultValue
/**
* If defined, it modifies the base value.
*/
modifier?: CheckResultBasedModifier
}
/**
* Returns the value text for a check-result-based parameter of an activatable
* skill.
+132 -53
View File
@@ -1,7 +1,6 @@
import { mapNullable, mapNullableDefault } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
CostMap,
IndefiniteOneTimeCost,
ModifiableOneTimeCost,
ModifiableSustainedCost,
@@ -12,12 +11,15 @@ import {
OneTimeCost,
SingleOneTimeCost,
SustainedCost,
} from "optolith-database-schema/types/_ActivatableSkillCost"
import { GetById } from "../../../../helpers/getTypes.js"
type OneTimeCostMap,
type SustainedCostMap,
} from "optolith-database-schema/gen"
import type { GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import {
appendNoteIfRequested,
getResponsiveText,
getResponsiveTextOptional,
replaceTextIfRequested,
responsive,
ResponsiveTextSize,
@@ -34,7 +36,7 @@ import {
import { getModifiableBySpeed, Speed } from "./speed.js"
const getModifiableOneTimeCostTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
responsiveTextSize: ResponsiveTextSize,
entity: Entity,
@@ -42,7 +44,7 @@ const getModifiableOneTimeCostTranslation = (
value: ModifiableOneTimeCost,
): string =>
mapNullable(
getSkillModificationLevelById(value.initial_modification_level),
getInstanceById("SkillModificationLevel", value.initial_modification_level),
modificationLevel => {
const cost = getModifiableBySpeed(
config => config.cost,
@@ -75,13 +77,15 @@ const getNonModifiableOneTimeCostPerCountableTranslation = (
const countableText = responsive(
responsiveTextSize,
() => locale.translate(" per {0}", entity),
() => locale.translate("/{0}", entity),
() => locale.translate(" per {$value}", { value: entity }),
() => locale.translate("/{$value}", { value: entity }),
)
const minimumTotalText =
mapNullable(perCountable.minimum_total, minimumTotal =>
locale.translate(", minimum of {0}", formatCost(minimumTotal)),
locale.translate(", minimum of {$value}", {
value: formatCost(minimumTotal),
}),
) ?? ""
return countableText + minimumTotalText
@@ -96,8 +100,14 @@ const getPermanentValueTranslation = (
? ""
: responsive(
responsiveTextSize,
() => locale.translate(", {0} of which are permanent", permanentValue),
() => locale.translate(" ({0} perm.)", permanentValue),
() =>
locale.translate(
".input {$value :number} {{, {$value} of which are permanent}}",
{
value: permanentValue,
},
),
() => locale.translate(" ({$value} perm.)", { value: permanentValue }),
)
const getNonModifiableOneTimeCostTranslation = (
@@ -164,36 +174,36 @@ const getIndefiniteOneTimeCostTranslation = (
)
const getSingleOneTimeCostTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
value: SingleOneTimeCost,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Modifiable":
return getModifiableOneTimeCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
responsiveTextSize,
entity,
speed,
value.modifiable,
value.Modifiable,
)
case "NonModifiable":
return getNonModifiableOneTimeCostTranslation(
locale,
entity,
responsiveTextSize,
value.non_modifiable,
value.NonModifiable,
)
case "Indefinite":
return getIndefiniteOneTimeCostTranslation(
locale,
entity,
responsiveTextSize,
value.indefinite,
value.Indefinite,
)
default:
return assertExhaustive(value)
@@ -202,14 +212,14 @@ const getSingleOneTimeCostTranslation = (
const getMultipleOneTimeCostsTranslation = (
type: "conjunction" | "disjunction",
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
value: MultipleOneTimeCosts,
): string => {
const modifiable = !value.every(part => part.tag === "Modifiable")
const modifiable = !value.every(part => part.kind === "Modifiable")
? getNonModifiableSuffixTranslation(
locale,
entity,
@@ -222,7 +232,7 @@ const getMultipleOneTimeCostsTranslation = (
value
.map(part =>
getSingleOneTimeCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
entity,
@@ -253,11 +263,11 @@ const getMultipleOneTimeCostsTranslation = (
)
}
const getCostMapTranslation = (
const getOneTimeCostMapTranslation = (
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
value: CostMap,
value: OneTimeCostMap,
): string => {
const translation = locale.translateMap(value.translations)
@@ -266,7 +276,14 @@ const getCostMapTranslation = (
}
if (translation?.replacement !== undefined) {
return translation.replacement
const res = getResponsiveTextOptional(
translation.replacement,
responsiveTextSize,
)
if (res !== undefined) {
return res
}
}
const labels = value.options
@@ -304,62 +321,116 @@ const getCostMapTranslation = (
labels +
(translation?.list_append ?? "") +
(permanentCosts !== undefined
? locale.translate(
", {0} of which are permanent",
formatCostP(permanentCosts),
)
? locale.translate(", {$value} of which are permanent", {
value: formatCostP(permanentCosts),
})
: "") +
notModifiable
)
}
const getSustainedCostMapTranslation = (
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
value: SustainedCostMap,
): string => {
const translation = locale.translateMap(value.translations)
if (value.translations !== undefined && translation === undefined) {
return MISSING_VALUE
}
if (translation?.replacement !== undefined) {
const res = getResponsiveTextOptional(
translation.replacement,
responsiveTextSize,
)
if (res !== undefined) {
return res
}
}
const labels = value.options
.map(
option =>
locale.translateMap(option.translations)?.label ?? MISSING_VALUE,
)
.join("/")
const costs = value.options.map(option => option.value).join("/")
const formatCostP = formatEnergyByEntity.bind(this, locale, entity)
const notModifiable = getNonModifiableSuffixTranslation(
locale,
entity,
ModifiableParameter.Cost,
responsiveTextSize,
)
return (
formatCostP(costs) +
locale.translate(" for ") +
mapNullableDefault(
translation?.listPrefix,
listPrepend => `${listPrepend} `,
"",
) +
labels +
(translation?.listSuffix ?? "") +
notModifiable
)
}
/**
* Returns the text for the cost of a one-time activatable skill.
*/
export const getOneTimeCostTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
value: OneTimeCost,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Single":
return getSingleOneTimeCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
entity,
responsiveTextSize,
value.single,
value.Single,
)
case "Conjunction":
return getMultipleOneTimeCostsTranslation(
"conjunction",
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
entity,
responsiveTextSize,
value.conjunction,
value.Conjunction,
)
case "Disjunction":
return getMultipleOneTimeCostsTranslation(
"disjunction",
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
entity,
responsiveTextSize,
value.disjunction,
value.Disjunction,
)
case "Map":
return getCostMapTranslation(
return getOneTimeCostMapTranslation(
locale,
entity,
responsiveTextSize,
value.map,
value.Map,
)
default:
return assertExhaustive(value)
@@ -367,7 +438,7 @@ export const getOneTimeCostTranslation = (
}
const getModifiableSustainedCostTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
entity: Entity,
@@ -375,7 +446,7 @@ const getModifiableSustainedCostTranslation = (
value: ModifiableSustainedCost,
) =>
mapNullable(
getSkillModificationLevelById(value.initial_modification_level),
getInstanceById("SkillModificationLevel", value.initial_modification_level),
modificationLevel => {
const cost = getModifiableBySpeed(
config => config.cost,
@@ -397,11 +468,13 @@ const getModifiableSustainedCostTranslation = (
responsiveTextSize,
() =>
`${formatCostP(cost) + locale.translate(" (casting)")} + ${
formatCostP(cost / 2) + locale.translate(" per {0}", interval)
formatCostP(cost / 2) +
locale.translate(" per {$value}", { value: interval })
}`,
() =>
`${formatCostP(cost)} + ${
formatCostP(cost / 2) + locale.translate("/{0}", interval)
formatCostP(cost / 2) +
locale.translate("/{$value}", { value: interval })
}`,
)
},
@@ -427,16 +500,15 @@ const getNonModifiableSustainedCostTranslation = (
const perCountable = responsive(
responsiveTextSize,
() => locale.translate(" per {0}", countable),
() => locale.translate("/{0}", countable),
() => locale.translate(" per {$value}", { value: countable }),
() => locale.translate("/{$value}", { value: countable }),
)
const minimumTotal =
value.per.minimum_total !== undefined
? locale.translate(
", minimum of {0}",
formatCostP(value.per.minimum_total),
)
? locale.translate(", minimum of {$value}", {
value: formatCostP(value.per.minimum_total),
})
: ""
return { countable: perCountable, minimumTotal }
@@ -458,13 +530,13 @@ const getNonModifiableSustainedCostTranslation = (
? locale.translate("half of the activation cost")
: formatCostP(value.value / 2)) +
per.countable +
locale.translate(" per {0}", interval)
locale.translate(" per {$value}", { value: interval })
}`,
() =>
`${formatCostP(value.value)} + ${
(value.is_minimum === true ? "50%" : formatCostP(value.value / 2)) +
per.countable +
locale.translate("/{0}", interval)
locale.translate("/{$value}", { value: interval })
}`,
) + per.minimumTotal
@@ -490,29 +562,36 @@ const getNonModifiableSustainedCostTranslation = (
* Returns the text for the cost of a sustained activatable skill.
*/
export const getSustainedCostTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
value: SustainedCost,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Modifiable":
return getModifiableSustainedCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
entity,
responsiveTextSize,
value.modifiable,
value.Modifiable,
)
case "NonModifiable":
return getNonModifiableSustainedCostTranslation(
locale,
entity,
responsiveTextSize,
value.non_modifiable,
value.NonModifiable,
)
case "Map":
return getSustainedCostMapTranslation(
locale,
entity,
responsiveTextSize,
value.Map,
)
default:
return assertExhaustive(value)
@@ -1,17 +1,20 @@
import { mapNullable } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { CastingTimeDuringLovemaking } from "optolith-database-schema/types/_ActivatableSkillCastingTime"
import {
import type {
BlessingDuration,
CantripDuration,
CastingTimeDuringLovemaking,
CheckResultBasedDuration,
DurationForOneTime,
DurationForSustained,
FixedDuration,
Immediate,
IndefiniteBlessingDuration,
IndefiniteBlessingDurationTranslation,
IndefiniteDuration,
IndefiniteDurationTranslation,
PermanentDuration,
} from "optolith-database-schema/types/_ActivatableSkillDuration"
import { BlessingDuration } from "optolith-database-schema/types/Blessing"
import { CantripDuration } from "optolith-database-schema/types/Cantrip"
} from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import {
getResponsiveText,
@@ -40,8 +43,8 @@ const getImmediateDurationTranslation = (
return responsive(
responsiveTextSize,
() => locale.translate("no more than {0}", maxText),
() => locale.translate("max. {0}", maxText),
() => locale.translate("no more than {$value}", { value: maxText }),
() => locale.translate("max. {$value}", { value: maxText }),
)
}),
locale.translate("Immediate"),
@@ -115,12 +118,16 @@ const getCheckResultBasedDurationTranslation = (
const getIndefiniteDurationTranslation = (
locale: LocaleEnvironment,
responsiveTextSize: ResponsiveTextSize,
value: IndefiniteDuration,
) =>
getResponsiveText(
locale.translateMap(value.translations)?.description,
responsiveTextSize,
)
value: IndefiniteDuration | IndefiniteBlessingDuration,
) => {
const description = locale.translateMap<
IndefiniteDurationTranslation | IndefiniteBlessingDurationTranslation
>(value.translations)?.description
return typeof description === "string"
? description
: getResponsiveText(description, responsiveTextSize)
}
/**
* Returns the text for the duration of a one-time activatable skill.
@@ -130,36 +137,36 @@ export const getDurationForOneTimeTranslation = (
responsiveTextSize: ResponsiveTextSize,
value: DurationForOneTime,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Immediate":
return getImmediateDurationTranslation(
locale,
responsiveTextSize,
value.immediate,
value.Immediate,
)
case "Permanent":
return getPermanentDurationTranslation(
locale,
responsiveTextSize,
value.permanent,
value.Permanent,
)
case "Fixed":
return getFixedDurationTranslation(
locale,
responsiveTextSize,
value.fixed,
value.Fixed,
)
case "CheckResultBased":
return getCheckResultBasedDurationTranslation(
locale,
responsiveTextSize,
value.check_result_based,
value.CheckResultBased,
)
case "Indefinite":
return getIndefiniteDurationTranslation(
locale,
responsiveTextSize,
value.indefinite,
value.Indefinite,
)
default:
return assertExhaustive(value)
@@ -205,30 +212,26 @@ export const getDurationTranslationForCantrip = (
responsiveTextSize: ResponsiveTextSize,
value: CantripDuration,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Immediate":
return getImmediateDurationTranslation(
locale,
responsiveTextSize,
value.immediate,
)
return getImmediateDurationTranslation(locale, responsiveTextSize, {})
case "Fixed":
return getFixedDurationTranslation(
locale,
responsiveTextSize,
value.fixed,
value.Fixed,
)
case "Indefinite":
return getIndefiniteDurationTranslation(
locale,
responsiveTextSize,
value.indefinite,
value.Indefinite,
)
case "DuringLovemaking":
return getDurationDuringLovemakingTranslation(
locale,
responsiveTextSize,
value.during_lovemaking,
value.DuringLovemaking,
)
default:
return assertExhaustive(value)
@@ -243,24 +246,20 @@ export const getDurationTranslationForBlessing = (
responsiveTextSize: ResponsiveTextSize,
value: BlessingDuration,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Immediate":
return getImmediateDurationTranslation(
locale,
responsiveTextSize,
value.immediate,
)
return getImmediateDurationTranslation(locale, responsiveTextSize, {})
case "Fixed":
return getFixedDurationTranslation(
locale,
responsiveTextSize,
value.fixed,
value.Fixed,
)
case "Indefinite":
return getIndefiniteDurationTranslation(
locale,
responsiveTextSize,
value.indefinite,
value.Indefinite,
)
default:
return assertExhaustive(value)
@@ -1,7 +1,7 @@
import { filterNonNullable } from "@optolith/helpers/array"
import { mapNullable } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { ActivatableSkillEffect } from "optolith-database-schema/types/_ActivatableSkillEffect"
import type { ActivatableSkillEffect } from "optolith-database-schema/gen"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { EntityDescriptionSection } from "../../../../index.js"
@@ -21,7 +21,9 @@ const getContentPartsForQualityLevels = (
},
...source.quality_levels.map((text, index) => ({
value: text,
label: locale.translate("QL {0}", getQualityLevelString(index)),
label: locale.translate("QL {$value}", {
value: getQualityLevelString(index),
}),
})),
mapNullable(source.text_after, textAfter => ({
value: textAfter,
@@ -36,25 +38,25 @@ export const getTextForEffect = (
locale: LocaleEnvironment,
effect: ActivatableSkillEffect,
): EntityDescriptionSection[] => {
switch (effect.tag) {
switch (effect.kind) {
case "Plain":
return [
{
label: locale.translate("Effect"),
value: effect.plain.text,
value: effect.Plain.text,
},
]
case "ForEachQualityLevel":
return getContentPartsForQualityLevels(
index => index + 1,
locale,
effect.for_each_quality_level,
effect.ForEachQualityLevel,
)
case "ForEachTwoQualityLevels":
return getContentPartsForQualityLevels(
index => `${index * 2 + 1}${index * 2 + 2}`,
locale,
effect.for_each_two_quality_levels,
effect.ForEachTwoQualityLevels,
)
default:
return assertExhaustive(effect)
+19 -19
View File
@@ -1,10 +1,10 @@
import {
import type {
FastOneTimePerformanceParameters,
FastSustainedPerformanceParameters,
SlowOneTimePerformanceParameters,
SlowSustainedPerformanceParameters,
} from "optolith-database-schema/types/_ActivatableSkill"
import { GetById } from "../../../../helpers/getTypes.js"
} from "optolith-database-schema/gen"
import type { GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { ResponsiveTextSize } from "../../responsiveText.js"
import {
@@ -27,7 +27,7 @@ import { Speed } from "./speed.js"
* Get the texts for all fast one-time performance parameters.
*/
export const getFastOneTimePerformanceParametersTranslations = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
@@ -39,14 +39,14 @@ export const getFastOneTimePerformanceParametersTranslations = (
duration: string
} => ({
castingTime: getFastCastingTimeTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
entity,
responsiveTextSize,
value.casting_time,
),
cost: getOneTimeCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Fast,
entity,
@@ -54,7 +54,7 @@ export const getFastOneTimePerformanceParametersTranslations = (
value.cost,
),
range: getTextForActivatableSkillRange(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Fast,
responsiveTextSize,
@@ -72,7 +72,7 @@ export const getFastOneTimePerformanceParametersTranslations = (
* Get the texts for all fast sustained performance parameters.
*/
export const getFastSustainedPerformanceParametersTranslations = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
@@ -84,14 +84,14 @@ export const getFastSustainedPerformanceParametersTranslations = (
duration: string
} => ({
castingTime: getFastCastingTimeTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
entity,
responsiveTextSize,
value.casting_time,
),
cost: getSustainedCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Fast,
entity,
@@ -99,7 +99,7 @@ export const getFastSustainedPerformanceParametersTranslations = (
value.cost,
),
range: getTextForActivatableSkillRange(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Fast,
responsiveTextSize,
@@ -117,7 +117,7 @@ export const getFastSustainedPerformanceParametersTranslations = (
* Get the texts for all slow one-time performance parameters.
*/
export const getSlowOneTimePerformanceParametersTranslations = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
@@ -129,14 +129,14 @@ export const getSlowOneTimePerformanceParametersTranslations = (
duration: string
} => ({
castingTime: getSlowCastingTimeTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
entity,
responsiveTextSize,
value.casting_time,
),
cost: getOneTimeCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Slow,
entity,
@@ -144,7 +144,7 @@ export const getSlowOneTimePerformanceParametersTranslations = (
value.cost,
),
range: getTextForActivatableSkillRange(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Slow,
responsiveTextSize,
@@ -162,7 +162,7 @@ export const getSlowOneTimePerformanceParametersTranslations = (
* Get the texts for all slow sustained performance parameters.
*/
export const getSlowSustainedPerformanceParametersTranslations = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
entity: Entity,
responsiveTextSize: ResponsiveTextSize,
@@ -174,14 +174,14 @@ export const getSlowSustainedPerformanceParametersTranslations = (
duration: string
} => ({
castingTime: getSlowCastingTimeTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
entity,
responsiveTextSize,
value.casting_time,
),
cost: getSustainedCostTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Slow,
entity,
@@ -189,7 +189,7 @@ export const getSlowSustainedPerformanceParametersTranslations = (
value.cost,
),
range: getTextForActivatableSkillRange(
getSkillModificationLevelById,
getInstanceById,
locale,
Speed.Slow,
responsiveTextSize,
@@ -11,8 +11,8 @@ export const wrapAsMinimum = (
): string =>
responsive(
responsiveTextSize,
() => locale.translate("at least {0}", text),
() => locale.translate("min. {0}", text),
() => locale.translate("at least {$value}", { value: text }),
() => locale.translate("min. {$value}", { value: text }),
)
/**
@@ -37,8 +37,8 @@ export const wrapAsMaximum = (
): string =>
responsive(
responsiveTextSize,
() => locale.translate("no more than {0}", text),
() => locale.translate("max. {0}", text),
() => locale.translate("no more than {$value}", { value: text }),
() => locale.translate("max. {$value}", { value: text }),
)
/**
@@ -1,7 +1,7 @@
import { mapNullable } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { UI } from "optolith-database-schema/types/UI"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import type { Translations } from "../../../../helpers/translate.js"
import { responsive, ResponsiveTextSize } from "../../responsiveText.js"
import { Entity } from "./entity.js"
@@ -14,13 +14,7 @@ export enum ModifiableParameter {
Range,
}
const translationKeyForNonModifiableSuffix: {
[entityKey in Entity]:
| {
[paramKey in ModifiableParameter]: keyof UI
}
| undefined
} = {
const translationKeyForNonModifiableSuffix = {
[Entity.Spell]: {
[ModifiableParameter.CastingTime]:
" (you cannot use a modification on this spells casting time)",
@@ -55,6 +49,12 @@ const translationKeyForNonModifiableSuffix: {
},
[Entity.Cantrip]: undefined,
[Entity.Blessing]: undefined,
} satisfies {
[entityKey in Entity]:
| {
[paramKey in ModifiableParameter]: keyof Translations
}
| undefined
}
/**
+22 -22
View File
@@ -1,15 +1,15 @@
import { mapNullable } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
import type {
BlessingRange,
CantripRange,
CheckResultBasedRange,
FixedRange,
ModifiableRange,
Range,
RangeValue,
} from "optolith-database-schema/types/_ActivatableSkillRange"
import { BlessingRange } from "optolith-database-schema/types/Blessing"
import { CantripRange } from "optolith-database-schema/types/Cantrip"
import { GetById } from "../../../../helpers/getTypes.js"
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import {
appendNoteIfRequested,
@@ -28,14 +28,14 @@ import {
import { getModifiableBySpeed, Speed } from "./speed.js"
const getModifiableRangeTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
responsiveTextSize: ResponsiveTextSize,
value: ModifiableRange,
) =>
mapNullable(
getSkillModificationLevelById(value.initial_modification_level),
getInstanceById("SkillModificationLevel", value.initial_modification_level),
modificationLevel => {
const range = getModifiableBySpeed(
config => config.range,
@@ -80,7 +80,7 @@ const getFixedRangeTranslation = (
responsiveTextSize: ResponsiveTextSize,
value: FixedRange,
) =>
formatLength(locale, responsiveTextSize, value.unit, value.value) +
formatLength(locale, responsiveTextSize, value.unit.kind, value.value) +
getNonModifiableSuffixTranslation(
locale,
entity,
@@ -103,7 +103,7 @@ const getCheckResultBasedRangeTranslation = (
const range = formatLength(
locale,
responsiveTextSize,
value.unit,
value.unit.kind,
getCheckResultBasedValueTranslation(locale.translate, value),
)
@@ -128,21 +128,21 @@ const getCheckResultBasedRangeTranslation = (
}
const getRangeValueTranslation = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
responsiveTextSize: ResponsiveTextSize,
entity: Entity,
value: RangeValue,
) => {
switch (value.tag) {
switch (value.kind) {
case "Modifiable":
return getModifiableRangeTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
responsiveTextSize,
value.modifiable,
value.Modifiable,
)
case "Sight":
return getSightTranslation(locale)
@@ -157,7 +157,7 @@ const getRangeValueTranslation = (
locale,
entity,
responsiveTextSize,
value.fixed,
value.Fixed,
)
}
case "CheckResultBased":
@@ -165,7 +165,7 @@ const getRangeValueTranslation = (
locale,
entity,
responsiveTextSize,
value.check_result_based,
value.CheckResultBased,
)
default:
return assertExhaustive(value)
@@ -176,7 +176,7 @@ const getRangeValueTranslation = (
* Returns the text for the range of an activatable skill.
*/
export const getTextForActivatableSkillRange = (
getSkillModificationLevelById: GetById.Static.SkillModificationLevel,
getInstanceById: GetInstanceById<"SkillModificationLevel">,
locale: LocaleEnvironment,
speed: Speed,
responsiveTextSize: ResponsiveTextSize,
@@ -184,7 +184,7 @@ export const getTextForActivatableSkillRange = (
value: Range,
): string => {
const rangeValue = getRangeValueTranslation(
getSkillModificationLevelById,
getInstanceById,
locale,
speed,
responsiveTextSize,
@@ -209,13 +209,13 @@ export const getTextForActivatableSkillRange = (
)
}
const getTextForTinyAcitvatableRange = (
const getTextForTinyActivatableRange = (
locale: LocaleEnvironment,
responsiveTextSize: ResponsiveTextSize,
entity: Entity,
value: CantripRange | BlessingRange,
): string => {
switch (value.tag) {
switch (value.kind) {
case "Self":
return getSelfTranslation(locale)
case "Touch":
@@ -225,7 +225,7 @@ const getTextForTinyAcitvatableRange = (
locale,
entity,
responsiveTextSize,
value.fixed,
value.Fixed,
)
default:
return assertExhaustive(value)
@@ -240,7 +240,7 @@ export const getTextForCantripRange = (
responsiveTextSize: ResponsiveTextSize,
value: CantripRange,
): string =>
getTextForTinyAcitvatableRange(
getTextForTinyActivatableRange(
locale,
responsiveTextSize,
Entity.Cantrip,
@@ -255,7 +255,7 @@ export const getTextForBlessingRange = (
responsiveTextSize: ResponsiveTextSize,
value: BlessingRange,
): string =>
getTextForTinyAcitvatableRange(
getTextForTinyActivatableRange(
locale,
responsiveTextSize,
Entity.Blessing,
@@ -3,7 +3,7 @@ import {
FastSkillModificationLevelConfig,
SkillModificationLevel,
SlowSkillModificationLevelConfig,
} from "optolith-database-schema/types/SkillModificationLevel"
} from "optolith-database-schema/gen"
/**
* The speed of an activatable skill.
@@ -1,11 +1,10 @@
import { mapNullable } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
import type {
AffectedTargetCategories,
SpecificAffectedTargetCategoryIdentifier,
} from "optolith-database-schema/types/_ActivatableSkillTargetCategory"
import { TargetCategoryReference } from "optolith-database-schema/types/_SimpleReferences"
import { GetById } from "../../../../helpers/getTypes.js"
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../../helpers/getTypes.js"
import { LocaleEnvironment } from "../../../../helpers/locale.js"
import { EntityDescriptionSection } from "../../../../index.js"
import { MISSING_VALUE } from "../../unknown.js"
@@ -21,45 +20,40 @@ const getLiturgicalChantsAndCeremoniesTranslation = (
locale: LocaleEnvironment,
) => locale.translate("Liturgical Chants and Ceremonies")
const getSpellworksTranslation = (locale: LocaleEnvironment) =>
locale.translate("Spellworks")
const getCantripsTranslation = (locale: LocaleEnvironment) =>
locale.translate("Cantrips")
const getPredefinedTranslation = (
getTargetCategoryById: GetById.Static.TargetCategory,
getInstanceById: GetInstanceById<"TargetCategory">,
locale: LocaleEnvironment,
value: TargetCategoryReference,
) => {
const numericId = value.id.target_category
const specificTargetCategory = getTargetCategoryById(numericId)
return (
mapNullable(
locale.translateMap(specificTargetCategory?.translations),
translation => translation.name,
) ?? MISSING_VALUE
)
}
id: string,
) =>
mapNullable(
locale.translateMap(getInstanceById("TargetCategory", id)?.translations),
translation => translation.name,
) ?? MISSING_VALUE
const getTargetCategoryTranslationByType = (
getTargetCategoryById: GetById.Static.TargetCategory,
getInstanceById: GetInstanceById<"TargetCategory">,
locale: LocaleEnvironment,
id: SpecificAffectedTargetCategoryIdentifier,
) => {
switch (id.tag) {
switch (id.kind) {
case "Self":
return getSelfTranslation(locale)
case "Zone":
return getZoneTranslation(locale)
case "LiturgicalChantsAndCeremonies":
return getLiturgicalChantsAndCeremoniesTranslation(locale)
case "Spellworks":
return getSpellworksTranslation(locale)
case "Cantrips":
return getCantripsTranslation(locale)
case "Predefined":
return getPredefinedTranslation(
getTargetCategoryById,
locale,
id.predefined,
)
return getPredefinedTranslation(getInstanceById, locale, id.Predefined)
default:
return assertExhaustive(id)
}
@@ -69,7 +63,7 @@ const getTargetCategoryTranslationByType = (
* Get the text for the target category.
*/
export const getTargetCategoryTranslation = (
getTargetCategoryById: GetById.Static.TargetCategory,
getInstanceById: GetInstanceById<"TargetCategory">,
locale: LocaleEnvironment,
values: AffectedTargetCategories,
): EntityDescriptionSection => ({
@@ -81,11 +75,7 @@ export const getTargetCategoryTranslation = (
.map(({ id, translations }) =>
appendInParensIfNotEmpty(
locale.translateMap(translations)?.note,
getTargetCategoryTranslationByType(
getTargetCategoryById,
locale,
id,
),
getTargetCategoryTranslationByType(getInstanceById, locale, id),
),
)
.join(", "),
@@ -1,4 +1,4 @@
import { ImprovementCost as RawImprovementCost } from "optolith-database-schema/types/_ImprovementCost"
import type { ImprovementCost } from "optolith-database-schema/gen"
import { Translate } from "../../../helpers/translate.js"
import { EntityDescriptionSection } from "../../../index.js"
@@ -7,8 +7,8 @@ import { EntityDescriptionSection } from "../../../index.js"
*/
export const createImprovementCost = (
translate: Translate,
improvementCost: RawImprovementCost,
improvementCost: ImprovementCost,
): EntityDescriptionSection => ({
label: translate("Improvement Cost"),
value: improvementCost,
value: improvementCost.kind,
})
+19 -13
View File
@@ -1,10 +1,10 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import {
import type {
DerivedCharacteristic,
SkillCheck,
SkillCheckPenalty,
} from "optolith-database-schema/types/_SkillCheck"
import { DerivedCharacteristic } from "optolith-database-schema/types/DerivedCharacteristic"
import { GetById } from "../../../helpers/getTypes.js"
} from "optolith-database-schema/gen"
import { type GetInstanceById } from "../../../helpers/getTypes.js"
import { Translate, TranslateMap } from "../../../helpers/translate.js"
import { EntityDescriptionSection } from "../../../index.js"
import { responsive, ResponsiveTextSize } from "../responsiveText.js"
@@ -16,7 +16,7 @@ export const getTextForCheck = (
deps: {
translate: Translate
translateMap: TranslateMap
getAttributeById: GetById.Static.Attribute
getInstanceById: GetInstanceById<"Attribute">
},
check: SkillCheck,
checkPenalty?: {
@@ -30,8 +30,8 @@ export const getTextForCheck = (
value:
check
.map(
({ id: { attribute: id } }) =>
deps.translateMap(deps.getAttributeById(id)?.translations)
id =>
deps.translateMap(deps.getInstanceById("Attribute", id)?.translations)
?.abbreviation ?? "??",
)
.join("/") +
@@ -53,7 +53,7 @@ export const getTextForCheck = (
getDerivedCharacteristicTranslation(checkPenalty.getToughness)
const penalty = (() => {
switch (checkPenalty.value) {
switch (checkPenalty.value.kind) {
case "Spirit": {
const translation = getSpiritTranslation()
return translation === undefined
@@ -97,9 +97,11 @@ export const getTextForCheck = (
responsiveText,
() =>
deps.translate(
"{0} or {1}, depending on which value is higher",
spiritTranslation.abbreviation,
toughnessTranslation.abbreviation,
"{$first} or {$second}, depending on which value is higher",
{
first: spiritTranslation.abbreviation,
second: toughnessTranslation.abbreviation,
},
),
() =>
`${spiritTranslation.abbreviation}/${toughnessTranslation.abbreviation}`,
@@ -120,6 +122,9 @@ export const getTextForCheck = (
() => deps.translate("CD"),
)
case "Object":
return deps.translate("Object")
default:
return assertExhaustive(checkPenalty.value)
}
@@ -127,8 +132,9 @@ export const getTextForCheck = (
return responsive(
responsiveText,
() => deps.translate(" (modified by {0})", penalty),
() => deps.translate(" ( {0})", penalty),
() =>
deps.translate(" (modified by {$modifier})", { modifier: penalty }),
() => deps.translate(" ({$modifier})", { modifier: penalty }),
)
})(),
})
+3 -4
View File
@@ -1,12 +1,11 @@
import { mapNullable } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { LocaleMap } from "optolith-database-schema/types/_LocaleMap"
import {
import type {
ResponsiveText,
ResponsiveTextOptional,
ResponsiveTextReplace,
} from "optolith-database-schema/types/_ResponsiveText"
import { TranslateMap } from "../../helpers/translate.js"
} from "optolith-database-schema/gen"
import { TranslateMap, type LocaleMap } from "../../helpers/translate.js"
import { appendInParensIfNotEmpty } from "./rated/activatable/parensIf.js"
import { MISSING_VALUE } from "./unknown.js"
+7 -7
View File
@@ -1,15 +1,15 @@
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { UI } from "optolith-database-schema/types/UI"
import { LocaleEnvironment } from "../../../helpers/locale.js"
import type { Translations } from "../../../helpers/translate.js"
import { Entity } from "../rated/activatable/entity.js"
type EnergyUnit = "ArcaneEnergy" | "KarmaPoints"
const lengthUnitTranslationKeys: {
[key in EnergyUnit]: keyof UI
} = {
ArcaneEnergy: "{0} AE",
KarmaPoints: "{0} KP",
const lengthUnitTranslationKeys = {
ArcaneEnergy: "{$value} AE",
KarmaPoints: "{$value} KP",
} as const satisfies {
[key in EnergyUnit]: keyof Translations
}
/**
@@ -22,7 +22,7 @@ export const formatEnergy = (
): string => {
const key = lengthUnitTranslationKeys[unit]
return locale.translate(key, value)
return locale.translate(key, { value })
}
/**
+25 -9
View File
@@ -1,14 +1,26 @@
import { UI } from "optolith-database-schema/types/UI"
import { LocaleEnvironment } from "../../../helpers/locale.js"
import type { Translations } from "../../../helpers/translate.js"
import { responsive, ResponsiveTextSize } from "../responsiveText.js"
type LengthUnit = "Steps" | "Miles"
const lengthUnitTranslationKeys: {
[key in LengthUnit]: [full: keyof UI, compressed: keyof UI]
} = {
Steps: ["{0} yards", "{0} yd"],
Miles: ["{0} miles", "{0} mi."],
const lengthUnitTranslationKeys = {
Steps: [
".input {$value :number} {{{$value} yards}}",
"{$value} yards",
"{$value} yd",
],
Miles: [
".input {$value :number} {{{$value} miles}}",
"{$value} miles",
"{$value} mi.",
],
} as const satisfies {
[key in LengthUnit]: [
fullNumber: keyof Translations,
full: keyof Translations,
compressed: keyof Translations,
]
}
/**
@@ -20,11 +32,15 @@ export const formatLength = (
unit: LengthUnit,
value: number | string,
) => {
const [fullKey, compressedKey] = lengthUnitTranslationKeys[unit]
const [fullNumberKey, fullKey, compressedKey] =
lengthUnitTranslationKeys[unit]
return responsive(
responsiveTextSize,
() => locale.translate(fullKey, value),
() => locale.translate(compressedKey, value),
() =>
locale.translate(typeof value === "number" ? fullNumberKey : fullKey, {
value,
}),
() => locale.translate(compressedKey, { value }),
)
}
+29 -20
View File
@@ -1,5 +1,5 @@
import { UI } from "optolith-database-schema/types/UI"
import { LocaleEnvironment } from "../../../helpers/locale.js"
import type { Translations } from "../../../helpers/translate.js"
import { ResponsiveTextSize, responsive } from "../responsiveText.js"
type TimeSpanUnit =
@@ -16,21 +16,26 @@ type TimeSpanUnit =
| "SeductionActions"
| "Rounds"
const timeSpanUnitTranslationKeys: {
[key in TimeSpanUnit]: [full: keyof UI, compressed: keyof UI]
} = {
Seconds: ["{0} seconds", "{0} s"],
Minutes: ["{0} minutes", "{0} min"],
Hours: ["{0} hours", "{0} h"],
Days: ["{0} days", "{0} d"],
Weeks: ["{0} weeks", "{0} wks."],
Months: ["{0} months", "{0} mos."],
Years: ["{0} years", "{0} yrs."],
Centuries: ["{0} centuries", "{0} cent."],
Actions: ["{0} actions", "{0} act"],
CombatRounds: ["{0} combat rounds", "{0} CR"],
SeductionActions: ["{0} seduction actions", "{0} SA"],
Rounds: ["{0} rounds", "{0} rnds"],
// prettier-ignore
const timeSpanUnitTranslationKeys = {
Seconds: [".input {$value :number} {{{$value} seconds}}", "{$value} seconds", "{$value} s"],
Minutes: [".input {$value :number} {{{$value} minutes}}", "{$value} minutes", "{$value} min"],
Hours: [".input {$value :number} {{{$value} hours}}", "{$value} hours", "{$value} h"],
Days: [".input {$value :number} {{{$value} days}}", "{$value} days", "{$value} d"],
Weeks: [".input {$value :number} {{{$value} weeks}}", "{$value} weeks", ".input {$value :number} {{{$value} wks.}}"],
Months: [".input {$value :number} {{{$value} months}}", "{$value} months", ".input {$value :number} {{{$value} mos.}}"],
Years: [".input {$value :number} {{{$value} years}}", "{$value} years", ".input {$value :number} {{{$value} yrs.}}"],
Centuries: [".input {$value :number} {{{$value} centuries}}", "{$value} centuries", "{$value} cent."],
Actions: [".input {$value :number} {{{$value} actions}}", "{$value} actions", "{$value} act"],
CombatRounds: [".input {$value :number} {{{$value} combat rounds}}", "{$value} combat rounds", "{$value} CR"],
SeductionActions: [".input {$value :number} {{{$value} seduction actions}}", "{$value} seduction actions", "{$value} SA"],
Rounds: [".input {$value :number} {{{$value} rounds}}", "{$value} rounds", "{$value} rnds"],
} as const satisfies {
[key in TimeSpanUnit]: [
fullNumber: keyof Translations,
full: keyof Translations,
compressed: keyof Translations,
]
}
/**
@@ -39,14 +44,18 @@ const timeSpanUnitTranslationKeys: {
export const formatTimeSpan = (
locale: LocaleEnvironment,
responsiveTextSize: ResponsiveTextSize,
unit: TimeSpanUnit,
unit: { kind: TimeSpanUnit },
value: number | string,
): string => {
const [fullKey, compressedKey] = timeSpanUnitTranslationKeys[unit]
const [fullNumberKey, fullKey, compressedKey] =
timeSpanUnitTranslationKeys[unit.kind]
return responsive(
responsiveTextSize,
() => locale.translate(fullKey, value),
() => locale.translate(compressedKey, value),
() =>
locale.translate(typeof value === "number" ? fullNumberKey : fullKey, {
value,
}),
() => locale.translate(compressedKey, { value }),
)
}
+55 -51
View File
@@ -1,9 +1,12 @@
import { isNotNullish } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { NewApplicationsAndUsesCache } from "optolith-database-schema/cache/newApplicationsAndUses"
import { Skill } from "optolith-database-schema/types/Skill"
import type { Skill } from "optolith-database-schema/gen"
import { createEntityDescriptionCreator } from "../creator.js"
import { All, GetById } from "../helpers/getTypes.js"
import type {
GetAllChildInstancesForParent,
GetAllInstances,
GetInstanceById,
} from "../helpers/getTypes.js"
import { createImprovementCost } from "./partial/rated/improvementCost.js"
import { getTextForCheck } from "./partial/rated/skillCheck.js"
@@ -13,17 +16,22 @@ import { getTextForCheck } from "./partial/rated/skillCheck.js"
export const getSkillEntityDescription = createEntityDescriptionCreator<
Skill,
{
getAttributeById: GetById.Static.Attribute
blessedTraditions: All.Static.BlessedTraditions
diseases: All.Static.Diseases
regions: All.Static.Regions
cache: NewApplicationsAndUsesCache
getInstanceById: GetInstanceById<"Attribute">
getAllInstances: GetAllInstances<
| "BlessedTradition"
| "Disease"
| "Region"
| "SkillUse"
| "NewSkillApplication"
>
getChildInstancesForInstanceId: GetAllChildInstancesForParent<"SkillApplication">
}
>(
(
{ getAttributeById, blessedTraditions, diseases, regions, cache },
{ getInstanceById, getAllInstances, getChildInstancesForInstanceId },
{ translate, translateMap, compare: localeCompare },
entry,
id,
) => {
const translation = translateMap(entry.translations)
@@ -31,51 +39,47 @@ export const getSkillEntityDescription = createEntityDescriptionCreator<
return undefined
}
const newApplications = (
entry === undefined ? [] : cache.newApplications[entry.id] ?? []
)
.map(x => translateMap(x.data.translations)?.name)
const newApplications = getAllInstances("NewSkillApplication")
.filter(application => application.skills.includes(id))
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
const uses = (entry === undefined ? [] : cache.uses[entry.id] ?? [])
.map(x => translateMap(x.data.translations)?.name)
const uses = getAllInstances("SkillUse")
.filter(use => use.skills.includes(id))
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
const applications = (() => {
switch (entry.applications.tag) {
case "Derived":
return (() => {
switch (entry.applications.derived) {
case "BlessedTraditions":
return Object.values(blessedTraditions)
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
case "Diseases":
return Object.values(diseases)
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
case "Regions":
return Object.values(regions)
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
default:
return assertExhaustive(entry.applications.derived)
}
})()
case "Explicit":
return entry.applications.explicit
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
default:
return assertExhaustive(entry.applications)
}
})()
const applications = [
...getChildInstancesForInstanceId("SkillApplication", id)
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare),
...(() => {
switch (entry.applications.derived?.kind) {
case "BlessedTraditions":
return getAllInstances("BlessedTradition")
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
case "Diseases":
return getAllInstances("Disease")
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
case "Regions":
return getAllInstances("Region")
.map(x => translateMap(x.translations)?.name)
.filter(isNotNullish)
.sort(localeCompare)
case undefined:
return []
default:
return assertExhaustive(entry.applications.derived)
}
})(),
]
return {
title: translation.name,
@@ -94,7 +98,7 @@ export const getSkillEntityDescription = createEntityDescriptionCreator<
value: uses.join(", "),
},
getTextForCheck(
{ translate, translateMap, getAttributeById },
{ translate, translateMap, getInstanceById },
entry.check,
),
{
@@ -104,9 +108,9 @@ export const getSkillEntityDescription = createEntityDescriptionCreator<
{
label: translate("Encumbrance"),
value:
entry.encumbrance === "True"
entry.encumbrance.kind === "Yes"
? translate("Yes")
: entry.encumbrance === "False"
: entry.encumbrance.kind === "No"
? translate("No")
: translation.encumbrance_description ?? translate("Maybe"),
},
+316 -363
View File
@@ -1,17 +1,17 @@
import { Compare } from "@optolith/helpers/compare"
import { isNotNullish, mapNullable } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { Cantrip } from "optolith-database-schema/types/Cantrip"
import { DerivedCharacteristic } from "optolith-database-schema/types/DerivedCharacteristic"
import { Ritual } from "optolith-database-schema/types/Ritual"
import { Spell } from "optolith-database-schema/types/Spell"
import {
MagicalTraditionReference,
PropertyReference,
} from "optolith-database-schema/types/_SimpleReferences"
import { Traditions } from "optolith-database-schema/types/_Spellwork"
import type {
Cantrip,
DerivedCharacteristic,
MagicalTradition_ID,
Property_ID,
Ritual,
Spell,
SpellworkTraditions,
} from "optolith-database-schema/gen"
import { createEntityDescriptionCreator } from "../creator.js"
import { GetById } from "../helpers/getTypes.js"
import type { GetInstanceById } from "../helpers/getTypes.js"
import { Translate, TranslateMap } from "../helpers/translate.js"
import { EntityDescriptionSection } from "../index.js"
import { getDurationTranslationForCantrip } from "./partial/rated/activatable/duration.js"
@@ -34,12 +34,12 @@ const getTextForProperty = (
deps: {
translate: Translate
translateMap: TranslateMap
getPropertyById: GetById.Static.Property
getInstanceById: GetInstanceById<"Property">
},
value: PropertyReference,
id: Property_ID,
): EntityDescriptionSection => {
const text = (() => {
const staticEntry = deps.getPropertyById(value.id.property)
const staticEntry = deps.getInstanceById("Property", id)
const staticEntryTranslation = deps.translateMap(staticEntry?.translations)
if (staticEntryTranslation === undefined) {
@@ -60,22 +60,20 @@ const getTextForTraditions = (
translate: Translate
translateMap: TranslateMap
localeCompare: Compare<string>
getMagicalTraditionById: GetById.Static.MagicalTradition
getInstanceById: GetInstanceById<"MagicalTradition">
},
value: Traditions,
value: SpellworkTraditions,
): EntityDescriptionSection => {
const text = (() => {
switch (value.tag) {
switch (value.kind) {
case "General":
return deps.translate("General")
case "Specific":
return value.specific
.map(trad =>
deps.translateMap(
deps.getMagicalTraditionById(trad.magical_tradition)
?.translations,
),
)
return value.Specific.map(trad =>
deps.translateMap(
deps.getInstanceById("MagicalTradition", trad)?.translations,
),
)
.filter(isNotNullish)
.map(trad => trad.name_for_arcane_spellworks ?? trad.name)
.sort(deps.localeCompare)
@@ -92,12 +90,12 @@ const getTextForTraditions = (
}
const getTraditionNameForArcaneSpellworksById = (
ref: MagicalTraditionReference,
getMagicalTraditionById: GetById.Static.MagicalTradition,
id: MagicalTradition_ID,
getInstanceById: GetInstanceById<"MagicalTradition">,
translateMap: TranslateMap,
) => {
const translation = translateMap(
getMagicalTraditionById(ref.id.magical_tradition)?.translations,
getInstanceById("MagicalTradition", id)?.translations,
)
return translation?.name_for_arcane_spellworks ?? translation?.name
}
@@ -108,133 +106,118 @@ const getTraditionNameForArcaneSpellworksById = (
export const getCantripEntityDescription = createEntityDescriptionCreator<
Cantrip,
{
getTargetCategoryById: GetById.Static.TargetCategory
getPropertyById: GetById.Static.Property
getMagicalTraditionById: GetById.Static.MagicalTradition
getCurriculumById: GetById.Static.Curriculum
getInstanceById: GetInstanceById<
"TargetCategory" | "Property" | "MagicalTradition" | "Curriculum"
>
}
>(
(
{
getTargetCategoryById,
getPropertyById,
getMagicalTraditionById,
getCurriculumById,
},
>(({ getInstanceById }, locale, entry) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
if (translation === undefined) {
return undefined
}
const range = getTextForCantripRange(
locale,
entry,
) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
ResponsiveTextSize.Full,
entry.parameters.range,
)
if (translation === undefined) {
return undefined
}
const duration = getDurationTranslationForCantrip(
locale,
ResponsiveTextSize.Full,
entry.parameters.duration,
)
const range = getTextForCantripRange(
locale,
ResponsiveTextSize.Full,
entry.parameters.range,
)
const duration = getDurationTranslationForCantrip(
locale,
ResponsiveTextSize.Full,
entry.parameters.duration,
)
return {
title: translation.name,
className: "cantrip",
body: [
{
label: translate("Effect"),
value: translation.effect,
},
{
label: translate("Range"),
value:
range !== translation.range
? `***${range}*** (${translation.range})`
: range,
},
{
label: translate("Duration"),
value:
duration !== translation.duration
? `***${duration}*** (${translation.duration})`
: duration,
},
getTargetCategoryTranslation(
getTargetCategoryById,
locale,
entry.target,
),
getTextForProperty(
{ translate, translateMap, getPropertyById },
entry.property,
),
mapNullable(entry.note, note => ({
label: translate("Note"),
value: (() => {
switch (note.tag) {
case "Common":
return note.common.list
.map(academyOrTradition => {
switch (academyOrTradition.tag) {
case "Academy":
return translateMap(
getCurriculumById(
academyOrTradition.academy.id.curriculum,
)?.translations,
)?.name
case "Tradition": {
return mapNullable(
getTraditionNameForArcaneSpellworksById(
academyOrTradition.tradition,
getMagicalTraditionById,
translateMap,
return {
title: translation.name,
className: "cantrip",
body: [
{
label: translate("Effect"),
value: translation.effect,
},
{
label: translate("Range"),
value:
range !== translation.range
? `***${range}*** (${translation.range})`
: range,
},
{
label: translate("Duration"),
value:
duration !== translation.duration
? `***${duration}*** (${translation.duration})`
: duration,
},
getTargetCategoryTranslation(getInstanceById, locale, entry.target),
getTextForProperty(
{ translate, translateMap, getInstanceById },
entry.property,
),
mapNullable(entry.note, note => ({
label: translate("Note"),
value: (() => {
switch (note.kind) {
case "Common":
return note.Common.list
.map(academyOrTradition => {
switch (academyOrTradition.kind) {
case "Academy":
return translateMap(
getInstanceById(
"Curriculum",
academyOrTradition.Academy,
)?.translations,
)?.name
case "Tradition": {
return mapNullable(
getTraditionNameForArcaneSpellworksById(
academyOrTradition.Tradition.id,
getInstanceById,
translateMap,
),
name =>
name +
parensIf(
translateMap(
academyOrTradition.Tradition.translations,
)?.note,
),
name =>
name +
parensIf(
translateMap(
academyOrTradition.tradition.translations,
)?.note,
),
)
}
default:
return assertExhaustive(academyOrTradition)
)
}
})
.filter(isNotNullish)
.sort(localeCompare)
.join(", ")
default:
return assertExhaustive(academyOrTradition)
}
})
.filter(isNotNullish)
.sort(localeCompare)
.join(", ")
case "Exclusive":
return note.exclusive.traditions
.map(tradition =>
getTraditionNameForArcaneSpellworksById(
tradition,
getMagicalTraditionById,
translateMap,
),
)
.filter(isNotNullish)
.sort(localeCompare)
.join(", ")
case "Exclusive":
return note.Exclusive.traditions
.map(tradition =>
getTraditionNameForArcaneSpellworksById(
tradition,
getInstanceById,
translateMap,
),
)
.filter(isNotNullish)
.sort(localeCompare)
.join(", ")
default:
return assertExhaustive(note)
}
})(),
})),
],
references: entry.src,
}
},
)
default:
return assertExhaustive(note)
}
})(),
})),
],
references: entry.src,
}
})
/**
* Get a JSON representation of the rules text for a skill.
@@ -242,122 +225,107 @@ export const getCantripEntityDescription = createEntityDescriptionCreator<
export const getSpellEntityDescription = createEntityDescriptionCreator<
Spell,
{
getAttributeById: GetById.Static.Attribute
getInstanceById: GetInstanceById<
| "Attribute"
| "SkillModificationLevel"
| "TargetCategory"
| "Property"
| "MagicalTradition"
>
getSpirit: () => DerivedCharacteristic | undefined
getToughness: () => DerivedCharacteristic | undefined
getSkillModificationLevelById: GetById.Static.SkillModificationLevel
getTargetCategoryById: GetById.Static.TargetCategory
getPropertyById: GetById.Static.Property
getMagicalTraditionById: GetById.Static.MagicalTradition
}
>(
(
{
getAttributeById,
getSpirit,
getToughness,
getSkillModificationLevelById,
getTargetCategoryById,
getPropertyById,
getMagicalTraditionById,
},
locale,
entry,
) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
>(({ getInstanceById, getSpirit, getToughness }, locale, entry) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
if (translation === undefined) {
return undefined
}
if (translation === undefined) {
return undefined
}
const { castingTime, cost, range, duration } = (() => {
switch (entry.parameters.tag) {
case "OneTime":
return getFastOneTimePerformanceParametersTranslations(
getSkillModificationLevelById,
locale,
Entity.Spell,
ResponsiveTextSize.Full,
entry.parameters.one_time,
)
case "Sustained":
return getFastSustainedPerformanceParametersTranslations(
getSkillModificationLevelById,
locale,
Entity.Spell,
ResponsiveTextSize.Full,
entry.parameters.sustained,
)
default:
return assertExhaustive(entry.parameters)
}
})()
return {
title: translation.name,
className: "spell",
body: [
getTextForCheck(
{ translate, translateMap, getAttributeById },
entry.check,
{
value: entry.check_penalty,
responsiveText: ResponsiveTextSize.Full,
getSpirit,
getToughness,
},
),
...getTextForEffect(locale, translation.effect),
{
label: translate("Casting Time"),
value:
castingTime !== translation.casting_time.full
? `***${castingTime}*** (${translation.casting_time.full})`
: castingTime,
},
{
label: translate("AE Cost"),
value:
cost !== translation.cost.full
? `***${cost}*** (${translation.cost.full})`
: cost,
},
{
label: translate("Range"),
value:
range !== translation.range.full
? `***${range}*** (${translation.range.full})`
: range,
},
{
label: translate("Duration"),
value:
duration !== translation.duration.full
? `***${duration}*** (${translation.duration.full})`
: duration,
},
getTargetCategoryTranslation(
getTargetCategoryById,
const { castingTime, cost, range, duration } = (() => {
switch (entry.parameters.kind) {
case "OneTime":
return getFastOneTimePerformanceParametersTranslations(
getInstanceById,
locale,
entry.target,
),
getTextForProperty(
{ translate, translateMap, getPropertyById },
entry.property,
),
getTextForTraditions(
{ translate, translateMap, localeCompare, getMagicalTraditionById },
entry.traditions,
),
createImprovementCost(translate, entry.improvement_cost),
],
references: entry.src,
Entity.Spell,
ResponsiveTextSize.Full,
entry.parameters.OneTime,
)
case "Sustained":
return getFastSustainedPerformanceParametersTranslations(
getInstanceById,
locale,
Entity.Spell,
ResponsiveTextSize.Full,
entry.parameters.Sustained,
)
default:
return assertExhaustive(entry.parameters)
}
},
)
})()
return {
title: translation.name,
className: "spell",
body: [
getTextForCheck(
{ translate, translateMap, getInstanceById },
entry.check,
{
value: entry.check_penalty,
responsiveText: ResponsiveTextSize.Full,
getSpirit,
getToughness,
},
),
...getTextForEffect(locale, translation.effect),
{
label: translate("Casting Time"),
value:
translation.casting_time &&
castingTime !== translation.casting_time.full
? `***${castingTime}*** (${translation.casting_time.full})`
: castingTime,
},
{
label: translate("AE Cost"),
value:
translation.cost && cost !== translation.cost.full
? `***${cost}*** (${translation.cost.full})`
: cost,
},
{
label: translate("Range"),
value:
translation.range && range !== translation.range.full
? `***${range}*** (${translation.range.full})`
: range,
},
{
label: translate("Duration"),
value:
translation.duration && duration !== translation.duration.full
? `***${duration}*** (${translation.duration.full})`
: duration,
},
getTargetCategoryTranslation(getInstanceById, locale, entry.target),
getTextForProperty(
{ translate, translateMap, getInstanceById },
entry.property,
),
getTextForTraditions(
{ translate, translateMap, localeCompare, getInstanceById },
entry.traditions,
),
createImprovementCost(translate, entry.improvement_cost),
],
references: entry.src,
}
})
/**
* Get a JSON representation of the rules text for a ritual.
@@ -365,119 +333,104 @@ export const getSpellEntityDescription = createEntityDescriptionCreator<
export const getRitualEntityDescription = createEntityDescriptionCreator<
Ritual,
{
getAttributeById: GetById.Static.Attribute
getInstanceById: GetInstanceById<
| "Attribute"
| "SkillModificationLevel"
| "TargetCategory"
| "Property"
| "MagicalTradition"
>
getSpirit: () => DerivedCharacteristic | undefined
getToughness: () => DerivedCharacteristic | undefined
getSkillModificationLevelById: GetById.Static.SkillModificationLevel
getTargetCategoryById: GetById.Static.TargetCategory
getPropertyById: GetById.Static.Property
getMagicalTraditionById: GetById.Static.MagicalTradition
}
>(
(
{
getAttributeById,
getSpirit,
getToughness,
getSkillModificationLevelById,
getTargetCategoryById,
getPropertyById,
getMagicalTraditionById,
},
locale,
entry,
) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
>(({ getInstanceById, getSpirit, getToughness }, locale, entry) => {
const { translate, translateMap, compare: localeCompare } = locale
const translation = translateMap(entry.translations)
if (translation === undefined) {
return undefined
}
if (translation === undefined) {
return undefined
}
const { castingTime, cost, range, duration } = (() => {
switch (entry.parameters.tag) {
case "OneTime":
return getSlowOneTimePerformanceParametersTranslations(
getSkillModificationLevelById,
locale,
Entity.Ritual,
ResponsiveTextSize.Full,
entry.parameters.one_time,
)
case "Sustained":
return getSlowSustainedPerformanceParametersTranslations(
getSkillModificationLevelById,
locale,
Entity.Ritual,
ResponsiveTextSize.Full,
entry.parameters.sustained,
)
default:
return assertExhaustive(entry.parameters)
}
})()
return {
title: translation.name,
className: "ritual",
body: [
getTextForCheck(
{ translate, translateMap, getAttributeById },
entry.check,
{
value: entry.check_penalty,
responsiveText: ResponsiveTextSize.Full,
getSpirit,
getToughness,
},
),
...getTextForEffect(locale, translation.effect),
{
label: translate("Ritual Time"),
value:
castingTime !== translation.casting_time.full
? `***${castingTime}*** (${translation.casting_time.full})`
: castingTime,
},
{
label: translate("AE Cost"),
value:
cost !== translation.cost.full
? `***${cost}*** (${translation.cost.full})`
: cost,
},
{
label: translate("Range"),
value:
range !== translation.range.full
? `***${range}*** (${translation.range.full})`
: range,
},
{
label: translate("Duration"),
value:
duration !== translation.duration.full
? `***${duration}*** (${translation.duration.full})`
: duration,
},
getTargetCategoryTranslation(
getTargetCategoryById,
const { castingTime, cost, range, duration } = (() => {
switch (entry.parameters.kind) {
case "OneTime":
return getSlowOneTimePerformanceParametersTranslations(
getInstanceById,
locale,
entry.target,
),
getTextForProperty(
{ translate, translateMap, getPropertyById },
entry.property,
),
getTextForTraditions(
{ translate, translateMap, localeCompare, getMagicalTraditionById },
entry.traditions,
),
createImprovementCost(translate, entry.improvement_cost),
],
references: entry.src,
Entity.Ritual,
ResponsiveTextSize.Full,
entry.parameters.OneTime,
)
case "Sustained":
return getSlowSustainedPerformanceParametersTranslations(
getInstanceById,
locale,
Entity.Ritual,
ResponsiveTextSize.Full,
entry.parameters.Sustained,
)
default:
return assertExhaustive(entry.parameters)
}
},
)
})()
return {
title: translation.name,
className: "ritual",
body: [
getTextForCheck(
{ translate, translateMap, getInstanceById },
entry.check,
{
value: entry.check_penalty,
responsiveText: ResponsiveTextSize.Full,
getSpirit,
getToughness,
},
),
...getTextForEffect(locale, translation.effect),
{
label: translate("Ritual Time"),
value:
translation.casting_time &&
castingTime !== translation.casting_time.full
? `***${castingTime}*** (${translation.casting_time.full})`
: castingTime,
},
{
label: translate("AE Cost"),
value:
translation.cost && cost !== translation.cost.full
? `***${cost}*** (${translation.cost.full})`
: cost,
},
{
label: translate("Range"),
value:
translation.range && range !== translation.range.full
? `***${range}*** (${translation.range.full})`
: range,
},
{
label: translate("Duration"),
value:
translation.duration && duration !== translation.duration.full
? `***${duration}*** (${translation.duration.full})`
: duration,
},
getTargetCategoryTranslation(getInstanceById, locale, entry.target),
getTextForProperty(
{ translate, translateMap, getInstanceById },
entry.property,
),
getTextForTraditions(
{ translate, translateMap, localeCompare, getInstanceById },
entry.traditions,
),
createImprovementCost(translate, entry.improvement_cost),
],
references: entry.src,
}
})
+20
View File
@@ -0,0 +1,20 @@
/**
* Creates an enum case object.
*/
export const Case = (<K extends string, T>(
kind: K,
value: T,
): T extends NonNullable<unknown> | null
? { kind: K } & { [Key in K]: Extract<T, NonNullable<unknown> | null> }
: { kind: K } =>
(value === undefined
? { kind }
: { kind, [kind]: value }) as T extends NonNullable<unknown> | null
? { kind: K } & { [Key in K]: Extract<T, NonNullable<unknown> | null> }
: { kind: K }) as {
<K extends string>(kind: K): { kind: K }
<K extends string, T extends NonNullable<unknown> | null>(
kind: K,
value: T,
): { kind: K } & { [Key in K]: T }
}
+14 -492
View File
@@ -1,497 +1,19 @@
/* eslint-disable jsdoc/require-jsdoc */
/* eslint-disable @typescript-eslint/no-namespace */
import { config as advantageConfig } from "optolith-database-schema/types/Advantage"
import { config as animalDiseaseConfig } from "optolith-database-schema/types/AnimalDisease"
import { config as animalTypeConfig } from "optolith-database-schema/types/AnimalType"
import { config as arcaneBardTraditionConfig } from "optolith-database-schema/types/ArcaneBardTradition"
import { config as arcaneDancerTraditionConfig } from "optolith-database-schema/types/ArcaneDancerTradition"
import { config as aspectConfig } from "optolith-database-schema/types/Aspect"
import { config as attributeConfig } from "optolith-database-schema/types/Attribute"
import { config as blessingConfig } from "optolith-database-schema/types/Blessing"
import { config as cantripConfig } from "optolith-database-schema/types/Cantrip"
import { config as ceremonyConfig } from "optolith-database-schema/types/Ceremony"
import { config as closeCombatTechniqueConfig } from "optolith-database-schema/types/CombatTechnique_Close"
import { config as rangedCombatTechniqueConfig } from "optolith-database-schema/types/CombatTechnique_Ranged"
import { config as conditionConfig } from "optolith-database-schema/types/Condition"
import { config as continentConfig } from "optolith-database-schema/types/Continent"
import { config as cultureConfig } from "optolith-database-schema/types/Culture"
import { config as derivedCharacteristicConfig } from "optolith-database-schema/types/DerivedCharacteristic"
import { config as disadvantageConfig } from "optolith-database-schema/types/Disadvantage"
import { config as diseaseConfig } from "optolith-database-schema/types/Disease"
import { config as elementConfig } from "optolith-database-schema/types/Element"
import { config as experienceLevelConfig } from "optolith-database-schema/types/ExperienceLevel"
import { config as eyeColorConfig } from "optolith-database-schema/types/EyeColor"
import { config as familiarsTrickConfig } from "optolith-database-schema/types/FamiliarsTrick"
import { config as hairColorConfig } from "optolith-database-schema/types/HairColor"
import { config as kirchenpraegungConfig } from "optolith-database-schema/types/Kirchenpraegung"
import { config as curriculumConfig } from "optolith-database-schema/types/Lessons_Curriculum"
import { config as guidelineConfig } from "optolith-database-schema/types/Lessons_Guideline"
import { config as liturgicalChantConfig } from "optolith-database-schema/types/LiturgicalChant"
import { config as localeConfig } from "optolith-database-schema/types/Locale"
import { config as metaConditionConfig } from "optolith-database-schema/types/MetaCondition"
import { config as pactCategoryConfig } from "optolith-database-schema/types/PactCategory"
import { config as patronConfig } from "optolith-database-schema/types/Patron"
import { config as patronCategoryConfig } from "optolith-database-schema/types/PatronCategory"
import { config as personalityTraitConfig } from "optolith-database-schema/types/PersonalityTrait"
import { config as professionConfig } from "optolith-database-schema/types/Profession"
import { config as propertyConfig } from "optolith-database-schema/types/Property"
import { config as raceConfig } from "optolith-database-schema/types/Race"
import { config as regionConfig } from "optolith-database-schema/types/Region"
import { config as ritualConfig } from "optolith-database-schema/types/Ritual"
import { config as serviceConfig } from "optolith-database-schema/types/Service"
import { config as sexPracticeConfig } from "optolith-database-schema/types/SexPractice"
import { config as skillConfig } from "optolith-database-schema/types/Skill"
import { config as skillGroupConfig } from "optolith-database-schema/types/SkillGroup"
import { config as skillModificationLevelConfig } from "optolith-database-schema/types/SkillModificationLevel"
import { config as socialStatusConfig } from "optolith-database-schema/types/SocialStatus"
import { config as spellConfig } from "optolith-database-schema/types/Spell"
import { config as stateConfig } from "optolith-database-schema/types/State"
import { config as talismanConfig } from "optolith-database-schema/types/Talisman"
import { config as targetCategoryConfig } from "optolith-database-schema/types/TargetCategory"
import { config as uIConfig } from "optolith-database-schema/types/UI"
import { config as equipmentPackageConfig } from "optolith-database-schema/types/equipment/EquipmentPackage"
import { config as ammunitionConfig } from "optolith-database-schema/types/equipment/item/Ammunition"
import { config as animalConfig } from "optolith-database-schema/types/equipment/item/Animal"
import { config as animalCareConfig } from "optolith-database-schema/types/equipment/item/AnimalCare"
import { config as armorConfig } from "optolith-database-schema/types/equipment/item/Armor"
import { config as bandageOrRemedyConfig } from "optolith-database-schema/types/equipment/item/BandageOrRemedy"
import { config as bookConfig } from "optolith-database-schema/types/equipment/item/Book"
import { config as ceremonialItemConfig } from "optolith-database-schema/types/equipment/item/CeremonialItem"
import { config as clothesConfig } from "optolith-database-schema/types/equipment/item/Clothes"
import { config as containerConfig } from "optolith-database-schema/types/equipment/item/Container"
import { config as elixirConfig } from "optolith-database-schema/types/equipment/item/Elixir"
import { config as equipmentOfBlessedOnesConfig } from "optolith-database-schema/types/equipment/item/EquipmentOfBlessedOnes"
import { config as gemOrPreciousStoneConfig } from "optolith-database-schema/types/equipment/item/GemOrPreciousStone"
import { config as illuminationLightSourceConfig } from "optolith-database-schema/types/equipment/item/IlluminationLightSource"
import { config as illuminationRefillsOrSuppliesConfig } from "optolith-database-schema/types/equipment/item/IlluminationRefillsOrSupplies"
import { config as jewelryConfig } from "optolith-database-schema/types/equipment/item/Jewelry"
import { config as liebesspielzeugConfig } from "optolith-database-schema/types/equipment/item/Liebesspielzeug"
import { config as luxuryGoodConfig } from "optolith-database-schema/types/equipment/item/LuxuryGood"
import { config as magicalArtifactConfig } from "optolith-database-schema/types/equipment/item/MagicalArtifact"
import { config as musicalInstrumentConfig } from "optolith-database-schema/types/equipment/item/MusicalInstrument"
import { config as orienteeringAidConfig } from "optolith-database-schema/types/equipment/item/OrienteeringAid"
import { config as poisonConfig } from "optolith-database-schema/types/equipment/item/Poison"
import { config as ropeOrChainConfig } from "optolith-database-schema/types/equipment/item/RopeOrChain"
import { config as stationaryConfig } from "optolith-database-schema/types/equipment/item/Stationary"
import { config as thievesToolConfig } from "optolith-database-schema/types/equipment/item/ThievesTool"
import { config as toolOfTheTradeConfig } from "optolith-database-schema/types/equipment/item/ToolOfTheTrade"
import { config as travelGearOrToolConfig } from "optolith-database-schema/types/equipment/item/TravelGearOrTool"
import { config as vehicleConfig } from "optolith-database-schema/types/equipment/item/Vehicle"
import { config as weaponConfig } from "optolith-database-schema/types/equipment/item/Weapon"
import { config as weaponAccessoryConfig } from "optolith-database-schema/types/equipment/item/WeaponAccessory"
import { config as armorTypeConfig } from "optolith-database-schema/types/equipment/item/sub/ArmorType"
import { config as reachConfig } from "optolith-database-schema/types/equipment/item/sub/Reach"
import { config as animistPowerConfig } from "optolith-database-schema/types/magicalActions/AnimistPower"
import { config as tribeConfig } from "optolith-database-schema/types/magicalActions/AnimistPower_Tribe"
import { config as curseConfig } from "optolith-database-schema/types/magicalActions/Curse"
import { config as dominationRitualConfig } from "optolith-database-schema/types/magicalActions/DominationRitual"
import { config as elvenMagicalSongConfig } from "optolith-database-schema/types/magicalActions/ElvenMagicalSong"
import { config as geodeRitualConfig } from "optolith-database-schema/types/magicalActions/GeodeRitual"
import { config as jesterTrickConfig } from "optolith-database-schema/types/magicalActions/JesterTrick"
import { config as magicalDanceConfig } from "optolith-database-schema/types/magicalActions/MagicalDance"
import { config as magicalMelodyConfig } from "optolith-database-schema/types/magicalActions/MagicalMelody"
import { config as magicalRuneConfig } from "optolith-database-schema/types/magicalActions/MagicalRune"
import { config as zibiljaRitualConfig } from "optolith-database-schema/types/magicalActions/ZibiljaRitual"
import { config as coreRuleConfig } from "optolith-database-schema/types/rule/CoreRule"
import { config as focusRuleConfig } from "optolith-database-schema/types/rule/FocusRule"
import { config as subjectConfig } from "optolith-database-schema/types/rule/FocusRule_Subject"
import { config as optionalRuleConfig } from "optolith-database-schema/types/rule/OptionalRule"
import { config as publicationConfig } from "optolith-database-schema/types/source/Publication"
import { config as advancedCombatSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/AdvancedCombatSpecialAbility"
import { config as advancedKarmaSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/AdvancedKarmaSpecialAbility"
import { config as advancedMagicalSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/AdvancedMagicalSpecialAbility"
import { config as advancedSkillSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/AdvancedSkillSpecialAbility"
import { config as ancestorGlyphConfig } from "optolith-database-schema/types/specialAbility/AncestorGlyph"
import { config as blessedTraditionConfig } from "optolith-database-schema/types/specialAbility/BlessedTradition"
import { config as brawlingSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/BrawlingSpecialAbility"
import { config as ceremonialItemSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/CeremonialItemSpecialAbility"
import { config as combatSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/CombatSpecialAbility"
import { config as combatStyleSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/CombatStyleSpecialAbility"
import { config as commandSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/CommandSpecialAbility"
import { config as familiarSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/FamiliarSpecialAbility"
import { config as fatePointSexSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/FatePointSexSpecialAbility"
import { config as fatePointSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/FatePointSpecialAbility"
import { config as generalSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/GeneralSpecialAbility"
import { config as karmaSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/KarmaSpecialAbility"
import { config as liturgicalStyleSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/LiturgicalStyleSpecialAbility"
import { config as lycantropicGiftConfig } from "optolith-database-schema/types/specialAbility/LycantropicGift"
import { config as magicStyleSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/MagicStyleSpecialAbility"
import { config as magicalSignConfig } from "optolith-database-schema/types/specialAbility/MagicalSign"
import { config as magicalSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/MagicalSpecialAbility"
import { config as magicalTraditionConfig } from "optolith-database-schema/types/specialAbility/MagicalTradition"
import { config as pactGiftConfig } from "optolith-database-schema/types/specialAbility/PactGift"
import { config as protectiveWardingCircleSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/ProtectiveWardingCircleSpecialAbility"
import { config as sermonConfig } from "optolith-database-schema/types/specialAbility/Sermon"
import { config as sexSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/SexSpecialAbility"
import { config as sikaryanDrainSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/SikaryanDrainSpecialAbility"
import { config as skillStyleSpecialAbilityConfig } from "optolith-database-schema/types/specialAbility/SkillStyleSpecialAbility"
import { config as vampiricGiftConfig } from "optolith-database-schema/types/specialAbility/VampiricGift"
import { config as visionConfig } from "optolith-database-schema/types/specialAbility/Vision"
import { config as languageConfig } from "optolith-database-schema/types/specialAbility/sub/Language"
import { config as scriptConfig } from "optolith-database-schema/types/specialAbility/sub/Script"
import { config as tradeSecretConfig } from "optolith-database-schema/types/specialAbility/sub/TradeSecret"
import { config as arcaneOrbEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/ArcaneOrbEnchantment"
import { config as attireEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/AttireEnchantment"
import { config as bowlEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/BowlEnchantment"
import { config as cauldronEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/CauldronEnchantment"
import { config as chronicleEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/ChronicleEnchantment"
import { config as daggerRitualConfig } from "optolith-database-schema/types/traditionArtifacts/DaggerRitual"
import { config as foolsHatEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/FoolsHatEnchantment"
import { config as instrumentEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/InstrumentEnchantment"
import { config as krallenkettenzauberConfig } from "optolith-database-schema/types/traditionArtifacts/Krallenkettenzauber"
import { config as orbEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/OrbEnchantment"
import { config as ringEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/RingEnchantment"
import { config as sickleRitualConfig } from "optolith-database-schema/types/traditionArtifacts/SickleRitual"
import { config as spellSwordEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/SpellSwordEnchantment"
import { config as staffEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/StaffEnchantment"
import { config as toyEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/ToyEnchantment"
import { config as trinkhornzauberConfig } from "optolith-database-schema/types/traditionArtifacts/Trinkhornzauber"
import { config as wandEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/WandEnchantment"
import { config as weaponEnchantmentConfig } from "optolith-database-schema/types/traditionArtifacts/WeaponEnchantment"
import { config as animalShapeConfig } from "optolith-database-schema/types/traditionArtifacts/sub/AnimalShape"
import { config as animalShapePathConfig } from "optolith-database-schema/types/traditionArtifacts/sub/AnimalShapePath"
import { config as animalShapeSizeConfig } from "optolith-database-schema/types/traditionArtifacts/sub/AnimalShapeSize"
import { config as brewConfig } from "optolith-database-schema/types/traditionArtifacts/sub/Brew"
type IdFromConfig<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Config extends { id: (data: any, filePath: string) => string | number },
> = ReturnType<Config["id"]>
import * as Database from "optolith-database-schema/gen"
type TypeFromConfig<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Config extends { id: (data: any, filePath: string) => string | number },
> = Parameters<Config["id"]>[0]
export type GetInstanceById<T extends keyof Database.EntityMap> = <U extends T>(
entity: U,
id: string,
) => Database.EntityMap[U] | undefined
type GetByIdFromConfig<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Config extends { id: (data: any, filePath: string) => string | number },
> = (id: IdFromConfig<Config>) => TypeFromConfig<Config> | undefined
export type GetAllInstances<T extends keyof Database.EntityMap> = <U extends T>(
entity: U,
) => Database.EntityMap[U][]
type AllFromConfig<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Config extends { id: (data: any, filePath: string) => string | number },
> = TypeFromConfig<Config>[]
// prettier-ignore
export namespace GetById {
export namespace Static {
export type AdvancedCombatSpecialAbility = GetByIdFromConfig<typeof advancedCombatSpecialAbilityConfig>
export type AdvancedKarmaSpecialAbility = GetByIdFromConfig<typeof advancedKarmaSpecialAbilityConfig>
export type AdvancedMagicalSpecialAbility = GetByIdFromConfig<typeof advancedMagicalSpecialAbilityConfig>
export type AdvancedSkillSpecialAbility = GetByIdFromConfig<typeof advancedSkillSpecialAbilityConfig>
export type Advantage = GetByIdFromConfig<typeof advantageConfig>
export type Ammunition = GetByIdFromConfig<typeof ammunitionConfig>
export type AncestorGlyph = GetByIdFromConfig<typeof ancestorGlyphConfig>
export type AnimalCare = GetByIdFromConfig<typeof animalCareConfig>
export type AnimalDisease = GetByIdFromConfig<typeof animalDiseaseConfig>
export type Animal = GetByIdFromConfig<typeof animalConfig>
export type AnimalShapePath = GetByIdFromConfig<typeof animalShapePathConfig>
export type AnimalShape = GetByIdFromConfig<typeof animalShapeConfig>
export type AnimalShapeSize = GetByIdFromConfig<typeof animalShapeSizeConfig>
export type AnimalType = GetByIdFromConfig<typeof animalTypeConfig>
export type AnimistPower = GetByIdFromConfig<typeof animistPowerConfig>
export type Tribe = GetByIdFromConfig<typeof tribeConfig>
export type ArcaneBardTradition = GetByIdFromConfig<typeof arcaneBardTraditionConfig>
export type ArcaneDancerTradition = GetByIdFromConfig<typeof arcaneDancerTraditionConfig>
export type ArcaneOrbEnchantment = GetByIdFromConfig<typeof arcaneOrbEnchantmentConfig>
export type Armor = GetByIdFromConfig<typeof armorConfig>
export type ArmorType = GetByIdFromConfig<typeof armorTypeConfig>
export type Aspect = GetByIdFromConfig<typeof aspectConfig>
export type AttireEnchantment = GetByIdFromConfig<typeof attireEnchantmentConfig>
export type Attribute = GetByIdFromConfig<typeof attributeConfig>
export type BandageOrRemedy = GetByIdFromConfig<typeof bandageOrRemedyConfig>
export type BlessedTradition = GetByIdFromConfig<typeof blessedTraditionConfig>
export type Blessing = GetByIdFromConfig<typeof blessingConfig>
export type Book = GetByIdFromConfig<typeof bookConfig>
export type BowlEnchantment = GetByIdFromConfig<typeof bowlEnchantmentConfig>
export type BrawlingSpecialAbility = GetByIdFromConfig<typeof brawlingSpecialAbilityConfig>
export type Brew = GetByIdFromConfig<typeof brewConfig>
export type Cantrip = GetByIdFromConfig<typeof cantripConfig>
export type CauldronEnchantment = GetByIdFromConfig<typeof cauldronEnchantmentConfig>
export type CeremonialItem = GetByIdFromConfig<typeof ceremonialItemConfig>
export type CeremonialItemSpecialAbility = GetByIdFromConfig<typeof ceremonialItemSpecialAbilityConfig>
export type Ceremony = GetByIdFromConfig<typeof ceremonyConfig>
export type ChronicleEnchantment = GetByIdFromConfig<typeof chronicleEnchantmentConfig>
export type CloseCombatTechnique = GetByIdFromConfig<typeof closeCombatTechniqueConfig>
export type Clothes = GetByIdFromConfig<typeof clothesConfig>
export type CombatSpecialAbility = GetByIdFromConfig<typeof combatSpecialAbilityConfig>
export type CombatStyleSpecialAbility = GetByIdFromConfig<typeof combatStyleSpecialAbilityConfig>
export type CommandSpecialAbility = GetByIdFromConfig<typeof commandSpecialAbilityConfig>
export type Condition = GetByIdFromConfig<typeof conditionConfig>
export type Container = GetByIdFromConfig<typeof containerConfig>
export type Continent = GetByIdFromConfig<typeof continentConfig>
export type CoreRule = GetByIdFromConfig<typeof coreRuleConfig>
export type Culture = GetByIdFromConfig<typeof cultureConfig>
export type Curse = GetByIdFromConfig<typeof curseConfig>
export type DaggerRitual = GetByIdFromConfig<typeof daggerRitualConfig>
export type DerivedCharacteristic = GetByIdFromConfig<typeof derivedCharacteristicConfig>
export type Disadvantage = GetByIdFromConfig<typeof disadvantageConfig>
export type Disease = GetByIdFromConfig<typeof diseaseConfig>
export type DominationRitual = GetByIdFromConfig<typeof dominationRitualConfig>
export type Element = GetByIdFromConfig<typeof elementConfig>
export type Elixir = GetByIdFromConfig<typeof elixirConfig>
export type ElvenMagicalSong = GetByIdFromConfig<typeof elvenMagicalSongConfig>
export type EquipmentOfBlessedOnes = GetByIdFromConfig<typeof equipmentOfBlessedOnesConfig>
export type EquipmentPackage = GetByIdFromConfig<typeof equipmentPackageConfig>
export type ExperienceLevel = GetByIdFromConfig<typeof experienceLevelConfig>
export type EyeColor = GetByIdFromConfig<typeof eyeColorConfig>
export type FamiliarSpecialAbility = GetByIdFromConfig<typeof familiarSpecialAbilityConfig>
export type FamiliarsTrick = GetByIdFromConfig<typeof familiarsTrickConfig>
export type FatePointSexSpecialAbility = GetByIdFromConfig<typeof fatePointSexSpecialAbilityConfig>
export type FatePointSpecialAbility = GetByIdFromConfig<typeof fatePointSpecialAbilityConfig>
export type FocusRule = GetByIdFromConfig<typeof focusRuleConfig>
export type Subject = GetByIdFromConfig<typeof subjectConfig>
export type FoolsHatEnchantment = GetByIdFromConfig<typeof foolsHatEnchantmentConfig>
export type GemOrPreciousStone = GetByIdFromConfig<typeof gemOrPreciousStoneConfig>
export type GeneralSpecialAbility = GetByIdFromConfig<typeof generalSpecialAbilityConfig>
export type GeodeRitual = GetByIdFromConfig<typeof geodeRitualConfig>
export type HairColor = GetByIdFromConfig<typeof hairColorConfig>
export type IlluminationLightSource = GetByIdFromConfig<typeof illuminationLightSourceConfig>
export type IlluminationRefillsOrSupplies = GetByIdFromConfig<typeof illuminationRefillsOrSuppliesConfig>
export type InstrumentEnchantment = GetByIdFromConfig<typeof instrumentEnchantmentConfig>
export type JesterTrick = GetByIdFromConfig<typeof jesterTrickConfig>
export type Jewelry = GetByIdFromConfig<typeof jewelryConfig>
export type KarmaSpecialAbility = GetByIdFromConfig<typeof karmaSpecialAbilityConfig>
export type Kirchenpraegung = GetByIdFromConfig<typeof kirchenpraegungConfig>
export type Krallenkettenzauber = GetByIdFromConfig<typeof krallenkettenzauberConfig>
export type Language = GetByIdFromConfig<typeof languageConfig>
export type Curriculum = GetByIdFromConfig<typeof curriculumConfig>
export type Guideline = GetByIdFromConfig<typeof guidelineConfig>
export type Liebesspielzeug = GetByIdFromConfig<typeof liebesspielzeugConfig>
export type LiturgicalChant = GetByIdFromConfig<typeof liturgicalChantConfig>
export type LiturgicalStyleSpecialAbility = GetByIdFromConfig<typeof liturgicalStyleSpecialAbilityConfig>
export type Locale = GetByIdFromConfig<typeof localeConfig>
export type LuxuryGood = GetByIdFromConfig<typeof luxuryGoodConfig>
export type LycantropicGift = GetByIdFromConfig<typeof lycantropicGiftConfig>
export type MagicalArtifact = GetByIdFromConfig<typeof magicalArtifactConfig>
export type MagicalDance = GetByIdFromConfig<typeof magicalDanceConfig>
export type MagicalMelody = GetByIdFromConfig<typeof magicalMelodyConfig>
export type MagicalRune = GetByIdFromConfig<typeof magicalRuneConfig>
export type MagicalSign = GetByIdFromConfig<typeof magicalSignConfig>
export type MagicalSpecialAbility = GetByIdFromConfig<typeof magicalSpecialAbilityConfig>
export type MagicalTradition = GetByIdFromConfig<typeof magicalTraditionConfig>
export type MagicStyleSpecialAbility = GetByIdFromConfig<typeof magicStyleSpecialAbilityConfig>
export type MetaCondition = GetByIdFromConfig<typeof metaConditionConfig>
export type MusicalInstrument = GetByIdFromConfig<typeof musicalInstrumentConfig>
export type OptionalRule = GetByIdFromConfig<typeof optionalRuleConfig>
export type OrbEnchantment = GetByIdFromConfig<typeof orbEnchantmentConfig>
export type OrienteeringAid = GetByIdFromConfig<typeof orienteeringAidConfig>
export type PactCategory = GetByIdFromConfig<typeof pactCategoryConfig>
export type PactGift = GetByIdFromConfig<typeof pactGiftConfig>
export type PatronCategory = GetByIdFromConfig<typeof patronCategoryConfig>
export type Patron = GetByIdFromConfig<typeof patronConfig>
export type PersonalityTrait = GetByIdFromConfig<typeof personalityTraitConfig>
export type Poison = GetByIdFromConfig<typeof poisonConfig>
export type Profession = GetByIdFromConfig<typeof professionConfig>
export type Property = GetByIdFromConfig<typeof propertyConfig>
export type ProtectiveWardingCircleSpecialAbility = GetByIdFromConfig<typeof protectiveWardingCircleSpecialAbilityConfig>
export type Publication = GetByIdFromConfig<typeof publicationConfig>
export type Race = GetByIdFromConfig<typeof raceConfig>
export type RangedCombatTechnique = GetByIdFromConfig<typeof rangedCombatTechniqueConfig>
export type Reach = GetByIdFromConfig<typeof reachConfig>
export type Region = GetByIdFromConfig<typeof regionConfig>
export type RingEnchantment = GetByIdFromConfig<typeof ringEnchantmentConfig>
export type Ritual = GetByIdFromConfig<typeof ritualConfig>
export type RopeOrChain = GetByIdFromConfig<typeof ropeOrChainConfig>
export type Script = GetByIdFromConfig<typeof scriptConfig>
export type Sermon = GetByIdFromConfig<typeof sermonConfig>
export type Service = GetByIdFromConfig<typeof serviceConfig>
export type SexPractice = GetByIdFromConfig<typeof sexPracticeConfig>
export type SexSpecialAbility = GetByIdFromConfig<typeof sexSpecialAbilityConfig>
export type SickleRitual = GetByIdFromConfig<typeof sickleRitualConfig>
export type SikaryanDrainSpecialAbility = GetByIdFromConfig<typeof sikaryanDrainSpecialAbilityConfig>
export type SkillGroup = GetByIdFromConfig<typeof skillGroupConfig>
export type SkillModificationLevel = GetByIdFromConfig<typeof skillModificationLevelConfig>
export type Skill = GetByIdFromConfig<typeof skillConfig>
export type SkillStyleSpecialAbility = GetByIdFromConfig<typeof skillStyleSpecialAbilityConfig>
export type SocialStatus = GetByIdFromConfig<typeof socialStatusConfig>
export type Spell = GetByIdFromConfig<typeof spellConfig>
export type SpellSwordEnchantment = GetByIdFromConfig<typeof spellSwordEnchantmentConfig>
export type StaffEnchantment = GetByIdFromConfig<typeof staffEnchantmentConfig>
export type State = GetByIdFromConfig<typeof stateConfig>
export type Stationary = GetByIdFromConfig<typeof stationaryConfig>
export type Talisman = GetByIdFromConfig<typeof talismanConfig>
export type TargetCategory = GetByIdFromConfig<typeof targetCategoryConfig>
export type ThievesTool = GetByIdFromConfig<typeof thievesToolConfig>
export type ToolOfTheTrade = GetByIdFromConfig<typeof toolOfTheTradeConfig>
export type ToyEnchantment = GetByIdFromConfig<typeof toyEnchantmentConfig>
export type TradeSecret = GetByIdFromConfig<typeof tradeSecretConfig>
export type TravelGearOrTool = GetByIdFromConfig<typeof travelGearOrToolConfig>
export type Trinkhornzauber = GetByIdFromConfig<typeof trinkhornzauberConfig>
export type UI = GetByIdFromConfig<typeof uIConfig>
export type VampiricGift = GetByIdFromConfig<typeof vampiricGiftConfig>
export type Vehicle = GetByIdFromConfig<typeof vehicleConfig>
export type Vision = GetByIdFromConfig<typeof visionConfig>
export type WandEnchantment = GetByIdFromConfig<typeof wandEnchantmentConfig>
export type WeaponAccessory = GetByIdFromConfig<typeof weaponAccessoryConfig>
export type WeaponEnchantment = GetByIdFromConfig<typeof weaponEnchantmentConfig>
export type Weapon = GetByIdFromConfig<typeof weaponConfig>
export type ZibiljaRitual = GetByIdFromConfig<typeof zibiljaRitualConfig>
}
}
// prettier-ignore
export namespace Singleton {
export namespace Static {
export type ExperienceLevel = TypeFromConfig<typeof experienceLevelConfig> | undefined
}
}
// prettier-ignore
export namespace All {
export namespace Static {
export type AdvancedCombatSpecialAbilities = AllFromConfig<typeof advancedCombatSpecialAbilityConfig>
export type AdvancedKarmaSpecialAbilities = AllFromConfig<typeof advancedKarmaSpecialAbilityConfig>
export type AdvancedMagicalSpecialAbilities = AllFromConfig<typeof advancedMagicalSpecialAbilityConfig>
export type AdvancedSkillSpecialAbilities = AllFromConfig<typeof advancedSkillSpecialAbilityConfig>
export type Advantages = AllFromConfig<typeof advantageConfig>
export type Ammunition = AllFromConfig<typeof ammunitionConfig>
export type AncestorGlyphs = AllFromConfig<typeof ancestorGlyphConfig>
export type AnimalCare = AllFromConfig<typeof animalCareConfig>
export type AnimalDiseases = AllFromConfig<typeof animalDiseaseConfig>
export type Animals = AllFromConfig<typeof animalConfig>
export type AnimalShapePaths = AllFromConfig<typeof animalShapePathConfig>
export type AnimalShapes = AllFromConfig<typeof animalShapeConfig>
export type AnimalShapeSizes = AllFromConfig<typeof animalShapeSizeConfig>
export type AnimalTypes = AllFromConfig<typeof animalTypeConfig>
export type AnimistPowers = AllFromConfig<typeof animistPowerConfig>
export type AnimistPowerTribes = AllFromConfig<typeof tribeConfig>
export type ArcaneBardTraditions = AllFromConfig<typeof arcaneBardTraditionConfig>
export type ArcaneDancerTraditions = AllFromConfig<typeof arcaneDancerTraditionConfig>
export type ArcaneOrbEnchantments = AllFromConfig<typeof arcaneOrbEnchantmentConfig>
export type Armors = AllFromConfig<typeof armorConfig>
export type ArmorTypes = AllFromConfig<typeof armorTypeConfig>
export type Aspects = AllFromConfig<typeof aspectConfig>
export type AttireEnchantments = AllFromConfig<typeof attireEnchantmentConfig>
export type Attributes = AllFromConfig<typeof attributeConfig>
export type BandagesAndRemedies = AllFromConfig<typeof bandageOrRemedyConfig>
export type BlessedTraditions = AllFromConfig<typeof blessedTraditionConfig>
export type Blessings = AllFromConfig<typeof blessingConfig>
export type Books = AllFromConfig<typeof bookConfig>
export type BowlEnchantments = AllFromConfig<typeof bowlEnchantmentConfig>
export type BrawlingSpecialAbilities = AllFromConfig<typeof brawlingSpecialAbilityConfig>
export type Brews = AllFromConfig<typeof brewConfig>
export type Cantrips = AllFromConfig<typeof cantripConfig>
export type CauldronEnchantments = AllFromConfig<typeof cauldronEnchantmentConfig>
export type CeremonialItems = AllFromConfig<typeof ceremonialItemConfig>
export type CeremonialItemSpecialAbilities = AllFromConfig<typeof ceremonialItemSpecialAbilityConfig>
export type Ceremonies = AllFromConfig<typeof ceremonyConfig>
export type ChronicleEnchantments = AllFromConfig<typeof chronicleEnchantmentConfig>
export type CloseCombatTechniques = AllFromConfig<typeof closeCombatTechniqueConfig>
export type Clothes = AllFromConfig<typeof clothesConfig>
export type CombatSpecialAbilities = AllFromConfig<typeof combatSpecialAbilityConfig>
export type CombatStyleSpecialAbilities = AllFromConfig<typeof combatStyleSpecialAbilityConfig>
export type CommandSpecialAbilities = AllFromConfig<typeof commandSpecialAbilityConfig>
export type Conditions = AllFromConfig<typeof conditionConfig>
export type Containers = AllFromConfig<typeof containerConfig>
export type Continents = AllFromConfig<typeof continentConfig>
export type CoreRules = AllFromConfig<typeof coreRuleConfig>
export type Cultures = AllFromConfig<typeof cultureConfig>
export type Curses = AllFromConfig<typeof curseConfig>
export type DaggerRituals = AllFromConfig<typeof daggerRitualConfig>
export type DerivedCharacteristics = AllFromConfig<typeof derivedCharacteristicConfig>
export type Disadvantages = AllFromConfig<typeof disadvantageConfig>
export type Diseases = AllFromConfig<typeof diseaseConfig>
export type DominationRituals = AllFromConfig<typeof dominationRitualConfig>
export type Elements = AllFromConfig<typeof elementConfig>
export type Elixirs = AllFromConfig<typeof elixirConfig>
export type ElvenMagicalSongs = AllFromConfig<typeof elvenMagicalSongConfig>
export type EquipmentOfBlessedOnes = AllFromConfig<typeof equipmentOfBlessedOnesConfig>
export type EquipmentPackages = AllFromConfig<typeof equipmentPackageConfig>
export type ExperienceLevels = AllFromConfig<typeof experienceLevelConfig>
export type EyeColors = AllFromConfig<typeof eyeColorConfig>
export type FamiliarSpecialAbilities = AllFromConfig<typeof familiarSpecialAbilityConfig>
export type FamiliarsTricks = AllFromConfig<typeof familiarsTrickConfig>
export type FatePointSexSpecialAbilities = AllFromConfig<typeof fatePointSexSpecialAbilityConfig>
export type FatePointSpecialAbilities = AllFromConfig<typeof fatePointSpecialAbilityConfig>
export type FocusRules = AllFromConfig<typeof focusRuleConfig>
export type FocusRuleSubjects = AllFromConfig<typeof subjectConfig>
export type FoolsHatEnchantments = AllFromConfig<typeof foolsHatEnchantmentConfig>
export type GemsAndPreciousStones = AllFromConfig<typeof gemOrPreciousStoneConfig>
export type GeneralSpecialAbilities = AllFromConfig<typeof generalSpecialAbilityConfig>
export type GeodeRituals = AllFromConfig<typeof geodeRitualConfig>
export type HairColors = AllFromConfig<typeof hairColorConfig>
export type IlluminationLightSources = AllFromConfig<typeof illuminationLightSourceConfig>
export type IlluminationRefillsAndSupplies = AllFromConfig<typeof illuminationRefillsOrSuppliesConfig>
export type InstrumentEnchantments = AllFromConfig<typeof instrumentEnchantmentConfig>
export type JesterTricks = AllFromConfig<typeof jesterTrickConfig>
export type Jewelry = AllFromConfig<typeof jewelryConfig>
export type KarmaSpecialAbilities = AllFromConfig<typeof karmaSpecialAbilityConfig>
export type Kirchenpraegungen = AllFromConfig<typeof kirchenpraegungConfig>
export type Krallenkettenzauber = AllFromConfig<typeof krallenkettenzauberConfig>
export type Languages = AllFromConfig<typeof languageConfig>
export type LessonsCurricula = AllFromConfig<typeof curriculumConfig>
export type LessonsGuidelines = AllFromConfig<typeof guidelineConfig>
export type Liebesspielzeug = AllFromConfig<typeof liebesspielzeugConfig>
export type LiturgicalChants = AllFromConfig<typeof liturgicalChantConfig>
export type LiturgicalStyleSpecialAbilities = AllFromConfig<typeof liturgicalStyleSpecialAbilityConfig>
export type Locales = AllFromConfig<typeof localeConfig>
export type LuxuryGoods = AllFromConfig<typeof luxuryGoodConfig>
export type LycantropicGifts = AllFromConfig<typeof lycantropicGiftConfig>
export type MagicalArtifacts = AllFromConfig<typeof magicalArtifactConfig>
export type MagicalDances = AllFromConfig<typeof magicalDanceConfig>
export type MagicalMelodies = AllFromConfig<typeof magicalMelodyConfig>
export type MagicalRunes = AllFromConfig<typeof magicalRuneConfig>
export type MagicalSigns = AllFromConfig<typeof magicalSignConfig>
export type MagicalSpecialAbilities = AllFromConfig<typeof magicalSpecialAbilityConfig>
export type MagicalTraditions = AllFromConfig<typeof magicalTraditionConfig>
export type MagicStyleSpecialAbilities = AllFromConfig<typeof magicStyleSpecialAbilityConfig>
export type MetaConditions = AllFromConfig<typeof metaConditionConfig>
export type MusicalInstruments = AllFromConfig<typeof musicalInstrumentConfig>
export type OptionalRules = AllFromConfig<typeof optionalRuleConfig>
export type OrbEnchantments = AllFromConfig<typeof orbEnchantmentConfig>
export type OrienteeringAids = AllFromConfig<typeof orienteeringAidConfig>
export type PactCategories = AllFromConfig<typeof pactCategoryConfig>
export type PactGifts = AllFromConfig<typeof pactGiftConfig>
export type PatronCategories = AllFromConfig<typeof patronCategoryConfig>
export type Patrons = AllFromConfig<typeof patronConfig>
export type PersonalityTraits = AllFromConfig<typeof personalityTraitConfig>
export type Poisons = AllFromConfig<typeof poisonConfig>
export type Professions = AllFromConfig<typeof professionConfig>
export type Properties = AllFromConfig<typeof propertyConfig>
export type ProtectiveWardingCircleSpecialAbilities = AllFromConfig<typeof protectiveWardingCircleSpecialAbilityConfig>
export type Publications = AllFromConfig<typeof publicationConfig>
export type Races = AllFromConfig<typeof raceConfig>
export type RangedCombatTechniques = AllFromConfig<typeof rangedCombatTechniqueConfig>
export type Reaches = AllFromConfig<typeof reachConfig>
export type Regions = AllFromConfig<typeof regionConfig>
export type RingEnchantments = AllFromConfig<typeof ringEnchantmentConfig>
export type Rituals = AllFromConfig<typeof ritualConfig>
export type RopesAndChains = AllFromConfig<typeof ropeOrChainConfig>
export type Scripts = AllFromConfig<typeof scriptConfig>
export type Sermons = AllFromConfig<typeof sermonConfig>
export type Services = AllFromConfig<typeof serviceConfig>
export type SexPractices = AllFromConfig<typeof sexPracticeConfig>
export type SexSpecialAbilities = AllFromConfig<typeof sexSpecialAbilityConfig>
export type SickleRituals = AllFromConfig<typeof sickleRitualConfig>
export type SikaryanDrainSpecialAbilities = AllFromConfig<typeof sikaryanDrainSpecialAbilityConfig>
export type SkillGroups = AllFromConfig<typeof skillGroupConfig>
export type SkillModificationLevels = AllFromConfig<typeof skillModificationLevelConfig>
export type Skills = AllFromConfig<typeof skillConfig>
export type SkillStyleSpecialAbilities = AllFromConfig<typeof skillStyleSpecialAbilityConfig>
export type SocialStatuses = AllFromConfig<typeof socialStatusConfig>
export type Spells = AllFromConfig<typeof spellConfig>
export type SpellSwordEnchantments = AllFromConfig<typeof spellSwordEnchantmentConfig>
export type StaffEnchantments = AllFromConfig<typeof staffEnchantmentConfig>
export type States = AllFromConfig<typeof stateConfig>
export type Stationary = AllFromConfig<typeof stationaryConfig>
export type Talismans = AllFromConfig<typeof talismanConfig>
export type TargetCategories = AllFromConfig<typeof targetCategoryConfig>
export type ThievesTools = AllFromConfig<typeof thievesToolConfig>
export type ToolsOfTheTrade = AllFromConfig<typeof toolOfTheTradeConfig>
export type ToyEnchantments = AllFromConfig<typeof toyEnchantmentConfig>
export type TradeSecrets = AllFromConfig<typeof tradeSecretConfig>
export type TravelGearAndTools = AllFromConfig<typeof travelGearOrToolConfig>
export type Trinkhornzauber = AllFromConfig<typeof trinkhornzauberConfig>
export type UI = AllFromConfig<typeof uIConfig>
export type VampiricGifts = AllFromConfig<typeof vampiricGiftConfig>
export type Vehicles = AllFromConfig<typeof vehicleConfig>
export type Visions = AllFromConfig<typeof visionConfig>
export type WandEnchantments = AllFromConfig<typeof wandEnchantmentConfig>
export type WeaponAccessories = AllFromConfig<typeof weaponAccessoryConfig>
export type WeaponEnchantments = AllFromConfig<typeof weaponEnchantmentConfig>
export type Weapons = AllFromConfig<typeof weaponConfig>
export type ZibiljaRituals = AllFromConfig<typeof zibiljaRitualConfig>
}
}
export type GetAllChildInstancesForParent<
T extends keyof Database.ChildEntityMap,
> = <U extends T>(
entity: U,
parentId: Database.ChildEntityMap[U][2],
) => Database.ChildEntityMap[U][0][]
+194 -196
View File
@@ -1,18 +1,16 @@
// TODO: Update for new identifier mappings
/**
* Used identifiers of optional rules.
*/
export enum OptionalRuleIdentifier {
MaximumAttributeScores = 8,
HigherDefenseStats = 17,
MaximumAttributeScores = "9df3e0d5-6aed-4b90-924b-c11603c9bb73",
HigherDefenseStats = "836787b2-eaec-41c3-8fdb-51591415311b",
}
/**
* Used identifiers of races.
*/
export enum RaceIdentifier {
Humans = 1,
Humans = "252841cf-f2d4-4fb9-af56-30de48531db5",
}
/**
@@ -26,46 +24,46 @@ export enum ProfessionIdentifier {
* Used identifiers of eye colors.
*/
export enum EyeColorIdentifier {
Red = 19,
Purple = 20,
Red = "f4990602-5605-4642-9902-5dcca7fe9bb2",
Purple = "84bfd76d-fa4c-4d21-ad27-f6a62343dc9c",
}
/**
* Used identifiers of hair colors.
*/
export enum HairColorIdentifier {
White = 24,
Green = 25,
White = "af44ab84-6bec-4aa8-a97d-72bb40a5eb2a",
Green = "b4140abd-cdb4-43c8-83b1-83e6d1060fef",
}
/**
* Used identifiers of attributes.
*/
export enum AttributeIdentifier {
Courage = 1,
Sagacity = 2,
Intuition = 3,
Charisma = 4,
Dexterity = 5,
Agility = 6,
Constitution = 7,
Strength = 8,
Courage = "88133847-a3ed-413a-bb67-e7b11d1e51ad",
Sagacity = "476dac00-49c1-486e-84bc-0ff669e4a003",
Intuition = "70ce45aa-66b6-4b56-bede-2a7ff6d82448",
Charisma = "f9e8d52f-985a-49c2-af75-9ae9624ad4cb",
Dexterity = "67159a5f-df4a-441f-ad2c-508e69689efb",
Agility = "b4140abd-cdb4-43c8-83b1-83e6d1060fef",
Constitution = "bc55f1aa-4204-42c9-b599-7cca65d9e463",
Strength = "6b7a5e6b-f130-4eae-a45d-a59ece45e50b",
}
/**
* Used identifiers of derived characteristics.
*/
export enum DerivedCharacteristicIdentifier {
LifePoints = 1,
ArcaneEnergy = 2,
KarmaPoints = 3,
Spirit = 4,
Toughness = 5,
Dodge = 6,
Initiative = 7,
Movement = 8,
FatePoints = 9,
WoundThreshold = 10,
LifePoints = "190845e8-c2c8-40ff-8908-248f01b49f8b",
ArcaneEnergy = "f9e8d52f-985a-49c2-af75-9ae9624ad4cb",
KarmaPoints = "42dca192-1cca-4c2e-97d1-8c3599ef022d",
Spirit = "b6f98337-77b4-4f8e-9b6d-fda3a49d5c75",
Toughness = "1fa344af-3e53-4f25-b36a-7f53f51b90f5",
Dodge = "5fc7d5d3-fdf6-4073-afba-3fd511d53c78",
Initiative = "0b97b4ce-75b0-4573-add9-86621dcf52a6",
Movement = "0c634904-d238-47ee-9b0f-2d6a9d5ff63a",
FatePoints = "21beccd1-bcfb-4cfb-b544-9b5066ed242a",
WoundThreshold = "6f1eb396-051b-44c7-a69d-12aba4552891",
}
/**
@@ -80,263 +78,263 @@ export type EnergyIdentifier =
* Used identifiers of skill.
*/
export enum SkillIdentifier {
Flying = 1,
Gaukelei = 2,
Climbing = 3,
BodyControl = 4,
FeatOfStrength = 5,
Riding = 6,
Swimming = 7,
SelfControl = 8,
Singing = 9,
Perception = 10,
Dancing = 11,
Pickpocket = 12,
Stealth = 13,
Carousing = 14,
Persuasion = 15,
Seduction = 16,
Intimidation = 17,
Etiquette = 18,
Streetwise = 19,
Empathy = 20,
FastTalk = 21,
Disguise = 22,
Willpower = 23,
Tracking = 24,
Ropes = 25,
Fishing = 26,
Orienting = 27,
PlantLore = 28,
AnimalLore = 29,
Survival = 30,
Gambling = 31,
Geography = 32,
History = 33,
Religions = 34,
Warfare = 35,
MagicalLore = 36,
Mechanics = 37,
Math = 38,
Law = 39,
MythsAndLegends = 40,
SphereLore = 41,
Astronomy = 42,
Alchemy = 43,
Sailing = 44,
Driving = 45,
Commerce = 46,
TreatPoison = 47,
TreatDisease = 48,
TreatSoul = 49,
TreatWounds = 50,
Woodworking = 51,
PrepareFood = 52,
Leatherworking = 53,
ArtisticAbility = 54,
Metalworking = 55,
Music = 56,
PickLocks = 57,
Earthencraft = 58,
Clothworking = 59,
Flying = "71b25c38-80bc-4218-b020-6b1406c170a5",
Gaukelei = "7a9cddc3-c8ca-4d68-b520-ffd773e44646",
Climbing = "7d10acd5-579f-430a-a07c-5f2c9030c758",
BodyControl = "83c5d33b-145c-4c29-8977-0fbaa4d32666",
FeatOfStrength = "845e9434-24d4-436d-8494-349f6fc00e7a",
Riding = "aa383b7c-aa8c-4ee2-b9da-dd7cd24b8941",
Swimming = "7fc87a4d-3a3a-498b-a12a-2ea5e0c68b19",
SelfControl = "811b1cb3-befa-4c41-b78d-12d55f32dbe9",
Singing = "4d4fbc6b-eb1e-430e-b8af-6af66b5128c2",
Perception = "347ef258-5a4b-4cf1-978a-f36b12196ac3",
Dancing = "c0990597-2334-4fa4-87c5-e3df6166fa9c",
Pickpocket = "87f8f170-9aaf-4ffa-a5e0-bf4473b51458",
Stealth = "344d2656-1541-4ba0-aa5b-238dc6626287",
Carousing = "ae3ff6b5-fc27-4e8b-ac1b-483f071b805e",
Persuasion = "e72ea51a-f411-453d-8920-8aa6f4daab60",
Seduction = "e5934263-9536-4025-ad53-fac54ec9f09b",
Intimidation = "10fd08ac-8e77-4d36-b507-720d4c633222",
Etiquette = "158636a0-8bb7-42d1-8436-2872ef43b75b",
Streetwise = "091e8792-2814-4fac-8c47-82ddb55a1b94",
Empathy = "d2b46106-41ec-4195-80e3-5e19f238084a",
FastTalk = "4a2876be-9146-45d3-b2d5-6fb33cd489aa",
Disguise = "a8ed8b4f-2391-4365-8273-d367617aa800",
Willpower = "d5a8c759-9379-4250-a27f-334a1411068d",
Tracking = "50270926-e802-4f61-92cb-fdd5cb24ddf0",
Ropes = "5cbdc561-368b-4e4e-8f7f-b97e32776815",
Fishing = "a872228e-fd8c-44b4-94e0-cfbdf137633f",
Orienting = "133ea1cb-2ebb-4cfd-a594-a9948f8fb2b6",
PlantLore = "cc6f188c-e271-41fc-9d64-6910c0c6fdc5",
AnimalLore = "a4eecb40-4d3d-4088-be28-366c003911df",
Survival = "2bb0fee1-a2c2-48ba-91a0-e4c362d36335",
Gambling = "c3763aa8-be38-4e73-b738-78bd2d3ae73f",
Geography = "019cc09e-85d7-4ab4-bdb5-6c13af4bf213",
History = "bbee9852-2160-4ff1-b7b9-42bcaa89a19f",
Religions = "8993613b-3f64-4bd9-b51f-8cd0141cfaef",
Warfare = "515f24b0-e580-45f8-94e9-f3a97601d323",
MagicalLore = "322ae078-e674-44cb-a050-360a9428841c",
Mechanics = "73a5c800-8384-4704-9dfa-a242eacd3270",
Math = "89d50281-6869-4758-95d1-66fba5109feb",
Law = "cd8aa58b-6803-49bd-9c86-6a800f21f46a",
MythsAndLegends = "c301fe38-2aca-4c89-9947-c220d8407f2c",
SphereLore = "82a1a676-2230-416b-8ced-24880161d6f6",
Astronomy = "320227fe-7923-41ed-ac62-b175808a9f5e",
Alchemy = "17511b2f-4f83-4018-befc-76bb68f02c4b",
Sailing = "41bd7d7e-576d-47d7-a614-aaa30286ea7d",
Driving = "f53e3d41-4b61-4f0d-80bf-8d67d62fe180",
Commerce = "60469391-2701-4cb2-bc18-914c61cb3fe4",
TreatPoison = "a4edde4c-8784-45e6-92cf-4dd71067eff6",
TreatDisease = "4e2ec767-68ab-49db-9f82-6042c0d04eba",
TreatSoul = "d68dc494-ab63-444f-ae97-c254ae01eca9",
TreatWounds = "b3e86df6-a7d3-4887-9d19-7e899cd146cb",
Woodworking = "4df39524-ec13-45d8-aabe-7288cfe7ab81",
PrepareFood = "763d869b-969f-41d4-b8ba-c2f7aa29ae50",
Leatherworking = "25ab080a-24e4-4f45-ab16-f6bd793d8398",
ArtisticAbility = "140d0c24-e49b-43a2-95c9-77743f35c752",
Metalworking = "c2922325-224a-4941-958f-a3acb553ae0e",
Music = "284bc585-8b9c-4cc1-96f5-442a1d1c4091",
PickLocks = "248fc7cd-e65f-49d5-995f-2d87ff3ff7d6",
Earthencraft = "1e7367c0-0256-4874-a92e-a0e4197c3487",
Clothworking = "bf50f5c9-b42f-4637-8685-b2e233dd48f7",
}
/**
* Used identifiers of skill groups.
*/
export enum SkillGroupIdentifier {
Physical = 1,
Social = 2,
Nature = 3,
Knowledge = 4,
Craft = 5,
Physical = "5b3b6139-bc02-4332-b092-de043c00793f",
Social = "f0a10163-221a-4a54-ae40-0bb71582262e",
Nature = "6ebc92b3-2c48-4f75-9d84-489788284835",
Knowledge = "ca6dd6da-f9ab-4120-9cb9-47f73254a6e2",
Craft = "15d0e623-6f85-4508-8921-1aa6edfd90c7",
}
/**
* Used identifiers of advantages.
*/
export enum AdvantageIdentifier {
CustomAdvantage = 0,
Aptitude = 4, // Begabung
Nimble = 9, // Flink
Blessed = 12,
Luck = 14,
ExceptionalSkill = 16,
ExceptionalCombatTechnique = 17,
IncreasedAstralPower = 20,
IncreasedKarmaPoints = 21,
IncreasedLifePoints = 22,
IncreasedSpirit = 23,
IncreasedToughness = 24,
ImmunityToPoison = 25,
ImmunityToDisease = 26,
MagicalAttunement = 29,
Rich = 33,
SociallyAdaptable = 37,
InspireConfidence = 43,
WeaponAptitude = 44,
Spellcaster = 47,
Unyielding = 51, // Eisern
HatredOf = 55,
LargeSpellSelection = 66,
LeichterGang = 85,
Preacher = 91,
Visionary = 92,
ManySermons = 93,
ManyVisions = 94,
Einkommen = 129,
CustomAdvantage = "e70b85db-d437-4f0e-991e-1d95684935e2",
Aptitude = "77795e79-7db3-4e19-8ecf-e622820bae9e", // Begabung
Nimble = "03367aac-81ff-4bfc-947c-20a2e4446364", // Flink
Blessed = "e5a9bb6d-9791-4d20-bf34-52a3aaf69726",
Luck = "b677661a-8881-456c-932f-c41369a5c21f",
ExceptionalSkill = "87c50831-9f8c-455d-a6d8-5610b232e932",
ExceptionalCombatTechnique = "046adc73-d4d1-4172-886a-544fca95a31b",
IncreasedAstralPower = "cf11a805-3012-4d57-94a8-0efb33803509",
IncreasedKarmaPoints = "cf31f067-ee38-4426-a6a5-3fb6e8b31a74",
IncreasedLifePoints = "dae3e503-a253-42f7-a75c-10b74dd57116",
IncreasedSpirit = "47deca36-35de-4a0b-9894-6c24cf242db8",
IncreasedToughness = "6d9b4c7c-35bf-435c-bccf-4fcee5ba3832",
ImmunityToPoison = "7b1e3cd6-34a6-4711-9535-8cd8ed66f1cd",
ImmunityToDisease = "1f019851-2b4d-4d01-ba69-a386d91ec499",
MagicalAttunement = "0a08218c-9b38-4c3a-84cf-86a50cd2b982",
Rich = "45dd8e80-dd2b-4573-99d5-fbf0810af9ce",
SociallyAdaptable = "d9aa63c1-9ad0-467b-a0cb-51e3450e48b0",
InspireConfidence = "13bfcc91-620e-44e9-aa45-10ed3b0849a7",
WeaponAptitude = "37ff9041-234d-4570-a845-f09ab5883bc3",
Spellcaster = "9770a700-acb7-4b60-b6ea-a329a9acb26b",
Unyielding = "693237d9-d64c-4f06-b725-cc5795babae4", // Eisern
HatredOf = "93255da0-50f2-4c7f-b4f3-66586c3a7c17",
LargeSpellSelection = "a7583667-850b-4d86-be2d-28ab2216c1e9",
LeichterGang = "7ad8cc78-6037-43e3-b717-d5a1592f5d55",
Preacher = "cb371b91-564a-4ca6-8778-e45c953f3bb0",
Visionary = "c499d999-e027-478c-9580-e00c0bf89a4c",
ManySermons = "838ec345-9f88-422e-ae20-5526836b72eb",
ManyVisions = "6f0d0843-2875-4377-b3c9-db57c6eff1bc",
Einkommen = "9284815b-7c40-44db-b37e-1f966b3097cd",
}
/**
* Used identifiers of disadvantages.
*/
export enum DisadvantageIdentifier {
CustomDisadvantage = 0,
AfraidOf = 1,
Poor = 2,
Slow = 4,
NoFlyingBalm = 14,
NoFamiliar = 15,
MagicalRestriction = 21,
DecreasedArcanePower = 23,
DecreasedKarmaPoints = 24,
DecreasedLifePoints = 25,
DecreasedSpirit = 26,
DecreasedToughness = 27,
BadLuck = 28,
PersonalityFlaw = 30,
Principles = 31,
BadHabit = 33,
NegativeTrait = 34, // Schlechte Eigenschaft
Stigma = 42,
Deaf = 44, // Taub
Incompetent = 45,
Obligations = 47, // Verpflichtungen
Maimed = 48, // Verstümmelt
BrittleBones = 56, // Gläsern
SmallSpellSelection = 64,
FewerSermons = 70,
FewerVisions = 71,
CustomDisadvantage = "1ba46bf8-e3ed-46b4-98e5-8e3edb6ed0a3",
AfraidOf = "652fe330-59d5-4784-9b4a-dbb527bf12c7",
Poor = "54ec1dce-32f2-44eb-b501-000dd0da1e3b",
Slow = "9229365c-6392-4896-8306-c3c7b68bb852",
NoFlyingBalm = "19d1e013-175b-4b62-859a-b8007a0bf767",
NoFamiliar = "36950e47-055b-4456-b57f-0501e4104e26",
MagicalRestriction = "efaacd60-3ed7-4693-a1bf-d69a3a3ab18c",
DecreasedArcanePower = "3629dbd4-5d0c-4683-be0c-500aed8161fb",
DecreasedKarmaPoints = "c2a66c6b-0cff-4da8-936c-b3f3ba02719d",
DecreasedLifePoints = "f0df81a0-b514-47d3-88a8-b94a52d6a329",
DecreasedSpirit = "08707e83-bff4-40a1-8a21-ca88d61384c8",
DecreasedToughness = "9bd86082-a773-4d21-b059-a6464b1d5fdc",
BadLuck = "77cde71d-c720-4be9-902c-65dca331c6d6",
PersonalityFlaw = "804fdfe2-3472-4719-8ff8-bfdb77c3e922",
Principles = "52bf0b68-316c-4ca0-abdc-e2691e779801",
BadHabit = "fe08344e-5e5e-4504-b9e0-58eb67e21743",
NegativeTrait = "19d422bd-b376-47a7-b69f-1bffde9f0361", // Schlechte Eigenschaft
Stigma = "8ef5d706-737b-4282-95aa-9549c90464cc",
Deaf = "33b1ebeb-5dae-41f9-8734-d32e9cd59e2a", // Taub
Incompetent = "5bde2e37-6a1e-4008-b75c-e9ac106e78cd",
Obligations = "a8a9aaab-1611-43d6-8803-b33a582a848f", // Verpflichtungen
Maimed = "496d8bea-35ee-4a5d-928d-8a855c882edc", // Verstümmelt
BrittleBones = "0ff139db-0a05-45ec-bcd6-42caea87d691", // Gläsern
SmallSpellSelection = "65ff9a29-ecf4-4f73-9945-7908c89e9059",
FewerSermons = "2f0a061a-fd26-492d-bff0-746b19bf2921",
FewerVisions = "bfe12f5c-a3b3-4f2d-bede-8b3f8e8513dd",
}
/**
* Used identifiers of ranged combat techniques.
*/
export enum RangedCombatTechniqueIdentifier {
SpittingFire = 4,
SpittingFire = "9329e5a2-6c0f-4ab0-9536-73707b74407f",
}
/**
* Used identifiers of advanced skill special abilities.
*/
export enum AdvancedSkillSpecialAbilityIdentifier {
Fachwissen = 2,
Fachwissen = "7bb1e727-f9e5-43ca-8f8a-50ae36b67951",
}
/**
* Used identifiers of combat special abilities.
*/
export enum CombatSpecialAbilityIdentifier {
CombatReflexes = 12,
CombatReflexes = "0e794818-2572-4fdb-86b3-ec52e9e339c3",
}
/**
* Used identifiers of general special abilities.
*/
export enum GeneralSpecialAbilityIdentifier {
SkillSpecialization = 9,
CraftInstruments = 17,
Hunter = 18,
Literacy = 27,
Language = 29,
LanguageSpecialization = 30,
FireEater = 53,
SkillSpecialization = "b2fbdf25-d44a-4d50-95a8-2501e220abdd",
CraftInstruments = "9c57c9ee-6619-4e13-b1cd-056d552d8739",
Hunter = "29239be5-984c-47b0-ba54-408e8978f3af",
Literacy = "2da6289d-6c2f-47ff-8046-5fef87dec62f",
Language = "6cfb462d-e6ab-4d91-bb4b-3d4c0dcac897",
LanguageSpecialization = "8a6d08a0-3a32-4b72-b3f7-e5aa44cda5bf",
FireEater = "05448a67-af4e-48a6-928b-5d9219b3aaf6",
}
/**
* Used identifiers of magical special abilities.
*/
export enum MagicalSpecialAbilityIdentifier {
PropertyKnowledge = 3,
GrosseMeditation = 12,
Adaptation = 18,
Imitationszauberei = 51,
PropertyKnowledge = "5d9f3ba7-0fb8-48ca-aebb-baa01c67b4ab",
GrosseMeditation = "0ffd4668-9d6f-4a87-9957-f099b5e58efb",
Adaptation = "131ec19f-b950-4b3b-8a76-6100adcb227e",
Imitationszauberei = "29a948ad-3c18-4e3e-b151-e0e7b53cca02",
}
/**
* Used identifiers of magical traditions.
*/
export enum MagicalTraditionIdentifier {
GuildMages = 1,
Witches = 2,
Elves = 3,
Unicorn = 4,
Druids = 5,
QabalyaMages = 6,
IntuitiveMages = 7,
Savants = 8,
Illusionists = 9,
ArcaneBards = 10,
ArcaneDancers = 11,
Schelme = 13,
Zauberalchimisten = 14,
TsatuariaAnhaengerinnen = 16,
Necker = 17,
Animisten = 18,
Geoden = 19,
Zibilijas = 20,
BrobimGeoden = 21,
Darna = 23,
Runenschoepfer = 24,
GuildMages = "d9b83dba-cf29-4243-9b85-e03672ac0f02",
Witches = "f3e5278f-8b84-4e65-9ae9-9dbab870ff32",
Elves = "7fafbac0-bd86-4c3d-b1fa-5a8b36b674dc",
Unicorn = "e427bff1-108e-4df3-acfc-0133b5e85f1d",
Druids = "fc8c24c4-3c11-4231-a866-2350bfdb0117",
QabalyaMages = "6dd001f3-506c-4c62-b0e9-facfa44435c1",
IntuitiveMages = "f5dccd70-fc77-4793-8fa2-383b31a7d96a",
Savants = "16e2ec01-eadd-45f0-93a2-d7384628dcf5",
Illusionists = "6e04db3b-1157-4d2c-af13-f7f4ca9711d0",
ArcaneBards = "0d3d1b5a-0550-4e47-9ccf-f2021c5409b6",
ArcaneDancers = "15a92260-95aa-43ee-87ed-e8083cb08897",
Schelme = "11b2d97a-632f-4bb5-a6bc-e53addff2071",
Zauberalchimisten = "a4f341a8-a62a-4d8d-af89-f490b4470f1d",
TsatuariaAnhaengerinnen = "0818d00e-e18a-4daf-bf39-daa5d5edb8b0",
Necker = "eceb1fff-7412-4371-a6f2-5fb5889cb3b2",
Animisten = "147071ec-93a2-4332-9ad4-d55dce2f2355",
Geoden = "2dd3c077-27a7-4dfd-a316-42dc1ba9b05a",
Zibilijas = "a6ee6ca5-41cd-4f5a-915a-7e775ede20af",
BrobimGeoden = "40441cf9-e503-4895-a900-5a00fc2df8bc",
Darna = "70f59d63-d862-47bc-bd07-c70c9e86d528",
Runenschoepfer = "ca29d28a-425f-4f64-a601-1c911d4446cf",
}
/**
* Used identifiers of magical special abilities.
*/
export enum MagicStyleSpecialAbilityIdentifier {
ScholarDesMagierkollegsZuHoningen = 24,
MadaschwesternStil = 55,
ScholarDesMagierkollegsZuHoningen = "9cc872c9-1f2c-4bb8-97ed-e0c9135f93a3",
MadaschwesternStil = "6fdade11-f4b8-46fc-b4dc-010bac9a4f81",
}
/**
* Used identifiers of pact gifts.
*/
export enum PactGiftIdentifier {
DunklesAbbildDerBuendnisgabe = 3,
DunklesAbbildDerBuendnisgabe = "98329d75-1cfe-4a4d-ad8e-0ba69c8c1be4",
}
/**
* Used identifiers of aspects.
*/
export enum AspectIdentifier {
General = 1,
AllgemeinSchamanenritus = 44,
General = "b77ab574-fcb2-443f-8952-83e85f5048ab",
AllgemeinSchamanenritus = "00b4f9d9-9654-48b7-8b70-2b2e5c961552",
}
/**
* Used identifiers of karma special abilities.
*/
export enum KarmaSpecialAbilityIdentifier {
AspectKnowledge = 1,
MasterOfAspect = 5,
HigherOrdination = 14,
AspectKnowledge = "a1c2c1ef-9b1a-4c0b-9bc0-51e4b944269e",
MasterOfAspect = "9174604f-70b4-4ce2-94b8-3dccd77ec7e1",
HigherOrdination = "6ff645b0-2b6f-4d7c-a718-c0493105a405",
}
/**
* Used identifiers of liturgical style special abilities.
*/
export enum LiturgicalStyleSpecialAbilityIdentifier {
BirdsOfPassage = 38, // Zugvögel
HuntressesOfTheWhiteMaiden = 40, // Jägerinnen der Weißen Maid
FollowersOfTheGoldenOne = 47, // Anhänger des Güldenen
BirdsOfPassage = "fa64616e-daa2-4ea4-a9b0-001579e413c4", // Zugvögel
HuntressesOfTheWhiteMaiden = "ce21e327-a750-4312-9a1d-6ab165bbcdb2", // Jägerinnen der Weißen Maid
FollowersOfTheGoldenOne = "53dc9a31-c608-4bb4-b92b-df2a4a567486", // Anhänger des Güldenen
}
/**
* Used identifiers of blessed traditions.
*/
export enum BlessedTraditionIdentifier {
Praios = 1,
Phex = 5,
Firun = 9,
Rahja = 12,
Praios = "b4b3ed0e-d4fc-4b72-ba4f-20c37e3dc7c2",
Phex = "24d3b724-3895-445b-9856-da7a3919df38",
Firun = "221d147d-ce08-402b-87d9-f59c079d0bc6",
Rahja = "84350c1e-ed9e-47e4-9fe8-d33e14df7753",
}
+15 -4
View File
@@ -1,14 +1,25 @@
import { UI } from "optolith-database-schema/types/UI"
import { LocaleMap } from "optolith-database-schema/types/_LocaleMap"
import { Locale } from "optolith-database-schema/gen"
/**
* The type of all translations
*/
export type Translations = NonNullable<Locale["translations"]>
/**
* Translates a given key into a string, optionally with parameters.
*/
export type Translate = <K extends keyof UI>(
export type Translate = <K extends keyof Translations>(
key: K,
...params: (string | number)[]
...rest: Translations[K] extends string & { __params: infer Params }
? [params: Params]
: []
) => string
/**
* A dictionary of locale identifiers to other values.
*/
export type LocaleMap<T> = Record<string, T>
/**
* Selects a value from a locale dictionary based on the selected locale.
*/
+1 -1
View File
@@ -1,4 +1,4 @@
import { PublicationRefs } from "optolith-database-schema/types/source/_PublicationRef"
import type { PublicationRefs } from "optolith-database-schema/gen"
/**
* A JSON representation of the rules text for a library entry.
+40 -68
View File
@@ -1,18 +1,11 @@
import { isNotNullish } from "@optolith/helpers/nullable"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { PublicationRefs } from "optolith-database-schema/types/source/_PublicationRef"
import { GetById } from "../helpers/getTypes.js"
import type { PublicationRefs } from "optolith-database-schema/gen"
import type { GetInstanceById } from "../helpers/getTypes.js"
import { LocaleEnvironment } from "../helpers/locale.js"
import {
isSimpleOccurrence,
isSimpleOccurrences,
isVersionedOccurrence,
} from "./occurrence.js"
import {
fromRawPageRange,
normalizePageRanges,
numberRangeToPageRange,
printPageRange,
printPageRanges,
} from "./pageRange.js"
@@ -20,13 +13,13 @@ import {
* Returns the translation of the references.
*/
export const getReferencesTranslation = (
getPublicationById: GetById.Static.Publication,
getInstanceById: GetInstanceById<"Publication">,
locale: LocaleEnvironment,
references: PublicationRefs,
) =>
references
.map(ref => {
const publication = getPublicationById(ref.id.publication)
const publication = getInstanceById("Publication", ref.id)
const publicationTranslations = locale.translateMap(
publication?.translations,
)
@@ -40,71 +33,50 @@ export const getReferencesTranslation = (
return undefined
}
if (isSimpleOccurrence(occurrences)) {
return `${publicationTranslations.name} ${printPageRange(
locale.translate,
numberRangeToPageRange(occurrences),
)}`
}
const initialPageRanges = normalizePageRanges(
occurrences.initial.pages.map(fromRawPageRange),
)
if (isSimpleOccurrences(occurrences)) {
const ranges = normalizePageRanges(
occurrences.map(numberRangeToPageRange),
)
return `${publicationTranslations.name} ${printPageRanges(
locale.translate,
ranges,
)}`
}
const initial =
occurrences.initial.printing === undefined
? printPageRanges(locale.translate, initialPageRanges)
: `${printPageRanges(
locale.translate,
initialPageRanges,
)} (${locale.translate(
".input {$printing :number} {{since the {$printing}. printing}}",
{ printing: occurrences.initial.printing },
)})`
if (isVersionedOccurrence(occurrences)) {
const initialPageRanges = normalizePageRanges(
occurrences.initial.pages.map(fromRawPageRange),
)
const initial =
occurrences.initial.printing === undefined
? printPageRanges(locale.translate, initialPageRanges)
: `${printPageRanges(
const revisions =
occurrences.revisions?.map(rev => {
switch (rev.kind) {
case "Since": {
const pageRanges = normalizePageRanges(
rev.Since.pages.map(fromRawPageRange),
)
return `${printPageRanges(
locale.translate,
initialPageRanges,
pageRanges,
)} (${locale.translate(
"since the {0}. printing",
occurrences.initial.printing,
".input {$printing :number} {{since the {$printing}. printing}}",
{ printing: rev.Since.printing },
)})`
const revisions =
occurrences.revisions?.map(rev => {
switch (rev.tag) {
case "Since": {
const pageRanges = normalizePageRanges(
rev.since.pages.map(fromRawPageRange),
)
return `${printPageRanges(
locale.translate,
pageRanges,
)} (${locale.translate(
"since the {0}. printing",
rev.since.printing,
)})`
}
case "Deprecated": {
return locale.translate(
"removed in {0}. printing",
rev.deprecated.printing,
)
}
default:
return assertExhaustive(rev)
}
}) ?? []
case "Deprecated": {
return locale.translate(
".input {$printing :number} {{removed in {$printing}. printing}}",
{ printing: rev.Deprecated.printing },
)
}
default:
return assertExhaustive(rev)
}
}) ?? []
const allPageRanges = [initial, ...revisions].join("; ")
const allPageRanges = [initial, ...revisions].join("; ")
return `${publicationTranslations.name} ${allPageRanges}`
}
return assertExhaustive(occurrences)
return `${publicationTranslations.name} ${allPageRanges}`
})
.filter(isNotNullish)
.join("; ")
-27
View File
@@ -1,27 +0,0 @@
import {
Occurrence,
SimpleOccurrence,
SimpleOccurrences,
VersionedOccurrence,
} from "optolith-database-schema/types/source/_PublicationRef"
/**
* Checks if the occurrence is a simple occurrence.
*/
export const isSimpleOccurrence = (
occurrence: Occurrence,
): occurrence is SimpleOccurrence => Object.hasOwn(occurrence, "first_page")
/**
* Checks if the occurrence is simple occurrences.
*/
export const isSimpleOccurrences = (
occurrence: Occurrence,
): occurrence is SimpleOccurrences => Array.isArray(occurrence)
/**
* Checks if the occurrence is a versioned occurrence.
*/
export const isVersionedOccurrence = (
occurrence: Occurrence,
): occurrence is VersionedOccurrence => Object.hasOwn(occurrence, "initial")
+15 -15
View File
@@ -1,21 +1,21 @@
import { Compare } from "@optolith/helpers/compare"
import { assertExhaustive } from "@optolith/helpers/typeSafety"
import { Page } from "optolith-database-schema/types/source/_PublicationRef"
import { Page } from "optolith-database-schema/gen"
import { Translate } from "../helpers/translate.js"
/**
* A comparison function for two pages.
*/
export const comparePage: Compare<Page> = (a, b) => {
switch (a.tag) {
switch (a.kind) {
case "InsideCoverFront":
return b.tag === "InsideCoverFront" ? 0 : -1
return b.kind === "InsideCoverFront" ? 0 : -1
case "InsideCoverBack":
return b.tag === "InsideCoverBack" ? 0 : 1
return b.kind === "InsideCoverBack" ? 0 : 1
case "Numbered":
return b.tag === "Numbered"
? a.numbered - b.numbered
: b.tag === "InsideCoverFront"
return b.kind === "Numbered"
? a.Numbered - b.Numbered
: b.kind === "InsideCoverFront"
? 1
: -1
default:
@@ -32,13 +32,13 @@ export const equalsPage = (a: Page, b: Page): boolean => comparePage(a, b) === 0
* Returns the successor of a page.
*/
export const succ = (page: Page): Page => {
switch (page.tag) {
switch (page.kind) {
case "InsideCoverFront":
return { tag: "Numbered", numbered: 1 }
return { kind: "Numbered", Numbered: 1 }
case "InsideCoverBack":
return { tag: "InsideCoverFront", inside_cover_front: {} }
return { kind: "InsideCoverFront" }
case "Numbered":
return { tag: "Numbered", numbered: page.numbered + 1 }
return { kind: "Numbered", Numbered: page.Numbered + 1 }
default:
return assertExhaustive(page)
}
@@ -48,21 +48,21 @@ export const succ = (page: Page): Page => {
* Creates a page object for a page number.
*/
export const numberToPage = (number: number): Page => ({
tag: "Numbered",
numbered: number,
kind: "Numbered",
Numbered: number,
})
/**
* Returns a string representation of a page.
*/
export const printPage = (translate: Translate, page: Page) => {
switch (page.tag) {
switch (page.kind) {
case "InsideCoverFront":
return translate("Front Cover Inside")
case "InsideCoverBack":
return translate("Back Cover Inside")
case "Numbered":
return page.numbered.toString()
return page.Numbered.toString()
default:
return assertExhaustive(page)
}
+6 -29
View File
@@ -1,17 +1,7 @@
import { range } from "@optolith/helpers/array"
import {
Page,
PageRange as RawPageRange,
SimpleOccurrence,
} from "optolith-database-schema/types/source/_PublicationRef"
import { Page, PageRange as RawPageRange } from "optolith-database-schema/gen"
import { Translate } from "../helpers/translate.js"
import {
comparePage,
equalsPage,
numberToPage,
printPage,
succ,
} from "./page.js"
import { comparePage, equalsPage, printPage, succ } from "./page.js"
/**
* A range of pages, including the first and last page, if the range includes
@@ -22,19 +12,6 @@ export type PageRange = {
lastPage?: Page
}
/**
* Converts a numeric range to a page object range.
*/
export const numberRangeToPageRange = (
numberRange: SimpleOccurrence,
): PageRange =>
numberRange.last_page === undefined
? { firstPage: numberToPage(numberRange.first_page) }
: {
firstPage: numberToPage(numberRange.first_page),
lastPage: numberToPage(numberRange.last_page),
}
/**
* Converts a page object range from the database to a local page object range.
*/
@@ -52,10 +29,10 @@ export const fromRawPageRange = (pageRange: RawPageRange): PageRange =>
export const normalizePageRanges = (ranges: PageRange[]): PageRange[] =>
ranges
.flatMap(({ firstPage, lastPage = firstPage }): Page[] => {
if (firstPage.tag === "Numbered" && lastPage.tag === "Numbered") {
return range(firstPage.numbered, lastPage.numbered).map(numbered => ({
tag: "Numbered",
numbered,
if (firstPage.kind === "Numbered" && lastPage.kind === "Numbered") {
return range(firstPage.Numbered, lastPage.Numbered).map(numbered => ({
kind: "Numbered",
Numbered: numbered,
}))
} else {
return [firstPage, lastPage]
+10 -9
View File
@@ -4,6 +4,7 @@ import {
joinPrerequisiteParts,
PrerequisitePart,
} from "../../../../src/entities/partial/prerequisites/part.js"
import { Case } from "../../../../src/helpers/enums.js"
import { defaultLocaleEnvironment } from "../../../helpers/locale.js"
describe("joinPrerequisiteParts", () => {
@@ -25,11 +26,11 @@ describe("joinPrerequisiteParts", () => {
it("should connect connected sentence types by semicolon", () => {
const parts: PrerequisitePart[] = [
{ value: "A", sentenceType: undefined, isMeta: false },
{ value: "B", sentenceType: "Connected", isMeta: false },
{ value: "C", sentenceType: "Connected", isMeta: false },
{ value: "B", sentenceType: Case("Connected"), isMeta: false },
{ value: "C", sentenceType: Case("Connected"), isMeta: false },
{ value: "D", sentenceType: undefined, isMeta: false },
{ value: "E", sentenceType: undefined, isMeta: false },
{ value: "F", sentenceType: "Connected", isMeta: false },
{ value: "F", sentenceType: Case("Connected"), isMeta: false },
]
const result = joinPrerequisiteParts(defaultLocaleEnvironment, parts)
assert.equal(result, "A; B; C; D, E; F")
@@ -38,15 +39,15 @@ describe("joinPrerequisiteParts", () => {
it("should connect standalone sentence types by periods", () => {
const parts: PrerequisitePart[] = [
{ value: "A", sentenceType: undefined, isMeta: false },
{ value: "B", sentenceType: "Standalone", isMeta: false },
{ value: "C", sentenceType: "Standalone", isMeta: false },
{ value: "B", sentenceType: Case("Standalone"), isMeta: false },
{ value: "C", sentenceType: Case("Standalone"), isMeta: false },
{ value: "D", sentenceType: undefined, isMeta: false },
{ value: "E", sentenceType: undefined, isMeta: false },
{ value: "F.", sentenceType: "Standalone", isMeta: false },
{ value: "G.", sentenceType: "Standalone", isMeta: false },
{ value: "F.", sentenceType: Case("Standalone"), isMeta: false },
{ value: "G.", sentenceType: Case("Standalone"), isMeta: false },
{ value: "H", sentenceType: undefined, isMeta: false },
{ value: "I", sentenceType: undefined, isMeta: false },
{ value: "J", sentenceType: "Standalone", isMeta: false },
{ value: "J", sentenceType: Case("Standalone"), isMeta: false },
]
const result = joinPrerequisiteParts(defaultLocaleEnvironment, parts)
assert.equal(result, "A. B. C. D, E. F. G. H, I. J.")
@@ -65,7 +66,7 @@ describe("joinPrerequisiteParts", () => {
it("throws an error if the sentenceType is unknown", () => {
const parts: PrerequisitePart[] = [
// @ts-expect-error Testing invalid input
{ value: "A", sentenceType: "any", isMeta: true },
{ value: "A", sentenceType: Case("any"), isMeta: true },
]
const block = () => joinPrerequisiteParts(defaultLocaleEnvironment, parts)
assert.throws(block)
@@ -1,13 +1,17 @@
import assert from "node:assert/strict"
import { randomUUID } from "node:crypto"
import { describe, it } from "node:test"
import { printStatePrerequisite } from "../../../../../src/entities/partial/prerequisites/single/state.js"
import { GetById } from "../../../../../src/helpers/getTypes.js"
import { Case } from "../../../../../src/helpers/enums.js"
import type { GetInstanceById } from "../../../../../src/helpers/getTypes.js"
import { defaultLocaleEnvironment } from "../../../../helpers/locale.js"
const ExampleUUID = randomUUID()
describe("getStatePrerequisiteTranslation", () => {
it("returns a PrerequisitePart object for the prerequisite", () => {
const getStateById: GetById.Static.State = () => ({
id: 1,
const getInstanceById: GetInstanceById<"State"> = () => ({
id: ExampleUUID,
src: [],
translations: {
"en-US": {
@@ -18,11 +22,8 @@ describe("getStatePrerequisiteTranslation", () => {
})
assert.deepEqual(
printStatePrerequisite(getStateById, defaultLocaleEnvironment, {
id: {
tag: "State",
state: 1,
},
printStatePrerequisite(getInstanceById, defaultLocaleEnvironment, {
id: ExampleUUID,
}),
{
label: "State ",
@@ -35,35 +36,26 @@ describe("getStatePrerequisiteTranslation", () => {
assert.deepEqual(
printStatePrerequisite(
() => ({
id: 1,
id: ExampleUUID,
src: [],
translations: {},
}),
defaultLocaleEnvironment,
{
id: {
tag: "State",
state: 1,
},
id: ExampleUUID,
},
),
undefined,
)
assert.deepEqual(
printStatePrerequisite(getStateById, defaultLocaleEnvironment, {
id: {
tag: "State",
state: 1,
},
display_option: {
tag: "ReplaceWith",
replace_with: {
translations: {
"en-US": "Replacement",
},
printStatePrerequisite(getInstanceById, defaultLocaleEnvironment, {
id: ExampleUUID,
display_option: Case("ReplaceWith", {
translations: {
"en-US": { replacement: "Replacement" },
},
},
}),
}),
{
value: "Replacement",
@@ -2,16 +2,17 @@ import assert from "node:assert/strict"
import { describe, it } from "node:test"
import { printTextPrerequisite } from "../../../../../src/entities/partial/prerequisites/single/text.js"
import { MISSING_VALUE } from "../../../../../src/entities/partial/unknown.js"
import { Case } from "../../../../../src/helpers/enums.js"
import { defaultLocaleEnvironment } from "../../../../helpers/locale.js"
describe("getTextPrerequisiteTranslation", () => {
it("returns a PrerequisitePart object for the prerequisite", () => {
assert.deepEqual(
printTextPrerequisite(defaultLocaleEnvironment, {
verification: "Pass",
verification: Case("Pass"),
sentence_type: undefined,
translations: {
"en-US": "A",
"en-US": { text: "A" },
},
}),
{
@@ -23,14 +24,14 @@ describe("getTextPrerequisiteTranslation", () => {
assert.deepEqual(
printTextPrerequisite(defaultLocaleEnvironment, {
verification: "Pass",
sentence_type: "Standalone",
verification: Case("Pass"),
sentence_type: Case("Standalone"),
is_meta: true,
translations: {},
}),
{
value: MISSING_VALUE,
sentenceType: "Standalone",
sentenceType: Case("Standalone"),
isMeta: true,
},
)
@@ -1,33 +1,34 @@
import assert from "node:assert/strict"
import { describe, it } from "node:test"
import { getCheckResultBasedValueTranslation } from "../../../../../src/entities/partial/rated/activatable/checkResultBased.js"
import { Case } from "../../../../../src/helpers/enums.js"
import { translateMock } from "../../../../helpers/translate.js"
describe("getTextForCheckResultBased", () => {
it("should return the value text for a check-result-based parameter of an activatable skill", () => {
assert.equal(
getCheckResultBasedValueTranslation(translateMock, {
base: "QualityLevels",
base: Case("QualityLevels"),
}),
"QL",
)
assert.equal(
getCheckResultBasedValueTranslation(translateMock, {
base: "SkillPoints",
base: Case("SkillPoints"),
}),
"SP",
)
assert.equal(
getCheckResultBasedValueTranslation(translateMock, {
base: "QualityLevels",
modifier: { arithmetic: "Divide", value: 2 },
base: Case("QualityLevels"),
modifier: { arithmetic: Case("Divide"), value: 2 },
}),
"QL / 2",
)
assert.equal(
getCheckResultBasedValueTranslation(translateMock, {
base: "SkillPoints",
modifier: { arithmetic: "Multiply", value: 3 },
base: Case("SkillPoints"),
modifier: { arithmetic: Case("Multiply"), value: 3 },
}),
"SP × 3",
)
+5 -14
View File
@@ -1,22 +1,13 @@
import { UI } from "optolith-database-schema/types/UI"
import { MessageFormat } from "messageformat"
import { Translate, TranslateMap } from "../../src/helpers/translate.js"
const insertParams = (str: string, params: (string | number)[]): string =>
str.replace(
/\{(?<index>\d+)\}/gu,
(_match, _p1, _offset, _s, { index: rawIndex }) => {
const index = Number.parseInt(rawIndex, 10)
return params[index]?.toString() ?? `{${rawIndex}}`
},
)
/**
* A mocked translate function.
*/
export const translateMock: Translate = <K extends keyof UI>(
key: K,
...options: (string | number)[]
) => insertParams(key, options)
export const translateMock: Translate = (key, ...rest) =>
new MessageFormat("en", key).format(
rest[0] as Record<string, unknown> | undefined,
)
/**
* A mocked translate map function.
+70 -96
View File
@@ -11,85 +11,73 @@ import {
describe("comparePage", () => {
it("returns 0 if the pages are equal", () => {
assert.equal(
comparePage(
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ tag: "InsideCoverBack", inside_cover_back: {} },
),
comparePage({ kind: "InsideCoverBack" }, { kind: "InsideCoverBack" }),
0,
)
assert.equal(
comparePage({ kind: "InsideCoverFront" }, { kind: "InsideCoverFront" }),
0,
)
assert.equal(
comparePage(
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ tag: "InsideCoverFront", inside_cover_front: {} },
),
0,
)
assert.equal(
comparePage(
{ tag: "Numbered", numbered: 42 },
{ tag: "Numbered", numbered: 42 },
{ kind: "Numbered", Numbered: 42 },
{ kind: "Numbered", Numbered: 42 },
),
0,
)
})
it("returns a negative number if first should be sorted before the second", () => {
assert.equal(
comparePage({ kind: "InsideCoverFront" }, { kind: "InsideCoverBack" }),
-1,
)
assert.equal(
comparePage(
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ kind: "InsideCoverFront" },
{ kind: "Numbered", Numbered: 42 },
),
-1,
)
assert.equal(
comparePage(
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ tag: "Numbered", numbered: 42 },
{ kind: "Numbered", Numbered: 42 },
{ kind: "InsideCoverBack" },
),
-1,
)
assert.equal(
comparePage(
{ tag: "Numbered", numbered: 42 },
{ tag: "InsideCoverBack", inside_cover_back: {} },
),
-1,
)
assert.equal(
comparePage(
{ tag: "Numbered", numbered: 24 },
{ tag: "Numbered", numbered: 42 },
{ kind: "Numbered", Numbered: 24 },
{ kind: "Numbered", Numbered: 42 },
),
-18,
)
})
it("returns a positive number if first should be sorted after the second", () => {
assert.equal(
comparePage({ kind: "InsideCoverBack" }, { kind: "InsideCoverFront" }),
1,
)
assert.equal(
comparePage(
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ kind: "Numbered", Numbered: 42 },
{ kind: "InsideCoverFront" },
),
1,
)
assert.equal(
comparePage(
{ tag: "Numbered", numbered: 42 },
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ kind: "InsideCoverBack" },
{ kind: "Numbered", Numbered: 42 },
),
1,
)
assert.equal(
comparePage(
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ tag: "Numbered", numbered: 42 },
),
1,
)
assert.equal(
comparePage(
{ tag: "Numbered", numbered: 42 },
{ tag: "Numbered", numbered: 24 },
{ kind: "Numbered", Numbered: 42 },
{ kind: "Numbered", Numbered: 24 },
),
18,
)
@@ -99,82 +87,70 @@ describe("comparePage", () => {
describe("equalsPage", () => {
it("returns true if the pages are equal", () => {
assert.equal(
equalsPage(
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ tag: "InsideCoverBack", inside_cover_back: {} },
),
equalsPage({ kind: "InsideCoverBack" }, { kind: "InsideCoverBack" }),
true,
)
assert.equal(
equalsPage({ kind: "InsideCoverFront" }, { kind: "InsideCoverFront" }),
true,
)
assert.equal(
equalsPage(
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ tag: "InsideCoverFront", inside_cover_front: {} },
),
true,
)
assert.equal(
equalsPage(
{ tag: "Numbered", numbered: 42 },
{ tag: "Numbered", numbered: 42 },
{ kind: "Numbered", Numbered: 42 },
{ kind: "Numbered", Numbered: 42 },
),
true,
)
})
it("returns false if the pages are not equal", () => {
assert.equal(
equalsPage({ kind: "InsideCoverFront" }, { kind: "InsideCoverBack" }),
false,
)
assert.equal(
equalsPage(
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ kind: "InsideCoverFront" },
{ kind: "Numbered", Numbered: 42 },
),
false,
)
assert.equal(
equalsPage(
{ tag: "InsideCoverFront", inside_cover_front: {} },
{ tag: "Numbered", numbered: 42 },
{ kind: "Numbered", Numbered: 42 },
{ kind: "InsideCoverBack" },
),
false,
)
assert.equal(
equalsPage(
{ tag: "Numbered", numbered: 42 },
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ kind: "Numbered", Numbered: 24 },
{ kind: "Numbered", Numbered: 42 },
),
false,
)
assert.equal(
equalsPage({ kind: "InsideCoverBack" }, { kind: "InsideCoverFront" }),
false,
)
assert.equal(
equalsPage(
{ kind: "Numbered", Numbered: 42 },
{ kind: "InsideCoverFront" },
),
false,
)
assert.equal(
equalsPage(
{ tag: "Numbered", numbered: 24 },
{ tag: "Numbered", numbered: 42 },
{ kind: "InsideCoverBack" },
{ kind: "Numbered", Numbered: 42 },
),
false,
)
assert.equal(
equalsPage(
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ tag: "InsideCoverFront", inside_cover_front: {} },
),
false,
)
assert.equal(
equalsPage(
{ tag: "Numbered", numbered: 42 },
{ tag: "InsideCoverFront", inside_cover_front: {} },
),
false,
)
assert.equal(
equalsPage(
{ tag: "InsideCoverBack", inside_cover_back: {} },
{ tag: "Numbered", numbered: 42 },
),
false,
)
assert.equal(
equalsPage(
{ tag: "Numbered", numbered: 42 },
{ tag: "Numbered", numbered: 24 },
{ kind: "Numbered", Numbered: 42 },
{ kind: "Numbered", Numbered: 24 },
),
false,
)
@@ -183,20 +159,20 @@ describe("equalsPage", () => {
describe("succ", () => {
it("returns the next page", () => {
assert.deepEqual(
succ({ tag: "InsideCoverFront", inside_cover_front: {} }),
{ tag: "Numbered", numbered: 1 },
)
assert.deepEqual(succ({ tag: "Numbered", numbered: 42 }), {
tag: "Numbered",
numbered: 43,
assert.deepEqual(succ({ kind: "InsideCoverFront" }), {
kind: "Numbered",
Numbered: 1,
})
assert.deepEqual(succ({ kind: "Numbered", Numbered: 42 }), {
kind: "Numbered",
Numbered: 43,
})
})
})
describe("numberToPage", () => {
it("returns a page object for the page number", () => {
assert.deepEqual(numberToPage(42), { tag: "Numbered", numbered: 42 })
assert.deepEqual(numberToPage(42), { kind: "Numbered", Numbered: 42 })
})
})
@@ -204,20 +180,18 @@ describe("printPage", () => {
it("returns a string representation of the page", () => {
assert.equal(
printPage(() => "Front Cover Inside", {
tag: "InsideCoverFront",
inside_cover_front: {},
kind: "InsideCoverFront",
}),
"Front Cover Inside",
)
assert.equal(
printPage(() => "Back Cover Inside", {
tag: "InsideCoverBack",
inside_cover_back: {},
kind: "InsideCoverBack",
}),
"Back Cover Inside",
)
assert.equal(
printPage(() => "", { tag: "Numbered", numbered: 42 }),
printPage(() => "", { kind: "Numbered", Numbered: 42 }),
"42",
)
})
+8 -25
View File
@@ -1,35 +1,18 @@
import assert from "assert/strict"
import { describe, it } from "node:test"
import { Page } from "optolith-database-schema/types/source/_PublicationRef"
import { Translate } from "../../src/helpers/translate.js"
import { Page } from "optolith-database-schema/gen"
import {
fromRawPageRange,
normalizePageRanges,
numberRangeToPageRange,
PageRange,
printPageRange,
printPageRanges,
} from "../../src/references/pageRange.js"
import { translateMock } from "../helpers/translate.js"
const mockTranslate: Translate = (key: string) => key
const mockPage: Page = Object.freeze({ tag: "Numbered", numbered: 1 })
const mockPage2: Page = Object.freeze({ tag: "Numbered", numbered: 2 })
const mockPage3: Page = Object.freeze({ tag: "Numbered", numbered: 3 })
describe("numberRangeToPageRange", () => {
it("should convert a numeric range to a page object range", () => {
const input = { first_page: 1, last_page: 2 }
const expected: PageRange = { firstPage: mockPage, lastPage: mockPage2 }
assert.deepEqual(numberRangeToPageRange(input), expected)
})
it("should handle single page ranges", () => {
const input = { first_page: 1 }
const expected: PageRange = { firstPage: mockPage }
assert.deepEqual(numberRangeToPageRange(input), expected)
})
})
const mockPage: Page = Object.freeze({ kind: "Numbered", Numbered: 1 })
const mockPage2: Page = Object.freeze({ kind: "Numbered", Numbered: 2 })
const mockPage3: Page = Object.freeze({ kind: "Numbered", Numbered: 3 })
describe("fromRawPageRange", () => {
it("should convert a raw page range to a local page object range", () => {
@@ -60,13 +43,13 @@ describe("printPageRange", () => {
it("should return a string representation of a page range", () => {
const input: PageRange = { firstPage: mockPage, lastPage: mockPage2 }
const expected = "12"
assert.equal(printPageRange(mockTranslate, input), expected)
assert.equal(printPageRange(translateMock, input), expected)
})
it("should handle single page ranges", () => {
const input: PageRange = { firstPage: mockPage }
const expected = "1"
assert.equal(printPageRange(mockTranslate, input), expected)
assert.equal(printPageRange(translateMock, input), expected)
})
})
@@ -77,6 +60,6 @@ describe("printPageRanges", () => {
{ firstPage: mockPage3 },
]
const expected = "12, 3"
assert.equal(printPageRanges(mockTranslate, input), expected)
assert.equal(printPageRanges(translateMock, input), expected)
})
})