diff --git a/measurements/A.py b/measurements/A.py
new file mode 100644
index 0000000..b7d0fb6
--- /dev/null
+++ b/measurements/A.py
@@ -0,0 +1,76 @@
+# A.py (Client and Primary Measurement Node)
+import concore
+import time
+import os
+import psutil
+import sys
+
+# --- ZMQ Initialization ---
+# This REQ socket connects to Node B
+concore.init_zmq_port(
+ port_name=PORT_NAME_F1_F2,
+ port_type="connect",
+ address="tcp://localhost:" + PORT_F1_F2,
+ socket_type_str="REQ"
+)
+
+print("Node A client started.")
+
+# --- Measurement Initialization ---
+min_latency = float('inf')
+max_latency = 0.0
+total_latency = 0.0
+message_count = 0
+total_bytes = 0
+process = psutil.Process(os.getpid())
+overall_start_time = time.monotonic()
+loop_start_time = 0
+
+current_value = 0
+max_value = 100
+
+while current_value < max_value:
+ loop_start_time = time.monotonic() # Start timer for round-trip latency
+ print(f"Node A: Sending value {current_value:.2f} to Node B.")
+
+ # 1. Send the current value as a request to the pipeline
+ concore.write(PORT_NAME_F1_F2, "value", [current_value])
+ total_bytes += sys.getsizeof([current_value])
+
+ # 2. Wait for the final, processed value in reply
+ received_data = concore.read(PORT_NAME_F1_F2, "value", [0.0])
+
+ loop_end_time = time.monotonic()
+ latency_ms = (loop_end_time - loop_start_time) * 1000
+
+ # Update metrics
+ message_count += 1
+ min_latency = min(min_latency, latency_ms)
+ max_latency = max(max_latency, latency_ms)
+ total_latency += latency_ms
+
+ current_value = received_data[0]
+ print(f"Node A: Received final value {current_value:.2f} from the pipeline. | Latency: {latency_ms:.2f} ms")
+ print("-" * 20)
+
+# --- Finalize and Report Measurements ---
+overall_end_time = time.monotonic()
+total_duration = overall_end_time - overall_start_time
+cpu_usage = process.cpu_percent() / total_duration if total_duration > 0 else 0
+avg_latency = total_latency / message_count if message_count > 0 else 0
+
+print("\n" + "="*35)
+print("--- NODE A: END-TO-END RESULTS ---")
+print(f"Total pipeline iterations: {message_count}")
+print(f"Total data sent: {total_bytes / 1024:.4f} KB")
+print(f"Total End-to-End Time: {total_duration:.4f} seconds")
+print("-" * 35)
+print(f"Min round-trip latency: {min_latency:.2f} ms")
+print(f"Avg round-trip latency: {avg_latency:.2f} ms")
+print(f"Max round-trip latency: {max_latency:.2f} ms")
+print("-" * 35)
+print(f"Approximate CPU usage: {cpu_usage:.2f}%")
+print("="*35)
+
+print(f"\nNode A: Final value {current_value:.2f} reached the target. Terminating.")
+concore.terminate_zmq()
diff --git a/measurements/B.py b/measurements/B.py
new file mode 100644
index 0000000..8ab05d0
--- /dev/null
+++ b/measurements/B.py
@@ -0,0 +1,60 @@
+# B.py (Broker with Measurements)
+import concore
+import time
+
+# --- ZMQ Initialization ---
+# This REP socket binds and waits for requests from Node A
+concore.init_zmq_port(
+ port_name=PORT_NAME_F1_F2,
+ port_type="bind",
+ address="tcp://*:" + PORT_F1_F2,
+ socket_type_str="REP"
+)
+# This REQ socket connects to Node C
+concore.init_zmq_port(
+ port_name=PORT_NAME_F2_F3,
+ port_type="connect",
+ address="tcp://localhost:" + PORT_F2_F3,
+ socket_type_str="REQ"
+)
+
+print("Node B broker started. Waiting for requests...")
+
+# --- Measurement Initialization ---
+start_time = time.monotonic()
+messages_routed = 0
+
+while True:
+ # 1. Wait for a request from Node A
+ value_from_a = concore.read(PORT_NAME_F1_F2, "value", [0.0])
+ received_value = value_from_a[0]
+ print(f"Node B: Received {received_value:.2f} from Node A. Forwarding to C...")
+
+ # 2. Send the received value as a new request to Node C
+ concore.write(PORT_NAME_F2_F3, "value", [received_value])
+
+ # 3. Wait for the reply from Node C
+ value_from_c = concore.read(PORT_NAME_F2_F3, "value", [0.0])
+ processed_value = value_from_c[0]
+ print(f"Node B: Received {processed_value:.2f} from Node C. Replying to A...")
+
+ # 4. Send the processed value back as a reply to Node A
+ concore.write(PORT_NAME_F1_F2, "value", [processed_value])
+ messages_routed += 1
+
+ # 5. Check termination condition
+ if processed_value >= 100:
+ break
+
+# --- Finalize and Report Measurements ---
+end_time = time.monotonic()
+duration = end_time - start_time
+
+print("\n" + "="*30)
+print("--- NODE B: RESULTS ---")
+print(f"Total messages routed: {messages_routed}")
+print(f"Total execution time: {duration:.4f} seconds")
+print("="*30)
+
+print("\nNode B: Terminating.")
+concore.terminate_zmq()
diff --git a/measurements/C.py b/measurements/C.py
new file mode 100644
index 0000000..1448069
--- /dev/null
+++ b/measurements/C.py
@@ -0,0 +1,62 @@
+# C.py (Processing Server and Measurement Endpoint)
+import concore
+import time
+import psutil
+import os
+import sys
+
+# --- ZMQ Initialization ---
+# This REP socket binds and waits for requests from Node B
+concore.init_zmq_port(
+ port_name=PORT_NAME_F2_F3,
+ port_type="bind",
+ address="tcp://*:" + PORT_F2_F3,
+ socket_type_str="REP"
+)
+
+print("Node C server started. Waiting for requests...")
+
+# --- Measurement Initialization ---
+process = psutil.Process(os.getpid())
+start_time = time.monotonic()
+message_count = 0
+total_bytes = 0
+
+while True:
+ # 1. Wait to receive a request from Node B
+ received_data = concore.read(PORT_NAME_F2_F3, "value", [0.0])
+ received_value = received_data[0]
+
+ # Track received data for metrics
+ message_count += 1
+ total_bytes += sys.getsizeof(received_data)
+
+ print(f"Node C: Received {received_value:.2f} from Node B.")
+
+ # 2. Process the value (increment by 10)
+ new_value = received_value + 10
+ print(f"Node C: Sending back processed value {new_value:.2f}.")
+
+ # 3. Send the reply back to Node B
+ concore.write(PORT_NAME_F2_F3, "value", [new_value])
+
+ # 4. Check the value to know when to shut down gracefully.
+ if new_value >= 100:
+ break
+
+# --- Finalize and Report Measurements ---
+end_time = time.monotonic()
+duration = end_time - start_time
+# This captures the CPU usage over the process's lifetime relative to the test duration
+cpu_usage = process.cpu_percent() / duration if duration > 0 else 0
+
+print("\n" + "="*30)
+print("--- NODE C: RESULTS ---")
+print(f"Total messages processed: {message_count}")
+print(f"Total data processed: {total_bytes / 1024:.4f} KB")
+print(f"Total execution time: {duration:.4f} seconds")
+print(f"Approximate CPU usage: {cpu_usage:.2f}%")
+print("="*30)
+
+print("\nNode C: Terminating.")
+concore.terminate_zmq()
diff --git a/measurements/ZeroMQOnly.graphml b/measurements/ZeroMQOnly.graphml
new file mode 100644
index 0000000..e2d88c6
--- /dev/null
+++ b/measurements/ZeroMQOnly.graphml
@@ -0,0 +1,280 @@
+
+
+
+
+
+
+
+
+
+
+
+ F1:A.py
+
+
+
+
+
+
+
+
+
+
+ F2:B.py
+
+
+
+
+
+
+
+
+
+
+ F3:C.py
+
+
+
+
+
+
+
+
+
+ 0x1234_U
+
+
+
+
+
+
+
+
+
+
+
+ 0x1235_Y
+
+
+
+
+
+
+
+ 1750189426493
+
+ DEL_NODE
+ WyIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiXQ==
+
+
+ ADD_NODE
+ WyJGMTpmaXJzdE5vZGUucHkiLHsid2lkdGgiOjEyOCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjoxMTYsInkiOjExMH0se30sIjNhMGU3YTg1LTFlYjAtNDE3My1hYjRmLTE0ZmQwZDdjN2E2ZiJd
+
+ 326ab944dc81b1821c8da10835df1b91
+
+
+ 1750189429966
+
+ SET_POS
+ WyIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTY5LCJ5IjoyNTh9XQ==
+
+
+ SET_POS
+ WyIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiLHsieCI6MTY5LCJ5IjoyNTh9LHsieCI6MTAwLCJ5IjoxMDB9XQ==
+
+ 680f94c71c2a0a6c26cb302206337ac4
+
+
+ 1750189440456
+
+ DEL_NODE
+ WyI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiXQ==
+
+
+ ADD_NODE
+ WyJGMjpzZWNvbmROb2RlLnB5Iix7IndpZHRoIjoxNTQsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NDA1LCJ5IjozMTh9LHt9LCI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiXQ==
+
+ 3d9bcbaa70f3846f8254748756b5cb84
+
+
+ 1750189448750
+
+ SET_POS
+ WyI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDE3LCJ5IjoyNTh9XQ==
+
+
+ SET_POS
+ WyI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiLHsieCI6NDE3LCJ5IjoyNTh9LHsieCI6MTAwLCJ5IjoxMDB9XQ==
+
+ a191948b47544272a56a2f705214ab55
+
+
+ 1750189460209
+
+ DEL_NODE
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiXQ==
+
+
+ ADD_NODE
+ WyJGMzp0aGlyZE5vZGUucHkiLHsid2lkdGgiOjEzNCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4Ijo2OTcsInkiOjExMH0se30sImYzMWNmY2ViLTk3MjctNDg4Zi04Y2E0LWY0MWQ0ZTM2MGUzOSJd
+
+ 69b8535e1d43f1d7f6ce343dff130655
+
+
+ 1750189464533
+
+ SET_POS
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6Njg4LCJ5IjoyNTd9XQ==
+
+
+ SET_POS
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsieCI6Njg4LCJ5IjoyNTd9LHsieCI6MTAwLCJ5IjoxMDB9XQ==
+
+ eaf400a73bea2db0fcb4d24fdc1e511c
+
+
+ 1750189470864
+
+ SET_POS
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsieCI6Njg4LCJ5IjoyNTd9LHsieCI6NjgwLCJ5IjoyNTl9XQ==
+
+
+ SET_POS
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsieCI6NjgwLCJ5IjoyNTl9LHsieCI6Njg4LCJ5IjoyNTd9XQ==
+
+ b077669aa6784b6d6783a10c1dc4cdd9
+
+
+ 1750189472901
+
+ DEL_EDGE
+ WyJkMGVjZGNlNy02MTI1LTRjNzAtOTBmNC02NDVkMTg0OTRhYmYiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiLCJ0YXJnZXRJRCI6IjcxMjYxMGRkLWZkMzQtNDQxZS05OTk5LTgyYjI0MDVhM2Q1ZSIsImxhYmVsIjoiMHg0NTY3X1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJkMGVjZGNlNy02MTI1LTRjNzAtOTBmNC02NDVkMTg0OTRhYmYifV0=
+
+ d24a689c7eaa05ea16bae0fe52dd67d1
+
+
+ 1750189489267
+
+ SET_POS
+ WyIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiLHsieCI6MTY5LCJ5IjoyNTh9LHsieCI6MTE2LCJ5IjoxMTB9XQ==
+
+
+ SET_POS
+ WyIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiLHsieCI6MTE2LCJ5IjoxMTB9LHsieCI6MTY5LCJ5IjoyNTh9XQ==
+
+ 5a81d32b9be7e01c9a3ee322528734ee
+
+
+ 1750189491699
+
+ SET_POS
+ WyI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiLHsieCI6NDE3LCJ5IjoyNTh9LHsieCI6NDA1LCJ5IjozMTh9XQ==
+
+
+ SET_POS
+ WyI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiLHsieCI6NDA1LCJ5IjozMTh9LHsieCI6NDE3LCJ5IjoyNTh9XQ==
+
+ 3d5e1d4dd3c116825682ca44a7ff6df9
+
+
+ 1750189499398
+
+ SET_POS
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsieCI6NjgwLCJ5IjoyNTl9LHsieCI6Njk3LCJ5IjoxMTB9XQ==
+
+
+ SET_POS
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsieCI6Njk3LCJ5IjoxMTB9LHsieCI6NjgwLCJ5IjoyNTl9XQ==
+
+ 8cd64e7bd8e811a830c632b7b27eb005
+
+
+ 1750189502566
+
+ DEL_EDGE
+ WyI2MWI0OTQ0Yi1iOWU5LTRmMmUtOWE4Mi0zMDA0ZmZlMzFlYTYiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiLCJ0YXJnZXRJRCI6ImYzMWNmY2ViLTk3MjctNDg4Zi04Y2E0LWY0MWQ0ZTM2MGUzOSIsImxhYmVsIjoiMHg1Njc4X1kiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6bnVsbCwic2hhcGUiOiJzb2xpZCJ9LCJpZCI6IjYxYjQ5NDRiLWI5ZTktNGYyZS05YTgyLTMwMDRmZmUzMWVhNiJ9XQ==
+
+ 771e97ad0acb41eb9d328619db10ceda
+
+
+ 1750189516115
+
+ UPDATE_EDGE
+ WyJkMGVjZGNlNy02MTI1LTRjNzAtOTBmNC02NDVkMTg0OTRhYmYiLHsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiMHg0NTY3X1UxIix0cnVlXQ==
+
+
+ UPDATE_EDGE
+ WyJkMGVjZGNlNy02MTI1LTRjNzAtOTBmNC02NDVkMTg0OTRhYmYiLHsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiMHg0NTY3X1UiLHRydWVd
+
+ 5b03334dacd3a042b436831f9d5ef10f
+
+
+ 1750189753337
+
+ UPDATE_NODE
+ WyIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiLHsid2lkdGgiOjEyOCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmaXJzdE5vZGUucHkiLHRydWVd
+
+
+ UPDATE_NODE
+ WyIzYTBlN2E4NS0xZWIwLTQxNzMtYWI0Zi0xNGZkMGQ3YzdhNmYiLHsid2lkdGgiOjEyOCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpBLnB5Iix0cnVlXQ==
+
+ 2ab3b1eeaa702bb111bf269e23855761
+
+
+ 1750189765951
+
+ UPDATE_NODE
+ WyI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiLHsid2lkdGgiOjE1NCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpzZWNvbmROb2RlLnB5Iix0cnVlXQ==
+
+
+ UPDATE_NODE
+ WyI3MTI2MTBkZC1mZDM0LTQ0MWUtOTk5OS04MmIyNDA1YTNkNWUiLHsid2lkdGgiOjE1NCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpCLnB5Iix0cnVlXQ==
+
+ e2494c096e25828dd77c851848832639
+
+
+ 1750189773017
+
+ UPDATE_NODE
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsid2lkdGgiOjEzNCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMzp0aGlyZE5vZGUucHkiLHRydWVd
+
+
+ UPDATE_NODE
+ WyJmMzFjZmNlYi05NzI3LTQ4OGYtOGNhNC1mNDFkNGUzNjBlMzkiLHsid2lkdGgiOjEzNCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMzpDLnB5Iix0cnVlXQ==
+
+ 5b9df460bea4d01e2ef0261302e1e7c1
+
+
+ 1750191811368
+
+ UPDATE_EDGE
+ WyJlNDhhZjM3NS03Mjc1LTRhOTQtOWExZC00YmQ2NmM3MzQ1NDgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4NDU2N19VIix0cnVlXQ==
+
+
+ UPDATE_EDGE
+ WyJlNDhhZjM3NS03Mjc1LTRhOTQtOWExZC00YmQ2NmM3MzQ1NDgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MTIzNF9VIix0cnVlXQ==
+
+ 46236a6533af1eb9059e6953fd17dd63
+
+
+ 1750191817718
+
+ UPDATE_EDGE
+ WyI5ZDEyNmRjMi05NjVhLTQxZjMtODA2ZS00ZmZlNzU4YTc2ZjMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4NTY3OF9ZIix0cnVlXQ==
+
+
+ UPDATE_EDGE
+ WyI5ZDEyNmRjMi05NjVhLTQxZjMtODA2ZS00ZmZlNzU4YTc2ZjMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MTIzNV9ZIix0cnVlXQ==
+
+ e4ead03fe18f22635d9cea49ae008114
+
+
+
\ No newline at end of file
diff --git a/measurements/comm_node_test.dir/concore2.py b/measurements/comm_node_test.dir/concore2.py
new file mode 100644
index 0000000..a018ddf
--- /dev/null
+++ b/measurements/comm_node_test.dir/concore2.py
@@ -0,0 +1,263 @@
+import time
+import os
+from ast import literal_eval
+import sys
+import re
+import zmq # Added for ZeroMQ
+
+#if windows, create script to kill this process
+# because batch files don't provide easy way to know pid of last command
+# ignored for posix!=windows, because "concorepid" is handled by script
+# ignored for docker (linux!=windows), because handled by docker stop
+if hasattr(sys, 'getwindowsversion'):
+ with open("concorekill.bat","w") as fpid:
+ fpid.write("taskkill /F /PID "+str(os.getpid())+"\n")
+
+# --- ZeroMQ Integration Start ---
+class ZeroMQPort:
+ def __init__(self, port_type, address, zmq_socket_type):
+ self.context = zmq.Context()
+ self.socket = self.context.socket(zmq_socket_type)
+ self.port_type = port_type # "bind" or "connect"
+ self.address = address
+ if self.port_type == "bind":
+ self.socket.bind(address)
+ print(f"ZMQ Port bound to {address}")
+ else:
+ self.socket.connect(address)
+ print(f"ZMQ Port connected to {address}")
+
+# Global ZeroMQ ports registry
+zmq_ports = {}
+
+def init_zmq_port(port_name, port_type, address, socket_type_str):
+ """
+ Initializes and registers a ZeroMQ port.
+ port_name (str): A unique name for this ZMQ port.
+ port_type (str): "bind" or "connect".
+ address (str): The ZMQ address (e.g., "tcp://*:5555", "tcp://localhost:5555").
+ socket_type_str (str): String representation of ZMQ socket type (e.g., "REQ", "REP", "PUB", "SUB").
+ """
+ if port_name in zmq_ports:
+ print(f"ZMQ Port {port_name} already initialized.")
+ return # Avoid reinitialization
+
+ try:
+ # Map socket type string to actual ZMQ constant (e.g., zmq.REQ, zmq.REP)
+ zmq_socket_type = getattr(zmq, socket_type_str.upper())
+ zmq_ports[port_name] = ZeroMQPort(port_type, address, zmq_socket_type)
+ print(f"Initialized ZMQ port: {port_name} ({socket_type_str}) on {address}")
+ except AttributeError:
+ print(f"Error: Invalid ZMQ socket type string '{socket_type_str}'.")
+ except zmq.error.ZMQError as e:
+ print(f"Error initializing ZMQ port {port_name} on {address}: {e}")
+ except Exception as e:
+ print(f"An unexpected error occurred during ZMQ port initialization for {port_name}: {e}")
+
+def terminate_zmq():
+ for port in zmq_ports.values():
+ try:
+ port.socket.close()
+ port.context.term()
+ except Exception as e:
+ print(f"Error while terminating ZMQ port {port.address}: {e}")
+# --- ZeroMQ Integration End ---
+
+def safe_literal_eval(filename, defaultValue):
+ try:
+ with open(filename, "r") as file:
+ return literal_eval(file.read())
+ except (FileNotFoundError, SyntaxError, ValueError, Exception) as e:
+ # Keep print for debugging, but can be made quieter
+ # print(f"Info: Error reading {filename} or file not found, using default: {e}")
+ return defaultValue
+
+iport = safe_literal_eval("concore.iport", {})
+oport = safe_literal_eval("concore.oport", {})
+
+s = ''
+olds = ''
+delay = 1
+retrycount = 0
+inpath = "./in" #must be rel path for local
+outpath = "./out"
+simtime = 0
+
+#9/21/22
+try:
+ sparams_path = os.path.join(inpath + "1", "concore.params")
+ if os.path.exists(sparams_path):
+ with open(sparams_path, "r") as f:
+ sparams = f.read()
+ if sparams: # Ensure sparams is not empty
+ if sparams[0] == '"' and sparams[-1] == '"': #windows keeps "" need to remove
+ sparams = sparams[1:-1]
+ if sparams != '{' and not (sparams.startswith('{') and sparams.endswith('}')): # Check if it needs conversion
+ print("converting sparams: "+sparams)
+ sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}"
+ print("converted sparams: " + sparams)
+ try:
+ params = literal_eval(sparams)
+ except Exception as e:
+ print(f"bad params content: {sparams}, error: {e}")
+ params = dict()
+ else:
+ params = dict()
+ else:
+ params = dict()
+except Exception as e:
+ # print(f"Info: concore.params not found or error reading, using empty dict: {e}")
+ params = dict()
+
+#9/30/22
+def tryparam(n, i):
+ return params.get(n, i)
+
+
+#9/12/21
+def default_maxtime(default):
+ global maxtime
+ maxtime_path = os.path.join(inpath + "1", "concore.maxtime")
+ maxtime = safe_literal_eval(maxtime_path, default)
+
+default_maxtime(100)
+
+def unchanged():
+ global olds, s
+ if olds == s:
+ s = ''
+ return True
+ olds = s
+ return False
+
+def read(port_identifier, name, initstr_val):
+ global s, simtime, retrycount
+
+ default_return_val = initstr_val
+ if isinstance(initstr_val, str):
+ try:
+ default_return_val = literal_eval(initstr_val)
+ except (SyntaxError, ValueError):
+ pass
+
+ if isinstance(port_identifier, str) and port_identifier in zmq_ports:
+ zmq_p = zmq_ports[port_identifier]
+ try:
+ message = zmq_p.socket.recv_json()
+ return message
+ except zmq.error.ZMQError as e:
+ print(f"ZMQ read error on port {port_identifier} (name: {name}): {e}. Returning default.")
+ return default_return_val
+ except Exception as e:
+ print(f"Unexpected error during ZMQ read on port {port_identifier} (name: {name}): {e}. Returning default.")
+ return default_return_val
+
+ try:
+ file_port_num = int(port_identifier)
+ except ValueError:
+ print(f"Error: Invalid port identifier '{port_identifier}' for file operation. Must be integer or ZMQ name.")
+ return default_return_val
+
+ time.sleep(delay)
+ file_path = os.path.join(inpath+str(file_port_num), name)
+ ins = ""
+
+ try:
+ with open(file_path, "r") as infile:
+ ins = infile.read()
+ except FileNotFoundError:
+ ins = str(initstr_val)
+ except Exception as e:
+ print(f"Error reading {file_path}: {e}. Using default value.")
+ return default_return_val
+
+ attempts = 0
+ max_retries = 5
+ while len(ins) == 0 and attempts < max_retries:
+ time.sleep(delay)
+ try:
+ with open(file_path, "r") as infile:
+ ins = infile.read()
+ except Exception as e:
+ print(f"Retry {attempts + 1}: Error reading {file_path} - {e}")
+ attempts += 1
+ retrycount += 1
+
+ if len(ins) == 0:
+ print(f"Max retries reached for {file_path}, using default value.")
+ return default_return_val
+
+ s += ins
+ try:
+ inval = literal_eval(ins)
+ if isinstance(inval, list) and len(inval) > 0:
+ current_simtime_from_file = inval[0]
+ if isinstance(current_simtime_from_file, (int, float)):
+ simtime = max(simtime, current_simtime_from_file)
+ return inval[1:]
+ else:
+ print(f"Warning: Unexpected data format in {file_path}: {ins}. Returning raw content or default.")
+ return inval
+ except Exception as e:
+ print(f"Error parsing content from {file_path} ('{ins}'): {e}. Returning default.")
+ return default_return_val
+
+
+def write(port_identifier, name, val, delta=0):
+ global simtime
+
+ if isinstance(port_identifier, str) and port_identifier in zmq_ports:
+ zmq_p = zmq_ports[port_identifier]
+ try:
+ zmq_p.socket.send_json(val)
+ except zmq.error.ZMQError as e:
+ print(f"ZMQ write error on port {port_identifier} (name: {name}): {e}")
+ except Exception as e:
+ print(f"Unexpected error during ZMQ write on port {port_identifier} (name: {name}): {e}")
+ return
+ try:
+ if isinstance(port_identifier, str) and port_identifier in zmq_ports:
+ file_path = os.path.join("../"+port_identifier, name)
+ else:
+ file_port_num = int(port_identifier)
+ file_path = os.path.join(outpath+str(file_port_num), name)
+ except ValueError:
+ print(f"Error: Invalid port identifier '{port_identifier}' for file operation. Must be integer or ZMQ name.")
+ return
+
+ if isinstance(val, str):
+ time.sleep(2 * delay)
+ elif not isinstance(val, list):
+ print(f"File write to {file_path} must have list or str value, got {type(val)}")
+ return
+
+ try:
+ with open(file_path, "w") as outfile:
+ if isinstance(val, list):
+ data_to_write = [simtime + delta] + val
+ outfile.write(str(data_to_write))
+ simtime += delta
+ else:
+ outfile.write(val)
+ except Exception as e:
+ print(f"Error writing to {file_path}: {e}")
+
+def initval(simtime_val_str):
+ global simtime
+ try:
+ val = literal_eval(simtime_val_str)
+ if isinstance(val, list) and len(val) > 0:
+ first_element = val[0]
+ if isinstance(first_element, (int, float)):
+ simtime = first_element
+ return val[1:]
+ else:
+ print(f"Error: First element in initval string '{simtime_val_str}' is not a number. Using data part as is or empty.")
+ return val[1:] if len(val) > 1 else []
+ else:
+ print(f"Error: initval string '{simtime_val_str}' is not a list or is empty. Returning empty list.")
+ return []
+
+ except Exception as e:
+ print(f"Error parsing simtime_val_str '{simtime_val_str}': {e}. Returning empty list.")
+ return []
\ No newline at end of file
diff --git a/measurements/comm_node_test.py b/measurements/comm_node_test.py
new file mode 100644
index 0000000..dac015e
--- /dev/null
+++ b/measurements/comm_node_test.py
@@ -0,0 +1,68 @@
+import concore
+import concore2
+import time
+import sys
+
+# --- Script Configuration ---
+concore.delay = 0.07
+concore2.delay = 0.07
+concore2.inpath = concore.inpath
+concore2.outpath = concore.outpath
+concore2.simtime = 0
+concore.default_maxtime(100) # This will be ignored by the new logic
+init_simtime_u = "[0.0, 0.0, 0.0]"
+init_simtime_ym = "[0.0, 0.0, 0.0]"
+
+# --- Measurement Initialization ---
+messages_processed = 0
+start_time = time.monotonic()
+
+# --- Main Script Logic ---
+u = concore.initval(init_simtime_u)
+ym = concore2.initval(init_simtime_ym)
+curr = 0
+max_value = 100
+iteration = 0
+iteration_limit = 15 # Safety break
+
+print("comm_node_test.py started...")
+
+while curr < max_value and iteration < iteration_limit:
+ # 1. Wait for a message from the 'u' channel
+ while concore.unchanged():
+ u = concore.read(concore.iport['U'], "u", init_simtime_u)
+
+ # 2. Forward it to the 'U1' channel
+ concore.write(concore.oport['U1'], "u", u)
+ curr = u[0]
+
+ # Break if the loop condition is met after the first read
+ if curr >= max_value:
+ # Forward a final message to ensure the next node also terminates
+ concore2.write(concore.oport['Y'], "ym", [curr])
+ break
+
+ # 3. Wait for a message from the 'Y1' channel
+ old2 = concore2.simtime
+ while concore2.unchanged() or concore2.simtime <= old2:
+ ym = concore2.read(concore.iport['Y1'], "ym", init_simtime_ym)
+
+ # 4. Forward it to the 'Y' channel
+ concore2.write(concore.oport['Y'], "ym", ym)
+ curr = ym[0]
+
+ print(f"comm_node: u={u[0]:.2f} | ym={ym[0]:.2f}")
+
+ messages_processed += 2 # Counting one read and one write as two "processed" messages
+ iteration += 1
+
+# --- Finalize and Report Measurements ---
+end_time = time.monotonic()
+duration = end_time - start_time
+
+print("\n" + "="*30)
+print("--- COMM_NODE_TEST: FINAL RESULTS ---")
+print(f"Total messages routed: {messages_processed}")
+print(f"Total execution time: {duration:.4f} seconds")
+print(f"concore retry count: {concore.retrycount}")
+print("="*30)
diff --git a/measurements/cpymax_test.py b/measurements/cpymax_test.py
new file mode 100644
index 0000000..c7b50ed
--- /dev/null
+++ b/measurements/cpymax_test.py
@@ -0,0 +1,78 @@
+import concore
+import time
+import os
+import psutil
+import sys
+
+# --- Measurement & Script Configuration ---
+concore.delay = 0.01
+init_simtime_u = "[0.0, 0.0, 0.0]"
+init_simtime_ym = "[0.0, 0.0, 0.0]"
+
+# --- Measurement Initialization ---
+min_latency = float('inf')
+max_latency = 0.0
+total_latency = 0.0
+message_count = 0
+total_bytes = 0
+process = psutil.Process(os.getpid())
+overall_start_time = time.monotonic()
+wallclock1 = time.perf_counter()
+
+# --- Main Script Logic ---
+u = concore.initval(init_simtime_u)
+curr = 0.0
+max_value = 100.0
+iteration_limit = 15 # Safety break
+iteration = 0
+
+print("cpymax_test.py started...")
+
+# Initiate the loop by writing an initial value
+print(f"ym=N/A u={u[0]:.2f} (initial)")
+concore.write(1, "u", u)
+
+while curr < max_value and iteration < iteration_limit:
+ # Wait for the processed value to come back
+ while concore.unchanged():
+ ym = concore.read(1, "ym", init_simtime_ym)
+
+ wallclock2 = time.perf_counter()
+ latency_ms = (wallclock2 - wallclock1) * 1000 # Round-trip time in milliseconds
+
+ # Update metrics
+ message_count += 1
+ total_bytes += sys.getsizeof(ym)
+ min_latency = min(min_latency, latency_ms)
+ max_latency = max(max_latency, latency_ms)
+ total_latency += latency_ms
+
+ # Prepare next value
+ u[0] = ym[0]
+ curr = u[0]
+ print(f"ym={ym[0]:.2f} u={u[0]:.2f} | Latency: {latency_ms:.2f} ms")
+
+ # Write the value back into the loop
+ concore.write(1, "u", u)
+ wallclock1 = time.perf_counter() # Reset timer for next round-trip
+ iteration += 1
+
+# --- Finalize and Report Measurements ---
+overall_end_time = time.monotonic()
+total_duration = overall_end_time - overall_start_time
+cpu_usage = process.cpu_percent() / total_duration if total_duration > 0 else 0
+avg_latency = total_latency / message_count if message_count > 0 else 0
+
+print("\n" + "="*30)
+print("--- CPYMAX_TEST: FINAL RESULTS ---")
+print(f"Total loop iterations: {message_count}")
+print(f"Total data received: {total_bytes / 1024:.4f} KB")
+print(f"Total execution time: {total_duration:.4f} seconds")
+print("-" * 30)
+print(f"Min round-trip latency: {min_latency:.2f} ms")
+print(f"Avg round-trip latency: {avg_latency:.2f} ms")
+print(f"Max round-trip latency: {max_latency:.2f} ms")
+print("-" * 30)
+print(f"Approximate CPU usage: {cpu_usage:.2f}%")
+print(f"concore retry count: {concore.retrycount}")
+print("="*30)
diff --git a/measurements/fileOnlyCommunication.graphml b/measurements/fileOnlyCommunication.graphml
new file mode 100644
index 0000000..522cad1
--- /dev/null
+++ b/measurements/fileOnlyCommunication.graphml
@@ -0,0 +1,508 @@
+
+
+
+
+
+
+
+
+
+
+
+ PZ:pmpymax_test.py
+
+
+
+
+
+
+
+
+
+
+ CZ:cpymax_test.py
+
+
+
+
+
+
+
+
+
+
+ F1:comm_node_test.py
+
+
+
+
+
+
+
+
+
+ U
+
+
+
+
+
+
+
+
+
+
+
+ Y
+
+
+
+
+
+
+
+
+
+
+
+ U1
+
+
+
+
+
+
+
+
+
+
+
+ Y1
+
+
+
+
+
+
+
+ 1664644923582
+
+ DEL_NODE
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciXQ==
+
+
+ ADD_NODE
+ WyJQWjpwbXB5bWF4LnB5Iix7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0se30sImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyJd
+
+ a53a7f7273a40c7970938b6de1829249
+
+
+ 1664644939781
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH1d
+
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH0seyJ4IjoxMDAsInkiOjEwMH1d
+
+ 3d4a875a8a6ea281598aa70364b0ea82
+
+
+ 1664644951652
+
+ DEL_NODE
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiXQ==
+
+
+ ADD_NODE
+ WyJDWjpjcHltYXgucHkiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotMTM3Ljc3NjIwMzU0OTQyMzgzLCJ5Ijo5MS4zMjAxMjcwNjgyNTY0MX0se30sImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSJd
+
+ 5ed7e3d12fd25656b2ad03e29c307d65
+
+
+ 1664644958838
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfV0=
+
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfSx7IngiOjEwMCwieSI6MTAwfV0=
+
+ 35c613c8203b65e1f44e066b3d783143
+
+
+ 1664644988539
+
+ DEL_NODE
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiXQ==
+
+
+ ADD_NODE
+ WyJGMTpmdW5jYWxsLnB5Iix7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0se30sImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCJd
+
+ 33d0b0cc4d3dbe3c42323e33f06993e9
+
+
+ 1664645002278
+
+ DEL_NODE
+ WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ==
+
+
+ ADD_NODE
+ WyJGMjpmdW5ib2R5LnB5Iix7IndpZHRoIjoxMjAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHt9LCJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ==
+
+ 8d0d4a735631afe6241c66143fb29db8
+
+
+ 1664645010353
+
+ SET_POS
+ WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MTEwLCJ5IjoxMTB9LHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d
+
+
+ SET_POS
+ WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX0seyJ4IjoxMTAsInkiOjExMH1d
+
+ 8a01a9ca8b3706bc3b1ce4de33669b6d
+
+
+ 1664645015576
+
+ DEL_EDGE
+ WyIwZjk1MWZiYy0wZDNmLTQzYzAtYmJmMC04NjViYzQ3ZjEyMGUiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiVSIsInN0eWxlIjp7InRoaWNrbmVzcyI6MSwiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInNoYXBlIjoic29saWQifSwiaWQiOiIwZjk1MWZiYy0wZDNmLTQzYzAtYmJmMC04NjViYzQ3ZjEyMGUifV0=
+
+ 14416fc2e3c48db65e2b5e1012027ee0
+
+
+ 1664645043815
+
+ DEL_EDGE
+ WyIzY2ZiNDBjZC01NTdhLTQ4NTAtOTNhNi1mZGMwOWNkMDA1ZjAiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiVTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiM2NmYjQwY2QtNTU3YS00ODUwLTkzYTYtZmRjMDljZDAwNWYwIn1d
+
+ 326a920ffd7e662bc64ca95c086fb9de
+
+
+ 1664645057658
+
+ DEL_EDGE
+ WyI3MTRkYjk4OS01NjcyLTQwM2ItYWU3Ni1mZDlhMjA4OTM0NzUiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiVTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiNzE0ZGI5ODktNTY3Mi00MDNiLWFlNzYtZmQ5YTIwODkzNDc1In1d
+
+ 4593337e9924ae4b23dc5c5576c31394
+
+
+ 1664645068951
+
+ DEL_EDGE
+ WyJhOGFlNzg5MC1iMmJiLTQyNzMtODc1My0wMTgxY2ViNDg2YzEiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiWTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiYThhZTc4OTAtYjJiYi00MjczLTg3NTMtMDE4MWNlYjQ4NmMxIn1d
+
+ 568d8b7a109ffacc4b912095793cb2ca
+
+
+ 1664645081283
+
+ DEL_EDGE
+ WyI1NWI5OWFiNi1hN2Q2LTRjNjctYWI0ZS1hOGUyOTM5YzFiMGYiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiWTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiNTViOTlhYjYtYTdkNi00YzY3LWFiNGUtYThlMjkzOWMxYjBmIn1d
+
+ 0d0aa0179f22f9d73a11f8ccfbcc145e
+
+
+ 1664645089735
+
+ SET_POS
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX1d
+
+
+ SET_POS
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4IjoxMDAsInkiOjEwMH1d
+
+ 1c19591402c0f2daca7d2b4a8af5e956
+
+
+ 1664645092868
+
+ DEL_EDGE
+ WyI3OWE1NDdmNS02NzBhLTQ1ZjYtYTc4My02ZGI4ZmYwZTY1NTkiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSIsImxhYmVsIjoiWSIsInN0eWxlIjp7InRoaWNrbmVzcyI6MSwiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInNoYXBlIjoic29saWQifSwiaWQiOiI3OWE1NDdmNS02NzBhLTQ1ZjYtYTc4My02ZGI4ZmYwZTY1NTkifV0=
+
+ 3c913497d8aa8f1c79bbdc03c3feec16
+
+
+ 1664645142026
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfSx7IngiOi0xNzAuNDQxMDYwODg1NDY2OTUsInkiOjkwLjAxMzUzMjc3NDgxNDY5fV0=
+
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9LHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfV0=
+
+ ecbd46b28ecaf800c8da0d2ada69b4de
+
+
+ 1664645149601
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH0seyJ4Ijo3NTQuNDAxODgxNDA3MTk2NSwieSI6OTkuMTM1NzM0OTcxOTM2NjR9XQ==
+
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NzU0LjQwMTg4MTQwNzE5NjUsInkiOjk5LjEzNTczNDk3MTkzNjY0fSx7IngiOjQwNC4yMzQ2MTA3NjQ4MTQyLCJ5IjotODkuMDEzODQzMjgzNjcxNzh9XQ==
+
+ ea35c112764d7964f8b7e35e9a18efbd
+
+
+ 1664645223291
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NzU0LjQwMTg4MTQwNzE5NjUsInkiOjk5LjEzNTczNDk3MTkzNjY0fSx7IngiOjY3Ni4wMDYyMjM4MDA2OTMsInkiOjEwMC40NDIzMjkyNjUzNzgzNn1d
+
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6Njc2LjAwNjIyMzgwMDY5MywieSI6MTAwLjQ0MjMyOTI2NTM3ODM2fSx7IngiOjc1NC40MDE4ODE0MDcxOTY1LCJ5Ijo5OS4xMzU3MzQ5NzE5MzY2NH1d
+
+ d669d3d37a4693ad860a18c69999b31f
+
+
+ 1664645228453
+
+ SET_POS
+ WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX0seyJ4IjozMzYuMDE4NjM3MDg1NTg2NjUsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d
+
+
+ SET_POS
+ WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d
+
+ f7eb6af4003cb4eff19f39421fc00174
+
+
+ 1664645231883
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6Njc2LjAwNjIyMzgwMDY5MywieSI6MTAwLjQ0MjMyOTI2NTM3ODM2fSx7IngiOjU4Ny4xNTc4MTE4NDY2NTU2LCJ5IjoxMDAuNDQyMzI5MjY1Mzc4MzZ9XQ==
+
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJ4Ijo2NzYuMDA2MjIzODAwNjkzLCJ5IjoxMDAuNDQyMzI5MjY1Mzc4MzZ9XQ==
+
+ 49dd0c2013be6e39c2f11ea967dbcab4
+
+
+ 1664645237206
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9LHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9XQ==
+
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9XQ==
+
+ 009fc03903a9ae6003caea49a6575ddb
+
+
+ 1664646509534
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiVTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sInR5cGUiOiJvcmRpbiIsInNvdXJjZSI6IjYyOGMyOTI0LWI2YzEtNDBjNi05ZjM5LTZjMDUxNmI3MGI1YSIsInRhcmdldCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImJlbmREYXRhIjp7ImJlbmREaXN0YW5jZSI6MCwiYmVuZFdlaWdodCI6MC41LCJiZW5kUG9pbnQiOnsieCI6NDkxLjU4ODIyNDQ2NjEyMTEsInkiOjEwMC42MzA4MzY4MzIxNzMyMn19LCJpZCI6IjcxNGRiOTg5LTU2NzItNDAzYi1hZTc2LWZkOWEyMDg5MzQ3NSJ9XQ==
+
+
+ DEL_EDGE
+ WyI3MTRkYjk4OS01NjcyLTQwM2ItYWU3Ni1mZDlhMjA4OTM0NzUiXQ==
+
+ 86704f8d36bc9bfa5f599c3a4b445d78
+
+
+ 1664646579649
+
+ DEL_EDGE
+ WyIwM2RlN2FjYS1hZTA0LTQ5ZWEtYThjZC04YTg3YTA0MjA0ZjEiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImlkIjoiMDNkZTdhY2EtYWUwNC00OWVhLWE4Y2QtOGE4N2EwNDIwNGYxIn1d
+
+ 44b7833e0adb98fcda7606fe873176a4
+
+
+ 1664646592082
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiWTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sInR5cGUiOiJvcmRpbiIsInNvdXJjZSI6ImZlYjllMGU5LTA2NTktNDdmYy1iNGQzLTZiZGRkOGM2YjNkNiIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImJlbmREYXRhIjp7ImJlbmREaXN0YW5jZSI6MjAsImJlbmRXZWlnaHQiOjAuNSwiYmVuZFBvaW50Ijp7IngiOjE4Ny42MDY5NDA0NzI4NDkzLCJ5Ijo3My4wMDY2NjE0ODk4MDV9fSwiaWQiOiI1NWI5OWFiNi1hN2Q2LTRjNjctYWI0ZS1hOGUyOTM5YzFiMGYifV0=
+
+
+ DEL_EDGE
+ WyI1NWI5OWFiNi1hN2Q2LTRjNjctYWI0ZS1hOGUyOTM5YzFiMGYiXQ==
+
+ 980dd3b8b785d6454a88fd4a0b28c931
+
+
+ 1664646592082
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiWTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJzaGFwZSI6InNvbGlkIn0sInR5cGUiOiJvcmRpbiIsInNvdXJjZSI6Ijg3ODFjMWFiLTI3MzUtNGE1NS1iMzQyLWExMzBhNTlmMzcwNyIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImJlbmREYXRhIjp7ImJlbmREaXN0YW5jZSI6MjAsImJlbmRXZWlnaHQiOjAuNSwiYmVuZFBvaW50Ijp7IngiOjQyNi42MTkzODI1NjIzMjg2LCJ5Ijo3Ni41MjAxMzYxMTU4NzI2NX19LCJpZCI6ImE4YWU3ODkwLWIyYmItNDI3My04NzUzLTAxODFjZWI0ODZjMSJ9XQ==
+
+
+ DEL_EDGE
+ WyJhOGFlNzg5MC1iMmJiLTQyNzMtODc1My0wMTgxY2ViNDg2YzEiXQ==
+
+ 167c73cd93b1abdcd56b452ed8d8c24e
+
+
+ 1664646592082
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiVTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJzaGFwZSI6InNvbGlkIn0sInR5cGUiOiJvcmRpbiIsInNvdXJjZSI6ImFhNjZiNDZiLTRkYTgtNDAxMC1iODk0LWQ0YmFhNWEzYWY4MiIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImJlbmREYXRhIjp7ImJlbmREaXN0YW5jZSI6MC4wMDAwMjc4NjgxNzM4NjU0NjQwMywiYmVuZFdlaWdodCI6MC41MDAwMDAwMDQwMzA1MDY2LCJiZW5kUG9pbnQiOnsieCI6MjQ1Ljc1OTMxODQ3MDQxOTI2LCJ5Ijo5OC4zNDU3NTk1MDM4MjE4N319LCJpZCI6IjNjZmI0MGNkLTU1N2EtNDg1MC05M2E2LWZkYzA5Y2QwMDVmMCJ9XQ==
+
+
+ DEL_EDGE
+ WyIzY2ZiNDBjZC01NTdhLTQ4NTAtOTNhNi1mZGMwOWNkMDA1ZjAiXQ==
+
+ d2945a87d6e5d69e9ab87ba9fc45210a
+
+
+ 1664646592082
+
+ ADD_NODE
+ WyJGMjpmdW5ib2R5LnB5Iix7IndpZHRoIjoxMjAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsiaWQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJsYWJlbCI6IkYyOmZ1bmJvZHkucHkiLCJ0eXBlIjoib3JkaW4iLCJzdHlsZSI6eyJ3aWR0aCI6MTIwLCJoZWlnaHQiOjUwLCJzaGFwZSI6InJlY3RhbmdsZSIsIm9wYWNpdHkiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZmNjMDAiLCJib3JkZXJDb2xvciI6IiMwMDAiLCJib3JkZXJXaWR0aCI6MX19LCJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ==
+
+
+ DEL_NODE
+ WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ==
+
+ 339f60a97384ac1435d5512fd70f37b7
+
+
+ 1664646604837
+
+ DEL_EDGE
+ WyIzN2UyMzg0NC1hODgwLTQ1MjktOTA2Mi00YmIyNTIxZTI5YzUiXQ==
+
+
+ ADD_EDGE
+ W3sic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiWTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiMzdlMjM4NDQtYTg4MC00NTI5LTkwNjItNGJiMjUyMWUyOWM1In1d
+
+ bfa293ad0bde125ea5db2d194297d66a
+
+
+ 1749408065766
+
+ UPDATE_NODE
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjExMSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsLnB5Iix0cnVlXQ==
+
+
+ UPDATE_NODE
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1MywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpjb21tX25vZGUucHkiLHRydWVd
+
+ 6806b2037ce2ff878ea6f1ec962044b0
+
+
+ 1749408086201
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJ4IjozODEuMTU3ODExODQ2NjU1NiwieSI6OTQuNDQyMzI5MjY1Mzc4MzZ9XQ==
+
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6MzgxLjE1NzgxMTg0NjY1NTYsInkiOjk0LjQ0MjMyOTI2NTM3ODM2fSx7IngiOjU4Ny4xNTc4MTE4NDY2NTU2LCJ5IjoxMDAuNDQyMzI5MjY1Mzc4MzZ9XQ==
+
+ c851b427b6f20d6ba88759a36ec55409
+
+
+ 1749408089116
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTE5Ni43NzYyMDM1NDk0MjM4MywieSI6OTQuMzIwMTI3MDY4MjU2NDF9XQ==
+
+
+ SET_POS
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE5Ni43NzYyMDM1NDk0MjM4MywieSI6OTQuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9XQ==
+
+ 5754a9589aae86257d22e65d39587d65
+
+
+ 1749408091800
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6MzgxLjE1NzgxMTg0NjY1NTYsInkiOjk0LjQ0MjMyOTI2NTM3ODM2fSx7IngiOjQwMS4xNTc4MTE4NDY2NTU2LCJ5Ijo5My40NDIzMjkyNjUzNzgzNn1d
+
+
+ SET_POS
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NDAxLjE1NzgxMTg0NjY1NTYsInkiOjkzLjQ0MjMyOTI2NTM3ODM2fSx7IngiOjM4MS4xNTc4MTE4NDY2NTU2LCJ5Ijo5NC40NDIzMjkyNjUzNzgzNn1d
+
+ 888e627d6b97ef44aaaef82e629bb77c
+
+
+ 1750196730434
+
+ UPDATE_NODE
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJDWjpjcHltYXgucHkiLHRydWVd
+
+
+ UPDATE_NODE
+ WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsid2lkdGgiOjE1NywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJDWjpjcHltYXhfdGVzdC5weSIsdHJ1ZV0=
+
+ a8b51b5dca1f266f68d8df4a6fab373d
+
+
+ 1750196739873
+
+ UPDATE_NODE
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1MywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpjb21tX25vZGUucHkiLHRydWVd
+
+
+ UPDATE_NODE
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE4NywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpjb21tX25vZGVfdGVzdC5weSIsdHJ1ZV0=
+
+ 45e59fe61196c6e17fa107b0b1758248
+
+
+ 1750196745274
+
+ UPDATE_NODE
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE4NywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpjb21tX25vZGVfdGVzdC5weSIsdHJ1ZV0=
+
+
+ UPDATE_NODE
+ WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE4NywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpjb21tX25vZGVfdGVzdC5weSIsdHJ1ZV0=
+
+ f67f25a50f6f37ff6cd2266ab2fb2c7c
+
+
+ 1750196749273
+
+ UPDATE_NODE
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsid2lkdGgiOjEzNiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJQWjpwbXB5bWF4LnB5Iix0cnVlXQ==
+
+
+ UPDATE_NODE
+ WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsid2lkdGgiOjE3MCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJQWjpwbXB5bWF4X3Rlc3QucHkiLHRydWVd
+
+ 4a9793f8c81214e6bf6b95371521c05d
+
+
+
\ No newline at end of file
diff --git a/measurements/pmpymax_test.py b/measurements/pmpymax_test.py
new file mode 100644
index 0000000..b735c25
--- /dev/null
+++ b/measurements/pmpymax_test.py
@@ -0,0 +1,57 @@
+import concore
+import time
+import os
+import psutil
+import sys
+
+# --- Script Configuration ---
+concore.delay = 0.01
+init_simtime_u = "[0.0, 0.0, 0.0]"
+init_simtime_ym = "[0.0, 0.0, 0.0]"
+
+# --- Measurement Initialization ---
+process = psutil.Process(os.getpid())
+start_time = time.monotonic()
+message_count = 0
+total_bytes = 0
+
+# --- Main Script Logic ---
+ym = concore.initval(init_simtime_ym)
+curr = 0.0
+max_value = 100.0
+iteration = 0
+iteration_limit = 15 # Safety break
+
+print("pmpymax_test.py started...")
+
+while curr < max_value and iteration < iteration_limit:
+ # Wait for a value from the other node
+ while concore.unchanged():
+ u = concore.read(1, "u", init_simtime_u)
+
+ # Update metrics for received data
+ message_count += 1
+ total_bytes += sys.getsizeof(u)
+
+ # Process the value
+ ym[0] = u[0] + 10 # Using a smaller increment to match the A-B-C logic
+ curr = ym[0]
+ print(f"pmpymax: u={u[0]:.2f} -> ym={ym[0]:.2f}")
+
+ # Write the processed value back
+ concore.write(1, "ym", ym, delta=1)
+ iteration += 1
+
+# --- Finalize and Report Measurements ---
+end_time = time.monotonic()
+duration = end_time - start_time
+cpu_usage = process.cpu_percent() / duration if duration > 0 else 0
+
+print("\n" + "="*30)
+print("--- PMPYMAX_TEST: FINAL RESULTS ---")
+print(f"Total messages processed: {message_count}")
+print(f"Total data processed: {total_bytes / 1024:.4f} KB")
+print(f"Total execution time: {duration:.4f} seconds")
+print(f"Approximate CPU usage: {cpu_usage:.2f}%")
+print(f"concore retry count: {concore.retrycount}")
+print("="*30)