Merge remote-tracking branch 'origin/v3-refactor' into v3
This commit is contained in:
commit
da0961d50e
|
@ -1292,8 +1292,8 @@ export const PerformanceIcon = () => {
|
||||||
<path
|
<path
|
||||||
d="M11.1484 1.16797C16.2895 1.16797 20.4921 5.3714 20.4922 10.5117C20.4922 12.7821 19.6669 14.8349 18.3467 16.4316L18.1807 16.2656C19.3378 14.8012 20.1179 12.9631 20.2236 10.9746L20.2354 10.5107C20.2364 9.46665 20.0573 8.43143 19.707 7.4502L19.5469 7.03223C19.1476 6.06682 18.5848 5.17876 17.8848 4.40625L17.5771 4.08301C16.733 3.23884 15.7302 2.56951 14.627 2.11328C13.524 1.65716 12.342 1.42257 11.1484 1.42383C10.1041 1.42277 9.06837 1.60175 8.08691 1.95215L7.66992 2.11328C6.70451 2.51257 5.81644 3.07536 5.04395 3.77539L4.71973 4.08398C3.98113 4.8228 3.37584 5.68237 2.93066 6.625L2.75 7.03418C2.3509 7.99977 2.12214 9.02598 2.07227 10.0674L2.06152 10.5127C2.06152 12.7338 2.80096 14.7019 4.10059 16.2803L3.93652 16.4443C2.58335 14.8587 1.80469 12.8058 1.80469 10.5117C1.80479 5.37146 6.00742 1.16807 11.1484 1.16797ZM10.8008 11.2383L10.3887 10.8076L13.8027 7.81543L10.8008 11.2383Z"
|
d="M11.1484 1.16797C16.2895 1.16797 20.4921 5.3714 20.4922 10.5117C20.4922 12.7821 19.6669 14.8349 18.3467 16.4316L18.1807 16.2656C19.3378 14.8012 20.1179 12.9631 20.2236 10.9746L20.2354 10.5107C20.2364 9.46665 20.0573 8.43143 19.707 7.4502L19.5469 7.03223C19.1476 6.06682 18.5848 5.17876 17.8848 4.40625L17.5771 4.08301C16.733 3.23884 15.7302 2.56951 14.627 2.11328C13.524 1.65716 12.342 1.42257 11.1484 1.42383C10.1041 1.42277 9.06837 1.60175 8.08691 1.95215L7.66992 2.11328C6.70451 2.51257 5.81644 3.07536 5.04395 3.77539L4.71973 4.08398C3.98113 4.8228 3.37584 5.68237 2.93066 6.625L2.75 7.03418C2.3509 7.99977 2.12214 9.02598 2.07227 10.0674L2.06152 10.5127C2.06152 12.7338 2.80096 14.7019 4.10059 16.2803L3.93652 16.4443C2.58335 14.8587 1.80469 12.8058 1.80469 10.5117C1.80479 5.37146 6.00742 1.16807 11.1484 1.16797ZM10.8008 11.2383L10.3887 10.8076L13.8027 7.81543L10.8008 11.2383Z"
|
||||||
stroke="url(#paint0_linear_1736_988)"
|
stroke="url(#paint0_linear_1736_988)"
|
||||||
stroke-width="1.80917"
|
strokeWidth="1.80917"
|
||||||
stroke-linecap="round"
|
strokeLinecap="round"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient
|
<linearGradient
|
||||||
|
@ -1304,8 +1304,8 @@ export const PerformanceIcon = () => {
|
||||||
y2="17.742"
|
y2="17.742"
|
||||||
gradientUnits="userSpaceOnUse"
|
gradientUnits="userSpaceOnUse"
|
||||||
>
|
>
|
||||||
<stop stop-color="#6F42C1" />
|
<stop stopColor="#6F42C1" />
|
||||||
<stop offset="1" stop-color="#B392F0" />
|
<stop offset="1" stopColor="#B392F0" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -1328,9 +1328,9 @@ export const GreenTickIcon = () => {
|
||||||
<path
|
<path
|
||||||
d="M4.85742 7.20505L6.91318 9.25578L10.3394 5.83789"
|
d="M4.85742 7.20505L6.91318 9.25578L10.3394 5.83789"
|
||||||
stroke="white"
|
stroke="white"
|
||||||
stroke-width="2.45534"
|
strokeWidth="2.45534"
|
||||||
stroke-linecap="round"
|
strokeLinecap="round"
|
||||||
stroke-linejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { useProductContext } from '../../../modules/simulation/products/productContext'
|
import { useProductContext } from '../../../modules/simulation/products/productContext'
|
||||||
import RegularDropDown from '../../ui/inputs/RegularDropDown';
|
import RegularDropDown from '../../ui/inputs/RegularDropDown';
|
||||||
import { useProductStore } from '../../../store/simulation/useProductStore';
|
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 useModuleStore from '../../../store/useModuleStore';
|
||||||
import CompareLayOut from '../../ui/compareVersion/CompareLayOut';
|
import CompareLayOut from '../../ui/compareVersion/CompareLayOut';
|
||||||
import ComparisonResult from '../../ui/compareVersion/ComparisonResult';
|
import ComparisonResult from '../../ui/compareVersion/ComparisonResult';
|
||||||
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore';
|
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore';
|
||||||
import { usePauseButtonStore, usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
import { usePauseButtonStore, usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
function ComparisonScene() {
|
function ComparisonScene() {
|
||||||
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
||||||
|
@ -19,6 +20,8 @@ function ComparisonScene() {
|
||||||
const { mainProduct } = useMainProduct();
|
const { mainProduct } = useMainProduct();
|
||||||
const { setIsPaused } = usePauseButtonStore();
|
const { setIsPaused } = usePauseButtonStore();
|
||||||
const { loadingProgress } = useLoadingProgress();
|
const { loadingProgress } = useLoadingProgress();
|
||||||
|
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||||
|
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
|
||||||
|
|
||||||
const handleSelectLayout = (option: string) => {
|
const handleSelectLayout = (option: string) => {
|
||||||
const product = products.find((product) => product.productName === option);
|
const product = products.find((product) => product.productName === option);
|
||||||
|
@ -26,6 +29,24 @@ function ComparisonScene() {
|
||||||
setComparisonProduct(product.productUuid, product.productName);
|
setComparisonProduct(product.productUuid, product.productName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{isVersionSaved && activeModule === "simulation" && selectedProduct && (
|
{isVersionSaved && activeModule === "simulation" && selectedProduct && (
|
||||||
|
@ -41,7 +62,8 @@ function ComparisonScene() {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<CompareLayOut />
|
<CompareLayOut />
|
||||||
{(comparisonProduct && mainProduct && !loadingProgress) && <ComparisonResult />}
|
|
||||||
|
{(shouldShowComparisonResult && !loadingProgress) && <ComparisonResult />}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { AIIcon } from "../../../icons/ExportCommonIcons";
|
import { AIIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../ui/inputs/RegularDropDown";
|
||||||
import { AnalysisPresetsType } from "../../../../types/analysis";
|
import { AnalysisPresetsType } from "../../../../types/analysis";
|
||||||
|
@ -19,55 +19,66 @@ const Analysis: React.FC = () => {
|
||||||
// { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } },
|
// { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } },
|
||||||
],
|
],
|
||||||
"Production capacity": [
|
"Production capacity": [
|
||||||
{ type: "range", inputs: { label: "Shift length", activeOption: "hr" } },
|
{ type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 6 } },
|
||||||
{ type: "default", inputs: { label: "Shifts / day", activeOption: "unit" } },
|
{ type: "default", inputs: { label: "Shifts / day", activeOption: "unit", defaultValue: 2 } },
|
||||||
{ type: "default", inputs: { label: "Working days / year", activeOption: "days" } },
|
{ type: "default", inputs: { label: "Working days / year", activeOption: "days", defaultValue: 300 } },
|
||||||
{ type: "default", inputs: { label: "Yield rate", activeOption: "%" } },
|
{ type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 92 } },
|
||||||
],
|
],
|
||||||
ROI: [
|
ROI: [
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Selling price", activeOption: "INR" },
|
inputs: { label: "Selling price", activeOption: "INR", defaultValue: 800 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Material cost", activeOption: "INR" },
|
inputs: { label: "Material cost", activeOption: "INR", defaultValue: 300 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Labor Cost", activeOption: "INR" },
|
inputs: { label: "Labor Cost", activeOption: "INR", defaultValue: 150 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Maintenance cost", activeOption: "INR" },
|
inputs: { label: "Maintenance cost", activeOption: "INR", defaultValue: 1200 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Electricity cost", activeOption: "INR" },
|
inputs: { label: "Electricity cost", activeOption: "INR", defaultValue: 840 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Fixed costs", activeOption: "INR" },
|
inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 1250 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Initial Investment", activeOption: "INR" },
|
inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 1500000 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Salvage value", activeOption: "Hrs" },
|
inputs: { label: "Salvage value", activeOption: "Day", defaultValue: 565 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Production period", activeOption: "yrs" },
|
inputs: { label: "Production period", activeOption: "yrs", defaultValue: 5 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
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();
|
const { inputValues, setInputValues, updateInputValue } = useInputValues();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -10,7 +10,8 @@ interface InputRendererProps {
|
||||||
onInputChange: (label: string, value: string) => void;
|
onInputChange: (label: string, value: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderAnalysisInputs: React.FC<InputRendererProps> = ({ keyName, presets,inputValues, onInputChange }) => {
|
const RenderAnalysisInputs: React.FC<InputRendererProps> = ({ keyName, presets, inputValues, onInputChange }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={`main-${keyName}`} className="analysis-inputs">
|
<div key={`main-${keyName}`} className="analysis-inputs">
|
||||||
{presets.map((preset, index) => {
|
{presets.map((preset, index) => {
|
||||||
|
@ -19,7 +20,7 @@ const RenderAnalysisInputs: React.FC<InputRendererProps> = ({ keyName, presets,i
|
||||||
<InputWithDropDown
|
<InputWithDropDown
|
||||||
key={index}
|
key={index}
|
||||||
label={preset.inputs.label}
|
label={preset.inputs.label}
|
||||||
value={inputValues[preset.inputs.label] || ""}
|
value={preset.inputs.defaultValue?.toString() || inputValues[preset.inputs.label] || ""}
|
||||||
activeOption={preset.inputs.activeOption}
|
activeOption={preset.inputs.activeOption}
|
||||||
onChange={(newValue) => onInputChange(preset.inputs.label, newValue)}
|
onChange={(newValue) => onInputChange(preset.inputs.label, newValue)}
|
||||||
/>
|
/>
|
||||||
|
@ -32,7 +33,7 @@ const RenderAnalysisInputs: React.FC<InputRendererProps> = ({ keyName, presets,i
|
||||||
label={preset.inputs.label}
|
label={preset.inputs.label}
|
||||||
min={0}
|
min={0}
|
||||||
max={8}
|
max={8}
|
||||||
value={5}
|
value={Number(preset.inputs.defaultValue) || Number(inputValues[preset.inputs.label]) || 5}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
|
||||||
import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon, } from "../../../icons/ExportCommonIcons";
|
import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon, } from "../../../icons/ExportCommonIcons";
|
||||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||||
import { handleResize } from "../../../../functions/handleResizePannel";
|
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 { useProductStore } from "../../../../store/simulation/useProductStore";
|
||||||
import { generateUUID } from "three/src/math/MathUtils";
|
import { generateUUID } from "three/src/math/MathUtils";
|
||||||
import RenderOverlay from "../../../templates/Overlay";
|
import RenderOverlay from "../../../templates/Overlay";
|
||||||
|
@ -48,6 +48,7 @@ const Simulations: React.FC = () => {
|
||||||
const [processes, setProcesses] = useState<Event[][]>();
|
const [processes, setProcesses] = useState<Event[][]>();
|
||||||
const { setToggleUI } = useToggleStore();
|
const { setToggleUI } = useToggleStore();
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
|
const { setMainProduct } = useMainProduct();
|
||||||
|
|
||||||
const { comparePopUp, setComparePopUp } = useCompareStore();
|
const { comparePopUp, setComparePopUp } = useCompareStore();
|
||||||
const { setIsVersionSaved } = useSaveVersion();
|
const { setIsVersionSaved } = useSaveVersion();
|
||||||
|
@ -85,8 +86,13 @@ const Simulations: React.FC = () => {
|
||||||
updatedProducts[newSelectedIndex].productUuid,
|
updatedProducts[newSelectedIndex].productUuid,
|
||||||
updatedProducts[newSelectedIndex].productName
|
updatedProducts[newSelectedIndex].productName
|
||||||
);
|
);
|
||||||
|
setMainProduct(
|
||||||
|
updatedProducts[newSelectedIndex].productUuid,
|
||||||
|
updatedProducts[newSelectedIndex].productName
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
setSelectedProduct("", "");
|
setSelectedProduct("", "");
|
||||||
|
setMainProduct("", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +108,7 @@ const Simulations: React.FC = () => {
|
||||||
renameProductApi({ productName: newName, productUuid, projectId: projectId || '' });
|
renameProductApi({ productName: newName, productUuid, projectId: projectId || '' });
|
||||||
if (selectedProduct.productUuid === productUuid) {
|
if (selectedProduct.productUuid === productUuid) {
|
||||||
setSelectedProduct(productUuid, newName);
|
setSelectedProduct(productUuid, newName);
|
||||||
|
setMainProduct(productUuid, newName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -172,9 +179,10 @@ const Simulations: React.FC = () => {
|
||||||
{/* eslint-disable-next-line */}
|
{/* eslint-disable-next-line */}
|
||||||
<div
|
<div
|
||||||
className="value"
|
className="value"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
setSelectedProduct(product.productUuid, product.productName)
|
setSelectedProduct(product.productUuid, product.productName)
|
||||||
}
|
setMainProduct(product.productUuid, product.productName)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
|
|
@ -121,8 +121,9 @@ const ROISummary = ({
|
||||||
<SonarCrownIcon />
|
<SonarCrownIcon />
|
||||||
<div className="icon"></div>
|
<div className="icon"></div>
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<span> {roiSummary.roiPercentage}%</span> ROI with payback
|
<span>{roiSummary.roiPercentage}% </span>
|
||||||
in just <span>{roiSummary.paybackPeriod}</span> months
|
ROI
|
||||||
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="roi-details">
|
<div className="roi-details">
|
||||||
|
|
|
@ -26,6 +26,7 @@ const ProductionCapacity = ({
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log('throughputData: ', throughputData);
|
||||||
if (throughputData > 0) {
|
if (throughputData > 0) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,8 +2,13 @@ import React, { useMemo } from "react";
|
||||||
import PerformanceResult from "./result-card/PerformanceResult";
|
import PerformanceResult from "./result-card/PerformanceResult";
|
||||||
import EnergyUsage from "./result-card/EnergyUsage";
|
import EnergyUsage from "./result-card/EnergyUsage";
|
||||||
import { Bar, Line, Pie } from "react-chartjs-2";
|
import { Bar, Line, Pie } from "react-chartjs-2";
|
||||||
|
import { useCompareProductDataStore } from "../../../store/builder/store";
|
||||||
|
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
|
||||||
|
|
||||||
const ComparisonResult = () => {
|
const ComparisonResult = () => {
|
||||||
|
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||||
|
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
||||||
|
const { mainProduct } = useMainProduct();
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
|
@ -150,7 +155,7 @@ const ComparisonResult = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overallScrapRate comparisionCard">
|
<div className="overallScrapRate comparisionCard">
|
||||||
<div className="overallScrapRate-header">Overall Scrap Rate</div>
|
<div className="overallScrapRate-header">Production Capacity</div>
|
||||||
<div className="overallScrapRate-wrapper">
|
<div className="overallScrapRate-wrapper">
|
||||||
<div className="overallScrapRate-value">
|
<div className="overallScrapRate-value">
|
||||||
<div className="overallScrapRate-label">Layout 1</div>
|
<div className="overallScrapRate-label">Layout 1</div>
|
||||||
|
|
|
@ -146,9 +146,6 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
||||||
newName,
|
newName,
|
||||||
projectId
|
projectId
|
||||||
);
|
);
|
||||||
// console.log("response: ", response);
|
|
||||||
console.log(' zoneAssetId.id,: ', zoneAssetId.id,);
|
|
||||||
|
|
||||||
setName(zoneAssetId.id, response.modelName);
|
setName(zoneAssetId.id, response.modelName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ const SimulationPlayer: React.FC = () => {
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<HourlySimulationIcon />
|
<HourlySimulationIcon />
|
||||||
</div>
|
</div>
|
||||||
<div className="label">ThroughPut Data</div>
|
<div className="label">ThroughPut</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="progress-wrapper">
|
<div className="progress-wrapper">
|
||||||
<div
|
<div
|
||||||
|
@ -202,7 +202,7 @@ const SimulationPlayer: React.FC = () => {
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<DailyProductionIcon />
|
<DailyProductionIcon />
|
||||||
</div>
|
</div>
|
||||||
<div className="label">Daily Production</div>
|
<div className="label">Production Capacity</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="progress-wrapper">
|
<div className="progress-wrapper">
|
||||||
<div
|
<div
|
||||||
|
@ -217,7 +217,7 @@ const SimulationPlayer: React.FC = () => {
|
||||||
<div className="icon">
|
<div className="icon">
|
||||||
<MonthlyROI />
|
<MonthlyROI />
|
||||||
</div>
|
</div>
|
||||||
<div className="label">Monthly ROI</div>
|
<div className="label">ROI</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="progress-wrapper">
|
<div className="progress-wrapper">
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { useInputValues, useProductionCapacityData, useROISummaryData } from '../../../../store/builder/store';
|
import { CompareProduct, useCompareProductDataStore, useInputValues, useMachineDowntime, useMachineUptime, useProductionCapacityData, useROISummaryData, useThroughPutData } from '../../../../store/builder/store';
|
||||||
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
||||||
import { useProductContext } from '../../products/productContext';
|
import { useProductContext } from '../../products/productContext';
|
||||||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||||
|
|
||||||
|
|
||||||
export default function ROIData() {
|
export default function ROIData() {
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { inputValues } = useInputValues();
|
const { inputValues } = useInputValues();
|
||||||
|
@ -12,28 +13,30 @@ export default function ROIData() {
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { setRoiSummaryData } = useROISummaryData();
|
const { setRoiSummaryData } = useROISummaryData();
|
||||||
const { products, getProductById } = useProductStore();
|
const { products, getProductById } = useProductStore();
|
||||||
const [compareProducts, setCompareProducts] = useState<any[]>([]);
|
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||||
|
const { machineActiveTime, setMachineActiveTime } = useMachineUptime();
|
||||||
|
const { machineIdleTime, setMachineIdleTime } = useMachineDowntime();
|
||||||
|
const { throughputData } = useThroughPutData()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) {
|
if (isPlaying) return;
|
||||||
setRoiSummaryData({
|
setRoiSummaryData({
|
||||||
productName: "",
|
productName: "",
|
||||||
roiPercentage: 0,
|
roiPercentage: 0,
|
||||||
paybackPeriod: 0,
|
paybackPeriod: 0,
|
||||||
totalCost: 0,
|
totalCost: 0,
|
||||||
revenueGenerated: 0,
|
revenueGenerated: 0,
|
||||||
netProfit: 0,
|
netProfit: 0,
|
||||||
netLoss: 0,
|
netLoss: 0,
|
||||||
})
|
});
|
||||||
return;
|
}, [isPlaying]);
|
||||||
}
|
|
||||||
|
|
||||||
if (inputValues === undefined) return;
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (inputValues === undefined || !isPlaying) return;
|
||||||
const electricityCost = parseFloat(inputValues["Electricity cost"]);
|
const electricityCost = parseFloat(inputValues["Electricity cost"]);
|
||||||
const fixedCost = parseFloat(inputValues["Fixed costs"]);
|
const fixedCost = parseFloat(inputValues["Fixed costs"]);
|
||||||
const laborCost = parseFloat(inputValues["Labor Cost"]);
|
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 materialCost = parseFloat(inputValues["Material cost"]);
|
||||||
const productionPeriod = parseFloat(inputValues["Production period"]);
|
const productionPeriod = parseFloat(inputValues["Production period"]);
|
||||||
const salvageValue = parseFloat(inputValues["Salvage value"]);
|
const salvageValue = parseFloat(inputValues["Salvage value"]);
|
||||||
|
@ -46,41 +49,26 @@ export default function ROIData() {
|
||||||
if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) &&
|
if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) &&
|
||||||
!isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) &&
|
!isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) &&
|
||||||
!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) {
|
!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) {
|
||||||
|
console.log('productionCapacityData: ', productionCapacityData);
|
||||||
|
|
||||||
const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear;
|
const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear;
|
||||||
// Total good units produced per year
|
|
||||||
const annualProductionUnits = productionCapacityData * totalHoursPerYear;
|
const annualProductionUnits = productionCapacityData * totalHoursPerYear;
|
||||||
// Revenue for a year
|
|
||||||
const annualRevenue = annualProductionUnits * sellingPrice;
|
const annualRevenue = annualProductionUnits * sellingPrice;
|
||||||
// Costs
|
|
||||||
const totalMaterialCost = annualProductionUnits * materialCost;
|
const totalMaterialCost = annualProductionUnits * materialCost;
|
||||||
const totalLaborCost = laborCost * totalHoursPerYear;
|
const totalLaborCost = laborCost * totalHoursPerYear;
|
||||||
const totalEnergyCost = electricityCost * totalHoursPerYear;
|
const totalEnergyCost = electricityCost * totalHoursPerYear;
|
||||||
const totalMaintenanceCost = maintenanceCost + fixedCost;
|
const totalMaintenanceCost = maintenanceCost + fixedCost;
|
||||||
const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost;
|
const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost;
|
||||||
// Annual Profit
|
|
||||||
const annualProfit = annualRevenue - totalAnnualCost;
|
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
|
|
||||||
|
|
||||||
|
|
||||||
//
|
const netProfit = annualProfit * productionPeriod;
|
||||||
//
|
const roiPercentage = ((annualProfit + salvageValue - initialInvestment) / initialInvestment) * 100;
|
||||||
//
|
const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
setRoiSummaryData({
|
setRoiSummaryData({
|
||||||
productName: selectedProduct.productName,
|
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)),
|
paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
||||||
totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
||||||
revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
||||||
|
@ -89,10 +77,7 @@ export default function ROIData() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const productCount = 1000;
|
const productCount = 1000;
|
||||||
|
|
||||||
// Cost per unit (based on full annual cost)
|
|
||||||
const costPerUnit = totalAnnualCost / annualProductionUnits;
|
const costPerUnit = totalAnnualCost / annualProductionUnits;
|
||||||
|
|
||||||
const costForTargetUnits = productCount * costPerUnit;
|
const costForTargetUnits = productCount * costPerUnit;
|
||||||
const revenueForTargetUnits = productCount * sellingPrice;
|
const revenueForTargetUnits = productCount * sellingPrice;
|
||||||
const profitForTargetUnits = revenueForTargetUnits - costForTargetUnits;
|
const profitForTargetUnits = revenueForTargetUnits - costForTargetUnits;
|
||||||
|
@ -100,55 +85,46 @@ export default function ROIData() {
|
||||||
const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0;
|
const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0;
|
||||||
const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0;
|
const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0;
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
const productData = getProductById(selectedProduct.productUuid);
|
const productData = getProductById(selectedProduct.productUuid);
|
||||||
|
const prev = useCompareProductDataStore.getState().compareProductsData;
|
||||||
|
const newData: CompareProduct = {
|
||||||
setCompareProducts(prev => {
|
productUuid: productData?.productUuid ?? '',
|
||||||
const newData = {
|
productName: productData?.productName ?? '',
|
||||||
productUuid: productData?.productUuid,
|
simulationData: {
|
||||||
productName: productData?.productName,
|
// costPerUnit: parseFloat(costPerUnit.toFixed(2)),
|
||||||
costPerUnit: parseFloat(costPerUnit.toFixed(2)),
|
// workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)),
|
||||||
workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)),
|
// shiftLength: parseFloat(shiftLength.toFixed(2)),
|
||||||
shiftLength: parseFloat(shiftLength.toFixed(2)),
|
// shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)),
|
||||||
shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)),
|
|
||||||
roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)),
|
roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)),
|
||||||
paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
// paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
||||||
totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
// totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
||||||
revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
// revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
||||||
netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0,
|
netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0,
|
||||||
netLoss: 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)),
|
||||||
const existingIndex = prev.findIndex(
|
throughputData: throughputData,
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
// console.log('compareProducts: ', compareProducts);
|
|
||||||
|
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]);
|
}, [inputValues, productionCapacityData, selectedProduct?.productUuid, isPlaying]);
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<></>
|
console.log('compareProductsData: ', compareProductsData);
|
||||||
)
|
}, [compareProductsData])
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,47 +1,59 @@
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { useInputValues, useProductionCapacityData, useThroughPutData } from '../../../../store/builder/store'
|
import { useInputValues, useProductionCapacityData, useThroughPutData } from '../../../../store/builder/store'
|
||||||
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
||||||
|
import { useProductContext } from '../../products/productContext';
|
||||||
|
|
||||||
export default function ProductionCapacityData() {
|
export default function ProductionCapacityData() {
|
||||||
const { throughputData } = useThroughPutData()
|
const { throughputData } = useThroughPutData()
|
||||||
const { productionCapacityData, setProductionCapacityData } = useProductionCapacityData()
|
const { productionCapacityData, setProductionCapacityData } = useProductionCapacityData()
|
||||||
const { inputValues } = useInputValues();
|
const { inputValues } = useInputValues();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
const { selectedProductStore } = useProductContext();
|
||||||
|
const { selectedProduct } = selectedProductStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) {
|
if (!isPlaying) {
|
||||||
|
console.log('isPlaying: ', isPlaying);
|
||||||
setProductionCapacityData(0);
|
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"]);
|
const shiftLength = parseFloat(inputValues["Shift length"]);
|
||||||
|
console.log('shiftLength: ', shiftLength);
|
||||||
|
|
||||||
const shiftsPerDay = parseFloat(inputValues["Shifts / day"]);
|
const shiftsPerDay = parseFloat(inputValues["Shifts / day"]);
|
||||||
|
|
||||||
const workingDaysPerYear = parseFloat(inputValues["Working days / year"]);
|
const workingDaysPerYear = parseFloat(inputValues["Working days / year"]);
|
||||||
|
|
||||||
const yieldRate = parseFloat(inputValues["Yield rate"]);
|
const yieldRate = parseFloat(inputValues["Yield rate"]);
|
||||||
|
|
||||||
|
|
||||||
if (!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) &&
|
if (!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) &&
|
||||||
!isNaN(yieldRate) && throughputData >= 0) {
|
!isNaN(yieldRate) && throughputData > 0) {
|
||||||
// Total units produced per day before yield
|
// Total units produced per day before yield
|
||||||
const dailyProduction = throughputData * shiftLength * shiftsPerDay;
|
const dailyProduction = throughputData * shiftLength * shiftsPerDay;
|
||||||
|
|
||||||
|
|
||||||
// Units after applying yield rate
|
// Units after applying yield rate
|
||||||
const goodUnitsPerDay = dailyProduction * (yieldRate / 100);
|
const goodUnitsPerDay = dailyProduction * (yieldRate / 100);
|
||||||
|
|
||||||
|
|
||||||
// Annual output
|
// Annual output
|
||||||
const annualProduction = goodUnitsPerDay * workingDaysPerYear;
|
const annualProduction = goodUnitsPerDay * workingDaysPerYear;
|
||||||
|
|
||||||
|
|
||||||
// Final production capacity per hour (after yield)
|
// Final production capacity per hour (after yield)
|
||||||
const productionPerHour = throughputData * (yieldRate / 100);
|
const productionPerHour = throughputData * (yieldRate / 100);
|
||||||
|
|
||||||
|
|
||||||
// Set the final capacity (units/hour)
|
// Set the final capacity (units/hour)
|
||||||
setProductionCapacityData(Number(productionPerHour.toFixed(2)));
|
setProductionCapacityData(Number(productionPerHour.toFixed(2)));
|
||||||
}
|
}
|
||||||
}, [throughputData, inputValues]);
|
}, [throughputData, inputValues, isPlaying]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<></>
|
<></>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||||
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
|
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 { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
||||||
import { useSceneContext } from '../../../scene/sceneContext';
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
import { useProductContext } from '../../products/productContext';
|
import { useProductContext } from '../../products/productContext';
|
||||||
|
import { set } from 'immer/dist/internal';
|
||||||
|
|
||||||
export default function ThroughPutData() {
|
export default function ThroughPutData() {
|
||||||
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore } = useSceneContext();
|
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore } = useSceneContext();
|
||||||
|
@ -19,6 +20,7 @@ export default function ThroughPutData() {
|
||||||
const { materialHistory, materials } = materialStore();
|
const { materialHistory, materials } = materialStore();
|
||||||
const { machineCount, setMachineCount } = useMachineCount();
|
const { machineCount, setMachineCount } = useMachineCount();
|
||||||
const { machineActiveTime, setMachineActiveTime } = useMachineUptime();
|
const { machineActiveTime, setMachineActiveTime } = useMachineUptime();
|
||||||
|
const { machineIdleTime, setMachineIdleTime } = useMachineDowntime();
|
||||||
const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle();
|
const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle();
|
||||||
const { setProcessBar } = useProcessBar();
|
const { setProcessBar } = useProcessBar();
|
||||||
const { setThroughputData } = useThroughPutData()
|
const { setThroughputData } = useThroughPutData()
|
||||||
|
@ -27,17 +29,24 @@ export default function ThroughPutData() {
|
||||||
// Setting machine count
|
// Setting machine count
|
||||||
let totalItems = 0;
|
let totalItems = 0;
|
||||||
let totalActiveTime = 0;
|
let totalActiveTime = 0;
|
||||||
|
let totalIdleTime = 0
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) {
|
if (!isPlaying) {
|
||||||
totalActiveTime = 0;
|
totalActiveTime = 0;
|
||||||
totalItems = 0;
|
totalItems = 0;
|
||||||
|
totalIdleTime = 0;
|
||||||
setMachineCount(0);
|
setMachineCount(0);
|
||||||
setMachineActiveTime(0);
|
setMachineActiveTime(0);
|
||||||
|
setMachineIdleTime(0);
|
||||||
setMaterialCycleTime(0);
|
setMaterialCycleTime(0);
|
||||||
setProcessBar([]);
|
setProcessBar([]);
|
||||||
setThroughputData(0);
|
setThroughputData(0);
|
||||||
return;
|
}
|
||||||
} else {
|
}, [isPlaying])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isPlaying) {
|
||||||
let process: any = [];
|
let process: any = [];
|
||||||
const fetchProductSequenceData = async () => {
|
const fetchProductSequenceData = async () => {
|
||||||
const productData = getProductById(selectedProduct.productUuid);
|
const productData = getProductById(selectedProduct.productUuid);
|
||||||
|
@ -53,6 +62,9 @@ export default function ThroughPutData() {
|
||||||
process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime })
|
process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime })
|
||||||
totalActiveTime += arm.activeTime;
|
totalActiveTime += arm.activeTime;
|
||||||
}
|
}
|
||||||
|
if (arm.idleTime > 0) {
|
||||||
|
totalIdleTime += arm.idleTime;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else if (item.type === "vehicle") {
|
} else if (item.type === "vehicle") {
|
||||||
vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid)
|
vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid)
|
||||||
|
@ -62,6 +74,9 @@ export default function ThroughPutData() {
|
||||||
|
|
||||||
totalActiveTime += vehicle.activeTime;
|
totalActiveTime += vehicle.activeTime;
|
||||||
}
|
}
|
||||||
|
if (vehicle.idleTime > 0) {
|
||||||
|
totalIdleTime += vehicle.idleTime;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else if (item.type === "machine") {
|
} else if (item.type === "machine") {
|
||||||
machines.filter(machine => machine.modelUuid === item.modelUuid)
|
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 })
|
process.push({ modelid: machine.modelUuid, modelName: machine.modelName, activeTime: machine?.activeTime })
|
||||||
totalActiveTime += machine.activeTime;
|
totalActiveTime += machine.activeTime;
|
||||||
}
|
}
|
||||||
|
if (machine.idleTime > 0) {
|
||||||
|
totalIdleTime += machine.idleTime;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else if (item.type === "transfer") {
|
} else if (item.type === "transfer") {
|
||||||
conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid)
|
conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid)
|
||||||
|
@ -83,7 +101,7 @@ export default function ThroughPutData() {
|
||||||
.forEach(storage => {
|
.forEach(storage => {
|
||||||
if (storage.activeTime > 0) {
|
if (storage.activeTime > 0) {
|
||||||
// totalActiveTime += storage.activeTime;
|
// totalActiveTime += storage.activeTime;
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -92,9 +110,10 @@ export default function ThroughPutData() {
|
||||||
totalItems += sequence.length;
|
totalItems += sequence.length;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
setMachineCount(totalItems);
|
setMachineCount(totalItems);
|
||||||
setMachineActiveTime(totalActiveTime);
|
setMachineActiveTime(totalActiveTime);
|
||||||
|
setMachineIdleTime(totalIdleTime);
|
||||||
let arr = process.map((item: any) => ({
|
let arr = process.map((item: any) => ({
|
||||||
name: item.modelName,
|
name: item.modelName,
|
||||||
completed: Math.round((item.activeTime / totalActiveTime) * 100)
|
completed: Math.round((item.activeTime / totalActiveTime) * 100)
|
||||||
|
@ -107,15 +126,15 @@ export default function ThroughPutData() {
|
||||||
fetchProductSequenceData();
|
fetchProductSequenceData();
|
||||||
}
|
}
|
||||||
// if (materialCycleTime <= 0) return
|
// if (materialCycleTime <= 0) return
|
||||||
}, [products, selectedProduct, getProductById, setMachineCount, materialCycleTime, armBots, vehicles, machines]);
|
}, [products, selectedProduct?.productUuid, getProductById, setMachineCount, materialCycleTime, armBots, vehicles, machines]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let timeoutId: ReturnType<typeof setTimeout>;
|
||||||
async function getMachineActive() {
|
async function getMachineActive() {
|
||||||
const productData = getProductById(selectedProduct.productUuid);
|
const productData = getProductById(selectedProduct.productUuid);
|
||||||
let anyArmActive;
|
let anyArmActive;
|
||||||
let anyVehicleActive;
|
let anyVehicleActive;
|
||||||
let anyMachineActive;
|
let anyMachineActive;
|
||||||
|
|
||||||
if (productData) {
|
if (productData) {
|
||||||
const productSequenceData = await determineExecutionMachineSequences([productData]);
|
const productSequenceData = await determineExecutionMachineSequences([productData]);
|
||||||
if (productSequenceData?.length > 0) {
|
if (productSequenceData?.length > 0) {
|
||||||
|
@ -161,7 +180,7 @@ export default function ThroughPutData() {
|
||||||
|
|
||||||
const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive;
|
const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive;
|
||||||
if (allInactive && materials.length === 0 && materialHistory.length > 0) {
|
if (allInactive && materials.length === 0 && materialHistory.length > 0) {
|
||||||
|
|
||||||
let totalCycleTimeSum = 0;
|
let totalCycleTimeSum = 0;
|
||||||
let cycleCount = 0;
|
let cycleCount = 0;
|
||||||
|
|
||||||
|
@ -182,21 +201,24 @@ export default function ThroughPutData() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
getMachineActive();
|
getMachineActive();
|
||||||
}, 500)
|
}, 1500);
|
||||||
}
|
}
|
||||||
}, [armBots, materials, materialHistory, machines, vehicles, selectedProduct])
|
|
||||||
|
return () => {
|
||||||
|
if (timeoutId) clearTimeout(timeoutId);
|
||||||
|
};
|
||||||
|
}, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid])
|
||||||
|
|
||||||
useEffect(() => {
|
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 utilization = machineActiveTime / 3600; // Active time per hour
|
||||||
const unitsPerMachinePerHour = 3600 / materialCycleTime;
|
const unitsPerMachinePerHour = 3600 / materialCycleTime;
|
||||||
const throughput = unitsPerMachinePerHour * machineCount * utilization;
|
const throughput = unitsPerMachinePerHour * machineCount * utilization;
|
||||||
setThroughputData(Number(throughput.toFixed(2))); // Keep as number
|
setThroughputData(Number(throughput.toFixed(2))); // Keep as number
|
||||||
//
|
|
||||||
}
|
}
|
||||||
}, [machineActiveTime, materialCycleTime, machineCount]);
|
}, [machineActiveTime, materialCycleTime, machineCount, selectedProduct?.productUuid, isPlaying]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -13,6 +13,7 @@ function Products() {
|
||||||
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, layout } = useSceneContext();
|
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, layout } = useSceneContext();
|
||||||
const { products, getProductById, addProduct, setProducts } = useProductStore();
|
const { products, getProductById, addProduct, setProducts } = useProductStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
|
const { setMainProduct } = useMainProduct();
|
||||||
const { selectedProduct, setSelectedProduct } = selectedProductStore();
|
const { selectedProduct, setSelectedProduct } = selectedProductStore();
|
||||||
const { addVehicle, clearvehicles } = vehicleStore();
|
const { addVehicle, clearvehicles } = vehicleStore();
|
||||||
const { addArmBot, clearArmBots } = armBotStore();
|
const { addArmBot, clearArmBots } = armBotStore();
|
||||||
|
@ -51,11 +52,13 @@ function Products() {
|
||||||
})
|
})
|
||||||
if (layout === 'Main Layout') {
|
if (layout === 'Main Layout') {
|
||||||
setSelectedProduct(id, name);
|
setSelectedProduct(id, name);
|
||||||
|
setMainProduct(id, name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setProducts(data);
|
setProducts(data);
|
||||||
if (layout === 'Main Layout') {
|
if (layout === 'Main Layout') {
|
||||||
setSelectedProduct(data[0].productUuid, data[0].productName);
|
setSelectedProduct(data[0].productUuid, data[0].productName);
|
||||||
|
setMainProduct(data[0].productUuid, data[0].productName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,12 +3,13 @@ export const setFloorItemApi = async (
|
||||||
organization: string,
|
organization: string,
|
||||||
modelUuid?: string,
|
modelUuid?: string,
|
||||||
modelName?: string,
|
modelName?: string,
|
||||||
|
projectId?: string,
|
||||||
assetId?: string,
|
assetId?: string,
|
||||||
projectId?: string,
|
projectId?: string,
|
||||||
position?: Object,
|
position?: Object,
|
||||||
rotation?: Object,
|
rotation?: Object,
|
||||||
isLocked?: boolean,
|
isLocked?: boolean,
|
||||||
isVisible?: boolean
|
isVisible?: boolean,
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const body: any = {
|
const body: any = {
|
||||||
|
@ -22,7 +23,6 @@ export const setFloorItemApi = async (
|
||||||
isLocked,
|
isLocked,
|
||||||
isVisible,
|
isVisible,
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(`${url_Backend_dwinzo}/api/V1/setAsset`, {
|
const response = await fetch(`${url_Backend_dwinzo}/api/V1/setAsset`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
@ -26,7 +26,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
|
||||||
auth: { token },
|
auth: { token },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const dashBoardSocket = io(
|
const dashBoardSocket = io(
|
||||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
|
||||||
|
@ -546,6 +546,10 @@ export const useMachineUptime = create<any>((set: any) => ({
|
||||||
machineActiveTime: 0,
|
machineActiveTime: 0,
|
||||||
setMachineActiveTime: (x: any) => set({ machineActiveTime: x }),
|
setMachineActiveTime: (x: any) => set({ machineActiveTime: x }),
|
||||||
}));
|
}));
|
||||||
|
export const useMachineDowntime = create<any>((set: any) => ({
|
||||||
|
machineIdleTime: 0,
|
||||||
|
setMachineIdleTime: (x: any) => set({ machineIdleTime: x }),
|
||||||
|
}));
|
||||||
export const useMaterialCycle = create<any>((set: any) => ({
|
export const useMaterialCycle = create<any>((set: any) => ({
|
||||||
materialCycleTime: 0,
|
materialCycleTime: 0,
|
||||||
setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }),
|
setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }),
|
||||||
|
@ -709,3 +713,30 @@ function getInitialViewSceneLabels(): boolean {
|
||||||
const saved = localStorage.getItem('viewSceneLabels');
|
const saved = localStorage.getItem('viewSceneLabels');
|
||||||
return saved ? JSON.parse(saved) : false;
|
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 }),
|
||||||
|
}));
|
|
@ -88,6 +88,7 @@ export const createMaterialStore = () => {
|
||||||
clearMaterials: () => {
|
clearMaterials: () => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.materials = [];
|
state.materials = [];
|
||||||
|
state.materialHistory = [];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -657,7 +657,7 @@
|
||||||
|
|
||||||
path {
|
path {
|
||||||
stroke: var(--text-button-color);
|
stroke: var(--text-button-color);
|
||||||
stroke-width: 1.3;
|
strokeWidth: 1.3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1021,7 +1021,7 @@
|
||||||
|
|
||||||
path {
|
path {
|
||||||
stroke: var(--accent-color);
|
stroke: var(--accent-color);
|
||||||
stroke-width: 1.5px;
|
strokeWidth: 1.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
@ -5,6 +5,7 @@ type Preset = {
|
||||||
activeOption: string;
|
activeOption: string;
|
||||||
min?: number;
|
min?: number;
|
||||||
max?: number;
|
max?: number;
|
||||||
|
defaultValue?: string | number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue