@optolith/entity-descriptions 0.13.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/lib/creator.js +1 -1
- package/lib/entities/activatable.d.ts +1 -1
- package/lib/entities/activatable.js +28 -18
- package/lib/entities/culture.js +3 -3
- package/lib/entities/curriculum.js +1 -1
- package/lib/entities/elixir.js +1 -1
- package/lib/entities/equipment.js +1 -1
- package/lib/entities/liturgicalChant.d.ts +2 -2
- package/lib/entities/liturgicalChant.js +4 -0
- package/lib/entities/partial/adventurePointsValue.js +8 -7
- package/lib/entities/partial/dice.js +2 -2
- package/lib/entities/partial/enhancements.js +2 -2
- package/lib/entities/partial/herbary.js +1 -1
- package/lib/entities/partial/prerequisites/index.d.ts +6 -1
- package/lib/entities/partial/prerequisites/index.js +24 -1
- package/lib/entities/partial/prerequisites/single/personalityTrait.js +1 -1
- package/lib/entities/partial/prerequisites/single/ratedSum.js +1 -1
- package/lib/entities/partial/profession/options/combatTechniquesForAdventurePoints.d.ts +16 -0
- package/lib/entities/partial/profession/options/combatTechniquesForAdventurePoints.js +43 -0
- package/lib/entities/partial/profession/options/numberOfSpellworksTotalingAdventurePoints.d.ts +16 -0
- package/lib/entities/partial/profession/options/numberOfSpellworksTotalingAdventurePoints.js +39 -0
- package/lib/entities/partial/profession/packages.d.ts +67 -0
- package/lib/entities/partial/profession/packages.js +84 -0
- package/lib/entities/partial/profession/variants.d.ts +21 -0
- package/lib/entities/partial/profession/variants.js +31 -0
- package/lib/entities/partial/rated/activatable/cost.js +11 -9
- package/lib/entities/partial/rated/activatable/effect.js +2 -2
- package/lib/entities/partial/reader.d.ts +25 -1
- package/lib/entities/partial/reader.js +20 -0
- package/lib/entities/partial/units/energy.js +2 -1
- package/lib/entities/partial/units/length.js +6 -3
- package/lib/entities/partial/units/timeSpan.js +11 -7
- package/lib/entities/partial/unknown.d.ts +4 -0
- package/lib/entities/partial/unknown.js +4 -0
- package/lib/entities/poison.js +1 -1
- package/lib/entities/profession.js +44 -62
- package/lib/entities/spell.d.ts +2 -2
- package/lib/entities/spell.js +3 -1
- package/lib/index.d.ts +69 -68
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { NonEmptyArray } from "@elyukai/utils/array/nonEmpty";
|
|
2
|
+
import type { Equality } from "@elyukai/utils/equality";
|
|
3
|
+
import type { AnyNonNullish } from "@elyukai/utils/nullable";
|
|
4
|
+
import { Reader } from "@elyukai/utils/reader";
|
|
5
|
+
import type { ExperienceLevel, Profession_ID, ProfessionPackage, VariantOptionAction } from "@optolith/database-schema/gen";
|
|
6
|
+
import type { StdEnv, StdReader } from "../../../env.js";
|
|
7
|
+
/**
|
|
8
|
+
* Profession Package with its associated experience level.
|
|
9
|
+
*/
|
|
10
|
+
export type PreparedProfessionPackage = {
|
|
11
|
+
id: string;
|
|
12
|
+
content: ProfessionPackage;
|
|
13
|
+
experienceLevel: ExperienceLevel;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Collects all profession packages for a given profession and returns them sorted by their associated experience level.
|
|
17
|
+
*/
|
|
18
|
+
export declare const prepareProfessionPackages: (professionId: Profession_ID) => StdReader<PreparedProfessionPackage[], "ibi" | "acibp", "ExperienceLevel", never, "ProfessionPackage">;
|
|
19
|
+
/**
|
|
20
|
+
* Configuration for retrieving, rendering and combining an option parameter.
|
|
21
|
+
*/
|
|
22
|
+
export type OptionParameterConfig<T, P, R, E> = {
|
|
23
|
+
selector: (option: T) => P;
|
|
24
|
+
equality: Equality<P | undefined>;
|
|
25
|
+
render: (option: P) => Reader<E, R>;
|
|
26
|
+
renderAsString: (option: P) => Reader<E, string>;
|
|
27
|
+
emptyText: string;
|
|
28
|
+
joiner: string;
|
|
29
|
+
};
|
|
30
|
+
type OptionParameterValueMap = [value: unknown, result: unknown][];
|
|
31
|
+
/**
|
|
32
|
+
* Option parameter configurations for multiple parameters.
|
|
33
|
+
*/
|
|
34
|
+
export type OptionParameterConfigs<T, P extends OptionParameterValueMap, E> = {
|
|
35
|
+
[K in keyof P]: OptionParameterConfig<T, P[K][0], P[K][1], E>;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Extract parameters for final text render.
|
|
39
|
+
*/
|
|
40
|
+
type OptionParameterTextRenderParameters<P extends OptionParameterValueMap> = {
|
|
41
|
+
[K in keyof P]: P[K][1] | string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Renders the text for multiple parameters.
|
|
45
|
+
*/
|
|
46
|
+
export type OptionParameterTextRender<P extends OptionParameterValueMap, E> = (...args: OptionParameterTextRenderParameters<P>) => Reader<E, string>;
|
|
47
|
+
/**
|
|
48
|
+
* Renders a two-parameter option for a list of profession packages.
|
|
49
|
+
*/
|
|
50
|
+
export declare const renderParameterizedOptionForMultiplePackages: <T, P extends OptionParameterValueMap, E>(professionPackages: NonEmptyArray<PreparedProfessionPackage>, optionSelector: (pkg: PreparedProfessionPackage) => T | undefined, allDifferent: {
|
|
51
|
+
type: "separate";
|
|
52
|
+
emptyText: string;
|
|
53
|
+
joiner: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: "combined";
|
|
56
|
+
}, renderText: OptionParameterTextRender<P, E>, ...configs: OptionParameterConfigs<T, P, E>) => Reader<E, string | undefined>;
|
|
57
|
+
/**
|
|
58
|
+
* Renders a two-parameter option for a list of profession packages.
|
|
59
|
+
*/
|
|
60
|
+
export declare const renderParameterizedOptionForBaseAndVariant: <T extends AnyNonNullish, P extends OptionParameterValueMap, E>(baseOptions: T | undefined, variantOptions: VariantOptionAction<T>, allDifferent: {
|
|
61
|
+
type: "separate";
|
|
62
|
+
emptyText: string;
|
|
63
|
+
joiner: string;
|
|
64
|
+
} | {
|
|
65
|
+
type: "combined";
|
|
66
|
+
}, renderRemove: (base: T) => Reader<E, string>, renderAdd: (override: T) => Reader<E, string>, renderText: OptionParameterTextRender<P, E>, ...configs: OptionParameterConfigs<T, P, E>) => Reader<E & StdEnv<"t">, string>;
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { allSame } from "@elyukai/utils/array/filters";
|
|
2
|
+
import { on } from "@elyukai/utils/function";
|
|
3
|
+
import { compareNumber } from "@elyukai/utils/ordering";
|
|
4
|
+
import { Reader } from "@elyukai/utils/reader";
|
|
5
|
+
import { assertExhaustive } from "@elyukai/utils/typeSafety";
|
|
6
|
+
import { LOGIC_ERROR } from "../unknown.js";
|
|
7
|
+
import { insteadOfR, renderVariantOptionPaths } from "./variants.js";
|
|
8
|
+
/**
|
|
9
|
+
* Collects all profession packages for a given profession and returns them sorted by their associated experience level.
|
|
10
|
+
*/
|
|
11
|
+
export const prepareProfessionPackages = (professionId) => Reader.asks(({ getInstanceById, getChildInstancesForInstanceId }) => getChildInstancesForInstanceId("ProfessionPackage", professionId)
|
|
12
|
+
.map((professionPackage) => ({
|
|
13
|
+
...professionPackage,
|
|
14
|
+
experienceLevel: getInstanceById("ExperienceLevel", professionPackage.content.experience_level),
|
|
15
|
+
}))
|
|
16
|
+
.filter((professionPackage) => professionPackage.experienceLevel !== undefined)
|
|
17
|
+
.toSorted(on(item => item.experienceLevel.adventure_points, compareNumber)));
|
|
18
|
+
const renderSeparatedOptionList = (options, render, emptyText, joiner) => Reader.traverse(options, option => option === undefined ? Reader.of(emptyText) : render(option)).map(list => list.join(joiner));
|
|
19
|
+
/**
|
|
20
|
+
* Renders a two-parameter option for a list of profession packages.
|
|
21
|
+
*/
|
|
22
|
+
export const renderParameterizedOptionForMultiplePackages = (professionPackages, optionSelector, allDifferent, renderText, ...configs) => {
|
|
23
|
+
const options = professionPackages.map(optionSelector);
|
|
24
|
+
const [firstOption] = options;
|
|
25
|
+
const sames = configs.map(config => allSame(options, on(option => (option === undefined ? undefined : config.selector(option)), config.equality)));
|
|
26
|
+
if (sames.some(same => same)) {
|
|
27
|
+
if (firstOption === undefined) {
|
|
28
|
+
return Reader.of(undefined);
|
|
29
|
+
}
|
|
30
|
+
return Reader.traverse(configs, (config, configIndex) => sames[configIndex] === true
|
|
31
|
+
? config.render(config.selector(firstOption))
|
|
32
|
+
: renderSeparatedOptionList(options, option => config.renderAsString(config.selector(option)), config.emptyText, config.joiner)).thenW(parameterValues => renderText(...parameterValues));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
switch (allDifferent.type) {
|
|
36
|
+
case "combined":
|
|
37
|
+
return Reader.traverse(configs, config => renderSeparatedOptionList(options, option => config.renderAsString(config.selector(option)), config.emptyText, config.joiner)).thenW(parameterValues => renderText(...parameterValues));
|
|
38
|
+
case "separate":
|
|
39
|
+
return renderSeparatedOptionList(options, option => Reader.traverse(configs, config => config.render(config.selector(option))).thenW(parameterValues => renderText(...parameterValues)), allDifferent.emptyText, allDifferent.joiner);
|
|
40
|
+
default:
|
|
41
|
+
return assertExhaustive(allDifferent);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Renders a two-parameter option for a list of profession packages.
|
|
47
|
+
*/
|
|
48
|
+
export const renderParameterizedOptionForBaseAndVariant = (baseOptions, variantOptions, allDifferent, renderRemove, renderAdd, renderText, ...configs) => renderVariantOptionPaths(baseOptions, variantOptions, {
|
|
49
|
+
remove: renderRemove,
|
|
50
|
+
add: renderAdd,
|
|
51
|
+
update: (base, override) => {
|
|
52
|
+
const sames = configs.map(config => config.equality(config.selector(base), config.selector(override)));
|
|
53
|
+
if (sames.every(same => same)) {
|
|
54
|
+
return Reader.of(LOGIC_ERROR); // Base and variant would be equal then, so the variant option should be removed or changed
|
|
55
|
+
}
|
|
56
|
+
if (sames.some(same => same)) {
|
|
57
|
+
return Reader.traverse(configs, (config, configIndex) => sames[configIndex] === true
|
|
58
|
+
? config.render(config.selector(base))
|
|
59
|
+
: config
|
|
60
|
+
.renderAsString(config.selector(base))
|
|
61
|
+
.thenW(baseValue => config
|
|
62
|
+
.renderAsString(config.selector(override))
|
|
63
|
+
.thenW(overrideValue => insteadOfR(overrideValue, baseValue)))).thenW(parameterValues => renderText(...parameterValues));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
switch (allDifferent.type) {
|
|
67
|
+
case "combined":
|
|
68
|
+
return Reader.traverse(configs, config => config
|
|
69
|
+
.renderAsString(config.selector(base))
|
|
70
|
+
.thenW(baseValue => config
|
|
71
|
+
.renderAsString(config.selector(override))
|
|
72
|
+
.thenW(overrideValue => insteadOfR(overrideValue, baseValue)))).thenW(parameterValues => renderText(...parameterValues));
|
|
73
|
+
case "separate":
|
|
74
|
+
return Reader.traverse(configs, config => config.render(config.selector(base)))
|
|
75
|
+
.thenW(parameterValues => renderText(...parameterValues))
|
|
76
|
+
.thenW(baseValue => Reader.traverse(configs, config => config.render(config.selector(override)))
|
|
77
|
+
.thenW(parameterValues => renderText(...parameterValues))
|
|
78
|
+
.thenW(overrideValue => insteadOfR(overrideValue, baseValue)));
|
|
79
|
+
default:
|
|
80
|
+
return assertExhaustive(allDifferent);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type AnyNonNullish } from "@elyukai/utils/nullable";
|
|
2
|
+
import { Reader } from "@elyukai/utils/reader";
|
|
3
|
+
import type { ProfessionPackage, ProfessionPackageOptions, ProfessionVariant, ProfessionVariantPackageOptions, VariantOptionAction } from "@optolith/database-schema/gen";
|
|
4
|
+
/**
|
|
5
|
+
* Renders an option for a profession variant, using the base profession package and the variant's options.
|
|
6
|
+
*/
|
|
7
|
+
export declare const renderVariantOption: <Env, K extends keyof ProfessionVariantPackageOptions>(base: ProfessionPackage, variant: ProfessionVariant, key: K, render: (base: ProfessionPackageOptions[K] | undefined, variant: NonNullable<ProfessionVariantPackageOptions[K]>) => Reader<Env, string>) => Reader<Env, string[]>;
|
|
8
|
+
/**
|
|
9
|
+
* Render a variant option based on whether it is a removal, addition, or override of the base option.
|
|
10
|
+
*/
|
|
11
|
+
export declare const renderVariantOptionPaths: <T extends AnyNonNullish, Env1, Env2, Env3>(base: T | undefined, variant: VariantOptionAction<T>, paths: {
|
|
12
|
+
remove: (base: T) => Reader<Env1, string>;
|
|
13
|
+
add: (variant: T) => Reader<Env2, string>;
|
|
14
|
+
update: (base: T, variant: T) => Reader<Env3, string>;
|
|
15
|
+
}) => Reader<Env1 & Env2 & Env3, string>;
|
|
16
|
+
/**
|
|
17
|
+
* Helper for "X instead of Y" text.
|
|
18
|
+
*/
|
|
19
|
+
export declare const insteadOfR: (replacement: string | number, base: string | number) => Reader<{
|
|
20
|
+
translate: import("../../../helpers/translate.js").Translate;
|
|
21
|
+
}, string>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { nullableToArray } from "@elyukai/utils/nullable";
|
|
2
|
+
import { Reader } from "@elyukai/utils/reader";
|
|
3
|
+
import { assertExhaustive } from "@elyukai/utils/typeSafety";
|
|
4
|
+
import { fixedNumberOrString, translateR } from "../reader.js";
|
|
5
|
+
import { MISSING_VALUE } from "../unknown.js";
|
|
6
|
+
/**
|
|
7
|
+
* Renders an option for a profession variant, using the base profession package and the variant's options.
|
|
8
|
+
*/
|
|
9
|
+
export const renderVariantOption = (base, variant, key, render) => (variant.options?.[key] === undefined
|
|
10
|
+
? Reader.of(undefined)
|
|
11
|
+
: render(base.options?.[key], variant.options[key])).map(text => nullableToArray(text));
|
|
12
|
+
/**
|
|
13
|
+
* Render a variant option based on whether it is a removal, addition, or override of the base option.
|
|
14
|
+
*/
|
|
15
|
+
export const renderVariantOptionPaths = (base, variant, paths) => {
|
|
16
|
+
switch (variant.kind) {
|
|
17
|
+
case "Remove":
|
|
18
|
+
return base === undefined ? Reader.of(MISSING_VALUE) : paths.remove(base);
|
|
19
|
+
case "Override":
|
|
20
|
+
return base === undefined ? paths.add(variant.Override) : paths.update(base, variant.Override);
|
|
21
|
+
default:
|
|
22
|
+
return assertExhaustive(variant);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Helper for "X instead of Y" text.
|
|
27
|
+
*/
|
|
28
|
+
export const insteadOfR = (replacement, base) => translateR("{$replacement} instead of {$base}", {
|
|
29
|
+
replacement: fixedNumberOrString(replacement),
|
|
30
|
+
base: fixedNumberOrString(base),
|
|
31
|
+
});
|
|
@@ -3,7 +3,7 @@ import { Reader } from "@elyukai/utils/reader";
|
|
|
3
3
|
import { mapNullable } from "@optolith/helpers/nullable";
|
|
4
4
|
import { assertExhaustive } from "@optolith/helpers/typeSafety";
|
|
5
5
|
import { renderParameterMap } from "../../map.js";
|
|
6
|
-
import { formatEnergyFnR, formatEnergyR, getInstanceByIdFnR, modifiableBySpeedR, responsiveLocaleJoinR, responsiveR, responsiveTextR, responsiveTranslateR, translateMapR, translateR, } from "../../reader.js";
|
|
6
|
+
import { fixedNumberOrString, formatEnergyFnR, formatEnergyR, getInstanceByIdFnR, modifiableBySpeedR, responsiveLocaleJoinR, responsiveR, responsiveTextR, responsiveTranslateR, responsiveTranslateSplitR, translateMapR, translateR, } from "../../reader.js";
|
|
7
7
|
import { appendNoteIfNeeded, replaceTextIfNeeded } from "../../responsiveText.js";
|
|
8
8
|
import { formatCombinedTimeSpanR } from "../../units/timeSpan.js";
|
|
9
9
|
import { MISSING_VALUE } from "../../unknown.js";
|
|
@@ -33,9 +33,11 @@ const appendPerCountableToCostIfNeeded = (value, baseCost) => {
|
|
|
33
33
|
})));
|
|
34
34
|
});
|
|
35
35
|
};
|
|
36
|
-
const appendPermanentCostIfNeeded = (permanentValue, baseCost) => mapNullable(permanentValue, value =>
|
|
37
|
-
const appendElvenPermanentCostIfNeeded = (permanent, baseCost) => mapNullable(permanent, value =>
|
|
36
|
+
const appendPermanentCostIfNeeded = (permanentValue, baseCost) => mapNullable(permanentValue, value => responsiveTranslateSplitR(".input {$value :number} {{, {$value} of which are permanent}}", " ({$value} perm.)", { value }, { value: value.toFixed() }).map(text => baseCost + text)) ?? Reader.of(baseCost);
|
|
37
|
+
const appendElvenPermanentCostIfNeeded = (permanent, baseCost) => mapNullable(permanent, value => responsiveTranslateSplitR(".input {$value :number} {{{$value} permanent AE}}", "{$value} pAE", {
|
|
38
38
|
value: value.value,
|
|
39
|
+
}, {
|
|
40
|
+
value: value.value.toFixed(),
|
|
39
41
|
})
|
|
40
42
|
.thenW(text => replaceTextIfNeeded(value.translations, text))
|
|
41
43
|
.map(text => baseCost + text)) ?? Reader.of(baseCost);
|
|
@@ -117,7 +119,7 @@ const renderMultipleOneTimeCosts = (type, value) => {
|
|
|
117
119
|
export const renderStandaloneCostMap = (value) => renderParameterMap(value, option => Reader.of(option.value), formatEnergyR, value.options.every(option => option.value.permanentValue !== undefined)
|
|
118
120
|
? {
|
|
119
121
|
format: values => translateR(", {$value} of which are permanent", {
|
|
120
|
-
value: values,
|
|
122
|
+
value: fixedNumberOrString(values),
|
|
121
123
|
}),
|
|
122
124
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- is checked beforehand
|
|
123
125
|
render: option => Reader.of(option.value.permanentValue),
|
|
@@ -132,7 +134,7 @@ const renderOneTimeCostMap = (value) => {
|
|
|
132
134
|
return renderParameterMap(value.Modifiable.map, option => deriveModifiableCost(option.initialModificationLevel).map(cost => cost ?? MISSING_VALUE), singleValue => formatEnergyR(singleValue), value.Modifiable.map.options.every(option => option.value.permanentValue !== undefined)
|
|
133
135
|
? {
|
|
134
136
|
format: values => translateR(", {$value} of which are permanent", {
|
|
135
|
-
value: values,
|
|
137
|
+
value: fixedNumberOrString(values),
|
|
136
138
|
}),
|
|
137
139
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- is checked beforehand
|
|
138
140
|
render: option => Reader.of(option.value.permanentValue),
|
|
@@ -142,7 +144,7 @@ const renderOneTimeCostMap = (value) => {
|
|
|
142
144
|
return renderParameterMap(value.NonModifiable.map, option => Reader.of(option.value), formatEnergyR, value.NonModifiable.map.options.every(option => option.value.permanentValue !== undefined)
|
|
143
145
|
? {
|
|
144
146
|
format: values => translateR(", {$value} of which are permanent", {
|
|
145
|
-
value: values,
|
|
147
|
+
value: fixedNumberOrString(values),
|
|
146
148
|
}),
|
|
147
149
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- is checked beforehand
|
|
148
150
|
render: option => Reader.of(option.value.permanentValue),
|
|
@@ -240,10 +242,10 @@ export const renderMagicalActionCost = (cost) => {
|
|
|
240
242
|
case "FirstPerson":
|
|
241
243
|
return Reader.asks(({ translate }) => translate("{$firstPersonValue} for the first person; {$additionalPersonValue} for each additional person", {
|
|
242
244
|
firstPersonValue: translate("{$value} AE", {
|
|
243
|
-
value: cost.FirstPerson.value,
|
|
245
|
+
value: cost.FirstPerson.value.toFixed(),
|
|
244
246
|
}),
|
|
245
247
|
additionalPersonValue: translate("{$value} AE", {
|
|
246
|
-
value: cost.FirstPerson.value / 2,
|
|
248
|
+
value: (cost.FirstPerson.value / 2).toFixed(),
|
|
247
249
|
}),
|
|
248
250
|
}));
|
|
249
251
|
case "ByPrimaryPatron":
|
|
@@ -252,7 +254,7 @@ export const renderMagicalActionCost = (cost) => {
|
|
|
252
254
|
return Reader.asks(({ translate }) => cost.All.minimum === undefined
|
|
253
255
|
? translate("All AE")
|
|
254
256
|
: translate("All AE, at least {$value} AE", {
|
|
255
|
-
value: cost.All.minimum,
|
|
257
|
+
value: cost.All.minimum.toFixed(),
|
|
256
258
|
}));
|
|
257
259
|
case "Map":
|
|
258
260
|
return renderStandaloneCostMap(cost.Map);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mapNullable } from "@optolith/helpers/nullable";
|
|
2
2
|
import { assertExhaustive } from "@optolith/helpers/typeSafety";
|
|
3
|
-
import { translateFnR } from "../../reader.js";
|
|
3
|
+
import { fixedNumberOrString, translateFnR } from "../../reader.js";
|
|
4
4
|
const getContentPartsForQualityLevels = (getQualityLevelString, source) => translateFnR.map((translate) => ({
|
|
5
5
|
label: translate("Effect"),
|
|
6
6
|
value: [
|
|
@@ -13,7 +13,7 @@ const getContentPartsForQualityLevels = (getQualityLevelString, source) => trans
|
|
|
13
13
|
style: "hidden",
|
|
14
14
|
items: source.quality_levels.map((text, index) => ({
|
|
15
15
|
label: translate("QL {$value}", {
|
|
16
|
-
value: getQualityLevelString(index),
|
|
16
|
+
value: fixedNumberOrString(getQualityLevelString(index)),
|
|
17
17
|
}),
|
|
18
18
|
value: text,
|
|
19
19
|
})),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Reader } from "@elyukai/utils/reader";
|
|
2
2
|
import type { ChildEntityMap, EntityMap, FastSkillModificationLevelConfig, ResponsiveText, ResponsiveTextOptional, SkillModificationLevel, SlowSkillModificationLevelConfig } from "@optolith/database-schema/gen";
|
|
3
3
|
import type { IdArgsVariant } from "tsondb/schema/gen";
|
|
4
|
+
import type { StdReader } from "../../env.js";
|
|
4
5
|
import type { GetAllChildInstancesForParent, GetAllInstances, GetInstanceById } from "../../helpers/getTypes.js";
|
|
5
6
|
import type { LocaleCompare, LocaleJoin, LocaleJoinType } from "../../helpers/locale.js";
|
|
6
7
|
import type { Format, LocaleMap, Translate, TranslateMap, TranslationKeyMatchingParamsOfKey, TranslationParamsInArray, Translations } from "../../helpers/translate.js";
|
|
@@ -99,7 +100,7 @@ export declare const attributedNameFromInstanceR: (instance: {
|
|
|
99
100
|
translations: LocaleMap<{
|
|
100
101
|
name: string;
|
|
101
102
|
}>;
|
|
102
|
-
} | undefined, context: string, ...args: IdArgsVariant) => Reader<{
|
|
103
|
+
} | undefined, context: string, ...args: IdArgsVariant<EntityMap, keyof EntityMap>) => Reader<{
|
|
103
104
|
translateMap: TranslateMap;
|
|
104
105
|
}, string | undefined>;
|
|
105
106
|
/**
|
|
@@ -204,6 +205,13 @@ export declare const responsiveTranslateR: <K extends keyof Translations, K2 ext
|
|
|
204
205
|
translate: Translate;
|
|
205
206
|
responsiveTextSize: ResponsiveTextSize;
|
|
206
207
|
}, string>;
|
|
208
|
+
/**
|
|
209
|
+
* Creates a responsive value from a translation key that has a full and a compressed version.
|
|
210
|
+
*/
|
|
211
|
+
export declare const responsiveTranslateSplitR: <K extends keyof Translations, K2 extends TranslationKeyMatchingParamsOfKey<K>>(fullKey: K, compressedKey: K2, ...rest: [...TranslationParamsInArray<K>, ...TranslationParamsInArray<K2>]) => Reader<{
|
|
212
|
+
translate: Translate;
|
|
213
|
+
responsiveTextSize: ResponsiveTextSize;
|
|
214
|
+
}, string>;
|
|
207
215
|
/**
|
|
208
216
|
* Creates a responsive value from a responsive text.
|
|
209
217
|
*/
|
|
@@ -266,4 +274,20 @@ export declare const mapNullableR: <T, U, R>(defaultValue: U, fn: (value: NonNul
|
|
|
266
274
|
* Use `Reader` instances directly in a template string.
|
|
267
275
|
*/
|
|
268
276
|
export declare const sequence: <E>(string: TemplateStringsArray, ...values: (Reader<E, string> | string)[]) => Reader<E, string>;
|
|
277
|
+
/**
|
|
278
|
+
* Formats a number according to the locale’s rules, returns a string as-is.
|
|
279
|
+
*/
|
|
280
|
+
export declare const formatNumber: (value: number) => StdReader<string, "fn">;
|
|
281
|
+
/**
|
|
282
|
+
* Formats an AP value in an appreviated form.
|
|
283
|
+
*/
|
|
284
|
+
export declare const formatAPValue: (value: number) => StdReader<string, "t" | "fn">;
|
|
285
|
+
/**
|
|
286
|
+
* Formats a number according to the locale’s rules, returns a string as-is.
|
|
287
|
+
*/
|
|
288
|
+
export declare const formatNumberOrString: (value: number | string) => StdReader<string, "fn">;
|
|
289
|
+
/**
|
|
290
|
+
* Formats a number in fixed-point notation, returns a string as-is.
|
|
291
|
+
*/
|
|
292
|
+
export declare const fixedNumberOrString: (value: number | string, fractionDigits?: number) => string;
|
|
269
293
|
export {};
|
|
@@ -135,6 +135,10 @@ export const responsiveThenR = (full, compressed) => Reader.asks(env => {
|
|
|
135
135
|
* Creates a responsive value from a translation key that has a full and a compressed version.
|
|
136
136
|
*/
|
|
137
137
|
export const responsiveTranslateR = (fullKey, compressedKey, ...rest) => Reader.asks(({ translate, responsiveTextSize }) => responsive(responsiveTextSize, () => translate(fullKey, ...rest), () => translate(compressedKey, ...rest)));
|
|
138
|
+
/**
|
|
139
|
+
* Creates a responsive value from a translation key that has a full and a compressed version.
|
|
140
|
+
*/
|
|
141
|
+
export const responsiveTranslateSplitR = (fullKey, compressedKey, ...rest) => Reader.asks(({ translate, responsiveTextSize }) => responsive(responsiveTextSize, () => translate(fullKey, ...rest.slice(0, 1)), () => translate(compressedKey, ...rest.slice(1))));
|
|
138
142
|
/**
|
|
139
143
|
* Creates a responsive value from a responsive text.
|
|
140
144
|
*/
|
|
@@ -198,3 +202,19 @@ export const mapNullableR = (defaultValue, fn) => (value) => isNotNullish(value)
|
|
|
198
202
|
* Use `Reader` instances directly in a template string.
|
|
199
203
|
*/
|
|
200
204
|
export const sequence = (string, ...values) => Reader.traverse(values, value => (value instanceof Reader ? value : Reader.of(value))).map(resolvedValues => string.reduce((acc, str, i) => acc + str + (resolvedValues[i] ?? ""), ""));
|
|
205
|
+
/**
|
|
206
|
+
* Formats a number according to the locale’s rules, returns a string as-is.
|
|
207
|
+
*/
|
|
208
|
+
export const formatNumber = (value) => Reader.asks(env => env.formatNumber(value));
|
|
209
|
+
/**
|
|
210
|
+
* Formats an AP value in an appreviated form.
|
|
211
|
+
*/
|
|
212
|
+
export const formatAPValue = (value) => formatNumber(value).thenW(formattedValue => translateR("{$value} AP", { value: formattedValue }));
|
|
213
|
+
/**
|
|
214
|
+
* Formats a number according to the locale’s rules, returns a string as-is.
|
|
215
|
+
*/
|
|
216
|
+
export const formatNumberOrString = (value) => Reader.asks(env => (typeof value === "number" ? env.formatNumber(value) : value));
|
|
217
|
+
/**
|
|
218
|
+
* Formats a number in fixed-point notation, returns a string as-is.
|
|
219
|
+
*/
|
|
220
|
+
export const fixedNumberOrString = (value, fractionDigits) => typeof value === "number" ? value.toFixed(fractionDigits) : value;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fixedNumberOrString } from "../reader.js";
|
|
1
2
|
const lengthUnitTranslationKeys = {
|
|
2
3
|
LifePoints: "{$value} LP",
|
|
3
4
|
ArcaneEnergy: "{$value} AE",
|
|
@@ -8,5 +9,5 @@ const lengthUnitTranslationKeys = {
|
|
|
8
9
|
*/
|
|
9
10
|
export const formatEnergy = (translate, unit, value) => {
|
|
10
11
|
const key = lengthUnitTranslationKeys[unit];
|
|
11
|
-
return translate(key, { value });
|
|
12
|
+
return translate(key, { value: fixedNumberOrString(value) });
|
|
12
13
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Reader } from "@elyukai/utils/reader";
|
|
2
|
+
import { fixedNumberOrString } from "../reader.js";
|
|
2
3
|
import { responsive } from "../responsiveText.js";
|
|
3
4
|
const lengthUnitTranslationKeys = {
|
|
4
5
|
Steps: [".input {$value :number} {{{$value} yards}}", "{$value} yards", "{$value} yd"],
|
|
@@ -9,9 +10,11 @@ const lengthUnitTranslationKeys = {
|
|
|
9
10
|
*/
|
|
10
11
|
export const formatLength = (translate, responsiveTextSize, unit, value) => {
|
|
11
12
|
const [fullNumberKey, fullKey, compressedKey] = lengthUnitTranslationKeys[typeof unit === "string" ? unit : unit.kind];
|
|
12
|
-
return responsive(responsiveTextSize, () => translate(typeof value === "number" ? fullNumberKey : fullKey,
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
return responsive(responsiveTextSize, () => translate(typeof value === "number" ? fullNumberKey : fullKey, typeof value === "number"
|
|
14
|
+
? {
|
|
15
|
+
value,
|
|
16
|
+
}
|
|
17
|
+
: { value }), () => translate(compressedKey, { value: fixedNumberOrString(value) }));
|
|
15
18
|
};
|
|
16
19
|
/**
|
|
17
20
|
* Returns the text for a length unit.
|
|
@@ -35,13 +35,17 @@ export const formatTimeSpan = (translate, translateMap, format, responsiveTextSi
|
|
|
35
35
|
}));
|
|
36
36
|
}
|
|
37
37
|
const [fullNumberKey, fullKey, compressedNumberKey, compressedKey] = timeSpanUnitTranslationKeys[typeof unit === "string" ? unit : unit.kind];
|
|
38
|
-
return responsive(responsiveTextSize, () => translate(typeof value === "number" ? fullNumberKey : fullKey,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
return responsive(responsiveTextSize, () => translate(typeof value === "number" ? fullNumberKey : fullKey, typeof value === "number"
|
|
39
|
+
? {
|
|
40
|
+
value,
|
|
41
|
+
style: interval ? "interval" : "default",
|
|
42
|
+
}
|
|
43
|
+
: { value }), () => translate(typeof value === "number" ? compressedNumberKey : compressedKey, typeof value === "number"
|
|
44
|
+
? {
|
|
45
|
+
value,
|
|
46
|
+
style: interval ? "interval" : "default",
|
|
47
|
+
}
|
|
48
|
+
: { value }));
|
|
45
49
|
};
|
|
46
50
|
/**
|
|
47
51
|
* Returns the text for a time span unit.
|
|
@@ -6,3 +6,7 @@ export declare const MISSING_VALUE = "###MISSING###";
|
|
|
6
6
|
* String to display when a translation that should be present produces an error.
|
|
7
7
|
*/
|
|
8
8
|
export declare const UNHANDLED_VALUE = "###UNHANDLEDERROR###";
|
|
9
|
+
/**
|
|
10
|
+
* String to display when there is a logic error in text generation.
|
|
11
|
+
*/
|
|
12
|
+
export declare const LOGIC_ERROR = "###LOGIC_ERROR###";
|
|
@@ -6,3 +6,7 @@ export const MISSING_VALUE = "###MISSING###";
|
|
|
6
6
|
* String to display when a translation that should be present produces an error.
|
|
7
7
|
*/
|
|
8
8
|
export const UNHANDLED_VALUE = "###UNHANDLEDERROR###";
|
|
9
|
+
/**
|
|
10
|
+
* String to display when there is a logic error in text generation.
|
|
11
|
+
*/
|
|
12
|
+
export const LOGIC_ERROR = "###LOGIC_ERROR###";
|
package/lib/entities/poison.js
CHANGED
|
@@ -379,7 +379,7 @@ export const getPoisonEntityDescription = createEntityDescriptionCreator(({ getI
|
|
|
379
379
|
? undefined
|
|
380
380
|
: {
|
|
381
381
|
label: `${translate("AP Value")} (${translate("Trade Secret")})`,
|
|
382
|
-
value: translate("{$value} AP", { value: tradeSecret.apValue }) +
|
|
382
|
+
value: translate("{$value} AP", { value: tradeSecret.apValue.toFixed() }) +
|
|
383
383
|
parensIf(mapNullable(tradeSecret.prerequisites, prerequisites => `${translate("Prerequisites")}: ${printPlainGeneralPrerequisites(prerequisites).run(env)}`)),
|
|
384
384
|
},
|
|
385
385
|
entry.source_type.kind === "AlchemicalPoison" ||
|