( events: TimelineEvent[], dataFlows: DataPacket[], currentTime: number, timelineStartTime?: number | null, )
| 258 | }; |
| 259 | |
| 260 | const calculateNodeStates = ( |
| 261 | events: TimelineEvent[], |
| 262 | dataFlows: DataPacket[], |
| 263 | currentTime: number, |
| 264 | timelineStartTime?: number | null, |
| 265 | ): Record<string, NodeVisualState> => { |
| 266 | const states: Record<string, NodeVisualState> = {}; |
| 267 | |
| 268 | if (events.length === 0) { |
| 269 | return states; |
| 270 | } |
| 271 | |
| 272 | const firstEventTimestamp = new Date(events[0].timestamp).getTime(); |
| 273 | const startTime = timelineStartTime ?? firstEventTimestamp; |
| 274 | const absoluteCurrentTime = startTime + currentTime; |
| 275 | const filteredPackets = dataFlows.filter((packet) => { |
| 276 | const packetTime = new Date(packet.timestamp).getTime(); |
| 277 | return packetTime <= absoluteCurrentTime; |
| 278 | }); |
| 279 | |
| 280 | const inputPacketsByNode = new Map<string, DataPacket[]>(); |
| 281 | const outputPacketsByNode = new Map<string, DataPacket[]>(); |
| 282 | |
| 283 | filteredPackets.forEach((packet) => { |
| 284 | if (!inputPacketsByNode.has(packet.targetNode)) { |
| 285 | inputPacketsByNode.set(packet.targetNode, []); |
| 286 | } |
| 287 | inputPacketsByNode.get(packet.targetNode)!.push(packet); |
| 288 | |
| 289 | if (!outputPacketsByNode.has(packet.sourceNode)) { |
| 290 | outputPacketsByNode.set(packet.sourceNode, []); |
| 291 | } |
| 292 | outputPacketsByNode.get(packet.sourceNode)!.push(packet); |
| 293 | }); |
| 294 | |
| 295 | // Group events by node |
| 296 | const nodeEvents = new Map<string, TimelineEvent[]>(); |
| 297 | events.forEach((event) => { |
| 298 | if (event.nodeId) { |
| 299 | if (!nodeEvents.has(event.nodeId)) { |
| 300 | nodeEvents.set(event.nodeId, []); |
| 301 | } |
| 302 | nodeEvents.get(event.nodeId)!.push(event); |
| 303 | } |
| 304 | }); |
| 305 | |
| 306 | // Calculate state for each node |
| 307 | nodeEvents.forEach((nodeEventList, nodeId) => { |
| 308 | const sortedEvents = [...nodeEventList].sort( |
| 309 | (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(), |
| 310 | ); |
| 311 | |
| 312 | const relevantEvents = sortedEvents.filter( |
| 313 | (event) => new Date(event.timestamp).getTime() <= absoluteCurrentTime, |
| 314 | ); |
| 315 | |
| 316 | if (relevantEvents.length === 0) { |
| 317 | states[nodeId] = { |
no test coverage detected