All files / src/context SimulationContext.jsx

97.36% Statements 37/38
75% Branches 3/4
100% Functions 16/16
97.36% Lines 37/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116      7x 7x             114x   114x                         148x 147x 4x   143x             109x 109x     109x             24x   24x 2x     24x 1x     24x 1x     24x 1x     24x 1x     24x 1x     24x 1x     24x 1x     24x 1x     24x 1x     24x 1x     24x 1x     24x                                  
import { createContext, useContext, useReducer, useCallback } from 'react';
import { INITIAL_SIMULATION_STATE, simulationReducer } from './simulationReducer';
 
const SimulationContext = createContext(null);
const SimulationDispatchContext = createContext(null);
 
/**
 * Simulation Context Provider
 * Manages global simulation state using useReducer for predictable state updates
 */
export function SimulationProvider({ children }) {
  const [state, dispatch] = useReducer(simulationReducer, INITIAL_SIMULATION_STATE);
 
  return (
    <SimulationContext.Provider value={state}>
      <SimulationDispatchContext.Provider value={dispatch}>
        {children}
      </SimulationDispatchContext.Provider>
    </SimulationContext.Provider>
  );
}
 
/**
 * Custom hook to access simulation state
 */
export function useSimulation() {
  const context = useContext(SimulationContext);
  if (context === null) {
    throw new Error('useSimulation must be used within a SimulationProvider');
  }
  return context;
}
 
/**
 * Custom hook to access simulation dispatch
 */
export function useSimulationDispatch() {
  const context = useContext(SimulationDispatchContext);
  Iif (context === null) {
    throw new Error('useSimulationDispatch must be used within a SimulationProvider');
  }
  return context;
}
 
/**
 * Custom hook for simulation actions
 */
export function useSimulationActions() {
  const dispatch = useSimulationDispatch();
 
  const addAtom = useCallback((x, y, z, type) => {
    dispatch({ type: 'ADD_ATOM', payload: { x, y, z, atomType: type } });
  }, [dispatch]);
 
  const removeAtom = useCallback((id) => {
    dispatch({ type: 'REMOVE_ATOM', payload: { id } });
  }, [dispatch]);
 
  const updateAtomPosition = useCallback((id, position) => {
    dispatch({ type: 'UPDATE_ATOM_POSITION', payload: { id, position } });
  }, [dispatch]);
 
  const updateAtomForce = useCallback((id, force) => {
    dispatch({ type: 'UPDATE_ATOM_FORCE', payload: { id, force } });
  }, [dispatch]);
 
  const resetSimulation = useCallback(() => {
    dispatch({ type: 'RESET_SIMULATION' });
  }, [dispatch]);
 
  const togglePause = useCallback(() => {
    dispatch({ type: 'TOGGLE_PAUSE' });
  }, [dispatch]);
 
  const toggleClear = useCallback(() => {
    dispatch({ type: 'TOGGLE_CLEAR' });
  }, [dispatch]);
 
  const setScale = useCallback((scale) => {
    dispatch({ type: 'SET_SCALE', payload: { scale } });
  }, [dispatch]);
 
  const incrementTime = useCallback(() => {
    dispatch({ type: 'INCREMENT_TIME' });
  }, [dispatch]);
 
  const addFireball = useCallback((fireball) => {
    dispatch({ type: 'ADD_FIREBALL', payload: fireball });
  }, [dispatch]);
 
  const updateFireballs = useCallback((fireballs) => {
    dispatch({ type: 'UPDATE_FIREBALLS', payload: fireballs });
  }, [dispatch]);
 
  const setPlayerForce = useCallback((force) => {
    dispatch({ type: 'SET_PLAYER_FORCE', payload: force });
  }, [dispatch]);
 
  return {
    addAtom,
    removeAtom,
    updateAtomPosition,
    updateAtomForce,
    resetSimulation,
    togglePause,
    toggleClear,
    setScale,
    incrementTime,
    addFireball,
    updateFireballs,
    setPlayerForce,
  };
}
 
export default SimulationContext;