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 = []; 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 ) ); }