Merge remote-tracking branch 'origin/v3-refactor' into v3

This commit is contained in:
Jerald-Golden-B 2025-06-12 17:17:34 +05:30
commit 0cde60fa76
15 changed files with 355 additions and 185 deletions

View File

@ -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,37 @@ function ComparisonScene() {
setComparisonProduct(product.productUuid, product.productName);
}
};
// useEffect(() => {
// setCompareProductsData([
// {
// "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": 281.7214285714286,
// "paybackPeriod": 1.7748028701097842,
// "netProfit": 9860250,
// "productionCapacity": 4599.25,
// "machineIdleTime": 1885,
// "machineActiveTime": 646,
// "throughputData": 183.97
// }
// }
// ])
// }, []); // ✅ Runs only once on mount
useEffect(() => {
if (mainProduct && comparisonProduct && compareProductsData.length > 1) {
@ -45,8 +75,6 @@ function ComparisonScene() {
}
}, [compareProductsData, mainProduct, comparisonProduct]);
return (
<>
{isVersionSaved && activeModule === "simulation" && selectedProduct && (

View File

@ -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",

View File

@ -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 = () => {
<div className="process-container">
<div className="throughput-value">
<span className="value">{productionCapacityData}</span>{" "}
Units/hour
Units/Month
</div>
<div className="lineChart">
<div className="assetUsage">

View File

@ -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();
const totalMonths = Math.round(yearsToAdd * 12);
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 = ({
<SonarCrownIcon />
<div className="icon"></div>
<div className="info">
<span>{roiSummary.roiPercentage}% </span>
ROI
<span>{roiSummary.roiPercentage.toFixed(2)}% </span>
ROI in the period of {productionPeriod} years
<span></span>
</div>
</div>
<div className="roi-details">
<div className="progress-wrapper">
<SemiCircleProgress />
<SemiCircleProgress
progress={(parseFloat(roiSummary.paybackPeriod.toFixed(2)) / (productionPeriod)) * 100}
years={parseFloat(roiSummary.paybackPeriod.toFixed(2))}
/>
<div className="content">
you're on track to hit it by
<div className="key">July 2029</div>
<div className="key">{getPaybackDateFromYears(roiSummary.paybackPeriod)}</div>
</div>
</div>
<div className="metrics">
<div className="metric-wrapper">
<div className="metric-item">
<span className="metric-label">Total Cost Incurred</span>
<span className="metric-value">
<span></span>
{roiSummary.totalCost}
{roiSummary.totalCost.toFixed(0)}
</span>
</div>
<div className="metric-item">
@ -148,7 +165,7 @@ const ROISummary = ({
<span className="metric-value">
<span></span>
{roiSummary.revenueGenerated}
{roiSummary.revenueGenerated.toFixed(0)}
</span>
</div>
</div>
@ -162,8 +179,8 @@ const ROISummary = ({
<div className="metric-value">
<span></span>
{roiSummary.netProfit > 0
? roiSummary.netProfit
: roiSummary.netLoss}
? roiSummary.netProfit.toFixed(0)
: roiSummary.netLoss.toFixed(0)}
</div>
</div>
</div>

View File

@ -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 && <div className="throughtputSummary-container analysis-card">
<div className="throughtputSummary-wrapper analysis-card-wrapper">
<div className="card-header">
@ -54,8 +55,7 @@ const ProductionCapacity = ({
<>
<div className="process-container">
<div className="throughput-value">
<span className="value">{throughputData}</span> Units/hour
<span className="value">{(Units_per_hour).toFixed(2) === "Infinity"? 0 : (Units_per_hour).toFixed(2) }</span> Units/hour
</div>
{/* Dynamic Progress Bar */}

View File

@ -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 [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) {
}
}, [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 (
<div className="compare-result-container">
@ -97,12 +138,12 @@ const ComparisonResult = () => {
<h4>Throughput (units/hr)</h4>
<div className="layers-wrapper">
<div className="layer-wrapper">
<div className="key">Layout 1</div>
<div className="value">500/ hr</div>
<div className="key">{comparedProducts[0]?.productName}</div>
<div className="value">{comparedProducts[0]?.simulationData.throughputData}/ hr</div>
</div>
<div className="layer-wrapper">
<div className="key">Layout 2</div>
<div className="value">550/ hr</div>
<div className="key">{comparedProducts[1]?.productName}</div>
<div className="value">{comparedProducts[1]?.simulationData.throughputData}/ hr</div>
</div>
<div className="chart">
<Bar data={throughputData} options={options} />
@ -115,17 +156,17 @@ const ComparisonResult = () => {
<div className="cycle-header">Cycle Time</div>
<div className="layers-wrapper">
<div className="layers">
<div className="layer-name">Layout 1</div>
<div className="layer-time">120 Sec</div>
<div className="layer-name">{comparedProducts[0]?.productName}</div>
<div className="layer-time">{compareProductsData[0]?.simulationData.machineActiveTime} Sec</div>
<div className="layer-profit">
<span></span>19.6%
<span></span>{(100 - product1CyclePercentage).toFixed(2)}%
</div>
</div>
<div className="layers">
<div className="layer-name">Layout 2</div>
<div className="layer-time">110 Sec</div>
<div className="layer-name">{comparedProducts[1]?.productName}</div>
<div className="layer-time">{compareProductsData[1]?.simulationData.machineActiveTime} Sec</div>
<div className="layer-profit">
<span></span>1.6%
<span></span>{(100 - product2CyclePercentage).toFixed(2)}%
</div>
</div>
</div>
@ -135,6 +176,31 @@ const ComparisonResult = () => {
</div>
</div>
<div className="cycle-time-container comparisionCard">
<div className="cycle-main">
<div className="cycle-header">Overall Downtime</div>
<div className="layers-wrapper">
<div className="layers">
<div className="layer-name">{comparedProducts[0]?.productName}</div>
<div className="layer-time">{compareProductsData[0]?.simulationData.machineIdleTime} Sec</div>
<div className="layer-profit">
<span></span>{(100 - product1IdlePercentage).toFixed(2)}%
</div>
</div>
<div className="layers">
<div className="layer-name">{comparedProducts[1]?.productName}</div>
<div className="layer-time">{compareProductsData[1]?.simulationData.machineIdleTime} Sec</div>
<div className="layer-profit">
<span></span>{(100 - product2IdlePercentage).toFixed(2)}%
</div>
</div>
</div>
</div>
<div className="chart">
<Pie data={downtimeData} options={options} />
</div>
</div>
{/*
<div className="overallDowntime-container comparisionCard">
<div className="overallDowntime-header">Overall Downtime</div>
<div className="totalDownTime-wrapper">
@ -152,23 +218,23 @@ const ComparisonResult = () => {
<Bar data={downtimeData} options={options} />
</div>
</div>
</div>
</div> */}
<div className="overallScrapRate comparisionCard">
<div className="overallScrapRate-header">Production Capacity</div>
<div className="overallScrapRate-wrapper">
<div className="overallScrapRate-value">
<div className="overallScrapRate-label">Layout 1</div>
<div className="overallScrapRate-key">Total scrap produced by</div>
<div className="overallScrapRateKey-value">2.7 ton</div>
<div className="overallScrapRate-label">{highestProductivityProduct?.productName}</div>
<div className="overallScrapRate-key">Total product produced</div>
<div className="overallScrapRateKey-value">{highestProductivityProduct?.simulationData.productionCapacity}</div>
</div>
<div className="chart">
<Bar data={scrapRateData} options={options} />
<Bar data={productionCapacityData} options={options} />
</div>
</div>
</div>
<PerformanceResult />
{ comparedProducts.length === 2 &&<PerformanceResult comparedProducts={comparedProducts}/>}
</div>
</div>
);

View File

@ -20,12 +20,16 @@ ChartJS.register(
);
const EnergyUsage = () => {
const data = {
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: [400, 600, 450, 1000, 1000],
data: randomizeData(),
borderColor: "#6a0dad",
fill: false,
tension: 0.5, // More curved line
@ -33,7 +37,7 @@ const EnergyUsage = () => {
},
{
label: "Simulation 2",
data: [300, 500, 700, 950, 1100],
data: randomizeData(),
borderColor: "#b19cd9",
fill: false,
tension: 0.5,
@ -41,6 +45,7 @@ const EnergyUsage = () => {
},
],
};
}, []);
const options = useMemo(
() => ({

View File

@ -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 (
<div className="performanceResult-wrapper comparisionCard">
<div className="header">
@ -26,30 +27,30 @@ const PerformanceResult = () => {
</div>
<div className="metric-value">98%</div>
</div>
<div className="label">Environmental impact</div>
<div className="label">Net Profit</div>
</div>
<div className="metrics-right">
<div className="metric-wrapper">
<div className="metric-label">Waste generation</div>
<div className="metric-label">ROI Percentage</div>
<div className="metric">
<div className="metric-icon">I</div>
<div className="metric-value">0.5%</div>
<div className="metric-icon"></div>
<div className="metric-value">{ProfitProduct.simulationData.roiPercentage.toFixed(2)}</div>
</div>
</div>
<div className="metric-wrapper">
<div className="metric-label">Risk management</div>
<div className="metric-label">Payback Period</div>
<div className="metric">
<div className="metric-icon">I</div>
<div className="metric-value">0.1%</div>
<div className="metric-icon"></div>
<div className="metric-value">{ProfitProduct.simulationData.netProfit}</div>
</div>
</div>
<div className="metric-wrapper">
<div className="metric">
<div className="metric-icon">I</div>
<div className="metric-value">0.5%</div>
<div className="metric-icon"></div>
<div className="metric-value">{parseFloat(ProfitProduct.simulationData.paybackPeriod.toFixed(2))}years</div>
</div>
</div>
</div>

View File

@ -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"]);
@ -49,41 +49,103 @@ 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;
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 totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear;
// const annualProductionUnits = productionCapacityData * totalHoursPerYear;
// const annualRevenue = annualProductionUnits * sellingPrice;
const netProfit = annualProfit * productionPeriod;
const roiPercentage = ((annualProfit + salvageValue - initialInvestment) / initialInvestment) * 100;
const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0
// 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
// 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,20 @@ 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: Payback_period_years,
// 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,10 +184,10 @@ export default function ROIData() {
}
}
}, [inputValues, productionCapacityData, selectedProduct?.productUuid, isPlaying]);
}, [inputValues, productionCapacityData, throughputData, isPlaying]);
useEffect(() => {
console.log('compareProductsData: ', compareProductsData);
}, [compareProductsData])
return null;

View File

@ -13,45 +13,22 @@ export default function ProductionCapacityData() {
useEffect(() => {
if (!isPlaying) {
console.log('isPlaying: ', isPlaying);
setProductionCapacityData(0);
}
}, [isPlaying]);
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;
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]);

View File

@ -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;
@ -179,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;
@ -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 (
<>

View File

@ -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")

View File

@ -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) {

View File

@ -726,6 +726,8 @@ export interface CompareProduct {
// totalCost: number;
// revenueGenerated: number;
netProfit: number;
productionCapacity: number;
paybackPeriod: number;
// netLoss: number;
machineIdleTime: number;
machineActiveTime: number;

View File

@ -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;
}