feat: Add ElementComponent for dashboard UI elements and Analyzer for comprehensive simulation performance tracking.

This commit is contained in:
2025-12-20 16:33:35 +05:30
parent 6a46ae7bd9
commit a30b42d39e
2 changed files with 42 additions and 24 deletions

View File

@@ -14,24 +14,10 @@ interface ElementComponentProps {
handleElementResizeStart: (elementId: string, event: React.MouseEvent) => void;
}
const ElementComponent: React.FC<ElementComponentProps> = ({
element,
blockId,
editMode,
selectedElement,
handleElementClick,
handleElementDragStart,
handleElementResizeStart,
}) => {
const ElementComponent: React.FC<ElementComponentProps> = ({ element, blockId, editMode, selectedElement, handleElementClick, handleElementDragStart, handleElementResizeStart }) => {
const isSelected = selectedElement === element.elementUuid;
const elementClasses = [
"element",
element.positionType === "absolute" ? "absolute" : "",
element.type === "graph" ? "graph" : "",
editMode ? "edit-mode" : "",
isSelected ? "selected" : "",
]
const elementClasses = ["element", element.positionType === "absolute" ? "absolute" : "", element.type === "graph" ? "graph" : "", editMode ? "edit-mode" : "", isSelected ? "selected" : ""]
.filter(Boolean)
.join(" ");
@@ -43,8 +29,7 @@ const ElementComponent: React.FC<ElementComponentProps> = ({
style={{
...element.style,
position: element.positionType || "relative",
left:
element.positionType === "absolute" ? `${element.position?.x || 0}px` : "auto",
left: element.positionType === "absolute" ? `${element.position?.x || 0}px` : "auto",
top: element.positionType === "absolute" ? `${element.position?.y || 0}px` : "auto",
width: element.size?.width || "auto",
height: element.size?.height || "auto",
@@ -55,16 +40,18 @@ const ElementComponent: React.FC<ElementComponentProps> = ({
e.stopPropagation();
handleElementClick(blockId, element.elementUuid, e);
}}
onMouseDown={(e) => handleElementDragStart(element.elementUuid, e)}
onMouseDown={(e) => {
// Only allow dragging for absolute positioned elements
if (element.positionType === "absolute") {
handleElementDragStart(element.elementUuid, e);
}
}}
>
<ElementContent element={element} resolvedData={resolveElementValue(element)} />
{editMode && (
<>
<div
className="resize-handle"
onMouseDown={(e) => handleElementResizeStart(element.elementUuid, e)}
>
<div className="resize-handle" onMouseDown={(e) => handleElementResizeStart(element.elementUuid, e)}>
<ResizeIcon />
</div>
</>

View File

@@ -187,6 +187,9 @@ function Analyzer() {
// Track previous actions for ArmBots to detect cycle completion
const previousArmBotActionsRef = useRef<Record<string, string | undefined>>({});
// Track previous actions for Machines to detect cycle completion
const previousMachineActionsRef = useRef<Record<string, string | undefined>>({});
// Track previous action counts for Humans to detect completion from EventManager
const previousHumanCountsRef = useRef<Record<string, Record<string, number>>>({});
@@ -228,6 +231,7 @@ function Analyzer() {
bottleneckEventsRef.current = {};
previousAssetStatesRef.current = {};
previousArmBotActionsRef.current = {};
previousMachineActionsRef.current = {};
previousHumanCountsRef.current = {};
previousVehiclePhasesRef.current = {};
previousCranePhasesRef.current = {};
@@ -278,7 +282,7 @@ function Analyzer() {
const calculateQualityMetrics = (assetId: string, totalOperations: number, defects: number, historicalData: any[] = []) => {
const errorCount = errorCountsRef.current[assetId] || 0;
const firstPassYield = totalOperations > 0 ? ((totalOperations - defects) / totalOperations) * 100 : 100;
const firstPassYield = totalOperations > 0 ? ((totalOperations - defects) / totalOperations) * 100 : 0;
const defectRate = totalOperations > 0 ? (defects / totalOperations) * 100 : 0;
const scrapRate = defects > 0 ? defects * 0.1 : 0; // Assuming 10% scrap rate
const reworkRate = defects > 0 ? defects * 0.9 : 0; // Assuming 90% rework
@@ -2395,6 +2399,33 @@ function Analyzer() {
});
}, [armBots, isPlaying]);
// Monitor Machine action changes to track cycles
useEffect(() => {
if (!isPlaying) return;
machines.forEach((machine) => {
const previousActionUuid = previousMachineActionsRef.current[machine.modelUuid];
const currentActionUuid = machine.currentAction?.actionUuid;
// Check if action completed (transition from an action to no action or different action)
if (previousActionUuid && previousActionUuid !== currentActionUuid) {
// Action completed - increment cycles
if (!completedActionsRef.current[machine.modelUuid]) {
completedActionsRef.current[machine.modelUuid] = 0;
}
completedActionsRef.current[machine.modelUuid]++;
// Also update parts processed (assume 1 part per cycle)
if (!completedActionsRef.current[`${machine.modelUuid}_parts`]) {
completedActionsRef.current[`${machine.modelUuid}_parts`] = 0;
}
completedActionsRef.current[`${machine.modelUuid}_parts`]++;
}
previousMachineActionsRef.current[machine.modelUuid] = currentActionUuid;
});
}, [machines, isPlaying]);
// Monitor Human action changes from EventManager
useEffect(() => {
if (!isPlaying || !humanEventManagerRef.current) return;