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.
This commit is contained in:
parent
8c8b81989c
commit
b350bc6d9e
|
@ -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 && (
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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 = ({
|
|||
<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>
|
||||
|
|
|
@ -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)}</span> Units/hour
|
||||
</div>
|
||||
|
||||
{/* Dynamic Progress Bar */}
|
||||
|
|
|
@ -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) {
|
||||
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 (
|
||||
<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,18 +218,18 @@ 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>
|
||||
|
|
|
@ -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(
|
||||
() => ({
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -726,6 +726,7 @@ export interface CompareProduct {
|
|||
// totalCost: number;
|
||||
// revenueGenerated: number;
|
||||
netProfit: number;
|
||||
productionCapacity: number;
|
||||
// netLoss: number;
|
||||
machineIdleTime: number;
|
||||
machineActiveTime: number;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue