Refactor simulation store structures to use arrays instead of records for conveyors, machines, storage units, vehicles, and products; remove useSimulationStore; enhance state management and helper functions for better performance and readability.

This commit is contained in:
2025-04-22 14:44:09 +05:30
parent 6363d5b9af
commit 7907bbab0a
9 changed files with 115 additions and 173 deletions

View File

@@ -1,6 +1,6 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useEventsStore } from '../../store/simulation/useEventsStore'; import { useEventsStore } from '../../store/simulation/useEventsStore';
import { useProductStore } from '../../store/simulation/useSimulationStore'; import { useProductStore } from '../../store/simulation/useProductStore';
function Simulation() { function Simulation() {
const { events } = useEventsStore(); const { events } = useEventsStore();

View File

@@ -1,7 +1,7 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
interface ArmBotStatus extends RoboticArmSchemaEvent { interface ArmBotStatus extends RoboticArmEventSchema {
productId: string; productId: string;
isActive: boolean; isActive: boolean;
idleTime: number; idleTime: number;
@@ -13,29 +13,24 @@ interface ArmBotStatus extends RoboticArmSchemaEvent {
} }
interface ArmBotStore { interface ArmBotStore {
armBots: Record<string, ArmBotStatus>; armBots: ArmBotStatus[];
// ArmBot actions addArmBot: (productId: string, event: RoboticArmEventSchema) => void;
addArmBot: (productId: string, event: RoboticArmSchemaEvent) => void;
removeArmBot: (modelUuid: string) => void; removeArmBot: (modelUuid: string) => void;
updateArmBot: ( updateArmBot: (
modelUuid: string, modelUuid: string,
updates: Partial<Omit<ArmBotStatus, 'modelUuid' | 'productId'>> updates: Partial<Omit<ArmBotStatus, 'modelUuid' | 'productId'>>
) => void; ) => void;
// Action management
startAction: (modelUuid: string, actionUuid: string) => void; startAction: (modelUuid: string, actionUuid: string) => void;
completeAction: (modelUuid: string) => void; completeAction: (modelUuid: string) => void;
cancelAction: (modelUuid: string) => void; cancelAction: (modelUuid: string) => void;
// Status updates
setArmBotActive: (modelUuid: string, isActive: boolean) => void; setArmBotActive: (modelUuid: string, isActive: boolean) => void;
// Time tracking
incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
// Helper functions
getArmBotById: (modelUuid: string) => ArmBotStatus | undefined; getArmBotById: (modelUuid: string) => ArmBotStatus | undefined;
getArmBotsByProduct: (productId: string) => ArmBotStatus[]; getArmBotsByProduct: (productId: string) => ArmBotStatus[];
getActiveArmBots: () => ArmBotStatus[]; getActiveArmBots: () => ArmBotStatus[];
@@ -45,47 +40,45 @@ interface ArmBotStore {
export const useArmBotStore = create<ArmBotStore>()( export const useArmBotStore = create<ArmBotStore>()(
immer((set, get) => ({ immer((set, get) => ({
armBots: {}, armBots: [],
// ArmBot actions
addArmBot: (productId, event) => { addArmBot: (productId, event) => {
set((state) => { set((state) => {
state.armBots[event.modelUuid] = { state.armBots.push({
...event, ...event,
productId, productId,
isActive: false, isActive: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
state: 'idle' state: 'idle',
}; });
}); });
}, },
removeArmBot: (modelUuid) => { removeArmBot: (modelUuid) => {
set((state) => { set((state) => {
delete state.armBots[modelUuid]; state.armBots = state.armBots.filter(a => a.modelUuid !== modelUuid);
}); });
}, },
updateArmBot: (modelUuid, updates) => { updateArmBot: (modelUuid, updates) => {
set((state) => { set((state) => {
const armBot = state.armBots[modelUuid]; const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot) { if (armBot) {
Object.assign(armBot, updates); Object.assign(armBot, updates);
} }
}); });
}, },
// Action management
startAction: (modelUuid, actionUuid) => { startAction: (modelUuid, actionUuid) => {
set((state) => { set((state) => {
const armBot = state.armBots[modelUuid]; const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot) { if (armBot) {
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid); const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
if (action) { if (action) {
armBot.currentAction = { armBot.currentAction = {
actionUuid: action.actionUuid, actionUuid: action.actionUuid,
actionName: action.actionName actionName: action.actionName,
}; };
armBot.isActive = true; armBot.isActive = true;
} }
@@ -95,7 +88,7 @@ export const useArmBotStore = create<ArmBotStore>()(
completeAction: (modelUuid) => { completeAction: (modelUuid) => {
set((state) => { set((state) => {
const armBot = state.armBots[modelUuid]; const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot && armBot.currentAction) { if (armBot && armBot.currentAction) {
armBot.currentAction = undefined; armBot.currentAction = undefined;
armBot.isActive = false; armBot.isActive = false;
@@ -105,7 +98,7 @@ export const useArmBotStore = create<ArmBotStore>()(
cancelAction: (modelUuid) => { cancelAction: (modelUuid) => {
set((state) => { set((state) => {
const armBot = state.armBots[modelUuid]; const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot) { if (armBot) {
armBot.currentAction = undefined; armBot.currentAction = undefined;
armBot.isActive = false; armBot.isActive = false;
@@ -113,20 +106,18 @@ export const useArmBotStore = create<ArmBotStore>()(
}); });
}, },
// Status updates
setArmBotActive: (modelUuid, isActive) => { setArmBotActive: (modelUuid, isActive) => {
set((state) => { set((state) => {
const armBot = state.armBots[modelUuid]; const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot) { if (armBot) {
armBot.isActive = isActive; armBot.isActive = isActive;
} }
}); });
}, },
// Time tracking
incrementActiveTime: (modelUuid, incrementBy) => { incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const armBot = state.armBots[modelUuid]; const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot) { if (armBot) {
armBot.activeTime += incrementBy; armBot.activeTime += incrementBy;
} }
@@ -135,38 +126,31 @@ export const useArmBotStore = create<ArmBotStore>()(
incrementIdleTime: (modelUuid, incrementBy) => { incrementIdleTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const armBot = state.armBots[modelUuid]; const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot) { if (armBot) {
armBot.idleTime += incrementBy; armBot.idleTime += incrementBy;
} }
}); });
}, },
// Helper functions
getArmBotById: (modelUuid) => { getArmBotById: (modelUuid) => {
return get().armBots[modelUuid]; return get().armBots.find(a => a.modelUuid === modelUuid);
}, },
getArmBotsByProduct: (productId) => { getArmBotsByProduct: (productId) => {
return Object.values(get().armBots).filter( return get().armBots.filter(a => a.productId === productId);
a => a.productId === productId
);
}, },
getActiveArmBots: () => { getActiveArmBots: () => {
return Object.values(get().armBots).filter(a => a.isActive); return get().armBots.filter(a => a.isActive);
}, },
getIdleArmBots: () => { getIdleArmBots: () => {
return Object.values(get().armBots).filter( return get().armBots.filter(a => !a.isActive && a.state === 'idle');
a => !a.isActive && a.state === 'idle'
);
}, },
getArmBotsByCurrentAction: (actionUuid) => { getArmBotsByCurrentAction: (actionUuid) => {
return Object.values(get().armBots).filter( return get().armBots.filter(a => a.currentAction?.actionUuid === actionUuid);
a => a.currentAction?.actionUuid === actionUuid
);
} }
})) }))
); );

View File

@@ -9,9 +9,8 @@ interface ConveyorStatus extends ConveyorEventSchema {
} }
interface ConveyorStore { interface ConveyorStore {
conveyors: Record<string, ConveyorStatus>; conveyors: ConveyorStatus[];
// Actions
addConveyor: (productId: string, event: ConveyorEventSchema) => void; addConveyor: (productId: string, event: ConveyorEventSchema) => void;
removeConveyor: (modelUuid: string) => void; removeConveyor: (modelUuid: string) => void;
updateConveyor: ( updateConveyor: (
@@ -19,15 +18,12 @@ interface ConveyorStore {
updates: Partial<Omit<ConveyorStatus, 'modelUuid' | 'productId'>> updates: Partial<Omit<ConveyorStatus, 'modelUuid' | 'productId'>>
) => void; ) => void;
// Status updates
setConveyorActive: (modelUuid: string, isActive: boolean) => void; setConveyorActive: (modelUuid: string, isActive: boolean) => void;
setConveyorState: (modelUuid: string, newState: ConveyorStatus['state']) => void; setConveyorState: (modelUuid: string, newState: ConveyorStatus['state']) => void;
// Time tracking
incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
// Helper functions
getConveyorById: (modelUuid: string) => ConveyorStatus | undefined; getConveyorById: (modelUuid: string) => ConveyorStatus | undefined;
getConveyorsByProduct: (productId: string) => ConveyorStatus[]; getConveyorsByProduct: (productId: string) => ConveyorStatus[];
getActiveConveyors: () => ConveyorStatus[]; getActiveConveyors: () => ConveyorStatus[];
@@ -36,41 +32,39 @@ interface ConveyorStore {
export const useConveyorStore = create<ConveyorStore>()( export const useConveyorStore = create<ConveyorStore>()(
immer((set, get) => ({ immer((set, get) => ({
conveyors: {}, conveyors: [],
// Actions
addConveyor: (productId, event) => { addConveyor: (productId, event) => {
set((state) => { set((state) => {
state.conveyors[event.modelUuid] = { state.conveyors.push({
...event, ...event,
productId, productId,
isActive: false, isActive: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
state: 'idle', state: 'idle',
}; });
}); });
}, },
removeConveyor: (modelUuid) => { removeConveyor: (modelUuid) => {
set((state) => { set((state) => {
delete state.conveyors[modelUuid]; state.conveyors = state.conveyors.filter(c => c.modelUuid !== modelUuid);
}); });
}, },
updateConveyor: (modelUuid, updates) => { updateConveyor: (modelUuid, updates) => {
set((state) => { set((state) => {
const conveyor = state.conveyors[modelUuid]; const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
if (conveyor) { if (conveyor) {
Object.assign(conveyor, updates); Object.assign(conveyor, updates);
} }
}); });
}, },
// Status updates
setConveyorActive: (modelUuid, isActive) => { setConveyorActive: (modelUuid, isActive) => {
set((state) => { set((state) => {
const conveyor = state.conveyors[modelUuid]; const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
if (conveyor) { if (conveyor) {
conveyor.isActive = isActive; conveyor.isActive = isActive;
} }
@@ -79,17 +73,16 @@ export const useConveyorStore = create<ConveyorStore>()(
setConveyorState: (modelUuid, newState) => { setConveyorState: (modelUuid, newState) => {
set((state) => { set((state) => {
const conveyor = state.conveyors[modelUuid]; const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
if (conveyor) { if (conveyor) {
conveyor.state = newState; conveyor.state = newState;
} }
}); });
}, },
// Time tracking
incrementActiveTime: (modelUuid, incrementBy) => { incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const conveyor = state.conveyors[modelUuid]; const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
if (conveyor) { if (conveyor) {
conveyor.activeTime += incrementBy; conveyor.activeTime += incrementBy;
} }
@@ -98,32 +91,27 @@ export const useConveyorStore = create<ConveyorStore>()(
incrementIdleTime: (modelUuid, incrementBy) => { incrementIdleTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const conveyor = state.conveyors[modelUuid]; const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
if (conveyor) { if (conveyor) {
conveyor.idleTime += incrementBy; conveyor.idleTime += incrementBy;
} }
}); });
}, },
// Helper functions
getConveyorById: (modelUuid) => { getConveyorById: (modelUuid) => {
return get().conveyors[modelUuid]; return get().conveyors.find(c => c.modelUuid === modelUuid);
}, },
getConveyorsByProduct: (productId) => { getConveyorsByProduct: (productId) => {
return Object.values(get().conveyors).filter( return get().conveyors.filter(c => c.productId === productId);
c => c.productId === productId
);
}, },
getActiveConveyors: () => { getActiveConveyors: () => {
return Object.values(get().conveyors).filter(c => c.isActive); return get().conveyors.filter(c => c.isActive);
}, },
getIdleConveyors: () => { getIdleConveyors: () => {
return Object.values(get().conveyors).filter( return get().conveyors.filter(c => !c.isActive && c.state === 'idle');
c => !c.isActive && c.state === 'idle'
);
}, },
})) }))
); );

View File

@@ -75,7 +75,7 @@ export const useEventsStore = create<EventsStore>()(
if (event && 'points' in event) { if (event && 'points' in event) {
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
} else if (event && 'point' in event) { } else if (event && 'point' in event) {
(event as VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent).point = point as any; (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any;
} }
}); });
}, },

View File

@@ -1,7 +1,7 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
interface MachineStatus extends MachineSchemaEvent { interface MachineStatus extends MachineEventSchema {
productId: string; productId: string;
isActive: boolean; isActive: boolean;
idleTime: number; idleTime: number;
@@ -9,10 +9,10 @@ interface MachineStatus extends MachineSchemaEvent {
} }
interface MachineStore { interface MachineStore {
machines: Record<string, MachineStatus>; machines: MachineStatus[];
// Actions // Actions
addMachine: (productId: string, machine: MachineSchemaEvent) => void; addMachine: (productId: string, machine: MachineEventSchema) => void;
removeMachine: (modelUuid: string) => void; removeMachine: (modelUuid: string) => void;
updateMachine: ( updateMachine: (
modelUuid: string, modelUuid: string,
@@ -36,31 +36,31 @@ interface MachineStore {
export const useMachineStore = create<MachineStore>()( export const useMachineStore = create<MachineStore>()(
immer((set, get) => ({ immer((set, get) => ({
machines: {}, machines: [],
// Actions // Actions
addMachine: (productId, machine) => { addMachine: (productId, machine) => {
set((state) => { set((state) => {
state.machines[machine.modelUuid] = { state.machines.push({
...machine, ...machine,
productId, productId,
isActive: false, isActive: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
state: 'idle', state: 'idle',
}; });
}); });
}, },
removeMachine: (modelUuid) => { removeMachine: (modelUuid) => {
set((state) => { set((state) => {
delete state.machines[modelUuid]; state.machines = state.machines.filter(m => m.modelUuid !== modelUuid);
}); });
}, },
updateMachine: (modelUuid, updates) => { updateMachine: (modelUuid, updates) => {
set((state) => { set((state) => {
const machine = state.machines[modelUuid]; const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) { if (machine) {
Object.assign(machine, updates); Object.assign(machine, updates);
} }
@@ -70,7 +70,7 @@ export const useMachineStore = create<MachineStore>()(
// Status updates // Status updates
setMachineActive: (modelUuid, isActive) => { setMachineActive: (modelUuid, isActive) => {
set((state) => { set((state) => {
const machine = state.machines[modelUuid]; const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) { if (machine) {
machine.isActive = isActive; machine.isActive = isActive;
} }
@@ -79,7 +79,7 @@ export const useMachineStore = create<MachineStore>()(
setMachineState: (modelUuid, newState) => { setMachineState: (modelUuid, newState) => {
set((state) => { set((state) => {
const machine = state.machines[modelUuid]; const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) { if (machine) {
machine.state = newState; machine.state = newState;
} }
@@ -89,7 +89,7 @@ export const useMachineStore = create<MachineStore>()(
// Time tracking // Time tracking
incrementActiveTime: (modelUuid, incrementBy) => { incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const machine = state.machines[modelUuid]; const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) { if (machine) {
machine.activeTime += incrementBy; machine.activeTime += incrementBy;
} }
@@ -98,7 +98,7 @@ export const useMachineStore = create<MachineStore>()(
incrementIdleTime: (modelUuid, incrementBy) => { incrementIdleTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const machine = state.machines[modelUuid]; const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) { if (machine) {
machine.idleTime += incrementBy; machine.idleTime += incrementBy;
} }
@@ -107,23 +107,19 @@ export const useMachineStore = create<MachineStore>()(
// Helpers // Helpers
getMachineById: (modelUuid) => { getMachineById: (modelUuid) => {
return get().machines[modelUuid]; return get().machines.find(m => m.modelUuid === modelUuid);
}, },
getMachinesByProduct: (productId) => { getMachinesByProduct: (productId) => {
return Object.values(get().machines).filter( return get().machines.filter(m => m.productId === productId);
m => m.productId === productId
);
}, },
getActiveMachines: () => { getActiveMachines: () => {
return Object.values(get().machines).filter(m => m.isActive); return get().machines.filter(m => m.isActive);
}, },
getIdleMachines: () => { getIdleMachines: () => {
return Object.values(get().machines).filter( return get().machines.filter(m => !m.isActive && m.state === 'idle');
m => !m.isActive && m.state === 'idle'
);
}, },
})) }))
); );

View File

@@ -123,7 +123,7 @@ export const useProductStore = create<ProductsStore>()(
if (event && 'points' in event) { if (event && 'points' in event) {
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
} else if (event && 'point' in event) { } else if (event && 'point' in event) {
(event as VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent).point = point as any; (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any;
} }
} }
}); });
@@ -193,7 +193,7 @@ export const useProductStore = create<ProductsStore>()(
} else if ('point' in event) { } else if ('point' in event) {
const point = (event as any).point; const point = (event as any).point;
if (event.type === "roboticArm") { if (event.type === "roboticArm") {
// Handle RoboticArmSchemaEvent // Handle RoboticArmEventSchema
if ('actions' in point) { if ('actions' in point) {
point.actions = point.actions.filter((a: any) => a.actionUuid !== actionUuid); point.actions = point.actions.filter((a: any) => a.actionUuid !== actionUuid);
} }

View File

@@ -1,7 +1,7 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
interface StorageUnitStatus extends StorageSchemaEvent { interface StorageUnitStatus extends StorageEventSchema {
productId: string; productId: string;
isActive: boolean; isActive: boolean;
idleTime: number; idleTime: number;
@@ -10,10 +10,10 @@ interface StorageUnitStatus extends StorageSchemaEvent {
} }
interface StorageUnitStore { interface StorageUnitStore {
storageUnits: Record<string, StorageUnitStatus>; storageUnits: StorageUnitStatus[];
// Actions // Actions
addStorageUnit: (productId: string, storageUnit: StorageSchemaEvent) => void; addStorageUnit: (productId: string, storageUnit: StorageEventSchema) => void;
removeStorageUnit: (modelUuid: string) => void; removeStorageUnit: (modelUuid: string) => void;
updateStorageUnit: ( updateStorageUnit: (
modelUuid: string, modelUuid: string,
@@ -42,34 +42,34 @@ interface StorageUnitStore {
export const useStorageUnitStore = create<StorageUnitStore>()( export const useStorageUnitStore = create<StorageUnitStore>()(
immer((set, get) => ({ immer((set, get) => ({
storageUnits: {}, storageUnits: [],
// Actions // Actions
addStorageUnit: (productId, storageUnit) => { addStorageUnit: (productId, storageUnit) => {
set((state) => { set((state) => {
state.storageUnits[storageUnit.modelUuid] = { state.storageUnits.push({
...storageUnit, ...storageUnit,
productId, productId,
isActive: false, isActive: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
currentLoad: 0, // Initialize currentLoad to 0 currentLoad: 0,
state: 'idle', state: 'idle',
}; });
}); });
}, },
removeStorageUnit: (modelUuid) => { removeStorageUnit: (modelUuid) => {
set((state) => { set((state) => {
delete state.storageUnits[modelUuid]; state.storageUnits = state.storageUnits.filter(s => s.modelUuid !== modelUuid);
}); });
}, },
updateStorageUnit: (modelUuid, updates) => { updateStorageUnit: (modelUuid, updates) => {
set((state) => { set((state) => {
const storageUnit = state.storageUnits[modelUuid]; const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
if (storageUnit) { if (unit) {
Object.assign(storageUnit, updates); Object.assign(unit, updates);
} }
}); });
}, },
@@ -77,18 +77,18 @@ export const useStorageUnitStore = create<StorageUnitStore>()(
// Status updates // Status updates
setStorageUnitActive: (modelUuid, isActive) => { setStorageUnitActive: (modelUuid, isActive) => {
set((state) => { set((state) => {
const storageUnit = state.storageUnits[modelUuid]; const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
if (storageUnit) { if (unit) {
storageUnit.isActive = isActive; unit.isActive = isActive;
} }
}); });
}, },
setStorageUnitState: (modelUuid, newState) => { setStorageUnitState: (modelUuid, newState) => {
set((state) => { set((state) => {
const storageUnit = state.storageUnits[modelUuid]; const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
if (storageUnit) { if (unit) {
storageUnit.state = newState; unit.state = newState;
} }
}); });
}, },
@@ -96,9 +96,9 @@ export const useStorageUnitStore = create<StorageUnitStore>()(
// Load updates // Load updates
updateStorageUnitLoad: (modelUuid, load) => { updateStorageUnitLoad: (modelUuid, load) => {
set((state) => { set((state) => {
const storageUnit = state.storageUnits[modelUuid]; const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
if (storageUnit) { if (unit) {
storageUnit.currentLoad = load; unit.currentLoad = load;
} }
}); });
}, },
@@ -106,53 +106,47 @@ export const useStorageUnitStore = create<StorageUnitStore>()(
// Time tracking // Time tracking
incrementActiveTime: (modelUuid, incrementBy) => { incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const storageUnit = state.storageUnits[modelUuid]; const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
if (storageUnit) { if (unit) {
storageUnit.activeTime += incrementBy; unit.activeTime += incrementBy;
} }
}); });
}, },
incrementIdleTime: (modelUuid, incrementBy) => { incrementIdleTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const storageUnit = state.storageUnits[modelUuid]; const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
if (storageUnit) { if (unit) {
storageUnit.idleTime += incrementBy; unit.idleTime += incrementBy;
} }
}); });
}, },
// Helpers // Helpers
getStorageUnitById: (modelUuid) => { getStorageUnitById: (modelUuid) => {
return get().storageUnits[modelUuid]; return get().storageUnits.find(s => s.modelUuid === modelUuid);
}, },
getStorageUnitsByProduct: (productId) => { getStorageUnitsByProduct: (productId) => {
return Object.values(get().storageUnits).filter( return get().storageUnits.filter(s => s.productId === productId);
s => s.productId === productId
);
}, },
getActiveStorageUnits: () => { getActiveStorageUnits: () => {
return Object.values(get().storageUnits).filter(s => s.isActive); return get().storageUnits.filter(s => s.isActive);
}, },
getIdleStorageUnits: () => { getIdleStorageUnits: () => {
return Object.values(get().storageUnits).filter( return get().storageUnits.filter(s => !s.isActive && s.state === 'idle');
s => !s.isActive && s.state === 'idle'
);
}, },
getFullStorageUnits: () => { getFullStorageUnits: () => {
return Object.values(get().storageUnits).filter( return get().storageUnits.filter(
s => s.currentLoad >= s.point.action.storageCapacity s => s.currentLoad >= s.point.action.storageCapacity
); );
}, },
getEmptyStorageUnits: () => { getEmptyStorageUnits: () => {
return Object.values(get().storageUnits).filter( return get().storageUnits.filter(s => s.currentLoad === 0);
s => s.currentLoad === 0
);
}, },
})) }))
); );

View File

@@ -1,7 +1,7 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
interface VehicleStatus extends VehicleSchemaEvent { interface VehicleStatus extends VehicleEventSchema {
productId: string; productId: string;
isActive: boolean; isActive: boolean;
idleTime: number; idleTime: number;
@@ -11,28 +11,21 @@ interface VehicleStatus extends VehicleSchemaEvent {
} }
interface VehiclesStore { interface VehiclesStore {
vehicles: Record<string, VehicleStatus>; vehicles: VehicleStatus[];
// Vehicle actions addVehicle: (productId: string, event: VehicleEventSchema) => void;
addVehicle: (productId: string, event: VehicleSchemaEvent) => void;
removeVehicle: (modelUuid: string) => void; removeVehicle: (modelUuid: string) => void;
updateVehicle: ( updateVehicle: (
modelUuid: string, modelUuid: string,
updates: Partial<Omit<VehicleStatus, 'modelUuid' | 'productId'>> updates: Partial<Omit<VehicleStatus, 'modelUuid' | 'productId'>>
) => void; ) => void;
// Status updates
setVehicleActive: (modelUuid: string, isActive: boolean) => void; setVehicleActive: (modelUuid: string, isActive: boolean) => void;
updateVehicleLoad: (modelUuid: string, load: number) => void; updateVehicleLoad: (modelUuid: string, load: number) => void;
// State management
setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void; setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void;
// Time tracking
incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
// Helper functions
getVehicleById: (modelUuid: string) => VehicleStatus | undefined; getVehicleById: (modelUuid: string) => VehicleStatus | undefined;
getVehiclesByProduct: (productId: string) => VehicleStatus[]; getVehiclesByProduct: (productId: string) => VehicleStatus[];
getActiveVehicles: () => VehicleStatus[]; getActiveVehicles: () => VehicleStatus[];
@@ -41,75 +34,67 @@ interface VehiclesStore {
export const useVehicleStore = create<VehiclesStore>()( export const useVehicleStore = create<VehiclesStore>()(
immer((set, get) => ({ immer((set, get) => ({
vehicles: {}, vehicles: [],
addVehicle: (productId, event) => { addVehicle: (productId, event) => {
set((state) => { set((state) => {
state.vehicles[event.modelUuid] = { state.vehicles.push({
...event, ...event,
isActive: false,
productId, productId,
isActive: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
currentLoad: 0, currentLoad: 0,
distanceTraveled: 0, distanceTraveled: 0,
}; });
}); });
}, },
removeVehicle: (modelUuid) => { removeVehicle: (modelUuid) => {
set((state) => { set((state) => {
delete state.vehicles[modelUuid]; state.vehicles = state.vehicles.filter(v => v.modelUuid !== modelUuid);
}); });
}, },
updateVehicle: (modelUuid, updates) => { updateVehicle: (modelUuid, updates) => {
set((state) => { set((state) => {
const vehicle = state.vehicles[modelUuid]; const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
if (vehicle) { if (vehicle) {
Object.assign(vehicle, updates); Object.assign(vehicle, updates);
} }
}); });
}, },
// Status updates
setVehicleActive: (modelUuid, isActive) => { setVehicleActive: (modelUuid, isActive) => {
set((state) => { set((state) => {
const vehicle = state.vehicles[modelUuid]; const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
if (vehicle) { if (vehicle) {
vehicle.isActive = isActive; vehicle.isActive = isActive;
if (isActive) {
vehicle.state = 'running';
} else {
vehicle.state = vehicle.currentLoad > 0 ? 'idle' : 'stopped';
}
} }
}); });
}, },
updateVehicleLoad: (modelUuid, load) => { updateVehicleLoad: (modelUuid, load) => {
set((state) => { set((state) => {
const vehicle = state.vehicles[modelUuid]; const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
if (vehicle) { if (vehicle) {
vehicle.currentLoad = load; vehicle.currentLoad = load;
} }
}); });
}, },
// State management
setVehicleState: (modelUuid, newState) => { setVehicleState: (modelUuid, newState) => {
set((state) => { set((state) => {
const vehicle = state.vehicles[modelUuid]; const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
if (vehicle) { if (vehicle) {
vehicle.state = newState; vehicle.state = newState;
} }
}); });
}, },
// Time tracking
incrementActiveTime: (modelUuid, incrementBy) => { incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const vehicle = state.vehicles[modelUuid]; const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
if (vehicle) { if (vehicle) {
vehicle.activeTime += incrementBy; vehicle.activeTime += incrementBy;
} }
@@ -118,32 +103,27 @@ export const useVehicleStore = create<VehiclesStore>()(
incrementIdleTime: (modelUuid, incrementBy) => { incrementIdleTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const vehicle = state.vehicles[modelUuid]; const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
if (vehicle) { if (vehicle) {
vehicle.idleTime += incrementBy; vehicle.idleTime += incrementBy;
} }
}); });
}, },
// Getters
getVehicleById: (modelUuid) => { getVehicleById: (modelUuid) => {
return get().vehicles[modelUuid]; return get().vehicles.find(v => v.modelUuid === modelUuid);
}, },
getVehiclesByProduct: (productId) => { getVehiclesByProduct: (productId) => {
return Object.values(get().vehicles).filter( return get().vehicles.filter(v => v.productId === productId);
v => v.productId === productId
);
}, },
getActiveVehicles: () => { getActiveVehicles: () => {
return Object.values(get().vehicles).filter(v => v.isActive); return get().vehicles.filter(v => v.isActive);
}, },
getIdleVehicles: () => { getIdleVehicles: () => {
return Object.values(get().vehicles).filter( return get().vehicles.filter(v => !v.isActive && v.currentLoad > 0);
v => !v.isActive && v.currentLoad > 0
);
} }
})) }))
); );

View File

@@ -97,29 +97,29 @@ interface ConveyorEventSchema extends AssetEventSchema {
points: ConveyorPointSchema[]; points: ConveyorPointSchema[];
} }
interface VehicleSchemaEvent extends AssetEventSchema { interface VehicleEventSchema extends AssetEventSchema {
type: "vehicle"; type: "vehicle";
speed: number; speed: number;
point: VehiclePointSchema; point: VehiclePointSchema;
} }
interface RoboticArmSchemaEvent extends AssetEventSchema { interface RoboticArmEventSchema extends AssetEventSchema {
type: "roboticArm"; type: "roboticArm";
speed: number; speed: number;
point: RoboticArmPointSchema; point: RoboticArmPointSchema;
} }
interface MachineSchemaEvent extends AssetEventSchema { interface MachineEventSchema extends AssetEventSchema {
type: "machine"; type: "machine";
point: MachinePointSchema; point: MachinePointSchema;
} }
interface StorageSchemaEvent extends AssetEventSchema { interface StorageEventSchema extends AssetEventSchema {
type: "storageUnit"; type: "storageUnit";
point: StoragePointSchema; point: StoragePointSchema;
} }
type EventsSchema = ConveyorEventSchema | VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent | []; type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema | [];
type productsSchema = { type productsSchema = {
productName: string; productName: string;