Implement machine count and uptime state management; refactor throughput calculations and logging in simulation components
This commit is contained in:
parent
6b7bd18e0c
commit
cf66fbf20d
|
@ -1,3 +1,5 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { useMachineCount, useMachineUptime } from "../../../store/store";
|
||||
import {
|
||||
ProductionCapacityIcon,
|
||||
ThroughputSummaryIcon,
|
||||
|
@ -16,7 +18,15 @@ const ProductionCapacity = ({
|
|||
const partialFillPercent =
|
||||
((progressPercent / 100) * totalBars - barsToFill) * 100;
|
||||
|
||||
const isLoading = true;
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { machineCount, setMachineCount } = useMachineCount()
|
||||
const { machineActiveTime, setMachineActiveTime } = useMachineUptime()
|
||||
useEffect(() => {
|
||||
setIsLoading(true);
|
||||
machineUtilization = machineActiveTime
|
||||
console.log('machineActiveTime: ', machineActiveTime);
|
||||
}, [machineActiveTime])
|
||||
|
||||
return (
|
||||
<div className="throughtputSummary-container analysis-card">
|
||||
<div className="throughtputSummary-wrapper analysis-card-wrapper">
|
||||
|
@ -62,7 +72,7 @@ const ProductionCapacity = ({
|
|||
</div>
|
||||
<div className="metric">
|
||||
<span className="label">Machine Utilization</span>
|
||||
<span className="value">{machineUtilization}</span>
|
||||
<span className="value">{machineActiveTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -1,31 +1,232 @@
|
|||
import React, { useEffect } from 'react'
|
||||
// import React, { useEffect, useState } from 'react';
|
||||
// import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
|
||||
// import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||
// import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
|
||||
// import { useArmBotStore } from '../../../../store/simulation/useArmBotStore';
|
||||
// import { useMachineCount, useMachineUptime, useMaterialCycle } from '../../../../store/store';
|
||||
// import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
|
||||
// import { useMachineStore } from '../../../../store/simulation/useMachineStore';
|
||||
// import { useConveyorStore } from '../../../../store/simulation/useConveyorStore';
|
||||
// import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnitStore';
|
||||
// import { useMaterialStore } from '../../../../store/simulation/useMaterialStore';
|
||||
|
||||
// export default function ThroughPut() {
|
||||
// const { selectedProduct } = useSelectedProduct();
|
||||
// const { products, getProductById } = useProductStore();
|
||||
// const { armBots } = useArmBotStore();
|
||||
// const { vehicles } = useVehicleStore();
|
||||
// const { machines } = useMachineStore();
|
||||
// const { conveyors } = useConveyorStore();
|
||||
// const { storageUnits } = useStorageUnitStore();
|
||||
// const { materials } = useMaterialStore();
|
||||
|
||||
// const { machineCount, setMachineCount } = useMachineCount();
|
||||
// const { setMachineActiveTime } = useMachineUptime();
|
||||
// const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle();
|
||||
|
||||
// const [totalActiveTime, setTotalActiveTime] = useState(0);
|
||||
|
||||
// // 1. Setting static active times and counting machines
|
||||
// useEffect(() => {
|
||||
// const productData = getProductById(selectedProduct.productId);
|
||||
// if (productData) {
|
||||
// const productSequenceData = determineExecutionMachineSequences([productData]);
|
||||
// if (productSequenceData?.length > 0) {
|
||||
// let totalItems = 0;
|
||||
|
||||
// productSequenceData.forEach((sequence) => {
|
||||
// totalItems += sequence.length;
|
||||
// sequence.forEach((item) => {
|
||||
// if (item.type === "roboticArm") {
|
||||
// armBots.filter(arm => arm.modelUuid === item.modelUuid)
|
||||
// .forEach(arm => {
|
||||
// if (arm.activeTime >= 0) {
|
||||
// console.log('armBot activeTime:', arm.activeTime);
|
||||
// }
|
||||
// });
|
||||
// } else if (item.type === "vehicle") {
|
||||
// vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid)
|
||||
// .forEach(vehicle => {
|
||||
// if (vehicle.activeTime >= 0) {
|
||||
// vehicle.activeTime = 10; // static
|
||||
// }
|
||||
// });
|
||||
// } else if (item.type === "machine") {
|
||||
// machines.filter(machine => machine.modelUuid === item.modelUuid)
|
||||
// .forEach(machine => {
|
||||
// if (machine.activeTime >= 0) {
|
||||
// machine.activeTime = 12; // static
|
||||
// }
|
||||
// });
|
||||
// } else if (item.type === "transfer") {
|
||||
// conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid)
|
||||
// .forEach(conveyor => {
|
||||
// if (conveyor.activeTime >= 0) {
|
||||
// conveyor.activeTime = 5; // static
|
||||
// }
|
||||
// });
|
||||
// } else if (item.type === "storageUnit") {
|
||||
// storageUnits.filter(storage => storage.modelUuid === item.modelUuid)
|
||||
// .forEach(storage => {
|
||||
// if (storage.activeTime >= 0) {
|
||||
// storage.activeTime = 8; // static
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
// setMachineCount(totalItems);
|
||||
// }
|
||||
// }
|
||||
// }, [products, selectedProduct, armBots, vehicles, machines, conveyors, storageUnits, getProductById, setMachineCount]);
|
||||
|
||||
// // 2. Set material cycle time (static also)
|
||||
// useEffect(() => {
|
||||
// materials.forEach((material) => {
|
||||
// material.startTime = 50;
|
||||
// material.endTime = 100;
|
||||
// const totalCycleTime = material.endTime - material.startTime;
|
||||
// setMaterialCycleTime(totalCycleTime);
|
||||
// });
|
||||
// }, [materials, setMaterialCycleTime]);
|
||||
|
||||
// // 3. Sum of all activeTimes after static values are set
|
||||
// useEffect(() => {
|
||||
// let sum = 0;
|
||||
// armBots.forEach(arm => { if (arm.activeTime > 0) sum += arm.activeTime; });
|
||||
// vehicles.forEach(vehicle => { if (vehicle.activeTime > 0) sum += vehicle.activeTime; });
|
||||
// machines.forEach(machine => { if (machine.activeTime > 0) sum += machine.activeTime; });
|
||||
// conveyors.forEach(conveyor => { if (conveyor.activeTime > 0) sum += conveyor.activeTime; });
|
||||
// storageUnits.forEach(storage => { if (storage.activeTime > 0) sum += storage.activeTime; });
|
||||
|
||||
// setTotalActiveTime(sum);
|
||||
// setMachineActiveTime(sum);
|
||||
|
||||
// }, [armBots, vehicles, machines, conveyors, storageUnits, setMachineActiveTime]);
|
||||
|
||||
// // 4. Calculate throughput when activeTime and materialCycleTime are ready
|
||||
// useEffect(() => {
|
||||
// if (totalActiveTime > 0 && materialCycleTime > 0) {
|
||||
// const avgProcessTime = (totalActiveTime / materialCycleTime) * 100;
|
||||
// console.log('Throughput (%):', avgProcessTime.toFixed(2));
|
||||
// }
|
||||
// }, [totalActiveTime, materialCycleTime]);
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// </>
|
||||
// );
|
||||
// }
|
||||
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
|
||||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
|
||||
import { useArmBotStore } from '../../../../store/simulation/useArmBotStore';
|
||||
import { useMachineCount, useMachineUptime, useMaterialCycle } from '../../../../store/store';
|
||||
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
|
||||
import { useMachineStore } from '../../../../store/simulation/useMachineStore';
|
||||
import { useConveyorStore } from '../../../../store/simulation/useConveyorStore';
|
||||
import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnitStore';
|
||||
import { useMaterialStore } from '../../../../store/simulation/useMaterialStore';
|
||||
|
||||
export default function ThroughPut() {
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const { products,getProductById } = useProductStore()
|
||||
const { products, getProductById } = useProductStore();
|
||||
const { armBots } = useArmBotStore();
|
||||
const { vehicles } = useVehicleStore();
|
||||
const { machines } = useMachineStore();
|
||||
const { conveyors } = useConveyorStore();
|
||||
const { storageUnits } = useStorageUnitStore();
|
||||
const { materials } = useMaterialStore();
|
||||
|
||||
const { setMachineCount } = useMachineCount();
|
||||
const { setMachineActiveTime } = useMachineUptime();
|
||||
const { setMaterialCycleTime } = useMaterialCycle();
|
||||
|
||||
const [totalActiveTime, setTotalActiveTime] = useState(0);
|
||||
const [throughputData, setThroughputData] = useState(0); // <=== ADD THIS
|
||||
|
||||
// Setting machine count
|
||||
useEffect(() => {
|
||||
let productData = getProductById(selectedProduct.productId)
|
||||
const productData = getProductById(selectedProduct.productId);
|
||||
if (productData) {
|
||||
let productSequenceData = determineExecutionMachineSequences([productData])
|
||||
console.log('productSequenceData: ', productSequenceData);
|
||||
const productSequenceData = determineExecutionMachineSequences([productData]);
|
||||
if (productSequenceData?.length > 0) {
|
||||
let totalItems = 0; // 👈 initialize total count
|
||||
productSequenceData.map((sequence, index) => {
|
||||
let totalItems = 0;
|
||||
productSequenceData.forEach((sequence) => {
|
||||
totalItems += sequence.length;
|
||||
// sequence.map((item, idx) => {});
|
||||
});
|
||||
console.log(`Total items across all sequences: ${totalItems}`); // 👈 FINAL TOTAL ✅
|
||||
} else {
|
||||
console.log('No productSequenceData found!');
|
||||
setMachineCount(totalItems);
|
||||
}
|
||||
}
|
||||
}, [products])
|
||||
}, [products, selectedProduct, getProductById, setMachineCount]);
|
||||
|
||||
// Setting material cycle time
|
||||
useEffect(() => {
|
||||
materials.forEach(() => {
|
||||
const staticStartTime = 50;
|
||||
const staticEndTime = 100;
|
||||
const totalCycleTime = staticEndTime - staticStartTime;
|
||||
setMaterialCycleTime(totalCycleTime);
|
||||
});
|
||||
}, [materials, setMaterialCycleTime]);
|
||||
|
||||
// Calculate Sum, Machine Uptime and Throughput
|
||||
useEffect(() => {
|
||||
let sum = 0;
|
||||
|
||||
console.log('armBots: ', armBots);
|
||||
armBots.forEach(arm => {
|
||||
console.log('arm.activeTime: ', arm.activeTime);
|
||||
if (arm.activeTime > 0) sum += arm.activeTime;
|
||||
});
|
||||
|
||||
vehicles.forEach(vehicle => {
|
||||
if (vehicle.activeTime > 0) sum += 10; // static
|
||||
});
|
||||
|
||||
machines.forEach(machine => {
|
||||
if (machine.activeTime > 0) sum += 12; // static
|
||||
});
|
||||
|
||||
conveyors.forEach(conveyor => {
|
||||
if (conveyor.activeTime > 0) sum += 5; // static
|
||||
});
|
||||
|
||||
storageUnits.forEach(storage => {
|
||||
if (storage.activeTime > 0) sum += 8; // static
|
||||
});
|
||||
|
||||
console.log('sum: ', sum);
|
||||
|
||||
const avgProcessTime = 100 - 50; // static 50
|
||||
const machineUptime = (sum / avgProcessTime) * 100;
|
||||
console.log('machineUptime: ', machineUptime.toFixed(2));
|
||||
|
||||
const machineCount = 3; // static
|
||||
const throughput = (3600 / avgProcessTime) * machineCount * (machineUptime / 100); // **IMPORTANT divide by 100 for %**
|
||||
console.log('throughPutData: ', throughput.toFixed(2));
|
||||
|
||||
setTotalActiveTime(sum);
|
||||
setMachineActiveTime(sum);
|
||||
setThroughputData(throughput); // Save it properly here
|
||||
|
||||
}, [armBots, vehicles, machines, conveyors, storageUnits, setMachineActiveTime]);
|
||||
|
||||
// Just display throughput when ready
|
||||
useEffect(() => {
|
||||
console.log('throughputData: ', throughputData);
|
||||
if (throughputData > 0) {
|
||||
console.log('Final Throughput (units/hour): ', throughputData.toFixed(2));
|
||||
}
|
||||
}, [throughputData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
|||
const isIdleRef = useRef<boolean>(false);
|
||||
let startTime: number;
|
||||
|
||||
const { setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore();
|
||||
const { setArmBotActive, setArmBotState, removeCurrentAction,incrementActiveTime,incrementIdleTime } = useArmBotStore();
|
||||
const { setIsVisible } = useMaterialStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const { getActionByUuid } = useProductStore();
|
||||
|
@ -161,8 +161,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
|||
useEffect(() => {
|
||||
if (!isPlaying) return;
|
||||
|
||||
const intervalMs = 1000 / isSpeedRef.current;
|
||||
console.log('intervalMs: ', intervalMs);
|
||||
const intervalMs = 1000
|
||||
|
||||
if (!armBot.isActive && armBot.state == "idle" && (currentPhase == "rest" || currentPhase == "init") && !isIdleRef.current) {
|
||||
isIdleRef.current = true
|
||||
|
@ -173,7 +172,8 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
|||
clearInterval(activeTimerId.current);
|
||||
activeTimerId.current = null;
|
||||
}
|
||||
console.log(`✅ Active Cycle completed in ${activeSecondsElapsed.current} seconds`);
|
||||
incrementActiveTime(armBot.modelUuid, activeSecondsElapsed.current)
|
||||
// console.log(`✅ Active Cycle completed in ${activeSecondsElapsed.current} seconds`);
|
||||
|
||||
// 🚨 2. Reset active timer seconds after logging
|
||||
activeSecondsElapsed.current = 0;
|
||||
|
@ -188,7 +188,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
|||
idleTimerId.current = setInterval(() => {
|
||||
if (!isPausedRef.current) {
|
||||
idleSecondsElapsed.current += 1;
|
||||
console.log(`🕒 Idle Timer: ${idleSecondsElapsed.current} seconds`);
|
||||
// console.log(`🕒 Idle Timer: ${idleSecondsElapsed.current} seconds`);
|
||||
}
|
||||
}, intervalMs);
|
||||
} else if (armBot.isActive && armBot.state != "idle" && currentPhase !== "rest" && armBot.currentAction && isIdleRef.current) {
|
||||
|
@ -200,7 +200,8 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
|||
clearInterval(idleTimerId.current);
|
||||
idleTimerId.current = null;
|
||||
}
|
||||
console.log(`🕒 Idle Cycle completed in: ${idleSecondsElapsed.current} seconds`);
|
||||
incrementIdleTime(armBot.modelUuid, idleSecondsElapsed.current)
|
||||
// console.log(`🕒 Idle Cycle completed in: ${idleSecondsElapsed.current} seconds`);
|
||||
idleSecondsElapsed.current = 0;
|
||||
|
||||
// 🚨 Start Active Timer
|
||||
|
@ -211,7 +212,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
|||
activeTimerId.current = setInterval(() => {
|
||||
if (!isPausedRef.current) {
|
||||
activeSecondsElapsed.current += 1
|
||||
console.log(`🕒 Active Timer: ${activeSecondsElapsed.current} seconds`);
|
||||
// console.log(`🕒 Active Timer: ${activeSecondsElapsed.current} seconds`);
|
||||
}
|
||||
}, intervalMs);
|
||||
}
|
||||
|
@ -287,6 +288,56 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
|||
// }, [armBot, currentPhase, isPlaying, isIdleRef.current, isPausedRef.current]);
|
||||
|
||||
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!isPlaying) return;
|
||||
|
||||
// let frameId: number | null = null;
|
||||
// let lastTime = performance.now();
|
||||
|
||||
// const tick = (currentTime: number) => {
|
||||
// const delta = currentTime - lastTime;
|
||||
// lastTime = currentTime;
|
||||
|
||||
// const secondsToAdd = delta / 1000; // ⚡️REAL time passed (NO speed multiplication)
|
||||
|
||||
// if (!isPausedRef.current) {
|
||||
// // Update Timer
|
||||
// if (isIdleRef.current) {
|
||||
// idleSecondsElapsed.current += secondsToAdd;
|
||||
// console.log(`🕒 Idle Timer: ${idleSecondsElapsed.current.toFixed(2)} seconds (Speed: ${isSpeedRef.current}x)`);
|
||||
// } else {
|
||||
// activeSecondsElapsed.current += secondsToAdd;
|
||||
// console.log(`🕒 Active Timer: ${activeSecondsElapsed.current.toFixed(2)} seconds (Speed: ${isSpeedRef.current}x)`);
|
||||
// }
|
||||
// }
|
||||
// frameId = requestAnimationFrame(tick);
|
||||
// };
|
||||
// // Detect mode switch
|
||||
// if (!armBot.isActive && armBot.state === "idle" && (currentPhase === "rest" || currentPhase === "init") && !isIdleRef.current) {
|
||||
// isIdleRef.current = true;
|
||||
|
||||
// console.log(`✅ Active Cycle completed in ${activeSecondsElapsed.current.toFixed(2)} seconds`);
|
||||
// activeSecondsElapsed.current = 0;
|
||||
// idleSecondsElapsed.current = 0;
|
||||
// } else if (armBot.isActive && armBot.state !== "idle" && currentPhase !== "rest" && armBot.currentAction && isIdleRef.current) {
|
||||
// isIdleRef.current = false;
|
||||
// console.log(`🕒 Idle Cycle completed in: ${idleSecondsElapsed.current.toFixed(2)} seconds`);
|
||||
// idleSecondsElapsed.current = 0;
|
||||
// activeSecondsElapsed.current = 0;
|
||||
// }
|
||||
|
||||
// frameId = requestAnimationFrame(tick);
|
||||
|
||||
// return () => {
|
||||
// if (frameId !== null) {
|
||||
// cancelAnimationFrame(frameId);
|
||||
// }
|
||||
// };
|
||||
// }, [armBot, currentPhase, isPlaying]);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid);
|
||||
if (targetMesh) {
|
||||
|
|
|
@ -430,3 +430,17 @@ export const useZoneAssetId = create<ZoneAssetState>((set) => ({
|
|||
zoneAssetId: null,
|
||||
setZoneAssetId: (asset) => set({ zoneAssetId: asset }),
|
||||
}));
|
||||
|
||||
|
||||
export const useMachineCount = create<any>((set: any) => ({
|
||||
machineCount: 0,
|
||||
setMachineCount: (x: any) => set({ activeLayer: x }),
|
||||
}));
|
||||
export const useMachineUptime = create<any>((set: any) => ({
|
||||
machineActiveTime: 0,
|
||||
setMachineActiveTime: (x: any) => set({ activeLayer: x }),
|
||||
}));
|
||||
export const useMaterialCycle = create<any>((set: any) => ({
|
||||
materialCycleTime: 0,
|
||||
setMaterialCycleTime: (x: any) => set({ activeLayer: x }),
|
||||
}));
|
Loading…
Reference in New Issue