File size: 3,544 Bytes
425a907
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { createContext, useContext, useReducer, useCallback } from 'react';
import { DEFAULT_CONFIG } from '../utils/constants.js';

const AppContext = createContext(null);
const AppDispatch = createContext(null);

const initialState = {
  // Step 1
  files: { d: null, p: null, r: null },
  dictCSV: null,
  panelCSV: null,
  selectedPanels: new Set(),
  p1ColFilters: {},
  fromPastResult: false,
  // Restore buffers from past result
  _rPanels: null, _rVars: null, _rC: null, _rMap: null, _rFix: null,
  // Step 2
  allRows: [],       // dict rows with _sel flag
  _dictToken: null,
  // Step 3
  contributions: {},  // { actKey: { panelKey: {min,max} } }
  // Step 4
  panelMap: {},       // { panelKey: { varName: bool } }
  // Step 5
  fixedVars: {},      // { panelKey: varName[] }
  // Step 6
  modelParams: {},    // { "pk|var": {min_Adstock, ...} }
  // Step 7
  config: JSON.parse(JSON.stringify(DEFAULT_CONFIG)),
};

function reducer(state, action) {
  switch (action.type) {
    case 'SET_DICT_CSV': return { ...state, dictCSV: action.payload };
    case 'SET_PANEL_CSV': return { ...state, panelCSV: action.payload };
    case 'SET_FILE': return { ...state, files: { ...state.files, [action.key]: action.value } };
    case 'SET_SELECTED_PANELS': return { ...state, selectedPanels: action.payload };
    case 'SET_P1_COL_FILTERS': return { ...state, p1ColFilters: action.payload };
    case 'SET_ALL_ROWS': return { ...state, allRows: action.payload, _dictToken: action.token };
    case 'TOGGLE_VAR_SEL': {
      const rows = state.allRows.map(r => r.__id === action.id ? { ...r, _sel: !r._sel } : r);
      return { ...state, allRows: rows };
    }
    case 'SET_ALL_VARS_SEL': {
      const rows = state.allRows.map(r => action.ids.has(r.__id) ? { ...r, _sel: action.on } : r);
      return { ...state, allRows: rows };
    }
    case 'SET_CONTRIBUTIONS': return { ...state, contributions: action.payload };
    case 'SET_PANEL_MAP': return { ...state, panelMap: action.payload };
    case 'SET_FIXED_VARS': return { ...state, fixedVars: action.payload };
    case 'SET_MODEL_PARAMS': return { ...state, modelParams: action.payload };
    case 'SET_CONFIG': return { ...state, config: action.payload };
    case 'SET_RESTORE_BUFFERS': return { ...state, ...action.payload };
    case 'SET_FROM_PAST_RESULT': return { ...state, fromPastResult: action.payload };
    case 'RESET_ALL': return { ...initialState, config: JSON.parse(JSON.stringify(DEFAULT_CONFIG)) };
    default: return state;
  }
}

export function AppProvider({ children }) {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <AppContext.Provider value={state}>
      <AppDispatch.Provider value={dispatch}>
        {children}
      </AppDispatch.Provider>
    </AppContext.Provider>
  );
}

export function useAppState() { return useContext(AppContext); }
export function useAppDispatch() { return useContext(AppDispatch); }

// Derived helpers
export function useSelPanelRows() {
  const { panelCSV, selectedPanels } = useAppState();
  if (!panelCSV) return [];
  return panelCSV.rows.filter(r => selectedPanels.has(String(r.__id)));
}

export function useSelVars() {
  const { allRows } = useAppState();
  return allRows.filter(r => r._sel).map(r => r.VARIABLE);
}

export function useActivityGroups() {
  const { allRows } = useAppState();
  const g = {};
  allRows.filter(r => r._sel).forEach(r => {
    const a = r.SN_ACTIVITY_LEVEL_1 || '(Unassigned)';
    if (!g[a]) g[a] = [];
    g[a].push(r.VARIABLE);
  });
  return g;
}