Make modifier section take options func and display bad numbers in red

This commit is contained in:
thepaperpilot 2023-02-15 00:09:06 -06:00
parent dcb3bc949d
commit 909c7a5f5e
2 changed files with 111 additions and 31 deletions

View file

@ -256,9 +256,11 @@ export interface Section {
* Takes an array of modifier "sections", and creates a JSXFunction that can render all those sections, and allow each section to be collapsed.
* Also returns a list of persistent refs that are used to control which sections are currently collapsed.
* @param sectionsFunc A function that returns the sections to display.
* @param smallerIsBetter Determines whether numbers larger or smaller than the base should be displayed as red.
*/
export function createCollapsibleModifierSections(
sectionsFunc: () => Section[]
sectionsFunc: () => Section[],
smallerIsBetter = false
): [JSXFunction, Persistent<Record<number, boolean>>] {
const sections: Section[] = [];
const processed:
@ -326,6 +328,9 @@ export function createCollapsibleModifierSections(
const hasPreviousSection = !firstVisibleSection;
firstVisibleSection = false;
const base = unref(processed.base[i]) ?? 1;
const total = s.modifier.apply(base);
return (
<>
{hasPreviousSection ? <br /> : null}
@ -335,11 +340,20 @@ export function createCollapsibleModifierSections(
{modifiers}
<hr />
<div class="modifier-container">
<span class="modifier-description">
Total
</span>
<span class="modifier-amount">
{format(s.modifier.apply(unref(processed.base[i]) ?? 1))}
<span class="modifier-description">Total</span>
<span
class="modifier-amount"
style={
(
smallerIsBetter === true
? Decimal.gt(total, base ?? 1)
: Decimal.lt(total, base ?? 1)
)
? "color: var(--danger)"
: ""
}
>
{formatSmall(total)}
{s.unit}
</span>
</div>

View file

@ -52,6 +52,8 @@ export interface AdditiveModifierOptions {
description?: Computable<CoercableComponent> | undefined;
/** A computable that will be processed and passed directly into the returned modifier. */
enabled?: Computable<boolean> | undefined;
/** Determines if numbers larger or smaller than 0 should be displayed as red. */
smallerIsBetter?: boolean;
}
/**
@ -62,7 +64,7 @@ export function createAdditiveModifier<T extends AdditiveModifierOptions>(
optionsFunc: () => T
): ModifierFromOptionalParams<T["description"], T["enabled"]> {
return createLazyProxy(() => {
const { addend, description, enabled } = optionsFunc();
const { addend, description, enabled, smallerIsBetter } = optionsFunc();
const processedAddend = convertComputable(addend);
const processedDescription = convertComputable(description);
@ -82,7 +84,18 @@ export function createAdditiveModifier<T extends AdditiveModifierOptions>(
{renderJSX(unref(processedDescription)!)}
</span>
) : null}
<span class="modifier-amount">
<span
class="modifier-amount"
style={
(
smallerIsBetter === true
? Decimal.gt(unref(processedAddend), 0)
: Decimal.lt(unref(processedAddend), 0)
)
? "color: var(--danger)"
: ""
}
>
{Decimal.gte(unref(processedAddend), 0) ? "+" : ""}
{formatSmall(unref(processedAddend))}
</span>
@ -100,6 +113,8 @@ export interface MultiplicativeModifierOptions {
description?: Computable<CoercableComponent> | undefined;
/** A computable that will be processed and passed directly into the returned modifier. */
enabled?: Computable<boolean> | undefined;
/** Determines if numbers larger or smaller than 1 should be displayed as red. */
smallerIsBetter?: boolean;
}
/**
@ -110,7 +125,7 @@ export function createMultiplicativeModifier<T extends MultiplicativeModifierOpt
optionsFunc: () => T
): ModifierFromOptionalParams<T["description"], T["enabled"]> {
return createLazyProxy(() => {
const { multiplier, description, enabled } = optionsFunc();
const { multiplier, description, enabled, smallerIsBetter } = optionsFunc();
const processedMultiplier = convertComputable(multiplier);
const processedDescription = convertComputable(description);
@ -130,7 +145,18 @@ export function createMultiplicativeModifier<T extends MultiplicativeModifierOpt
{renderJSX(unref(processedDescription)!)}
</span>
) : null}
<span class="modifier-amount">
<span
class="modifier-amount"
style={
(
smallerIsBetter === true
? Decimal.gt(unref(processedMultiplier), 1)
: Decimal.lt(unref(processedMultiplier), 1)
)
? "color: var(--danger)"
: ""
}
>
×{formatSmall(unref(processedMultiplier))}
</span>
</div>
@ -149,6 +175,8 @@ export interface ExponentialModifierOptions {
enabled?: Computable<boolean> | undefined;
/** Add 1 before calculating, then remove it afterwards. This prevents low numbers from becoming lower. */
supportLowNumbers?: boolean;
/** Determines if numbers larger or smaller than 1 should be displayed as red. */
smallerIsBetter?: boolean;
}
/**
@ -159,7 +187,8 @@ export function createExponentialModifier<T extends ExponentialModifierOptions>(
optionsFunc: () => T
): ModifierFromOptionalParams<T["description"], T["enabled"]> {
return createLazyProxy(() => {
const { exponent, description, enabled, supportLowNumbers } = optionsFunc();
const { exponent, description, enabled, supportLowNumbers, smallerIsBetter } =
optionsFunc();
const processedExponent = convertComputable(exponent);
const processedDescription = convertComputable(description);
@ -200,7 +229,18 @@ export function createExponentialModifier<T extends ExponentialModifierOptions>(
{supportLowNumbers ? " (+1 effective)" : null}
</span>
) : null}
<span class="modifier-amount">
<span
class="modifier-amount"
style={
(
smallerIsBetter === true
? Decimal.gt(unref(processedExponent), 1)
: Decimal.lt(unref(processedExponent), 1)
)
? "color: var(--danger)"
: ""
}
>
^{formatSmall(unref(processedExponent))}
</span>
</div>
@ -252,35 +292,50 @@ export function createSequentialModifier<
}) as unknown as S;
}
/** An object that configures a modifier section via {@link createModifierSection}. */
export interface ModifierSectionOptions {
/** The header for the section. */
title: string;
/** Smaller text that appears in the header after the title. */
subtitle?: string;
/** The modifier to render. */
modifier: WithRequired<Modifier, "description">;
/** The base value that'll be passed into the modifier. Defaults to 1. */
base?: DecimalSource;
/** The unit of the value being modified, if any. */
unit?: string;
/** The label to use for the base value. Defaults to "Base". */
baseText?: CoercableComponent;
/** Determines if numbers larger or smaller than the base should be displayed as red. */
smallerIsBetter?: boolean;
}
/**
* Create a JSX element that displays a modifier.
* Intended to be used with the output from {@link createSequentialModifier}.
* @param title The header for the section.
* @param subtitle Smaller text that appears in the header after the title.
* @param modifier The modifier to render.
* @param base The base value that'll be passed into the modifier.
* @param unit The unit of the value being modified, if any.
* @param baseText The label to use for the base value.
* @param options Modifier section options.
*/
export function createModifierSection(
title: string,
subtitle: string,
modifier: WithRequired<Modifier, "description">,
base: DecimalSource = 1,
unit = "",
baseText: CoercableComponent = "Base"
) {
export function createModifierSection({
title,
subtitle,
modifier,
base,
unit,
baseText,
smallerIsBetter
}: ModifierSectionOptions) {
const total = modifier.apply(base ?? 1);
return (
<div>
<h3>
{title}
{subtitle ? <span class="subtitle"> ({subtitle})</span> : null}
{subtitle == null ? null : <span class="subtitle"> ({subtitle})</span>}
</h3>
<br />
<div class="modifier-container">
<span class="modifier-description">{renderJSX(baseText)}</span>
<span class="modifier-description">{renderJSX(baseText ?? "Base")}</span>
<span class="modifier-amount">
{formatSmall(base)}
{formatSmall(base ?? 1)}
{unit}
</span>
</div>
@ -288,8 +343,19 @@ export function createModifierSection(
<hr />
<div class="modifier-container">
<span class="modifier-description">Total</span>
<span class="modifier-amount">
{formatSmall(modifier.apply(base))}
<span
class="modifier-amount"
style={
(
smallerIsBetter === true
? Decimal.gt(total, base ?? 1)
: Decimal.lt(total, base ?? 1)
)
? "color: var(--danger)"
: ""
}
>
{formatSmall(total)}
{unit}
</span>
</div>