refactor: use dictionary for tiny activatable state
This commit is contained in:
@@ -100,12 +100,17 @@ export const selectAdventurePointsSpentOnLiturgicalChants = createSelector(
|
||||
sumRatedMaps,
|
||||
)
|
||||
|
||||
const sumTinyActivatables = (tinyActivatables: TinyActivatable[]): SpentAdventurePoints => ({
|
||||
general: count(tinyActivatables, isTinyActivatableActive),
|
||||
bound: 0,
|
||||
})
|
||||
|
||||
/**
|
||||
* Returns the adventure points spent on cantrips.
|
||||
*/
|
||||
export const selectAdventurePointsSpentOnCantrips = createSelector(
|
||||
selectDynamicCantrips,
|
||||
(cantrips): SpentAdventurePoints => ({ general: cantrips?.length ?? 0, bound: 0 }),
|
||||
sumTinyActivatables,
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -113,7 +118,7 @@ export const selectAdventurePointsSpentOnCantrips = createSelector(
|
||||
*/
|
||||
export const selectAdventurePointsSpentOnBlessings = createSelector(
|
||||
selectDynamicBlessings,
|
||||
(blessings): SpentAdventurePoints => ({ general: blessings?.length ?? 0, bound: 0 }),
|
||||
sumTinyActivatables,
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,10 @@ import {
|
||||
} from "../slices/databaseSlice.ts"
|
||||
|
||||
import { createSelector } from "@reduxjs/toolkit"
|
||||
import { getOptions } from "../../shared/domain/activatable/activatableEntry.ts"
|
||||
import {
|
||||
getOptions,
|
||||
isTinyActivatableActive,
|
||||
} from "../../shared/domain/activatable/activatableEntry.ts"
|
||||
import {
|
||||
AdvantageIdentifier,
|
||||
KarmaSpecialAbilityIdentifier,
|
||||
@@ -89,7 +92,7 @@ export const selectVisibleBlessings = createSelector(
|
||||
): [active: DisplayedActiveBlessing[], inactive: DisplayedActiveBlessing[]] =>
|
||||
partition(
|
||||
Object.values(staticBlessings).map(blessing => ({ kind: "blessing", static: blessing })),
|
||||
staticBlessing => dynamicBlessings.includes(staticBlessing.static.id),
|
||||
staticBlessing => isTinyActivatableActive(getDynamicBlessingById(staticBlessing.static.id)),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { createSimpleActivatableSlice } from "./simpleActivatableSlice.ts"
|
||||
import { createTinyActivatableSlice } from "./tinyActivatableSlice.ts"
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||
export const {
|
||||
actions: { addAction: addBlessing, removeAction: removeBlessing },
|
||||
reducer: blessingsReducer,
|
||||
} = createSimpleActivatableSlice({
|
||||
} = createTinyActivatableSlice({
|
||||
namespace: "blessings",
|
||||
entityName: "Blessing",
|
||||
getState: state => state.blessings,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { createSimpleActivatableSlice } from "./simpleActivatableSlice.ts"
|
||||
import { createTinyActivatableSlice } from "./tinyActivatableSlice.ts"
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||
export const {
|
||||
actions: { addAction: addCantrip, removeAction: removeCantrip },
|
||||
reducer: cantripsReducer,
|
||||
} = createSimpleActivatableSlice({
|
||||
} = createTinyActivatableSlice({
|
||||
namespace: "cantrips",
|
||||
entityName: "Cantrip",
|
||||
getState: state => state.cantrips,
|
||||
|
||||
@@ -167,7 +167,12 @@ const staticInitialState: Omit<CharacterState, "dateCreated" | "dateLastModified
|
||||
close: {},
|
||||
ranged: {},
|
||||
},
|
||||
cantrips: [1],
|
||||
cantrips: {
|
||||
1: {
|
||||
id: 1,
|
||||
active: true,
|
||||
},
|
||||
},
|
||||
spells: {
|
||||
1: {
|
||||
id: 1,
|
||||
@@ -205,7 +210,12 @@ const staticInitialState: Omit<CharacterState, "dateCreated" | "dateLastModified
|
||||
geodeRituals: {},
|
||||
zibiljaRituals: {},
|
||||
},
|
||||
blessings: [1],
|
||||
blessings: {
|
||||
1: {
|
||||
id: 1,
|
||||
active: true,
|
||||
},
|
||||
},
|
||||
liturgicalChants: {
|
||||
1: {
|
||||
id: 1,
|
||||
|
||||
+12
-9
@@ -1,12 +1,12 @@
|
||||
import { ActionCreatorWithPayload, AnyAction, Draft, createAction } from "@reduxjs/toolkit"
|
||||
import { TinyActivatableSet } from "../../shared/domain/activatable/activatableEntry.ts"
|
||||
import { TinyActivatableMap } from "../../shared/domain/activatable/activatableEntry.ts"
|
||||
import { Reducer, createImmerReducer } from "../../shared/utils/redux.ts"
|
||||
import { CharacterState } from "./characterSlice.ts"
|
||||
|
||||
/**
|
||||
* Functions for working with simple activatable entries.
|
||||
*/
|
||||
export type SimpleActivatableSlice<N extends string, E extends string> = {
|
||||
export type TinyActivatableSlice<N extends string, E extends string> = {
|
||||
/**
|
||||
* The actions that can be dispatched to modify the state.
|
||||
*/
|
||||
@@ -31,11 +31,11 @@ export type SimpleActivatableSlice<N extends string, E extends string> = {
|
||||
/**
|
||||
* Creates a slice for a map of simple activatable entries.
|
||||
*/
|
||||
export const createSimpleActivatableSlice = <N extends string, E extends string>(config: {
|
||||
export const createTinyActivatableSlice = <N extends string, E extends string>(config: {
|
||||
namespace: N
|
||||
entityName: E
|
||||
getState: (state: Draft<CharacterState>) => Draft<TinyActivatableSet>
|
||||
}): SimpleActivatableSlice<N, E> => {
|
||||
getState: (state: Draft<CharacterState>) => Draft<TinyActivatableMap>
|
||||
}): TinyActivatableSlice<N, E> => {
|
||||
const addAction = createAction<number, `${N}/add${E}`>(
|
||||
`${config.namespace}/add${config.entityName}`,
|
||||
)
|
||||
@@ -46,12 +46,15 @@ export const createSimpleActivatableSlice = <N extends string, E extends string>
|
||||
const reducer = createImmerReducer((state: Draft<CharacterState>, action) => {
|
||||
const focusedState = config.getState(state)
|
||||
if (addAction.match(action)) {
|
||||
if (!focusedState.includes(action.payload)) {
|
||||
focusedState.push(action.payload)
|
||||
if (!Object.hasOwn(focusedState, action.payload)) {
|
||||
focusedState[action.payload] = {
|
||||
id: action.payload,
|
||||
active: true,
|
||||
}
|
||||
}
|
||||
} else if (removeAction.match(action)) {
|
||||
if (focusedState.includes(action.payload)) {
|
||||
focusedState.splice(focusedState.indexOf(action.payload), 1)
|
||||
if (Object.hasOwn(focusedState, action.payload)) {
|
||||
delete focusedState[action.payload]
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -4,9 +4,25 @@ import { isNotNullish } from "../../utils/nullable.ts"
|
||||
import { assertExhaustive } from "../../utils/typeSafety.ts"
|
||||
|
||||
/**
|
||||
* A simple set of activated activatable identifiers.
|
||||
* An activated activatable identifier.
|
||||
*/
|
||||
export type TinyActivatableSet = number[]
|
||||
export type TinyActivatable = {
|
||||
id: number
|
||||
active: true
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple map of activated activatable identifiers.
|
||||
*/
|
||||
export type TinyActivatableMap = {
|
||||
[id: number]: TinyActivatable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a given tiny activatable entry is active.
|
||||
*/
|
||||
export const isTinyActivatableActive = (activatable: TinyActivatable | undefined): boolean =>
|
||||
activatable?.active ?? false
|
||||
|
||||
/**
|
||||
* An activatable entry.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActivatableMap, TinyActivatableSet } from "./activatable/activatableEntry.ts"
|
||||
import { ActivatableMap, TinyActivatableMap } from "./activatable/activatableEntry.ts"
|
||||
import { Color } from "./color.ts"
|
||||
import { Energy, EnergyWithBuyBack } from "./energy.ts"
|
||||
import { Pact } from "./pact.ts"
|
||||
@@ -324,7 +324,7 @@ export type Character = {
|
||||
ranged: RatedMap
|
||||
}
|
||||
|
||||
cantrips: TinyActivatableSet
|
||||
cantrips: TinyActivatableMap
|
||||
spells: ActivatableRatedWithEnhancementsMap
|
||||
rituals: ActivatableRatedWithEnhancementsMap
|
||||
|
||||
@@ -340,7 +340,7 @@ export type Character = {
|
||||
zibiljaRituals: ActivatableRatedMap
|
||||
}
|
||||
|
||||
blessings: TinyActivatableSet
|
||||
blessings: TinyActivatableMap
|
||||
liturgicalChants: ActivatableRatedWithEnhancementsMap
|
||||
ceremonies: ActivatableRatedWithEnhancementsMap
|
||||
|
||||
|
||||
@@ -15,8 +15,13 @@ import { MagicalMelody } from "optolith-database-schema/types/magicalActions/Mag
|
||||
import { ZibiljaRitual } from "optolith-database-schema/types/magicalActions/ZibiljaRitual"
|
||||
import { isNotNullish } from "../../utils/nullable.ts"
|
||||
import { assertExhaustive } from "../../utils/typeSafety.ts"
|
||||
import { Activatable, TinyActivatableSet } from "../activatable/activatableEntry.ts"
|
||||
import {
|
||||
Activatable,
|
||||
TinyActivatable,
|
||||
isTinyActivatableActive,
|
||||
} from "../activatable/activatableEntry.ts"
|
||||
import { FilterApplyingRatedDependencies } from "../dependencies/filterApplyingDependencies.ts"
|
||||
import { GetById } from "../getTypes.ts"
|
||||
import { getHighestAttributeValue } from "./attribute.ts"
|
||||
import {
|
||||
ActivatableRated,
|
||||
@@ -201,12 +206,13 @@ export type DisplayedActiveSpellwork =
|
||||
* Filters the given list of active cantrips by tradition.
|
||||
*/
|
||||
export const getVisibleActiveCantrips = (
|
||||
staticCantrips: Record<number, Cantrip>,
|
||||
dynamicCantrips: TinyActivatableSet,
|
||||
getStaticCantripById: GetById.Static.Cantrip,
|
||||
dynamicCantrips: TinyActivatable[],
|
||||
getIsUnfamiliar: (id: number) => boolean,
|
||||
): DisplayedActiveCantrip[] =>
|
||||
dynamicCantrips
|
||||
.map(id => staticCantrips[id])
|
||||
.filter(isTinyActivatableActive)
|
||||
.map(dynamicCantrip => getStaticCantripById(dynamicCantrip.id))
|
||||
.filter(isNotNullish)
|
||||
.map(staticCantrip => ({
|
||||
kind: "cantrip",
|
||||
|
||||
@@ -14,9 +14,9 @@ import { PublicationRefs } from "optolith-database-schema/types/source/_Publicat
|
||||
import { assertExhaustive } from "../../utils/typeSafety.ts"
|
||||
import {
|
||||
Activatable,
|
||||
TinyActivatableSet,
|
||||
firstLevel,
|
||||
getFirstOptionOfType,
|
||||
isTinyActivatableActive,
|
||||
} from "../activatable/activatableEntry.ts"
|
||||
import { CombinedActiveMagicalTradition } from "../activatable/magicalTradition.ts"
|
||||
import {
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
compareImprovementCost,
|
||||
fromRaw,
|
||||
} from "../adventurePoints/improvementCost.ts"
|
||||
import { GetById } from "../getTypes.ts"
|
||||
import { MagicalTraditionIdentifier } from "../identifier.ts"
|
||||
import { checkPrerequisitesOfSpellwork } from "../prerequisites/fullPrerequisiteValidationForType.ts"
|
||||
import {
|
||||
@@ -171,8 +172,8 @@ export type DisplayedInactiveSpellwork =
|
||||
* Filters the given list of inactive cantrips by tradition.
|
||||
*/
|
||||
export const getVisibleInactiveCantrips = (
|
||||
staticCantrips: Record<number, Cantrip>,
|
||||
dynamicCantrips: TinyActivatableSet,
|
||||
staticCantrips: Cantrip[],
|
||||
getDynamicCantripById: GetById.Dynamic.Cantrip,
|
||||
activeTraditions: CombinedActiveMagicalTradition[],
|
||||
getIsEntryAvailable: (src: PublicationRefs) => boolean,
|
||||
getIsUnfamiliar: (id: number) => boolean,
|
||||
@@ -182,7 +183,7 @@ export const getVisibleInactiveCantrips = (
|
||||
: Object.values(staticCantrips)
|
||||
.filter(
|
||||
cantrip =>
|
||||
!dynamicCantrips.includes(cantrip.id) &&
|
||||
!isTinyActivatableActive(getDynamicCantripById(cantrip.id)) &&
|
||||
getIsEntryAvailable(cantrip.src) &&
|
||||
(cantrip.note?.tag !== "Exclusive" ||
|
||||
// if the cantrip is exclusive to specific tradition, at least one of the
|
||||
|
||||
Reference in New Issue
Block a user