feat: Add ElementComponent for dashboard UI elements and Analyzer for comprehensive simulation performance tracking.
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user