feat: add asset-specific analysis functions for conveyors and vehicles to calculate various performance and operational metrics.

This commit is contained in:
2025-12-29 11:42:02 +05:30
parent 7128ef5a84
commit 9ae5d657b7

View File

@@ -474,17 +474,32 @@ export const analyzeStorage = (storage: any, materials: any[]) => {
};
};
// Humans analysis update
export const analyzeHuman = (human: any, materials: any[]) => {
// Simplified for brevity, but logically complete
const assetId = human.modelUuid;
const errorCount = errorCounts[assetId] || 0;
const timeMetrics = calculateAdvancedTimeMetrics(human.idleTime || 0, human.activeTime || 0, assetId, errorCount);
const actionsCompleted = completedActions[assetId] || 0;
const distanceTraveled = human.distanceTraveled || 0;
const currentLoad = human.currentLoad || 0;
const loadCapacity = human.point?.actions?.[0]?.loadCapacity || 1;
const loadCapacity = human.point?.action?.loadCapacity || human.point?.actions?.[0]?.loadCapacity || 1;
const loadUtilization = (currentLoad / loadCapacity) * 100;
const workerActions = completedActions[`${assetId}_worker`] || 0;
const manufacturerActions = completedActions[`${assetId}_manufacturer`] || 0;
const operatorActions = completedActions[`${assetId}_operator`] || 0;
const assemblerActions = completedActions[`${assetId}_assembler`] || 0;
const totalRecordedActions = workerActions + manufacturerActions + operatorActions + assemblerActions || 1;
const workloadDistribution = [
{ actionType: "Worker", count: workerActions, percentage: (workerActions / totalRecordedActions) * 100 },
{ actionType: "Manufacturer", count: manufacturerActions, percentage: (manufacturerActions / totalRecordedActions) * 100 },
{ actionType: "Operator", count: operatorActions, percentage: (operatorActions / totalRecordedActions) * 100 },
{ actionType: "Assembler", count: assemblerActions, percentage: (assemblerActions / totalRecordedActions) * 100 },
].filter((w) => w.count > 0);
const workloadSummary = workloadDistribution.map((d) => `${d.actionType}: ${Math.round(d.percentage)}%`).join(" | ") || "0%";
const idealActionsPerHour = PERFORMANCE_BENCHMARKS.HUMAN_IDEAL_ACTIONS_PER_HOUR;
const actualActionsPerHour = timeMetrics.totalTime > 0 ? (actionsCompleted / timeMetrics.totalTime) * 3600 : 0;
const performanceRate = Math.min((actualActionsPerHour / idealActionsPerHour) * 100, 100);
@@ -533,8 +548,8 @@ export const analyzeHuman = (human: any, materials: any[]) => {
averageSpeed: timeMetrics.totalTime > 0 ? distanceTraveled / timeMetrics.totalTime : 0,
loadEfficiency: loadUtilization,
},
workloadDistribution: [], // Skipped detail implementation for brevity
workloadSummary: "0%",
workloadDistribution,
workloadSummary,
efficiency: {
overallEffectiveness: calculateOEE(timeMetrics.uptime, performanceRate, qualityMetrics.firstPassYield),
availability: timeMetrics.uptime,
@@ -569,6 +584,15 @@ export const analyzeCrane = (crane: any, materials: any[]) => {
const avgLiftHeight = totalLifts > 0 ? totalLiftHeight / totalLifts : 0;
const avgLoadsPerCycle = cyclesCompleted > 0 ? loadsHandled / cyclesCompleted : 0;
// Success rates
const liftAttempts = totalLifts + errorCount;
const liftSuccessRate = liftAttempts > 0 ? (totalLifts / liftAttempts) * 100 : 100; // Use 100 as default if no attempts
const positioningAccuracy = totalLifts > 0 ? Math.max(0, 100 - (errorCount / totalLifts) * 50) : 100; // Estimation based on error count
// Load utilization
const maxPickUpCount = crane.point?.action?.maxPickUpCount || crane.point?.actions?.[0]?.maxPickUpCount || 1;
const loadUtilization = (avgLoadsPerCycle / maxPickUpCount) * 100;
const costMetrics = calculateCostMetrics(assetId, "crane", crane.activeTime || 0, loadsHandled);
const energyMetrics = calculateEnergyMetrics("crane", crane.activeTime || 0);
@@ -600,6 +624,7 @@ export const analyzeCrane = (crane: any, materials: any[]) => {
currentLoad: crane.currentLoad,
currentMaterials: crane.currentMaterials,
currentAction: crane.currentAction || null,
loadUtilization,
},
timeMetrics: { ...timeMetrics, idleTime: crane.idleTime, activeTime: crane.activeTime, averageCycleTime: actualCycleTime },
throughput: {
@@ -614,16 +639,16 @@ export const analyzeCrane = (crane: any, materials: any[]) => {
wip: crane.currentLoad,
bottleneckIndex: timeMetrics.utilizationRate > ANALYSIS_SETTINGS.BOTTLENECK_UTILIZATION_THRESHOLD ? 1 : 0,
},
movementMetrics: { totalLifts, averageLiftHeight: avgLiftHeight, movementEfficiency: 0, loadEfficiency: 0, cycleEfficiency: performance.timeEfficiency },
movementMetrics: { totalLifts, averageLiftHeight: avgLiftHeight, movementEfficiency: liftSuccessRate, loadEfficiency: loadUtilization, cycleEfficiency: performance.timeEfficiency },
efficiency: {
overallEffectiveness: calculateOEE(timeMetrics.uptime, performance.performanceRate, qualityMetrics.firstPassYield),
availability: timeMetrics.uptime,
performance: performance.performanceRate,
quality: qualityMetrics.firstPassYield,
loadUtilization: 0,
loadUtilization,
cycleTimeEfficiency: performance.timeEfficiency,
},
quality: qualityMetrics,
quality: { ...qualityMetrics, liftSuccessRate, positioningAccuracy },
costMetrics: { ...costMetrics, costPerLift: totalLifts > 0 ? costMetrics.totalCost / totalLifts : 0, costPerCycle: cyclesCompleted > 0 ? costMetrics.totalCost / cyclesCompleted : 0 },
energyMetrics: { ...energyMetrics, energyPerLift: totalLifts > 0 ? energyMetrics.energyConsumed / totalLifts : 0 },
historicalData: historicalData[assetId] || [],