From 7e85cf4e53ae3497035f31f39f813a4be70ef54f Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Wed, 11 Jun 2025 16:33:21 +0530 Subject: [PATCH 01/10] feat: Add default values to analysis presets and enhance input handling in components --- .../layout/sidebarRight/analysis/Analysis.tsx | 41 +++++++++------ .../analysis/RenderAnalysisInputs.tsx | 7 +-- .../ui/analysis/ThroughputSummary.tsx | 1 + app/src/components/ui/list/List.tsx | 7 +-- .../simulation/analysis/ROI/roiData.tsx | 52 ++++++++++--------- .../productionCapacityData.tsx | 23 ++++++-- .../analysis/throughPut/throughPutData.tsx | 33 ++++++++---- .../assest/floorAsset/setFloorItemApi.ts | 5 +- app/src/store/simulation/useMaterialStore.ts | 1 + app/src/types/analysis.d.ts | 1 + 10 files changed, 108 insertions(+), 63 deletions(-) diff --git a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx index b314f19..6da2f8b 100644 --- a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx +++ b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { AIIcon } from "../../../icons/ExportCommonIcons"; import RegularDropDown from "../../../ui/inputs/RegularDropDown"; import { AnalysisPresetsType } from "../../../../types/analysis"; @@ -19,55 +19,66 @@ const Analysis: React.FC = () => { // { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } }, ], "Production capacity": [ - { type: "range", inputs: { label: "Shift length", activeOption: "hr" } }, - { type: "default", inputs: { label: "Shifts / day", activeOption: "unit" } }, - { type: "default", inputs: { label: "Working days / year", activeOption: "days" } }, - { type: "default", inputs: { label: "Yield rate", activeOption: "%" } }, + { type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 8 } }, + { type: "default", inputs: { label: "Shifts / day", activeOption: "unit", defaultValue: 2 } }, + { type: "default", inputs: { label: "Working days / year", activeOption: "days", defaultValue: 300 } }, + { type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 90 } }, ], ROI: [ { type: "default", - inputs: { label: "Selling price", activeOption: "INR" }, + inputs: { label: "Selling price", activeOption: "INR", defaultValue: 1500 }, }, { type: "default", - inputs: { label: "Material cost", activeOption: "INR" }, + inputs: { label: "Material cost", activeOption: "INR", defaultValue: 300 }, }, { type: "default", - inputs: { label: "Labor Cost", activeOption: "INR" }, + inputs: { label: "Labor Cost", activeOption: "INR", defaultValue: 200 }, }, { type: "default", - inputs: { label: "Maintenance cost", activeOption: "INR" }, + inputs: { label: "Maintenance cost", activeOption: "INR", defaultValue: 1200 }, }, { type: "default", - inputs: { label: "Electricity cost", activeOption: "INR" }, + inputs: { label: "Electricity cost", activeOption: "INR", defaultValue: 1000 }, }, { type: "default", - inputs: { label: "Fixed costs", activeOption: "INR" }, + inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 5000 }, }, { type: "default", - inputs: { label: "Initial Investment", activeOption: "INR" }, + inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 100000 }, }, { type: "default", - inputs: { label: "Salvage value", activeOption: "Hrs" }, + inputs: { label: "Salvage value", activeOption: "Hrs", defaultValue: 5000 }, }, { type: "default", - inputs: { label: "Production period", activeOption: "yrs" }, + inputs: { label: "Production period", activeOption: "yrs", defaultValue: 5 }, }, { type: "default", - inputs: { label: "Tax rate", activeOption: "%" }, + inputs: { label: "Tax rate", activeOption: "%", defaultValue: 30 }, }, ], }; + useEffect(() => { + Object.values(AnalysisPresets).forEach((category) => { + category.forEach((item) => { + const { label, defaultValue } = item.inputs; + if (defaultValue !== undefined) { + updateInputValue(label, defaultValue.toString()); + } + }); + }); + }, []); + const { inputValues, setInputValues, updateInputValue } = useInputValues(); return ( diff --git a/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx b/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx index 6f52438..30df2c5 100644 --- a/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx +++ b/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx @@ -10,7 +10,8 @@ interface InputRendererProps { onInputChange: (label: string, value: string) => void; } -const RenderAnalysisInputs: React.FC = ({ keyName, presets,inputValues, onInputChange }) => { +const RenderAnalysisInputs: React.FC = ({ keyName, presets, inputValues, onInputChange }) => { + return (
{presets.map((preset, index) => { @@ -19,7 +20,7 @@ const RenderAnalysisInputs: React.FC = ({ keyName, presets,i onInputChange(preset.inputs.label, newValue)} /> @@ -32,7 +33,7 @@ const RenderAnalysisInputs: React.FC = ({ keyName, presets,i label={preset.inputs.label} min={0} max={8} - value={5} + value={Number(preset.inputs.defaultValue) || Number(inputValues[preset.inputs.label]) || 5} /> ); } diff --git a/app/src/components/ui/analysis/ThroughputSummary.tsx b/app/src/components/ui/analysis/ThroughputSummary.tsx index 0568b5d..22cb95a 100644 --- a/app/src/components/ui/analysis/ThroughputSummary.tsx +++ b/app/src/components/ui/analysis/ThroughputSummary.tsx @@ -26,6 +26,7 @@ const ProductionCapacity = ({ const [isLoading, setIsLoading] = useState(true); useEffect(() => { + console.log('throughputData: ', throughputData); if (throughputData > 0) { setIsLoading(false); } else { diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 22653ff..08cf504 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -122,7 +122,7 @@ const List: React.FC = ({ items = [], remove }) => { zoneUuid: selectedZone.zoneUuid, zoneName: newName, }; - const response = await zoneCameraUpdate(zonesdata, organization,projectId); + const response = await zoneCameraUpdate(zonesdata, organization, projectId); if (response.message === "zone updated") { setSelectedZone((prev) => ({ ...prev, zoneName: newName })); setZones((prevZones: any[]) => @@ -143,9 +143,10 @@ const List: React.FC = ({ items = [], remove }) => { let response = await setFloorItemApi( organization, zoneAssetId.id, - newName + newName, + projectId ); - // console.log("response: ", response); + console.log("response: ", response); setName(zoneAssetId.id, response.modelName); } diff --git a/app/src/modules/simulation/analysis/ROI/roiData.tsx b/app/src/modules/simulation/analysis/ROI/roiData.tsx index 6551d54..59bf784 100644 --- a/app/src/modules/simulation/analysis/ROI/roiData.tsx +++ b/app/src/modules/simulation/analysis/ROI/roiData.tsx @@ -16,6 +16,7 @@ export default function ROIData() { useEffect(() => { if (!isPlaying) { + console.log("running ROIData effect"); setRoiSummaryData({ productName: "", roiPercentage: 0, @@ -25,11 +26,10 @@ export default function ROIData() { netProfit: 0, netLoss: 0, }) + return; } - if (inputValues === undefined) return; - const electricityCost = parseFloat(inputValues["Electricity cost"]); const fixedCost = parseFloat(inputValues["Fixed costs"]); const laborCost = parseFloat(inputValues["Labor Cost"]); @@ -60,23 +60,14 @@ export default function ROIData() { const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost; // Annual Profit const annualProfit = annualRevenue - totalAnnualCost; - + // Net Profit over production period const netProfit = annualProfit * productionPeriod; // ROI const roiPercentage = ((netProfit + salvageValue - initialInvestment) / initialInvestment) * 100; // Payback Period const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0 - - // - // - // - // - // - // - // - // setRoiSummaryData({ productName: selectedProduct.productName, @@ -99,17 +90,9 @@ export default function ROIData() { const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0; const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0; - - // - // - // - // - // - // - const productData = getProductById(selectedProduct.productUuid); - - + + setCompareProducts(prev => { const newData = { productUuid: productData?.productUuid, @@ -140,11 +123,30 @@ export default function ROIData() { return [...prev, newData]; } }); - // console.log('compareProducts: ', compareProducts); - + + } - }, [inputValues, productionCapacityData]); + }, [inputValues, productionCapacityData, selectedProduct?.productUuid]); + useEffect(() => { + + console.log('compareProducts: ', compareProducts); + }, [compareProducts]); + useEffect(() => { + // Clear ROI summary data when product changes + setRoiSummaryData({ + productName: "", + roiPercentage: 0, + paybackPeriod: 0, + totalCost: 0, + revenueGenerated: 0, + netProfit: 0, + netLoss: 0, + }); + + // Optionally clear comparison data for this product only + setCompareProducts(prev => prev.filter(p => p.productUuid !== selectedProduct.productUuid)); + }, [selectedProduct?.productUuid]); return ( <> diff --git a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx index 5c376a7..a9966ef 100644 --- a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx +++ b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx @@ -1,12 +1,15 @@ import React, { useEffect } from 'react' import { useInputValues, useProductionCapacityData, useThroughPutData } from '../../../../store/builder/store' import { usePlayButtonStore } from '../../../../store/usePlayButtonStore'; +import { useProductContext } from '../../products/productContext'; export default function ProductionCapacityData() { const { throughputData } = useThroughPutData() const { productionCapacityData, setProductionCapacityData } = useProductionCapacityData() const { inputValues } = useInputValues(); const { isPlaying } = usePlayButtonStore(); + const { selectedProductStore } = useProductContext(); + const { selectedProduct } = selectedProductStore(); useEffect(() => { if (!isPlaying) { @@ -16,32 +19,42 @@ export default function ProductionCapacityData() { if (!inputValues || throughputData === undefined) return; const shiftLength = parseFloat(inputValues["Shift length"]); + console.log('shiftLength: ', shiftLength); + const shiftsPerDay = parseFloat(inputValues["Shifts / day"]); + const workingDaysPerYear = parseFloat(inputValues["Working days / year"]); + const yieldRate = parseFloat(inputValues["Yield rate"]); + if (!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && - !isNaN(yieldRate) && throughputData >= 0) { + !isNaN(yieldRate) && throughputData > 0) { // Total units produced per day before yield const dailyProduction = throughputData * shiftLength * shiftsPerDay; - + // Units after applying yield rate const goodUnitsPerDay = dailyProduction * (yieldRate / 100); - + // Annual output const annualProduction = goodUnitsPerDay * workingDaysPerYear; - + // Final production capacity per hour (after yield) const productionPerHour = throughputData * (yieldRate / 100); - + // Set the final capacity (units/hour) setProductionCapacityData(Number(productionPerHour.toFixed(2))); } }, [throughputData, inputValues]); + useEffect(() => { + + setProductionCapacityData(0); + + }, [selectedProduct?.productUuid]); return ( <> diff --git a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx index 78bd1a7..fa43e0b 100644 --- a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx +++ b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx @@ -36,7 +36,7 @@ export default function ThroughPutData() { setMaterialCycleTime(0); setProcessBar([]); setThroughputData(0); - return; + return; } else { let process: any = []; const fetchProductSequenceData = async () => { @@ -83,7 +83,7 @@ export default function ThroughPutData() { .forEach(storage => { if (storage.activeTime > 0) { // totalActiveTime += storage.activeTime; -// + // } }); } @@ -92,7 +92,7 @@ export default function ThroughPutData() { totalItems += sequence.length; }); - + setMachineCount(totalItems); setMachineActiveTime(totalActiveTime); let arr = process.map((item: any) => ({ @@ -107,15 +107,15 @@ export default function ThroughPutData() { fetchProductSequenceData(); } // if (materialCycleTime <= 0) return - }, [products, selectedProduct, getProductById, setMachineCount, materialCycleTime, armBots, vehicles, machines]); + }, [products, selectedProduct?.productUuid, getProductById, setMachineCount, materialCycleTime, armBots, vehicles, machines]); useEffect(() => { + let timeoutId: ReturnType; async function getMachineActive() { const productData = getProductById(selectedProduct.productUuid); let anyArmActive; let anyVehicleActive; let anyMachineActive; - if (productData) { const productSequenceData = await determineExecutionMachineSequences([productData]); if (productSequenceData?.length > 0) { @@ -161,7 +161,7 @@ export default function ThroughPutData() { const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive; if (allInactive && materials.length === 0 && materialHistory.length > 0) { - + let totalCycleTimeSum = 0; let cycleCount = 0; @@ -182,11 +182,15 @@ export default function ThroughPutData() { } } if (isPlaying) { - setTimeout(() => { + timeoutId = setTimeout(() => { getMachineActive(); - }, 500) + }, 1500); } - }, [armBots, materials, materialHistory, machines, vehicles, selectedProduct]) + + return () => { + if (timeoutId) clearTimeout(timeoutId); + }; + }, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid]) useEffect(() => { if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0) { @@ -196,7 +200,16 @@ export default function ThroughPutData() { setThroughputData(Number(throughput.toFixed(2))); // Keep as number // } - }, [machineActiveTime, materialCycleTime, machineCount]); + }, [machineActiveTime, materialCycleTime, machineCount, selectedProduct?.productUuid]); + useEffect(() => { + totalActiveTime = 0; + totalItems = 0; + setMachineCount(0); + setMachineActiveTime(0); + setMaterialCycleTime(0); + setProcessBar([]); + setThroughputData(0); + }, [selectedProduct?.productUuid]); return ( <> diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts index d9e67e9..aa745ae 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts @@ -3,24 +3,25 @@ export const setFloorItemApi = async ( organization: string, modelUuid?: string, modelName?: string, + projectId?: string, modelfileID?: string, position?: Object, rotation?: Object, isLocked?: boolean, - isVisible?: boolean + isVisible?: boolean, ) => { try { const body: any = { organization, modelUuid, modelName, + projectId, position, rotation, modelfileID, isLocked, isVisible, }; - const response = await fetch(`${url_Backend_dwinzo}/api/V1/setAsset`, { method: "POST", headers: { diff --git a/app/src/store/simulation/useMaterialStore.ts b/app/src/store/simulation/useMaterialStore.ts index 123ebb0..a500d9a 100644 --- a/app/src/store/simulation/useMaterialStore.ts +++ b/app/src/store/simulation/useMaterialStore.ts @@ -88,6 +88,7 @@ export const createMaterialStore = () => { clearMaterials: () => { set((state) => { state.materials = []; + state.materialHistory = []; }); }, diff --git a/app/src/types/analysis.d.ts b/app/src/types/analysis.d.ts index 151afb4..41f9f81 100644 --- a/app/src/types/analysis.d.ts +++ b/app/src/types/analysis.d.ts @@ -5,6 +5,7 @@ type Preset = { activeOption: string; min?: number; max?: number; + defaultValue?: string | number; }; }; From 526e962388522419ee2c8c257ee5f8ebecc7466e Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Thu, 12 Jun 2025 09:44:53 +0530 Subject: [PATCH 02/10] feat: Add projectId parameter to setFloorItemApi and update related components in MainScene and List --- app/src/components/layout/scenes/MainScene.tsx | 6 ++++++ app/src/components/ui/list/List.tsx | 7 ++++++- .../factoryBuilder/assest/floorAsset/setFloorItemApi.ts | 6 +++--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/src/components/layout/scenes/MainScene.tsx b/app/src/components/layout/scenes/MainScene.tsx index 7f398df..b2a4b86 100644 --- a/app/src/components/layout/scenes/MainScene.tsx +++ b/app/src/components/layout/scenes/MainScene.tsx @@ -64,12 +64,18 @@ function MainScene() { } }; const handleObjectRename = async (newName: string) => { + if (!projectId) return const email = localStorage.getItem("email") ?? ""; const organization = email?.split("@")[1]?.split(".")[0]; let response = await setFloorItemApi( organization, selectedFloorItem.userData.modelUuid, newName, + undefined, + undefined, + undefined, + undefined, + undefined, projectId ); selectedFloorItem.userData = { diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 2ca44ac..d5c71ab 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -144,10 +144,15 @@ const List: React.FC = ({ items = [], remove }) => { organization, zoneAssetId.id, newName, + undefined, + undefined, + undefined, + undefined, + undefined, projectId ); // console.log("response: ", response); - console.log(' zoneAssetId.id,: ', zoneAssetId.id,); + console.log(' zoneAssetId.id,: ', zoneAssetId.id,); setName(zoneAssetId.id, response.modelName); } diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts index b819062..6bff9e5 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts @@ -3,24 +3,24 @@ export const setFloorItemApi = async ( organization: string, modelUuid?: string, modelName?: string, - projectId?: string, modelfileID?: string, position?: Object, rotation?: Object, isLocked?: boolean, - isVisible?: boolean + isVisible?: boolean, + projectId?: string ) => { try { const body: any = { organization, modelUuid, modelName, - projectId, position, rotation, modelfileID, isLocked, isVisible, + projectId, }; const response = await fetch(`${url_Backend_dwinzo}/api/V1/setAsset`, { From e60be88ded70c349546e623f784f84bb5254b201 Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Thu, 12 Jun 2025 12:04:45 +0530 Subject: [PATCH 03/10] feat: Enhance comparison functionality and update analysis defaults across components --- .../components/icons/ExportCommonIcons.tsx | 14 +- .../layout/scenes/ComparisonScene.tsx | 26 +++- .../layout/sidebarRight/analysis/Analysis.tsx | 16 +- .../sidebarRight/simulation/Simulations.tsx | 14 +- app/src/components/ui/analysis/ROISummary.tsx | 5 +- .../ui/compareVersion/ComparisonResult.tsx | 7 +- .../ui/simulation/simulationPlayer.tsx | 6 +- .../simulation/analysis/ROI/roiData.tsx | 142 +++++++----------- .../productionCapacityData.tsx | 15 +- .../analysis/throughPut/throughPutData.tsx | 39 +++-- .../modules/simulation/products/products.tsx | 3 + app/src/store/builder/store.ts | 33 +++- app/src/store/useCompareProductStore.ts | 18 +++ app/src/styles/layout/sidebar.scss | 4 +- 14 files changed, 206 insertions(+), 136 deletions(-) create mode 100644 app/src/store/useCompareProductStore.ts diff --git a/app/src/components/icons/ExportCommonIcons.tsx b/app/src/components/icons/ExportCommonIcons.tsx index 039a0a9..6f9a1fb 100644 --- a/app/src/components/icons/ExportCommonIcons.tsx +++ b/app/src/components/icons/ExportCommonIcons.tsx @@ -1292,8 +1292,8 @@ export const PerformanceIcon = () => { { y2="17.742" gradientUnits="userSpaceOnUse" > - - + + @@ -1328,9 +1328,9 @@ export const GreenTickIcon = () => { ); diff --git a/app/src/components/layout/scenes/ComparisonScene.tsx b/app/src/components/layout/scenes/ComparisonScene.tsx index d29b54a..c0de4f7 100644 --- a/app/src/components/layout/scenes/ComparisonScene.tsx +++ b/app/src/components/layout/scenes/ComparisonScene.tsx @@ -1,12 +1,13 @@ import { useProductContext } from '../../../modules/simulation/products/productContext' import RegularDropDown from '../../ui/inputs/RegularDropDown'; import { useProductStore } from '../../../store/simulation/useProductStore'; -import { useLoadingProgress, useSaveVersion } from '../../../store/builder/store'; +import { useCompareProductDataStore, useLoadingProgress, useSaveVersion } from '../../../store/builder/store'; import useModuleStore from '../../../store/useModuleStore'; import CompareLayOut from '../../ui/compareVersion/CompareLayOut'; import ComparisonResult from '../../ui/compareVersion/ComparisonResult'; import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore'; import { usePauseButtonStore, usePlayButtonStore } from '../../../store/usePlayButtonStore'; +import { useEffect, useState } from 'react'; function ComparisonScene() { const { isPlaying, setIsPlaying } = usePlayButtonStore(); @@ -19,6 +20,8 @@ function ComparisonScene() { const { mainProduct } = useMainProduct(); const { setIsPaused } = usePauseButtonStore(); const { loadingProgress } = useLoadingProgress(); + const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); + const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false); const handleSelectLayout = (option: string) => { const product = products.find((product) => product.productName === option); @@ -27,6 +30,24 @@ function ComparisonScene() { setIsPaused(true); } }; + + useEffect(() => { + if (mainProduct && comparisonProduct && compareProductsData.length > 1) { + // console.log('compareProductsData: ', compareProductsData); + const hasMain = compareProductsData.some(val => val.productUuid === mainProduct.productUuid); + const hasComparison = compareProductsData.some(val => val.productUuid === comparisonProduct.productUuid); + if (hasMain && hasComparison && mainProduct.productUuid !== comparisonProduct.productUuid) { + setShouldShowComparisonResult(true); + } else { + setShouldShowComparisonResult(false); + } + } else { + setShouldShowComparisonResult(false); + } + }, [compareProductsData, mainProduct, comparisonProduct]); + + + return ( <> {isVersionSaved && activeModule === "simulation" && selectedProduct && ( @@ -42,7 +63,8 @@ function ComparisonScene() {
} - {(comparisonProduct && mainProduct && !loadingProgress) && } + + {(shouldShowComparisonResult && !loadingProgress) && } )} diff --git a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx index 6da2f8b..2b2fe8a 100644 --- a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx +++ b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx @@ -19,15 +19,15 @@ const Analysis: React.FC = () => { // { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } }, ], "Production capacity": [ - { type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 8 } }, + { type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 6 } }, { type: "default", inputs: { label: "Shifts / day", activeOption: "unit", defaultValue: 2 } }, { type: "default", inputs: { label: "Working days / year", activeOption: "days", defaultValue: 300 } }, - { type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 90 } }, + { type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 92 } }, ], ROI: [ { type: "default", - inputs: { label: "Selling price", activeOption: "INR", defaultValue: 1500 }, + inputs: { label: "Selling price", activeOption: "INR", defaultValue: 800 }, }, { type: "default", @@ -35,7 +35,7 @@ const Analysis: React.FC = () => { }, { type: "default", - inputs: { label: "Labor Cost", activeOption: "INR", defaultValue: 200 }, + inputs: { label: "Labor Cost", activeOption: "INR", defaultValue: 150 }, }, { type: "default", @@ -43,19 +43,19 @@ const Analysis: React.FC = () => { }, { type: "default", - inputs: { label: "Electricity cost", activeOption: "INR", defaultValue: 1000 }, + inputs: { label: "Electricity cost", activeOption: "INR", defaultValue: 840 }, }, { type: "default", - inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 5000 }, + inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 1250 }, }, { type: "default", - inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 100000 }, + inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 1500000 }, }, { type: "default", - inputs: { label: "Salvage value", activeOption: "Hrs", defaultValue: 5000 }, + inputs: { label: "Salvage value", activeOption: "Day", defaultValue: 565 }, }, { type: "default", diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx index 80745ff..57f364c 100644 --- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx +++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"; import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon, } from "../../../icons/ExportCommonIcons"; import RenameInput from "../../../ui/inputs/RenameInput"; import { handleResize } from "../../../../functions/handleResizePannel"; -import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore"; +import { useMainProduct, useSelectedAsset } from "../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../store/simulation/useProductStore"; import { generateUUID } from "three/src/math/MathUtils"; import RenderOverlay from "../../../templates/Overlay"; @@ -48,6 +48,7 @@ const Simulations: React.FC = () => { const [processes, setProcesses] = useState(); const { setToggleUI } = useToggleStore(); const { projectId } = useParams(); + const { setMainProduct } = useMainProduct(); const { comparePopUp, setComparePopUp } = useCompareStore(); const { setIsVersionSaved } = useSaveVersion(); @@ -85,8 +86,13 @@ const Simulations: React.FC = () => { updatedProducts[newSelectedIndex].productUuid, updatedProducts[newSelectedIndex].productName ); + setMainProduct( + updatedProducts[newSelectedIndex].productUuid, + updatedProducts[newSelectedIndex].productName + ); } else { setSelectedProduct("", ""); + setMainProduct("", ""); } } @@ -102,6 +108,7 @@ const Simulations: React.FC = () => { renameProductApi({ productName: newName, productUuid, projectId: projectId || '' }); if (selectedProduct.productUuid === productUuid) { setSelectedProduct(productUuid, newName); + setMainProduct(productUuid, newName); } }; @@ -172,9 +179,10 @@ const Simulations: React.FC = () => { {/* eslint-disable-next-line */}
+ onClick={() => { setSelectedProduct(product.productUuid, product.productName) - } + setMainProduct(product.productUuid, product.productName) + }} >
- {roiSummary.roiPercentage}% ROI with payback - in just {roiSummary.paybackPeriod} months + {roiSummary.roiPercentage}% + ROI +
diff --git a/app/src/components/ui/compareVersion/ComparisonResult.tsx b/app/src/components/ui/compareVersion/ComparisonResult.tsx index 79fa57c..36ad1a7 100644 --- a/app/src/components/ui/compareVersion/ComparisonResult.tsx +++ b/app/src/components/ui/compareVersion/ComparisonResult.tsx @@ -2,8 +2,13 @@ import React, { useMemo } from "react"; import PerformanceResult from "./result-card/PerformanceResult"; import EnergyUsage from "./result-card/EnergyUsage"; import { Bar, Line, Pie } from "react-chartjs-2"; +import { useCompareProductDataStore } from "../../../store/builder/store"; +import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore"; const ComparisonResult = () => { + const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); + const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); + const { mainProduct } = useMainProduct(); const options = useMemo( () => ({ responsive: true, @@ -150,7 +155,7 @@ const ComparisonResult = () => {
-
Overall Scrap Rate
+
Production Capacity
Layout 1
diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx index ab0631a..d60bb6e 100644 --- a/app/src/components/ui/simulation/simulationPlayer.tsx +++ b/app/src/components/ui/simulation/simulationPlayer.tsx @@ -187,7 +187,7 @@ const SimulationPlayer: React.FC = () => {
-
ThroughPut Data
+
ThroughPut
{
-
Daily Production
+
Production Capacity
{
-
Monthly ROI
+
ROI
([]); + const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); + const { machineActiveTime, setMachineActiveTime } = useMachineUptime(); + const { machineIdleTime, setMachineIdleTime } = useMachineDowntime(); + const { throughputData } = useThroughPutData() useEffect(() => { - if (!isPlaying) { - console.log("running ROIData effect"); - setRoiSummaryData({ - productName: "", - roiPercentage: 0, - paybackPeriod: 0, - totalCost: 0, - revenueGenerated: 0, - netProfit: 0, - netLoss: 0, - }) + if (isPlaying) return; + setRoiSummaryData({ + productName: "", + roiPercentage: 0, + paybackPeriod: 0, + totalCost: 0, + revenueGenerated: 0, + netProfit: 0, + netLoss: 0, + }); + }, [isPlaying]); - return; - } - if (inputValues === undefined) return; + useEffect(() => { + if (inputValues === undefined || !isPlaying) return; const electricityCost = parseFloat(inputValues["Electricity cost"]); const fixedCost = parseFloat(inputValues["Fixed costs"]); const laborCost = parseFloat(inputValues["Labor Cost"]); - const maintenanceCost = parseFloat(inputValues["Maintenance cost"]); // Remove space typ + const maintenanceCost = parseFloat(inputValues["Maintenance cost"]); const materialCost = parseFloat(inputValues["Material cost"]); const productionPeriod = parseFloat(inputValues["Production period"]); const salvageValue = parseFloat(inputValues["Salvage value"]); @@ -46,32 +49,26 @@ export default function ROIData() { if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) && !isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) && !isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) { + console.log('productionCapacityData: ', productionCapacityData); const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear; - // Total good units produced per year const annualProductionUnits = productionCapacityData * totalHoursPerYear; - // Revenue for a year const annualRevenue = annualProductionUnits * sellingPrice; - // Costs + const totalMaterialCost = annualProductionUnits * materialCost; const totalLaborCost = laborCost * totalHoursPerYear; const totalEnergyCost = electricityCost * totalHoursPerYear; const totalMaintenanceCost = maintenanceCost + fixedCost; const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost; - // Annual Profit const annualProfit = annualRevenue - totalAnnualCost; - // Net Profit over production period const netProfit = annualProfit * productionPeriod; - // ROI - const roiPercentage = ((netProfit + salvageValue - initialInvestment) / initialInvestment) * 100; - // Payback Period + const roiPercentage = ((annualProfit + salvageValue - initialInvestment) / initialInvestment) * 100; const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0 - setRoiSummaryData({ productName: selectedProduct.productName, - roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)), // normalized to 0.x format + roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)), paybackPeriod: parseFloat(paybackPeriod.toFixed(2)), totalCost: parseFloat(totalAnnualCost.toFixed(2)), revenueGenerated: parseFloat(annualRevenue.toFixed(2)), @@ -80,77 +77,54 @@ export default function ROIData() { }); const productCount = 1000; - - // Cost per unit (based on full annual cost) const costPerUnit = totalAnnualCost / annualProductionUnits; - const costForTargetUnits = productCount * costPerUnit; const revenueForTargetUnits = productCount * sellingPrice; const profitForTargetUnits = revenueForTargetUnits - costForTargetUnits; const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0; const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0; + const productData = getProductById(selectedProduct.productUuid); - - - setCompareProducts(prev => { - const newData = { - productUuid: productData?.productUuid, - productName: productData?.productName, - costPerUnit: parseFloat(costPerUnit.toFixed(2)), - workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)), - shiftLength: parseFloat(shiftLength.toFixed(2)), - shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)), + const prev = useCompareProductDataStore.getState().compareProductsData; + const newData: CompareProduct = { + productUuid: productData?.productUuid ?? '', + productName: productData?.productName ?? '', + simulationData: { + // costPerUnit: parseFloat(costPerUnit.toFixed(2)), + // workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)), + // shiftLength: parseFloat(shiftLength.toFixed(2)), + // shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)), roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)), - paybackPeriod: parseFloat(paybackPeriod.toFixed(2)), - totalCost: parseFloat(totalAnnualCost.toFixed(2)), - revenueGenerated: parseFloat(annualRevenue.toFixed(2)), + // paybackPeriod: parseFloat(paybackPeriod.toFixed(2)), + // totalCost: parseFloat(totalAnnualCost.toFixed(2)), + // revenueGenerated: parseFloat(annualRevenue.toFixed(2)), netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0, - netLoss: netProfit < 0 ? parseFloat((-netProfit).toFixed(2)) : 0 - }; - - const existingIndex = prev.findIndex( - item => item.productUuid === productData?.productUuid - ); - - if (existingIndex !== -1) { - // Replace the existing item - const updated = [...prev]; - updated[existingIndex] = newData; - return updated; - } else { - // Add as new item - return [...prev, newData]; + // netLoss: netProfit < 0 ? parseFloat((-netProfit).toFixed(2)) : 0, + machineIdleTime: parseFloat(machineIdleTime.toFixed(2)), + machineActiveTime: parseFloat(machineActiveTime.toFixed(2)), + throughputData: throughputData, } - }); + }; + const existingIndex = prev.findIndex((item: CompareProduct) => + item.productUuid === productData?.productUuid + ); + if (existingIndex !== -1) { + const updated = [...prev]; + updated[existingIndex] = newData; + setCompareProductsData(updated); + } else { + setCompareProductsData([...prev, newData]); + } } - }, [inputValues, productionCapacityData, selectedProduct?.productUuid]); + }, [inputValues, productionCapacityData, selectedProduct?.productUuid, isPlaying]); + useEffect(() => { + console.log('compareProductsData: ', compareProductsData); + }, [compareProductsData]) - console.log('compareProducts: ', compareProducts); - }, [compareProducts]); - useEffect(() => { - // Clear ROI summary data when product changes - setRoiSummaryData({ - productName: "", - roiPercentage: 0, - paybackPeriod: 0, - totalCost: 0, - revenueGenerated: 0, - netProfit: 0, - netLoss: 0, - }); - - // Optionally clear comparison data for this product only - setCompareProducts(prev => prev.filter(p => p.productUuid !== selectedProduct.productUuid)); - }, [selectedProduct?.productUuid]); - - return ( - <> - ) + return null; } - - diff --git a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx index a9966ef..ced9ddc 100644 --- a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx +++ b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx @@ -13,10 +13,14 @@ export default function ProductionCapacityData() { useEffect(() => { if (!isPlaying) { + console.log('isPlaying: ', isPlaying); setProductionCapacityData(0); - return; } - if (!inputValues || throughputData === undefined) return; + }, [isPlaying]); + + useEffect(() => { + if (!inputValues || throughputData === undefined || !isPlaying) return; + console.log('throughputData: ', throughputData); const shiftLength = parseFloat(inputValues["Shift length"]); console.log('shiftLength: ', shiftLength); @@ -49,12 +53,7 @@ export default function ProductionCapacityData() { // Set the final capacity (units/hour) setProductionCapacityData(Number(productionPerHour.toFixed(2))); } - }, [throughputData, inputValues]); - useEffect(() => { - - setProductionCapacityData(0); - - }, [selectedProduct?.productUuid]); + }, [throughputData, inputValues, isPlaying]); return ( <> diff --git a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx index fa43e0b..72189e0 100644 --- a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx +++ b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx @@ -1,10 +1,11 @@ import { useEffect } from 'react'; import { useProductStore } from '../../../../store/simulation/useProductStore'; import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences'; -import { useMachineCount, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store'; +import { useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store'; import { usePlayButtonStore } from '../../../../store/usePlayButtonStore'; import { useSceneContext } from '../../../scene/sceneContext'; import { useProductContext } from '../../products/productContext'; +import { set } from 'immer/dist/internal'; export default function ThroughPutData() { const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore } = useSceneContext(); @@ -19,6 +20,7 @@ export default function ThroughPutData() { const { materialHistory, materials } = materialStore(); const { machineCount, setMachineCount } = useMachineCount(); const { machineActiveTime, setMachineActiveTime } = useMachineUptime(); + const { machineIdleTime, setMachineIdleTime } = useMachineDowntime(); const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle(); const { setProcessBar } = useProcessBar(); const { setThroughputData } = useThroughPutData() @@ -27,17 +29,24 @@ export default function ThroughPutData() { // Setting machine count let totalItems = 0; let totalActiveTime = 0; + let totalIdleTime = 0 + useEffect(() => { if (!isPlaying) { totalActiveTime = 0; totalItems = 0; + totalIdleTime = 0; setMachineCount(0); setMachineActiveTime(0); + setMachineIdleTime(0); setMaterialCycleTime(0); setProcessBar([]); setThroughputData(0); - return; - } else { + } + }, [isPlaying]) + + useEffect(() => { + if (isPlaying) { let process: any = []; const fetchProductSequenceData = async () => { const productData = getProductById(selectedProduct.productUuid); @@ -53,6 +62,9 @@ export default function ThroughPutData() { process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime }) totalActiveTime += arm.activeTime; } + if (arm.idleTime > 0) { + totalIdleTime += arm.idleTime; + } }); } else if (item.type === "vehicle") { vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid) @@ -62,6 +74,9 @@ export default function ThroughPutData() { totalActiveTime += vehicle.activeTime; } + if (vehicle.idleTime > 0) { + totalIdleTime += vehicle.idleTime; + } }); } else if (item.type === "machine") { machines.filter(machine => machine.modelUuid === item.modelUuid) @@ -70,6 +85,9 @@ export default function ThroughPutData() { process.push({ modelid: machine.modelUuid, modelName: machine.modelName, activeTime: machine?.activeTime }) totalActiveTime += machine.activeTime; } + if (machine.idleTime > 0) { + totalIdleTime += machine.idleTime; + } }); } else if (item.type === "transfer") { conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid) @@ -95,6 +113,7 @@ export default function ThroughPutData() { setMachineCount(totalItems); setMachineActiveTime(totalActiveTime); + setMachineIdleTime(totalIdleTime); let arr = process.map((item: any) => ({ name: item.modelName, completed: Math.round((item.activeTime / totalActiveTime) * 100) @@ -193,23 +212,13 @@ export default function ThroughPutData() { }, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid]) useEffect(() => { - if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0) { + if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0 && isPlaying) { const utilization = machineActiveTime / 3600; // Active time per hour const unitsPerMachinePerHour = 3600 / materialCycleTime; const throughput = unitsPerMachinePerHour * machineCount * utilization; setThroughputData(Number(throughput.toFixed(2))); // Keep as number - // } - }, [machineActiveTime, materialCycleTime, machineCount, selectedProduct?.productUuid]); - useEffect(() => { - totalActiveTime = 0; - totalItems = 0; - setMachineCount(0); - setMachineActiveTime(0); - setMaterialCycleTime(0); - setProcessBar([]); - setThroughputData(0); - }, [selectedProduct?.productUuid]); + }, [machineActiveTime, materialCycleTime, machineCount, selectedProduct?.productUuid, isPlaying]); return ( <> diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx index 0b26902..a242f5b 100644 --- a/app/src/modules/simulation/products/products.tsx +++ b/app/src/modules/simulation/products/products.tsx @@ -13,6 +13,7 @@ function Products() { const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, layout } = useSceneContext(); const { products, getProductById, addProduct, setProducts } = useProductStore(); const { selectedProductStore } = useProductContext(); + const { setMainProduct } = useMainProduct(); const { selectedProduct, setSelectedProduct } = selectedProductStore(); const { addVehicle, clearvehicles } = vehicleStore(); const { addArmBot, clearArmBots } = armBotStore(); @@ -51,11 +52,13 @@ function Products() { }) if (layout === 'Main Layout') { setSelectedProduct(id, name); + setMainProduct(id, name); } } else { setProducts(data); if (layout === 'Main Layout') { setSelectedProduct(data[0].productUuid, data[0].productName); + setMainProduct(data[0].productUuid, data[0].productName); } } }) diff --git a/app/src/store/builder/store.ts b/app/src/store/builder/store.ts index 4502c71..eba4c47 100644 --- a/app/src/store/builder/store.ts +++ b/app/src/store/builder/store.ts @@ -26,7 +26,7 @@ export const useSocketStore = create((set: any, get: any) => ({ auth: { token }, } ); - + const dashBoardSocket = io( `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`, @@ -546,6 +546,10 @@ export const useMachineUptime = create((set: any) => ({ machineActiveTime: 0, setMachineActiveTime: (x: any) => set({ machineActiveTime: x }), })); +export const useMachineDowntime = create((set: any) => ({ + machineIdleTime: 0, + setMachineIdleTime: (x: any) => set({ machineIdleTime: x }), +})); export const useMaterialCycle = create((set: any) => ({ materialCycleTime: 0, setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }), @@ -709,3 +713,30 @@ function getInitialViewSceneLabels(): boolean { const saved = localStorage.getItem('viewSceneLabels'); return saved ? JSON.parse(saved) : false; } +export interface CompareProduct { + productUuid: string; + productName: string; + simulationData: { + // costPerUnit: number; + // workingDaysPerYear: number; + // shiftLength: number; + // shiftsPerDay: number; + roiPercentage: number; + // paybackPeriod: number; + // totalCost: number; + // revenueGenerated: number; + netProfit: number; + // netLoss: number; + machineIdleTime: number; + machineActiveTime: number; + throughputData: number; + } +} + +export const useCompareProductDataStore = create<{ + compareProductsData: CompareProduct[]; + setCompareProductsData: (x: CompareProduct[]) => void; +}>((set) => ({ + compareProductsData: [], + setCompareProductsData: (x) => set({ compareProductsData: x }), +})); \ No newline at end of file diff --git a/app/src/store/useCompareProductStore.ts b/app/src/store/useCompareProductStore.ts new file mode 100644 index 0000000..d5972f8 --- /dev/null +++ b/app/src/store/useCompareProductStore.ts @@ -0,0 +1,18 @@ +// store/simulation/useCompareProductDataStore.ts +import { create } from 'zustand'; + +interface CompareProduct { + productUuid: string; + productName: string; + costPerUnit: number; + workingDaysPerYear: number; + shiftLength: number; + shiftsPerDay: number; + roiPercentage: number; + paybackPeriod: number; + totalCost: number; + revenueGenerated: number; + netProfit: number; + netLoss: number; +} + diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index b043e29..d5e1a6c 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -657,7 +657,7 @@ path { stroke: var(--text-button-color); - stroke-width: 1.3; + strokeWidth: 1.3; } } } @@ -1021,7 +1021,7 @@ path { stroke: var(--accent-color); - stroke-width: 1.5px; + strokeWidth: 1.5px; } &:hover { From b3c4f9eb65e5f87db34276155a8fdebb6bc77fda Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 12 Jun 2025 12:07:28 +0530 Subject: [PATCH 04/10] refactor: remove unnecessary setIsPaused calls in ComparisonScene and CompareLayOut; improve wall visibility logic in hideWalls --- .../layout/scenes/ComparisonScene.tsx | 1 - .../components/layout/scenes/MainScene.tsx | 18 +++++++---- .../ui/compareVersion/CompareLayOut.tsx | 1 - .../builder/geomentries/walls/hideWalls.ts | 30 +++++++++---------- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/app/src/components/layout/scenes/ComparisonScene.tsx b/app/src/components/layout/scenes/ComparisonScene.tsx index d29b54a..e3c2bab 100644 --- a/app/src/components/layout/scenes/ComparisonScene.tsx +++ b/app/src/components/layout/scenes/ComparisonScene.tsx @@ -24,7 +24,6 @@ function ComparisonScene() { const product = products.find((product) => product.productName === option); if (product) { setComparisonProduct(product.productUuid, product.productName); - setIsPaused(true); } }; return ( diff --git a/app/src/components/layout/scenes/MainScene.tsx b/app/src/components/layout/scenes/MainScene.tsx index 7f398df..a1d0a01 100644 --- a/app/src/components/layout/scenes/MainScene.tsx +++ b/app/src/components/layout/scenes/MainScene.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import { useLoadingProgress, useRenameModeStore, @@ -42,7 +42,7 @@ function MainScene() { const { setMainProduct } = useMainProduct(); const { selectedProductStore } = useProductContext(); const { selectedProduct } = selectedProductStore(); - const { isVersionSaved } = useSaveVersion(); + const { isVersionSaved, setIsVersionSaved } = useSaveVersion(); const { activeModule } = useModuleStore(); const { selectedUser } = useSelectedUserStore(); const { loadingProgress } = useLoadingProgress(); @@ -52,11 +52,19 @@ function MainScene() { const { visualizationSocket } = useSocketStore(); const { selectedZone } = useSelectedZoneStore(); const { setFloatingWidget } = useFloatingWidget(); - const { comparisonProduct } = useComparisonProduct(); + const { clearComparisonProduct } = useComparisonProduct(); const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem(); const { setName } = useAssetsStore(); const { projectId } = useParams() const { isRenameMode, setIsRenameMode } = useRenameModeStore(); + + useEffect(() => { + if (activeModule !== 'simulation') { + clearComparisonProduct(); + setIsVersionSaved(false); + } + }, [activeModule]) + const handleSelectLayout = (option: string) => { const product = products.find((product) => product.productName === option); if (product) { @@ -99,10 +107,10 @@ function MainScene() { {activeModule !== "market" && !isPlaying && !isVersionSaved && ( )} - {(isPlaying || comparisonProduct !== null) && + {(isPlaying) && activeModule === "simulation" && loadingProgress == 0 && } - {(isPlaying || comparisonProduct !== null) && + {(isPlaying) && activeModule !== "simulation" && } {isRenameMode && selectedFloorItem?.userData.modelName && } diff --git a/app/src/components/ui/compareVersion/CompareLayOut.tsx b/app/src/components/ui/compareVersion/CompareLayOut.tsx index 48bb686..9229dba 100644 --- a/app/src/components/ui/compareVersion/CompareLayOut.tsx +++ b/app/src/components/ui/compareVersion/CompareLayOut.tsx @@ -118,7 +118,6 @@ const CompareLayOut = () => { if (product) { setComparisonProduct(product.productUuid, product.productName); setLoadingProgress(1); - setIsPaused(true); } }; diff --git a/app/src/modules/builder/geomentries/walls/hideWalls.ts b/app/src/modules/builder/geomentries/walls/hideWalls.ts index f8bf52a..02233b0 100644 --- a/app/src/modules/builder/geomentries/walls/hideWalls.ts +++ b/app/src/modules/builder/geomentries/walls/hideWalls.ts @@ -1,5 +1,4 @@ import * as THREE from 'three'; - import * as Types from "../../../../types/world/worldTypes"; function hideWalls( @@ -7,21 +6,24 @@ function hideWalls( scene: THREE.Scene, camera: THREE.Camera ): void { - - ////////// Altering the visibility of the Walls when the world direction of the wall is facing the camera ////////// - - const v = new THREE.Vector3(); - const u = new THREE.Vector3(); + const wallNormal = new THREE.Vector3(); + const cameraToWall = new THREE.Vector3(); + const cameraDirection = new THREE.Vector3(); if (visibility === true) { for (const children of scene.children) { if (children.name === "Walls" && children.children[0]?.children.length > 0) { children.children[0].children.forEach((child: any) => { if (child.children[0]?.userData.WallType === "RoomWall") { - child.children[0].getWorldDirection(v); - camera.getWorldDirection(u); - if (child.children[0].material) { - child.children[0].material.visible = (2 * v.dot(u)) >= -0.5; + const wallMesh = child.children[0]; + wallMesh.getWorldDirection(wallNormal); + cameraToWall.copy(wallMesh.position).sub(camera.position).normalize(); + camera.getWorldDirection(cameraDirection); + const isFacingCamera = wallNormal.dot(cameraToWall) > 0; + const isInFrontOfCamera = cameraDirection.dot(cameraToWall) > -0.3; + + if (wallMesh.material) { + wallMesh.material.visible = isFacingCamera && isInFrontOfCamera; } } }); @@ -31,10 +33,8 @@ function hideWalls( for (const children of scene.children) { if (children.name === "Walls" && children.children[0]?.children.length > 0) { children.children[0].children.forEach((child: any) => { - if (child.children[0]?.userData.WallType === "RoomWall") { - if (child.children[0].material) { - child.children[0].material.visible = true; - } + if (child.children[0]?.userData.WallType === "RoomWall" && child.children[0].material) { + child.children[0].material.visible = true; } }); } @@ -42,4 +42,4 @@ function hideWalls( } } -export default hideWalls; +export default hideWalls; \ No newline at end of file From c989e2f35dcbc1a2752fa7a8de649e95a4a072ca Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 12 Jun 2025 12:09:22 +0530 Subject: [PATCH 05/10] fix: remove duplicate projectId parameter in setFloorItemApi function --- .../services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts index 4ef6167..9c0003d 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts @@ -5,7 +5,6 @@ export const setFloorItemApi = async ( modelName?: string, projectId?: string, assetId?: string, - projectId?: string, position?: Object, rotation?: Object, isLocked?: boolean, From 8c8b81989c7b6ccf01366067d9287d199b40ec1c Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 12 Jun 2025 12:12:39 +0530 Subject: [PATCH 06/10] fix: remove unnecessary undefined parameters in setFloorItemApi call --- app/src/components/layout/scenes/MainScene.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/src/components/layout/scenes/MainScene.tsx b/app/src/components/layout/scenes/MainScene.tsx index eb2745c..67dc35a 100644 --- a/app/src/components/layout/scenes/MainScene.tsx +++ b/app/src/components/layout/scenes/MainScene.tsx @@ -79,11 +79,6 @@ function MainScene() { organization, selectedFloorItem.userData.modelUuid, newName, - undefined, - undefined, - undefined, - undefined, - undefined, projectId ); selectedFloorItem.userData = { From b350bc6d9e3989e0659b8c32bc18a63900094ff7 Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Thu, 12 Jun 2025 16:39:25 +0530 Subject: [PATCH 07/10] Refactor ComparisonScene and Analysis components; update simulation logic and UI - Removed unused pause button store from ComparisonScene. - Added commented-out mock data setup in ComparisonScene for testing. - Updated default values in Analysis component for production capacity and ROI calculations. - Adjusted ProductionCapacity component to reflect monthly production capacity. - Enhanced ROISummary to calculate payback date and improved net profit calculations. - Modified ThroughputSummary to calculate units per hour based on shift length. - Improved ComparisonResult to dynamically display compared products' data. - Updated EnergyUsage to randomize data for better testing. - Refined ROIData calculations to include labor count and adjusted cost calculations. - Enhanced production capacity calculations in productionCapacityData. - Updated throughput calculations in throughPutData to consider shift length and yield rate. - Cleaned up console logs in vehicleInstance for better readability. - Added productionCapacity field to CompareProduct interface in store. - Minor styling adjustments in simulation.scss for better layout. --- .../layout/scenes/ComparisonScene.tsx | 34 +++- .../layout/sidebarRight/analysis/Analysis.tsx | 16 +- .../ui/analysis/ProductionCapacity.tsx | 4 +- app/src/components/ui/analysis/ROISummary.tsx | 35 +++-- .../ui/analysis/ThroughputSummary.tsx | 16 +- .../ui/compareVersion/ComparisonResult.tsx | 146 +++++++++++++----- .../result-card/EnergyUsage.tsx | 47 +++--- .../simulation/analysis/ROI/roiData.tsx | 143 ++++++++++++----- .../productionCapacityData.tsx | 35 +---- .../analysis/throughPut/throughPutData.tsx | 19 ++- .../instances/instance/vehicleInstance.tsx | 2 - app/src/store/builder/store.ts | 1 + .../components/simulation/simulation.scss | 3 +- 13 files changed, 333 insertions(+), 168 deletions(-) diff --git a/app/src/components/layout/scenes/ComparisonScene.tsx b/app/src/components/layout/scenes/ComparisonScene.tsx index f0c2b7a..6b7cad0 100644 --- a/app/src/components/layout/scenes/ComparisonScene.tsx +++ b/app/src/components/layout/scenes/ComparisonScene.tsx @@ -6,7 +6,7 @@ import useModuleStore from '../../../store/useModuleStore'; import CompareLayOut from '../../ui/compareVersion/CompareLayOut'; import ComparisonResult from '../../ui/compareVersion/ComparisonResult'; import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore'; -import { usePauseButtonStore, usePlayButtonStore } from '../../../store/usePlayButtonStore'; +import { usePlayButtonStore } from '../../../store/usePlayButtonStore'; import { useEffect, useState } from 'react'; function ComparisonScene() { @@ -18,7 +18,6 @@ function ComparisonScene() { const { selectedProduct } = selectedProductStore(); const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); const { mainProduct } = useMainProduct(); - const { setIsPaused } = usePauseButtonStore(); const { loadingProgress } = useLoadingProgress(); const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false); @@ -29,6 +28,35 @@ function ComparisonScene() { setComparisonProduct(product.productUuid, product.productName); } }; + // useEffect(() => { + // setCompareProductsData([ + // { + // productUuid: "15193386-ec58-4ec6-8a92-e665a39eebf1", + // productName: "Product 1", + // simulationData: { + // roiPercentage: 65.54, + // netProfit: 499037750, + // machineIdleTime: 1024, + // machineActiveTime: 235, + // productionCapacity: 1000, + // throughputData: 62.42 + // } + // }, + // { + // productUuid: "f614bf50-f61d-41c5-acc0-3783fb4da6b8", + // productName: "Product 2", + // simulationData: { + // roiPercentage: 169.99, + // netProfit: 1282397750, + // machineIdleTime: 1897, + // machineActiveTime: 653, + // productionCapacity: 2000, + // throughputData: 157.03 + // } + // } + // ]) + // }, []); // ✅ Runs only once on mount + useEffect(() => { if (mainProduct && comparisonProduct && compareProductsData.length > 1) { @@ -45,8 +73,6 @@ function ComparisonScene() { } }, [compareProductsData, mainProduct, comparisonProduct]); - - return ( <> {isVersionSaved && activeModule === "simulation" && selectedProduct && ( diff --git a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx index 2b2fe8a..d903b7e 100644 --- a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx +++ b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx @@ -19,15 +19,15 @@ const Analysis: React.FC = () => { // { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } }, ], "Production capacity": [ - { type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 6 } }, - { type: "default", inputs: { label: "Shifts / day", activeOption: "unit", defaultValue: 2 } }, + { type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 1 } }, + { type: "default", inputs: { label: "Shifts / day", activeOption: "unit", defaultValue: 3 } }, { type: "default", inputs: { label: "Working days / year", activeOption: "days", defaultValue: 300 } }, - { type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 92 } }, + { type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 98 } }, ], ROI: [ { type: "default", - inputs: { label: "Selling price", activeOption: "INR", defaultValue: 800 }, + inputs: { label: "Selling price", activeOption: "INR", defaultValue: 500 }, }, { type: "default", @@ -37,6 +37,10 @@ const Analysis: React.FC = () => { type: "default", inputs: { label: "Labor Cost", activeOption: "INR", defaultValue: 150 }, }, + { + type: "default", + inputs: { label: "Labor Count", activeOption: "", defaultValue: 1 }, + }, { type: "default", inputs: { label: "Maintenance cost", activeOption: "INR", defaultValue: 1200 }, @@ -47,11 +51,11 @@ const Analysis: React.FC = () => { }, { type: "default", - inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 1250 }, + inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 1150 }, }, { type: "default", - inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 1500000 }, + inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 3500000 }, }, { type: "default", diff --git a/app/src/components/ui/analysis/ProductionCapacity.tsx b/app/src/components/ui/analysis/ProductionCapacity.tsx index 84d293d..6ff0b42 100644 --- a/app/src/components/ui/analysis/ProductionCapacity.tsx +++ b/app/src/components/ui/analysis/ProductionCapacity.tsx @@ -26,6 +26,8 @@ const ThroughputSummary: React.FC = () => { unit: "KWH", }; + + // Dynamic shift data const shiftUtilization = [ { shift: 1, percentage: 30, color: "#F3C64D" }, @@ -126,7 +128,7 @@ const ThroughputSummary: React.FC = () => {
{productionCapacityData}{" "} - Units/hour + Units/Month
diff --git a/app/src/components/ui/analysis/ROISummary.tsx b/app/src/components/ui/analysis/ROISummary.tsx index 735cd9e..3a0a570 100644 --- a/app/src/components/ui/analysis/ROISummary.tsx +++ b/app/src/components/ui/analysis/ROISummary.tsx @@ -9,7 +9,7 @@ import { import SemiCircleProgress from "./SemiCircleProgress"; import { ArrowIcon } from "../../icons/ExportCommonIcons"; import SkeletonUI from "../../templates/SkeletonUI"; -import { useROISummaryData } from "../../../store/builder/store"; +import { useInputValues, useROISummaryData } from "../../../store/builder/store"; const ROISummary = ({ roiSummaryData = { @@ -67,6 +67,8 @@ const ROISummary = ({ }, }) => { const [isTableOpen, setIsTableOpen] = useState(false); // State to handle the table open/close + const { inputValues } = useInputValues(); + const productionPeriod = parseFloat(inputValues["Production period"]); // Function to toggle the breakdown table visibility const toggleTable = () => { @@ -95,6 +97,17 @@ const ROISummary = ({ } }, [roiSummary]); + function getPaybackDateFromYears(yearsToAdd: number) { + const now = new Date(); + console.log('yearsToAdd: ', yearsToAdd); + const totalMonths = Math.round(yearsToAdd * 12); + console.log('totalMonths: ', totalMonths); + const paybackDate = new Date(now.getFullYear(), now.getMonth() + totalMonths, now.getDate()); + const month = paybackDate.toLocaleString("en-GB", { month: "long" }); + const year = paybackDate.getFullYear(); + return `${month} ${year}`; + } + return ( <> @@ -121,26 +134,30 @@ const ROISummary = ({
- {roiSummary.roiPercentage}% - ROI + {roiSummary.roiPercentage.toFixed(2)}% + ROI in the period of {productionPeriod} years
- +
you're on track to hit it by -
July 2029
+
{getPaybackDateFromYears(roiSummary.paybackPeriod)}
+
Total Cost Incurred - {roiSummary.totalCost} + {roiSummary.totalCost.toFixed(0)}
@@ -148,7 +165,7 @@ const ROISummary = ({ - {roiSummary.revenueGenerated} + {roiSummary.revenueGenerated.toFixed(0)}
@@ -162,8 +179,8 @@ const ROISummary = ({
{roiSummary.netProfit > 0 - ? roiSummary.netProfit - : roiSummary.netLoss} + ? roiSummary.netProfit.toFixed(0) + : roiSummary.netLoss.toFixed(0)}
diff --git a/app/src/components/ui/analysis/ThroughputSummary.tsx b/app/src/components/ui/analysis/ThroughputSummary.tsx index 22cb95a..304c651 100644 --- a/app/src/components/ui/analysis/ThroughputSummary.tsx +++ b/app/src/components/ui/analysis/ThroughputSummary.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { useMachineCount, useMachineUptime, useMaterialCycle, useProductionCapacityData, useThroughPutData } from "../../../store/builder/store"; +import { useInputValues, useMachineCount, useMachineUptime, useMaterialCycle, useProductionCapacityData, useThroughPutData } from "../../../store/builder/store"; import { ThroughputSummaryIcon, } from "../../icons/analysis"; @@ -14,29 +14,30 @@ const ProductionCapacity = ({ const { machineActiveTime } = useMachineUptime(); const { materialCycleTime } = useMaterialCycle(); const { throughputData } = useThroughPutData() + const { inputValues } = useInputValues(); const progressPercent = machineActiveTime; + const shiftLength = parseFloat(inputValues["Shift length"]); const totalBars = 6; const barsToFill = Math.floor((progressPercent / 100) * totalBars); - const partialFillPercent = - ((progressPercent / 100) * totalBars - barsToFill) * 100; + const partialFillPercent = ((progressPercent / 1000) * totalBars - barsToFill) * 100; const [isLoading, setIsLoading] = useState(true); useEffect(() => { - console.log('throughputData: ', throughputData); if (throughputData > 0) { setIsLoading(false); } else { - setIsLoading(true); + setIsLoading(false); } }, [throughputData]) + const Units_per_hour = ((shiftLength * 60) / (materialCycleTime / 60) / shiftLength) + return ( <> - {!isLoading &&
@@ -54,8 +55,7 @@ const ProductionCapacity = ({ <>
- {throughputData} Units/hour - + {(Units_per_hour).toFixed(2)} Units/hour
{/* Dynamic Progress Bar */} diff --git a/app/src/components/ui/compareVersion/ComparisonResult.tsx b/app/src/components/ui/compareVersion/ComparisonResult.tsx index 36ad1a7..caec3b4 100644 --- a/app/src/components/ui/compareVersion/ComparisonResult.tsx +++ b/app/src/components/ui/compareVersion/ComparisonResult.tsx @@ -1,14 +1,41 @@ -import React, { useMemo } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import PerformanceResult from "./result-card/PerformanceResult"; import EnergyUsage from "./result-card/EnergyUsage"; import { Bar, Line, Pie } from "react-chartjs-2"; -import { useCompareProductDataStore } from "../../../store/builder/store"; +import { CompareProduct, useCompareProductDataStore } from "../../../store/builder/store"; import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore"; const ComparisonResult = () => { - const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); - const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); - const { mainProduct } = useMainProduct(); + const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); + const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); + const { mainProduct } = useMainProduct(); + const [comparedProducts, setComparedProducts] = useState<[CompareProduct, CompareProduct] | []>([]); + + useEffect(() => { + if (compareProductsData.length > 0 && mainProduct && comparisonProduct) { + const mainProductData = compareProductsData.find( + (product) => product.productUuid === mainProduct.productUuid + ); + const comparisonProductData = compareProductsData.find( + (product) => product.productUuid === comparisonProduct.productUuid + ); + + if (mainProductData && comparisonProductData) { + setComparedProducts([mainProductData, comparisonProductData]); + } else { + setComparedProducts([]); + } + } else { + setComparedProducts([]); + } + }, [compareProductsData, mainProduct, comparisonProduct]); + + useEffect(() => { + if (comparedProducts.length === 2) { + console.log(comparedProducts); + } + }, [comparedProducts]); + const options = useMemo( () => ({ responsive: true, @@ -30,11 +57,11 @@ const ComparisonResult = () => { const purpleLight = "#b19cd9"; const throughputData = { - labels: ["Layout 1", "Layout 2"], + labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName], datasets: [ { label: "Throughput (units/hr)", - data: [500, 550], + data: [comparedProducts[0]?.simulationData.throughputData, comparedProducts[1]?.simulationData.throughputData], backgroundColor: [purpleDark, purpleLight], borderColor: [purpleDark, purpleLight], borderWidth: 1, @@ -46,11 +73,11 @@ const ComparisonResult = () => { const cycleTimePieData = { - labels: ["Layout 1", "Layout 2"], + labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName], datasets: [ { label: "Cycle Time (sec)", - data: [120, 110], + data: [comparedProducts[0]?.simulationData.machineActiveTime, comparedProducts[1]?.simulationData.machineActiveTime], backgroundColor: [purpleDark, purpleLight], borderColor: "#fff", borderWidth: 2, @@ -59,11 +86,24 @@ const ComparisonResult = () => { }; const downtimeData = { - labels: ["Layout 1", "Layout 2"], + labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName], datasets: [ { label: "Downtime (mins)", - data: [17, 12], + data: [comparedProducts[0]?.simulationData.machineIdleTime, comparedProducts[1]?.simulationData.machineIdleTime], + backgroundColor: [purpleDark, purpleLight], + borderColor: "#fff", + borderWidth: 2, + }, + ], + }; + + const productionCapacityData = { + labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName], + datasets: [ + { + label: "Production Capacity (units)", + data: [comparedProducts[0]?.simulationData.productionCapacity, comparedProducts[1]?.simulationData.productionCapacity], backgroundColor: [purpleDark, purpleLight], borderColor: [purpleDark, purpleLight], borderWidth: 1, @@ -73,20 +113,21 @@ const ComparisonResult = () => { ], }; - const scrapRateData = { - labels: ["Layout 1", "Layout 2"], - datasets: [ - { - label: "Scrap Rate (tons)", - data: [2.7, 1.9], - backgroundColor: [purpleDark, purpleLight], - borderColor: [purpleDark, purpleLight], - borderWidth: 1, - borderRadius: 10, - borderSkipped: false, - }, - ], - }; + const highestProductivityProduct = (comparedProducts[0]?.simulationData?.productionCapacity ?? 0) > (comparedProducts[1]?.simulationData?.productionCapacity ?? 0) ? comparedProducts[0] : comparedProducts[1]; + + const product1CyclePercentage = (comparedProducts[0]?.simulationData?.machineActiveTime ?? 0) / + ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0)) * 100; + const product2CyclePercentage = ((comparedProducts[1]?.simulationData?.machineActiveTime ?? 0) / + ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100; + + const product1IdlePercentage = (comparedProducts[0]?.simulationData?.machineIdleTime ?? 0) / + ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0)) * 100; + const product2IdlePercentage = ((comparedProducts[1]?.simulationData?.machineIdleTime ?? 0) / + ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100; return (
@@ -97,12 +138,12 @@ const ComparisonResult = () => {

Throughput (units/hr)

-
Layout 1
-
500/ hr
+
{comparedProducts[0]?.productName}
+
{comparedProducts[0]?.simulationData.throughputData}/ hr
-
Layout 2
-
550/ hr
+
{comparedProducts[1]?.productName}
+
{comparedProducts[1]?.simulationData.throughputData}/ hr
@@ -115,17 +156,17 @@ const ComparisonResult = () => {
Cycle Time
-
Layout 1
-
120 Sec
+
{comparedProducts[0]?.productName}
+
{compareProductsData[0]?.simulationData.machineActiveTime} Sec
- 19.6% + {(100 - product1CyclePercentage).toFixed(2)}%
-
Layout 2
-
110 Sec
+
{comparedProducts[1]?.productName}
+
{compareProductsData[1]?.simulationData.machineActiveTime} Sec
- 1.6% + {(100 - product2CyclePercentage).toFixed(2)}%
@@ -135,6 +176,31 @@ const ComparisonResult = () => {
+
+
+
Overall Downtime
+
+
+
{comparedProducts[0]?.productName}
+
{compareProductsData[0]?.simulationData.machineIdleTime} Sec
+
+ {(100 - product1IdlePercentage).toFixed(2)}% +
+
+
+
{comparedProducts[1]?.productName}
+
{compareProductsData[1]?.simulationData.machineIdleTime} Sec
+
+ {(100 - product2IdlePercentage).toFixed(2)}% +
+
+
+
+
+ +
+
+{/*
Overall Downtime
@@ -152,18 +218,18 @@ const ComparisonResult = () => {
-
+
*/}
Production Capacity
-
Layout 1
-
Total scrap produced by
-
2.7 ton
+
{highestProductivityProduct?.productName}
+
Total product produced
+
{highestProductivityProduct?.simulationData.productionCapacity}
- +
diff --git a/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx b/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx index 93e80ec..efe6bc2 100644 --- a/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx +++ b/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx @@ -20,27 +20,32 @@ ChartJS.register( ); const EnergyUsage = () => { - const data = { - labels: ["Mon", "Tue", "Wed", "Thu", "Fri"], - datasets: [ - { - label: "Simulation 1", - data: [400, 600, 450, 1000, 1000], - borderColor: "#6a0dad", - fill: false, - tension: 0.5, // More curved line - pointRadius: 0, // Remove point indicators - }, - { - label: "Simulation 2", - data: [300, 500, 700, 950, 1100], - borderColor: "#b19cd9", - fill: false, - tension: 0.5, - pointRadius: 0, - }, - ], - }; + const data = useMemo(() => { + const randomizeData = () => + Array.from({ length: 5 }, () => Math.floor(Math.random() * (2000 - 300 + 1)) + 300); + + return { + labels: ["Mon", "Tue", "Wed", "Thu", "Fri"], + datasets: [ + { + label: "Simulation 1", + data: randomizeData(), + borderColor: "#6a0dad", + fill: false, + tension: 0.5, // More curved line + pointRadius: 0, // Remove point indicators + }, + { + label: "Simulation 2", + data: randomizeData(), + borderColor: "#b19cd9", + fill: false, + tension: 0.5, + pointRadius: 0, + }, + ], + }; + }, []); const options = useMemo( () => ({ diff --git a/app/src/modules/simulation/analysis/ROI/roiData.tsx b/app/src/modules/simulation/analysis/ROI/roiData.tsx index a633473..ef016d0 100644 --- a/app/src/modules/simulation/analysis/ROI/roiData.tsx +++ b/app/src/modules/simulation/analysis/ROI/roiData.tsx @@ -4,7 +4,6 @@ import { usePlayButtonStore } from '../../../../store/usePlayButtonStore'; import { useProductContext } from '../../products/productContext'; import { useProductStore } from '../../../../store/simulation/useProductStore'; - export default function ROIData() { const { selectedProductStore } = useProductContext(); const { inputValues } = useInputValues(); @@ -36,6 +35,7 @@ export default function ROIData() { const electricityCost = parseFloat(inputValues["Electricity cost"]); const fixedCost = parseFloat(inputValues["Fixed costs"]); const laborCost = parseFloat(inputValues["Labor Cost"]); + const laborCount = parseFloat(inputValues["Labor Count"]); const maintenanceCost = parseFloat(inputValues["Maintenance cost"]); const materialCost = parseFloat(inputValues["Material cost"]); const productionPeriod = parseFloat(inputValues["Production period"]); @@ -51,39 +51,101 @@ export default function ROIData() { !isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) { console.log('productionCapacityData: ', productionCapacityData); - const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear; - const annualProductionUnits = productionCapacityData * totalHoursPerYear; - const annualRevenue = annualProductionUnits * sellingPrice; + // const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear; + // const annualProductionUnits = productionCapacityData * totalHoursPerYear; + // const annualRevenue = annualProductionUnits * sellingPrice; - const totalMaterialCost = annualProductionUnits * materialCost; - const totalLaborCost = laborCost * totalHoursPerYear; - const totalEnergyCost = electricityCost * totalHoursPerYear; - const totalMaintenanceCost = maintenanceCost + fixedCost; - const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost; - const annualProfit = annualRevenue - totalAnnualCost; + // const totalMaterialCost = annualProductionUnits * materialCost; + // const totalLaborCost = laborCost * totalHoursPerYear; + // const totalEnergyCost = electricityCost * totalHoursPerYear; + // const totalMaintenanceCost = maintenanceCost + fixedCost; + // const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost; + // const annualProfit = annualRevenue - totalAnnualCost; - const netProfit = annualProfit * productionPeriod; - const roiPercentage = ((annualProfit + salvageValue - initialInvestment) / initialInvestment) * 100; - const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0 + // const netProfit = annualProfit * productionPeriod; + // const roiPercentage = ((annualProfit + salvageValue - initialInvestment) / initialInvestment) * 100; + // const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0 + + // setRoiSummaryData({ + // productName: selectedProduct.productName, + // roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)), + // paybackPeriod: parseFloat(paybackPeriod.toFixed(2)), + // totalCost: parseFloat(totalAnnualCost.toFixed(2)), + // revenueGenerated: parseFloat(annualRevenue.toFixed(2)), + // netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0, + // netLoss: netProfit < 0 ? -netProfit : 0 + // }); + + // const productCount = 1000; + // const costPerUnit = totalAnnualCost / annualProductionUnits; + // const costForTargetUnits = productCount * costPerUnit; + // const revenueForTargetUnits = productCount * sellingPrice; + // const profitForTargetUnits = revenueForTargetUnits - costForTargetUnits; + + // const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0; + // const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0; + + // const productData = getProductById(selectedProduct.productUuid); + // const prev = useCompareProductDataStore.getState().compareProductsData; + // const newData: CompareProduct = { + // productUuid: productData?.productUuid ?? '', + // productName: productData?.productName ?? '', + // simulationData: { + // // costPerUnit: parseFloat(costPerUnit.toFixed(2)), + // // workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)), + // // shiftLength: parseFloat(shiftLength.toFixed(2)), + // // shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)), + // roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)), + // // paybackPeriod: parseFloat(paybackPeriod.toFixed(2)), + // // totalCost: parseFloat(totalAnnualCost.toFixed(2)), + // // revenueGenerated: parseFloat(annualRevenue.toFixed(2)), + // netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0, + // productionCapacity: parseFloat(productionCapacityData.toFixed(2)), + // // netLoss: netProfit < 0 ? parseFloat((-netProfit).toFixed(2)) : 0, + // machineIdleTime: parseFloat(machineIdleTime.toFixed(2)), + // machineActiveTime: parseFloat(machineActiveTime.toFixed(2)), + // throughputData: throughputData, + // } + // }; + + // const existingIndex = prev.findIndex((item: CompareProduct) => + // item.productUuid === productData?.productUuid + // ); + + // if (existingIndex !== -1) { + // const updated = [...prev]; + // updated[existingIndex] = newData; + // setCompareProductsData(updated); + // } else { + // setCompareProductsData([...prev, newData]); + // } + + const Annual_units = throughputData * workingDaysPerYear + const Total_units = Annual_units * productionPeriod + + const Total_revenue = Total_units * sellingPrice + const Total_variable_cost = Total_units * (materialCost + (laborCost)) + + const Total_fixed_cost = (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear * productionPeriod + const Total_cost = Total_variable_cost + Total_fixed_cost + + const Net_profit = Total_revenue - Total_cost + (salvageValue * workingDaysPerYear * productionPeriod) + + const ROI = (Net_profit / initialInvestment) * 100 + + const Annual_net_profit = (Annual_units * (sellingPrice - materialCost - laborCost)) - (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear + (salvageValue * workingDaysPerYear) + const Payback_period_years = initialInvestment / Annual_net_profit; setRoiSummaryData({ productName: selectedProduct.productName, - roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)), - paybackPeriod: parseFloat(paybackPeriod.toFixed(2)), - totalCost: parseFloat(totalAnnualCost.toFixed(2)), - revenueGenerated: parseFloat(annualRevenue.toFixed(2)), - netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0, - netLoss: netProfit < 0 ? -netProfit : 0 + roiPercentage: ROI, + paybackPeriod: Payback_period_years, + totalCost: Total_cost, + revenueGenerated: Total_revenue, + netProfit: Net_profit > 0 ? Net_profit : 0, + netLoss: Net_profit < 0 ? -Net_profit : 0 }); - const productCount = 1000; - const costPerUnit = totalAnnualCost / annualProductionUnits; - const costForTargetUnits = productCount * costPerUnit; - const revenueForTargetUnits = productCount * sellingPrice; - const profitForTargetUnits = revenueForTargetUnits - costForTargetUnits; - - const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0; - const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0; const productData = getProductById(selectedProduct.productUuid); const prev = useCompareProductDataStore.getState().compareProductsData; @@ -91,18 +153,19 @@ export default function ROIData() { productUuid: productData?.productUuid ?? '', productName: productData?.productName ?? '', simulationData: { - // costPerUnit: parseFloat(costPerUnit.toFixed(2)), - // workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)), - // shiftLength: parseFloat(shiftLength.toFixed(2)), - // shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)), - roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)), - // paybackPeriod: parseFloat(paybackPeriod.toFixed(2)), - // totalCost: parseFloat(totalAnnualCost.toFixed(2)), - // revenueGenerated: parseFloat(annualRevenue.toFixed(2)), - netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0, - // netLoss: netProfit < 0 ? parseFloat((-netProfit).toFixed(2)) : 0, - machineIdleTime: parseFloat(machineIdleTime.toFixed(2)), - machineActiveTime: parseFloat(machineActiveTime.toFixed(2)), + // costPerUnit: costPerUnit, + // workingDaysPerYear: workingDaysPerYear, + // shiftLength: shiftLength, + // shiftsPerDay: shiftsPerDay, + roiPercentage: ROI, + // paybackPeriod: paybackPeriod, + // totalCost: totalAnnualCost, + // revenueGenerated: annualRevenue, + netProfit: Net_profit > 0 ? Net_profit : 0, + productionCapacity: productionCapacityData, + // netLoss: netProfit < 0 ? (-netProfit) : 0, + machineIdleTime: machineIdleTime, + machineActiveTime: machineActiveTime, throughputData: throughputData, } }; @@ -120,7 +183,7 @@ export default function ROIData() { } } - }, [inputValues, productionCapacityData, selectedProduct?.productUuid, isPlaying]); + }, [inputValues, productionCapacityData, throughputData, isPlaying]); useEffect(() => { console.log('compareProductsData: ', compareProductsData); diff --git a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx index ced9ddc..960a025 100644 --- a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx +++ b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx @@ -20,38 +20,15 @@ export default function ProductionCapacityData() { useEffect(() => { if (!inputValues || throughputData === undefined || !isPlaying) return; - console.log('throughputData: ', throughputData); - - const shiftLength = parseFloat(inputValues["Shift length"]); - console.log('shiftLength: ', shiftLength); - - const shiftsPerDay = parseFloat(inputValues["Shifts / day"]); - const workingDaysPerYear = parseFloat(inputValues["Working days / year"]); - const yieldRate = parseFloat(inputValues["Yield rate"]); + if (!isNaN(workingDaysPerYear) && throughputData > 0) { + const Monthly_working_days = workingDaysPerYear / 12; + const Production_capacity_per_month = throughputData * Monthly_working_days; + console.log('Production_capacity_per_month: ', Production_capacity_per_month); + console.log('throughputData: ', throughputData); - - if (!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && - !isNaN(yieldRate) && throughputData > 0) { - // Total units produced per day before yield - const dailyProduction = throughputData * shiftLength * shiftsPerDay; - - - // Units after applying yield rate - const goodUnitsPerDay = dailyProduction * (yieldRate / 100); - - - // Annual output - const annualProduction = goodUnitsPerDay * workingDaysPerYear; - - - // Final production capacity per hour (after yield) - const productionPerHour = throughputData * (yieldRate / 100); - - - // Set the final capacity (units/hour) - setProductionCapacityData(Number(productionPerHour.toFixed(2))); + setProductionCapacityData(Number(Production_capacity_per_month.toFixed(2))); } }, [throughputData, inputValues, isPlaying]); diff --git a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx index 72189e0..ccda49c 100644 --- a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx +++ b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { useProductStore } from '../../../../store/simulation/useProductStore'; import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences'; -import { useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store'; +import { useInputValues, useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store'; import { usePlayButtonStore } from '../../../../store/usePlayButtonStore'; import { useSceneContext } from '../../../scene/sceneContext'; import { useProductContext } from '../../products/productContext'; @@ -25,6 +25,7 @@ export default function ThroughPutData() { const { setProcessBar } = useProcessBar(); const { setThroughputData } = useThroughPutData() const { isPlaying } = usePlayButtonStore(); + const { inputValues } = useInputValues(); // Setting machine count let totalItems = 0; @@ -212,13 +213,17 @@ export default function ThroughPutData() { }, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid]) useEffect(() => { - if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0 && isPlaying) { - const utilization = machineActiveTime / 3600; // Active time per hour - const unitsPerMachinePerHour = 3600 / materialCycleTime; - const throughput = unitsPerMachinePerHour * machineCount * utilization; - setThroughputData(Number(throughput.toFixed(2))); // Keep as number + const shiftLength = parseFloat(inputValues["Shift length"]); + const shiftsPerDay = parseFloat(inputValues["Shifts / day"]); + const yieldRate = parseFloat(inputValues["Yield rate"]); + + if (shiftLength > 0 && materialCycleTime > 0 && machineCount > 0 && isPlaying) { + const Units_per_shift = (shiftLength * 60) / (materialCycleTime / 60); + + const Throughput_per_day = Units_per_shift * shiftsPerDay * (yieldRate / 100); + setThroughputData(Number(Throughput_per_day.toFixed(2))); // Keep as number } - }, [machineActiveTime, materialCycleTime, machineCount, selectedProduct?.productUuid, isPlaying]); + }, [materialCycleTime, machineCount, isPlaying, inputValues]); return ( <> diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 9952888..6eb41a3 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -48,7 +48,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) const computePath = useCallback( (start: any, end: any) => { - console.log('end: ', end); try { const navMeshQuery = new NavMeshQuery(navMesh); const { path: segmentPath } = navMeshQuery.computePath(start, end); @@ -57,7 +56,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) && Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z) ) { - console.log('if ', segmentPath); return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || []; } else { console.log("There is no path here...Choose valid path") diff --git a/app/src/store/builder/store.ts b/app/src/store/builder/store.ts index eba4c47..09a5690 100644 --- a/app/src/store/builder/store.ts +++ b/app/src/store/builder/store.ts @@ -726,6 +726,7 @@ export interface CompareProduct { // totalCost: number; // revenueGenerated: number; netProfit: number; + productionCapacity: number; // netLoss: number; machineIdleTime: number; machineActiveTime: number; diff --git a/app/src/styles/components/simulation/simulation.scss b/app/src/styles/components/simulation/simulation.scss index 403d7ee..302ad7a 100644 --- a/app/src/styles/components/simulation/simulation.scss +++ b/app/src/styles/components/simulation/simulation.scss @@ -64,13 +64,14 @@ .production-details { .production-wrapper { display: flex; - align-items: center; + // align-items: center; flex-direction: column; gap: 6px; .header { display: flex; flex-direction: row; + justify-content: start; gap: 6px; } From a0605dea28481641956feb078838926bfff155ae Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 12 Jun 2025 16:58:34 +0530 Subject: [PATCH 08/10] fix: exclude commentHolder from intersection checks in CommentsGroup --- app/src/modules/collaboration/comments/commentsGroup.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/modules/collaboration/comments/commentsGroup.tsx b/app/src/modules/collaboration/comments/commentsGroup.tsx index e1721ad..92dfce3 100644 --- a/app/src/modules/collaboration/comments/commentsGroup.tsx +++ b/app/src/modules/collaboration/comments/commentsGroup.tsx @@ -49,6 +49,7 @@ function CommentsGroup() { !intersect.object.name.includes("zonePlane") && !intersect.object.name.includes("SelectionGroup") && !intersect.object.name.includes("selectionAssetGroup") && + !intersect.object.name.includes("commentHolder") && !intersect.object.name.includes("SelectionGroupBoundingBoxLine") && !intersect.object.name.includes("SelectionGroupBoundingBox") && !intersect.object.name.includes("SelectionGroupBoundingLine") && @@ -76,11 +77,13 @@ function CommentsGroup() { !intersect.object.name.includes("zonePlane") && !intersect.object.name.includes("SelectionGroup") && !intersect.object.name.includes("selectionAssetGroup") && + !intersect.object.name.includes("commentHolder") && !intersect.object.name.includes("SelectionGroupBoundingBoxLine") && !intersect.object.name.includes("SelectionGroupBoundingBox") && !intersect.object.name.includes("SelectionGroupBoundingLine") && intersect.object.type !== "GridHelper" ); + console.log('intersects: ', intersects); if (intersects.length > 0) { const position = new Vector3(intersects[0].point.x, Math.max(intersects[0].point.y, 0), intersects[0].point.z); From 999c6e65598c232297bad4091e262e266c5835f6 Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Thu, 12 Jun 2025 17:10:29 +0530 Subject: [PATCH 09/10] fix: clean up imports and remove console log in DashboardHome; add project update logic in Scene --- app/src/app.tsx | 3 +- .../components/Dashboard/DashboardHome.tsx | 1 - app/src/modules/scene/scene.tsx | 70 +++++++++++++++++-- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/app/src/app.tsx b/app/src/app.tsx index b03d4df..6aa1547 100644 --- a/app/src/app.tsx +++ b/app/src/app.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from "react"; import { Cache } from "three"; -import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import { BrowserRouter as Router, Routes, Route, useParams } from "react-router-dom"; import Dashboard from "./pages/Dashboard"; import Project from "./pages/Project"; import UserAuth from "./pages/UserAuth"; @@ -14,6 +14,7 @@ const App: React.FC = () => { Cache.enabled = true; }, []); + return ( diff --git a/app/src/components/Dashboard/DashboardHome.tsx b/app/src/components/Dashboard/DashboardHome.tsx index e82c474..2dc271b 100644 --- a/app/src/components/Dashboard/DashboardHome.tsx +++ b/app/src/components/Dashboard/DashboardHome.tsx @@ -116,7 +116,6 @@ const DashboardHome: React.FC = () => { const renderProjects = () => { const projectList = recentProjects[Object.keys(recentProjects)[0]]; - console.log('projectList: ', projectList); if (!projectList?.length) { return
No recent projects found
; } diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 7777a30..ee47596 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -1,6 +1,5 @@ -import { useMemo } from "react"; +import { useEffect, useMemo } from "react"; import { Canvas } from "@react-three/fiber"; -import { Color } from "three"; import { KeyboardControls } from "@react-three/drei"; import { SceneProvider } from "./sceneContext"; @@ -9,6 +8,12 @@ import Visualization from "../visualization/visualization"; import Setup from "./setup/setup"; import Simulation from "../simulation/simulation"; import Collaboration from "../collaboration/collaboration"; +import useModuleStore from "../../store/useModuleStore"; +import { useParams } from "react-router-dom"; +import { getAllProjects } from "../../services/dashboard/getAllProjects"; +import { getUserData } from "../../components/Dashboard/functions/getUserData"; +import { useLoadingProgress, useSocketStore } from "../../store/builder/store"; +import { useAssetsStore } from "../../store/builder/useAssetStore"; export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Comparison Layout' }) { const map = useMemo(() => [ @@ -17,19 +22,76 @@ export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Co { name: "left", keys: ["ArrowLeft", "a", "A"] }, { name: "right", keys: ["ArrowRight", "d", "D"] }, ], []); + const { assets } = useAssetsStore(); + const { userId, organization } = getUserData(); + const { activeModule } = useModuleStore(); + const { projectId } = useParams(); + const { projectSocket } = useSocketStore(); + const { loadingProgress } = useLoadingProgress(); + const handleUpdatingProject = async () => { + if (!projectId) return; + try { + const projects = await getAllProjects(userId, organization); + let projectUuid = projects.Projects.find( + (val: any) => val.projectUuid === projectId || val._id === projectId + ); + + + if (activeModule === "builder" && loadingProgress !== 1) { + const canvas = + document.getElementById("sceneCanvas")?.children[0]?.children[0]; + const screenshotDataUrl = (canvas as HTMLCanvasElement)?.toDataURL("image/png"); + setTimeout(() => { + const updateProjects = { + projectId: projectUuid, + organization, + userId, + projectName: projectUuid.projectName, + thumbnail: screenshotDataUrl, + }; + if (projectSocket) { + projectSocket.emit("v1:project:update", updateProjects); + } + }, 8000); + } else { + const canvas = + document.getElementById("sceneCanvas")?.children[0]?.children[0]; + const screenshotDataUrl = (canvas as HTMLCanvasElement)?.toDataURL("image/png"); + const updateProjects = { + projectId: projectUuid, + organization, + userId, + projectName: projectUuid.projectName, + thumbnail: screenshotDataUrl, + }; + // console.log('screenshotDataUrl: ', screenshotDataUrl); + // console.log('updateProjects: ', updateProjects); + if (projectSocket) { + projectSocket.emit("v1:project:update", updateProjects); + } + } + + } catch (error) { } + }; + useEffect(() => { + handleUpdatingProject() + }, [activeModule, assets, loadingProgress]) return ( { e.preventDefault(); }} onCreated={(e) => { - e.scene.background = new Color(0x19191d); + e.scene.background = null; }} + gl={{ powerPreference: "high-performance", antialias: true, preserveDrawingBuffer: true }} > From 064de39eaca6b1a639b1b75a81067664f7b57780 Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Thu, 12 Jun 2025 17:17:16 +0530 Subject: [PATCH 10/10] feat: update simulation data structure and improve performance metrics display --- .../layout/scenes/ComparisonScene.tsx | 38 ++++++++++--------- app/src/components/ui/analysis/ROISummary.tsx | 4 +- .../ui/analysis/ThroughputSummary.tsx | 2 +- .../ui/compareVersion/ComparisonResult.tsx | 4 +- .../result-card/PerformanceResult.tsx | 21 +++++----- .../simulation/analysis/ROI/roiData.tsx | 5 ++- .../productionCapacityData.tsx | 6 +-- .../analysis/throughPut/throughPutData.tsx | 2 +- app/src/pages/UserAuth.tsx | 8 ++-- app/src/store/builder/store.ts | 1 + 10 files changed, 48 insertions(+), 43 deletions(-) diff --git a/app/src/components/layout/scenes/ComparisonScene.tsx b/app/src/components/layout/scenes/ComparisonScene.tsx index 6b7cad0..ce8e455 100644 --- a/app/src/components/layout/scenes/ComparisonScene.tsx +++ b/app/src/components/layout/scenes/ComparisonScene.tsx @@ -31,27 +31,29 @@ function ComparisonScene() { // useEffect(() => { // setCompareProductsData([ // { - // productUuid: "15193386-ec58-4ec6-8a92-e665a39eebf1", - // productName: "Product 1", - // simulationData: { - // roiPercentage: 65.54, - // netProfit: 499037750, - // machineIdleTime: 1024, - // machineActiveTime: 235, - // productionCapacity: 1000, - // throughputData: 62.42 + // "productUuid": "15193386-ec58-4ec6-8a92-e665a39eebf1", + // "productName": "Product 1", + // "simulationData": { + // "roiPercentage": 273.9428571428571, + // "paybackPeriod": 1.8251981643721318, + // "netProfit": 9588000, + // "productionCapacity": 4508.5, + // "machineIdleTime": 1450, + // "machineActiveTime": 430, + // "throughputData": 180.34 // } // }, // { - // productUuid: "f614bf50-f61d-41c5-acc0-3783fb4da6b8", - // productName: "Product 2", - // simulationData: { - // roiPercentage: 169.99, - // netProfit: 1282397750, - // machineIdleTime: 1897, - // machineActiveTime: 653, - // productionCapacity: 2000, - // throughputData: 157.03 + // "productUuid": "f614bf50-f61d-41c5-acc0-3783fb4da6b8", + // "productName": "Product 2", + // "simulationData": { + // "roiPercentage": 281.7214285714286, + // "paybackPeriod": 1.7748028701097842, + // "netProfit": 9860250, + // "productionCapacity": 4599.25, + // "machineIdleTime": 1885, + // "machineActiveTime": 646, + // "throughputData": 183.97 // } // } // ]) diff --git a/app/src/components/ui/analysis/ROISummary.tsx b/app/src/components/ui/analysis/ROISummary.tsx index 3a0a570..5e52cc0 100644 --- a/app/src/components/ui/analysis/ROISummary.tsx +++ b/app/src/components/ui/analysis/ROISummary.tsx @@ -99,9 +99,9 @@ const ROISummary = ({ function getPaybackDateFromYears(yearsToAdd: number) { const now = new Date(); - console.log('yearsToAdd: ', yearsToAdd); + const totalMonths = Math.round(yearsToAdd * 12); - console.log('totalMonths: ', totalMonths); + const paybackDate = new Date(now.getFullYear(), now.getMonth() + totalMonths, now.getDate()); const month = paybackDate.toLocaleString("en-GB", { month: "long" }); const year = paybackDate.getFullYear(); diff --git a/app/src/components/ui/analysis/ThroughputSummary.tsx b/app/src/components/ui/analysis/ThroughputSummary.tsx index 304c651..52fa9f4 100644 --- a/app/src/components/ui/analysis/ThroughputSummary.tsx +++ b/app/src/components/ui/analysis/ThroughputSummary.tsx @@ -55,7 +55,7 @@ const ProductionCapacity = ({ <>
- {(Units_per_hour).toFixed(2)} Units/hour + {(Units_per_hour).toFixed(2) === "Infinity"? 0 : (Units_per_hour).toFixed(2) } Units/hour
{/* Dynamic Progress Bar */} diff --git a/app/src/components/ui/compareVersion/ComparisonResult.tsx b/app/src/components/ui/compareVersion/ComparisonResult.tsx index caec3b4..4ce4467 100644 --- a/app/src/components/ui/compareVersion/ComparisonResult.tsx +++ b/app/src/components/ui/compareVersion/ComparisonResult.tsx @@ -32,7 +32,7 @@ const ComparisonResult = () => { useEffect(() => { if (comparedProducts.length === 2) { - console.log(comparedProducts); + } }, [comparedProducts]); @@ -234,7 +234,7 @@ const ComparisonResult = () => {
- + { comparedProducts.length === 2 &&}
); diff --git a/app/src/components/ui/compareVersion/result-card/PerformanceResult.tsx b/app/src/components/ui/compareVersion/result-card/PerformanceResult.tsx index f21d573..b0a94c2 100644 --- a/app/src/components/ui/compareVersion/result-card/PerformanceResult.tsx +++ b/app/src/components/ui/compareVersion/result-card/PerformanceResult.tsx @@ -5,7 +5,8 @@ import { TickIcon, } from "../../../icons/ExportCommonIcons"; -const PerformanceResult = () => { +const PerformanceResult = ({ comparedProducts }: any) => { + const ProfitProduct = comparedProducts[0].simulationData.netProfit > comparedProducts[1].simulationData.netProfit ? comparedProducts[0] : comparedProducts[1]; return (
@@ -26,30 +27,30 @@ const PerformanceResult = () => {
98%
-
Environmental impact
+
Net Profit
-
Waste generation
+
ROI Percentage
-
I
-
0.5%
+
+
{ProfitProduct.simulationData.roiPercentage.toFixed(2)}
-
Risk 
management
+
Payback Period
-
I
-
0.1%
+
+
{ProfitProduct.simulationData.netProfit}
-
I
-
0.5%
+
+
{parseFloat(ProfitProduct.simulationData.paybackPeriod.toFixed(2))}years
diff --git a/app/src/modules/simulation/analysis/ROI/roiData.tsx b/app/src/modules/simulation/analysis/ROI/roiData.tsx index ef016d0..2a26f8d 100644 --- a/app/src/modules/simulation/analysis/ROI/roiData.tsx +++ b/app/src/modules/simulation/analysis/ROI/roiData.tsx @@ -49,7 +49,7 @@ export default function ROIData() { if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) && !isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) && !isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) { - console.log('productionCapacityData: ', productionCapacityData); + // const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear; // const annualProductionUnits = productionCapacityData * totalHoursPerYear; @@ -158,6 +158,7 @@ export default function ROIData() { // shiftLength: shiftLength, // shiftsPerDay: shiftsPerDay, roiPercentage: ROI, + paybackPeriod: Payback_period_years, // paybackPeriod: paybackPeriod, // totalCost: totalAnnualCost, // revenueGenerated: annualRevenue, @@ -186,7 +187,7 @@ export default function ROIData() { }, [inputValues, productionCapacityData, throughputData, isPlaying]); useEffect(() => { - console.log('compareProductsData: ', compareProductsData); + }, [compareProductsData]) return null; diff --git a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx index 960a025..888a519 100644 --- a/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx +++ b/app/src/modules/simulation/analysis/productionCapacity/productionCapacityData.tsx @@ -13,7 +13,7 @@ export default function ProductionCapacityData() { useEffect(() => { if (!isPlaying) { - console.log('isPlaying: ', isPlaying); + setProductionCapacityData(0); } }, [isPlaying]); @@ -25,8 +25,8 @@ export default function ProductionCapacityData() { if (!isNaN(workingDaysPerYear) && throughputData > 0) { const Monthly_working_days = workingDaysPerYear / 12; const Production_capacity_per_month = throughputData * Monthly_working_days; - console.log('Production_capacity_per_month: ', Production_capacity_per_month); - console.log('throughputData: ', throughputData); + + setProductionCapacityData(Number(Production_capacity_per_month.toFixed(2))); } diff --git a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx index ccda49c..87655cd 100644 --- a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx +++ b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx @@ -180,7 +180,7 @@ export default function ThroughPutData() { } const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive; - if (allInactive && materials.length === 0 && materialHistory.length > 0) { + if (materials.length >= 0 && materialHistory.length > 0) { let totalCycleTimeSum = 0; let cycleCount = 0; diff --git a/app/src/pages/UserAuth.tsx b/app/src/pages/UserAuth.tsx index 6ec0036..9ecc018 100644 --- a/app/src/pages/UserAuth.tsx +++ b/app/src/pages/UserAuth.tsx @@ -43,7 +43,7 @@ const UserAuth: React.FC = () => { const organization = email.split("@")[1].split(".")[0]; try { const res = await signInApi(email, password, organization, fingerprint); - console.log('res: ', res); + // console.log('res: ', res); if (res.message.message === "login successfull") { setError(""); setOrganization(organization); @@ -56,10 +56,10 @@ const UserAuth: React.FC = () => { localStorage.setItem("refreshToken", res.message.refreshToken); try { - console.log('res.message.userId: ', res.message.userId); - console.log('organization: ', organization); + // console.log('res.message.userId: ', res.message.userId); + // console.log('organization: ', organization); const projects = await recentlyViewed(organization, res.message.userId); - console.log('projects: ', projects); + // console.log('projects: ', projects); if (res.message.isShare) { if (Object.values(projects.RecentlyViewed).length > 0) { diff --git a/app/src/store/builder/store.ts b/app/src/store/builder/store.ts index 09a5690..890a0e8 100644 --- a/app/src/store/builder/store.ts +++ b/app/src/store/builder/store.ts @@ -727,6 +727,7 @@ export interface CompareProduct { // revenueGenerated: number; netProfit: number; productionCapacity: number; + paybackPeriod: number; // netLoss: number; machineIdleTime: number; machineActiveTime: number;