diff options
Diffstat (limited to 'jb-ui/src/models')
| -rw-r--r-- | jb-ui/src/models/grlEventsSlice.ts | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/jb-ui/src/models/grlEventsSlice.ts b/jb-ui/src/models/grlEventsSlice.ts new file mode 100644 index 0000000..912c4ca --- /dev/null +++ b/jb-ui/src/models/grlEventsSlice.ts @@ -0,0 +1,58 @@ +import { EventEnvelope } from "@/api_fsb"; +import { RootState } from "@/store"; +import { createEntityAdapter, createSelector, createSlice } from '@reduxjs/toolkit'; + +const eventAdapter = createEntityAdapter({ + selectId: (model: EventEnvelope) => model.event_uuid!, + sortComparer: (a, b) => { + // ASC by timestamp + return a.timestamp!.localeCompare(b.timestamp!); + }, +}); + + +const grlEventsSlice = createSlice({ + name: 'grlEvents', + initialState: eventAdapter.getInitialState(), + + reducers: { + addEvent: eventAdapter.addOne, + addEvents: eventAdapter.addMany, + upsertEvent: eventAdapter.upsertOne, // Add or Update + + } +}) + + +export const { + addEvent, addEvents, upsertEvent +} = grlEventsSlice.actions; + + +export const eventSelectors = eventAdapter.getSelectors( + (state: RootState) => state.events +); + +export const selectAllEvents = (state: RootState): EventEnvelope[] => eventSelectors.selectAll(state); + +const BASE_SPEED = 40; // px/sec at idle +const MAX_SPEED = 380; // px/sec at surge + +const RATE_WINDOW_MS = 10_000; // ms window to measure message frequency +const RATE_TO_SPEED = 55; // px/sec added per msg/sec + + +// --- Speed: derived from arrival rate of recent items --- +export const selectCurrentSpeed = createSelector(selectAllEvents, (items) => { + const now = Date.now(); + + const recentCount = items.filter((m) => { + const ts = new Date(m.timestamp!).getTime(); + return now - ts < RATE_WINDOW_MS; + }).length; + + const rate = recentCount / (RATE_WINDOW_MS / 1_000); // msgs/sec + return Math.min(BASE_SPEED + rate * RATE_TO_SPEED, MAX_SPEED); +}); + +export default grlEventsSlice.reducer |
