2025-05-28 15:36:51 -07:00

452 lines
12 KiB
TypeScript

import { takeEvery, call, put, select } from "redux-saga/effects";
import {
ApiRequests,
SagaHelpers,
UnpackMakeApiResponseData,
DiceRolls,
RollGroupContract,
HelperUtils,
} from "@dndbeyond/character-rules-engine/es";
import { rollResultActions, rollResultActionTypes } from "../actions";
import {
RollResultAction,
RollResultComponentGroupPersistAction,
RollResultComponentSimulatedGroupsPersistAction,
RollResultDiceRollSetAction,
RollResultGroupAddAction,
RollResultGroupCreateAction,
RollResultGroupDestroyAction,
RollResultGroupOrderSetAction,
RollResultGroupRemoveAction,
RollResultGroupResetAction,
RollResultGroupsLoadAction,
RollResultComponentPersistAction,
} from "../actions/rollResult/typings";
import { appSelectors, rollResultSelectors } from "../selectors";
import { RollResultUtils } from "../utils";
export default function* saga() {
yield takeEvery(
Object.keys(rollResultActionTypes).map((key) => rollResultActionTypes[key]),
filter
);
}
function* filter(action: RollResultAction) {
switch (action.type) {
case rollResultActionTypes.ROLL_RESULT_GROUPS_LOAD:
yield call(handleRollResultGroupsLoad, action);
break;
case rollResultActionTypes.ROLL_RESULT_GROUP_CREATE:
yield call(handleRollResultGroupCreate, action);
break;
case rollResultActionTypes.ROLL_RESULT_GROUP_ADD:
yield call(handleRollResultGroupAdd, action);
break;
case rollResultActionTypes.ROLL_RESULT_GROUP_DESTROY:
yield call(handleRollResultGroupDestroy, action);
break;
case rollResultActionTypes.ROLL_RESULT_GROUP_REMOVE:
yield call(handleRollResultGroupRemove, action);
break;
case rollResultActionTypes.ROLL_RESULT_DICE_ROLL_SET:
yield call(handleRollResultDiceRollSet, action);
break;
case rollResultActionTypes.ROLL_RESULT_GROUP_ORDER_SET:
yield call(handleRollResultGroupOrderSet, action);
break;
case rollResultActionTypes.ROLL_RESULT_GROUP_RESET:
yield call(handleRollResultGroupReset, action);
break;
case rollResultActionTypes.ROLL_RESULT_COMPONENT_GROUP_PERSIST:
yield call(handleRollResultPersistGroup, action);
break;
case rollResultActionTypes.ROLL_RESULT_COMPONENT_PERSIST:
yield call(handleRollResultPersist, action);
break;
case rollResultActionTypes.ROLL_RESULT_COMPONENT_SIMULATED_GROUPS_PERSIST:
yield call(handleRollResultPersistSimulatedGroups, action);
break;
default:
//not implemented
}
}
function* handleRollResultGroupsLoad(action: RollResultGroupsLoadAction) {
const { componentKey, simulatedGroupCount, simulatedRollResultCount } =
action.payload;
const responseData: UnpackMakeApiResponseData<
typeof ApiRequests.getCharacterRollResultGroups
> = yield call(
SagaHelpers.getApiRequestData,
ApiRequests.getCharacterRollResultGroups,
{ params: { componentKey } }
);
if (responseData === null || responseData.length === 0) {
if (simulatedGroupCount) {
let groups: Array<RollGroupContract> = [];
let lastGroup: RollGroupContract | null = null;
for (let i = 0; i < simulatedGroupCount; i++) {
const rollGroupContract = DiceRolls.simulateRollGroupContract(
{
componentKey,
nextGroupKey: lastGroup?.nextGroupKey ?? null,
},
simulatedRollResultCount
);
groups.push(rollGroupContract);
lastGroup = rollGroupContract;
}
yield put(
rollResultActions.rollResultComponentSimulatedGroupsSet(
componentKey,
groups
)
);
}
} else {
yield put(
rollResultActions.rollResultComponentGroupsSetCommit(
componentKey,
responseData
)
);
}
}
function* handleRollResultGroupCreate(action: RollResultGroupCreateAction) {
const { componentKey, simulatedRollResultCount } = action.payload;
const simulatedGroupsLookup: ReturnType<
typeof rollResultSelectors.getRollResultComponentSimulatedGroupsLookup
> = yield select(
rollResultSelectors.getRollResultComponentSimulatedGroupsLookup
);
const currentSimulatedGroups = RollResultUtils.getComponentOrderedGroups(
componentKey,
simulatedGroupsLookup
);
if (currentSimulatedGroups.length) {
const newGroup = DiceRolls.simulateRollGroupContract(
{
componentKey,
nextGroupKey: currentSimulatedGroups[0].groupKey ?? null,
},
simulatedRollResultCount
);
yield put(
rollResultActions.rollResultComponentSimulatedGroupsSet(componentKey, [
newGroup,
...currentSimulatedGroups,
])
);
yield put(
rollResultActions.rollResultComponentSimulatedGroupsPersist(componentKey)
);
} else {
const currentGroupLookup: ReturnType<
typeof rollResultSelectors.getRollResultComponentGroupsLookup
> = yield select(rollResultSelectors.getRollResultComponentGroupsLookup);
const currentGroups = RollResultUtils.getComponentOrderedGroups(
componentKey,
currentGroupLookup
);
const newGroup = DiceRolls.simulateRollGroupContract(
{
componentKey,
nextGroupKey: currentGroups[0]?.groupKey ?? null,
},
simulatedRollResultCount
);
yield put(rollResultActions.rollResultGroupAdd(newGroup));
}
}
function* handleRollResultGroupAdd(action: RollResultGroupAddAction) {
const { componentKey, group } = action.payload;
const responseData: UnpackMakeApiResponseData<
typeof ApiRequests.postCharacterRollResultGroup
> = yield call(
SagaHelpers.getApiRequestData,
ApiRequests.postCharacterRollResultGroup,
group
);
if (responseData !== null) {
yield put(rollResultActions.rollResultGroupAddCommit(group));
}
}
function* handleRollResultGroupDestroy(action: RollResultGroupDestroyAction) {
const { groupKey, nextGroupKey, componentKey } = action.payload;
const currentGroupLookup = yield select(
rollResultSelectors.getRollResultComponentGroupsLookup
);
const currentGroups = RollResultUtils.getGroupsByComponentKey(
componentKey,
currentGroupLookup
);
const groupToUpdate = currentGroups.find(
(group) => group.nextGroupKey === groupKey
);
yield put(rollResultActions.rollResultGroupRemove(componentKey, groupKey));
if (groupToUpdate) {
yield put(
rollResultActions.rollResultGroupOrderSet(
componentKey,
groupToUpdate.groupKey,
nextGroupKey
)
);
}
}
function* handleRollResultGroupOrderSet(action: RollResultGroupOrderSetAction) {
const { componentKey, groupKey, nextGroupKey } = action.payload;
const responseData: UnpackMakeApiResponseData<
typeof ApiRequests.putCharacterRollResultGroupOrder
> = yield call(
SagaHelpers.getApiRequestData,
ApiRequests.putCharacterRollResultGroupOrder,
{
groupKey,
componentKey,
nextGroupKey,
}
);
yield put(
rollResultActions.rollResultGroupOrderSetCommit(
componentKey,
groupKey,
nextGroupKey
)
);
}
function* handleRollResultGroupRemove(action: RollResultGroupRemoveAction) {
const { componentKey, groupKey } = action.payload;
const responseData: UnpackMakeApiResponseData<
typeof ApiRequests.deleteCharacterRollResultGroup
> = yield call(
SagaHelpers.getApiRequestData,
ApiRequests.deleteCharacterRollResultGroup,
{
groupKey,
componentKey,
}
);
yield put(
rollResultActions.rollResultGroupRemoveCommit(componentKey, groupKey)
);
}
function* handleRollResultPersistSimulatedGroups(
action: RollResultComponentSimulatedGroupsPersistAction
) {
const { componentKey, groupKey, rollKey, properties } = action.payload;
const simulatedGroupsLookup: ReturnType<
typeof rollResultSelectors.getRollResultComponentSimulatedGroupsLookup
> = yield select(
rollResultSelectors.getRollResultComponentSimulatedGroupsLookup
);
const currentSimulatedGroups = RollResultUtils.getGroupsByComponentKey(
componentKey,
simulatedGroupsLookup
);
if (currentSimulatedGroups.length) {
for (let i = 0; i < currentSimulatedGroups.length; i++) {
const group = currentSimulatedGroups[i];
if (rollKey && groupKey === group.groupKey) {
// If an initial roll is with the simulated group
const rollIndex = group.rollResults.findIndex(
(rollResult) => rollResult.rollKey === rollKey
);
group.rollResults.splice(rollIndex, 1, {
...group.rollResults[rollIndex],
...properties,
});
}
yield put(rollResultActions.rollResultGroupAdd(group));
}
yield put(
rollResultActions.rollResultComponentSimulatedGroupsSet(componentKey, [])
);
}
}
function* handleRollResultPersistGroup(
action: RollResultComponentGroupPersistAction
) {
const { componentKey, groupKey, rollResults } = action.payload;
const currentGroupLookup = yield select(
rollResultSelectors.getRollResultComponentGroupsLookup
);
const currentGroups = RollResultUtils.getGroupsByComponentKey(
componentKey,
currentGroupLookup
);
const groupToUpdate = currentGroups.find(
(group) => group.groupKey === groupKey
);
if (groupToUpdate) {
const responseData: UnpackMakeApiResponseData<
typeof ApiRequests.putCharacterRollResultGroup
> = yield call(
SagaHelpers.getApiRequestData,
ApiRequests.putCharacterRollResultGroup,
{
groupKey,
componentKey,
rollResults,
}
);
}
}
function* handleRollResultPersist(action: RollResultComponentPersistAction) {
const {
componentKey,
groupKey,
rollKey,
properties: { rollTotal, rollValues, assignedValue },
nextRollKey,
} = action.payload;
if (groupKey && rollKey) {
const responseData: UnpackMakeApiResponseData<
typeof ApiRequests.putCharacterRollResult
> = yield call(
SagaHelpers.getApiRequestData,
ApiRequests.putCharacterRollResult,
{
rollKey,
nextRollKey,
rollTotal,
assignedValue,
rollValues,
groupKey,
componentKey,
}
);
}
}
function* handleRollResultDiceRollSet(action: RollResultDiceRollSetAction) {
const { rollKey, properties, nextRollKey } = action.payload;
const parentKeyInfoLookup: ReturnType<
typeof appSelectors.getRollParentKeyInfoLookup
> = yield select(appSelectors.getRollParentKeyInfoLookup);
const simulatedParentKeyInfoLookup: ReturnType<
typeof appSelectors.getSimulatedRollParentKeyInfoLookup
> = yield select(appSelectors.getSimulatedRollParentKeyInfoLookup);
const parentKeyInfo = HelperUtils.lookupDataOrFallback(
parentKeyInfoLookup,
rollKey
);
const simulatedParentKeyInfo = HelperUtils.lookupDataOrFallback(
simulatedParentKeyInfoLookup,
rollKey
);
if (parentKeyInfo) {
const { groupKey, componentKey } = parentKeyInfo;
yield put(
rollResultActions.rollResultComponentPersist(
componentKey,
groupKey,
rollKey,
properties,
nextRollKey
)
);
yield put(
rollResultActions.rollResultDiceRollSetCommit(
componentKey,
groupKey,
rollKey,
properties,
nextRollKey
)
);
} else if (simulatedParentKeyInfo) {
const { groupKey, componentKey } = simulatedParentKeyInfo;
yield put(
rollResultActions.rollResultComponentSimulatedGroupsPersist(
componentKey,
groupKey,
rollKey,
properties
)
);
yield put(
rollResultActions.rollResultComponentSimulatedDiceRollSet(
componentKey,
groupKey,
rollKey,
properties
)
);
}
}
function* handleRollResultGroupReset(action: RollResultGroupResetAction) {
const { componentKey, groupKey, rollResults } = action.payload;
yield put(
rollResultActions.rollResultComponentGroupPersist(
componentKey,
groupKey,
rollResults
)
);
yield put(
rollResultActions.rollResultGroupResetCommit(
componentKey,
groupKey,
rollResults
)
);
}