From df0d70c69231324b8b10764bfe0018999deef566 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Mon, 2 Jun 2025 19:39:22 +0530 Subject: [PATCH 01/17] Added A zeromq based study and also corrected some existing studies --- 0mq/funbody_zmq.dir/concore2.py | 113 ++++++++ 0mq/funbody_zmq.py | 45 ++++ 0mq/funcall_zmq.dir/concore2.py | 113 ++++++++ 0mq/funcall_zmq.py | 39 +++ 0mq/test0mq3.graphml | 459 ++++++++++++++++++++++++++++++++ demo/controllerFile.py | 47 ++-- demo/pm.py | 31 ++- demo/pmFile.py | 47 ++-- 8 files changed, 836 insertions(+), 58 deletions(-) create mode 100644 0mq/funbody_zmq.dir/concore2.py create mode 100644 0mq/funbody_zmq.py create mode 100644 0mq/funcall_zmq.dir/concore2.py create mode 100644 0mq/funcall_zmq.py create mode 100644 0mq/test0mq3.graphml diff --git a/0mq/funbody_zmq.dir/concore2.py b/0mq/funbody_zmq.dir/concore2.py new file mode 100644 index 0000000..e3ec817 --- /dev/null +++ b/0mq/funbody_zmq.dir/concore2.py @@ -0,0 +1,113 @@ +import time +import os +from ast import literal_eval +import sys +import re + +#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") + +try: + iport = literal_eval(open("concore.iport").read()) +except: + iport = dict() +try: + oport = literal_eval(open("concore.oport").read()) +except: + oport = dict() + + +s = '' +olds = '' +delay = 1 +retrycount = 0 +inpath = "./in" #must be rel path for local +outpath = "./out" + +#9/21/22 +try: + sparams = open(inpath+"1/concore.params").read() + if sparams[0] == '"': #windows keeps "" need to remove + sparams = sparams[1:] + sparams = sparams[0:sparams.find('"')] + if sparams != '{': + print("converting sparams: "+sparams) + sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" + print("converted sparams: " + sparams) + try: + params = literal_eval(sparams) + except: + print("bad params: "+sparams) +except: + params = dict() +#9/30/22 +def tryparam(n,i): + try: + return params[n] + except: + return i + + +#9/12/21 +def default_maxtime(default): + global maxtime + try: + maxtime = literal_eval(open(inpath+"1/concore.maxtime").read()) + except: + maxtime = default +default_maxtime(100) + +def unchanged(): + global olds,s + if olds==s: + s = '' + return True + else: + olds = s + return False + +def read(port, name, initstr): + global s,simtime,retrycount + time.sleep(delay) + try: + infile = open(inpath+str(port)+"/"+name); + ins = infile.read() + except: + ins = initstr + while len(ins)==0: + time.sleep(delay) + ins = infile.read() + retrycount += 1 + s += ins + inval = literal_eval(ins) + simtime = max(simtime,inval[0]) + return inval[1:] + +def write(port, name, val, delta=0): + global outpath,simtime + if isinstance(val,str): + time.sleep(2*delay) + elif isinstance(val,list)==False: + print("mywrite must have list or str") + quit() + try: + with open(outpath+str(port)+"/"+name,"w") as outfile: + if isinstance(val,list): + outfile.write(str([simtime+delta]+val)) + simtime += delta + else: + outfile.write(val) + except: + print("skipping"+outpath+str(port)+"/"+name); + +def initval(simtime_val): + global simtime + val = literal_eval(simtime_val) + simtime = val[0] + return val[1:] + diff --git a/0mq/funbody_zmq.py b/0mq/funbody_zmq.py new file mode 100644 index 0000000..b3ecd63 --- /dev/null +++ b/0mq/funbody_zmq.py @@ -0,0 +1,45 @@ +# funbody2_zmq.py +import zmq +import time +import concore +import concore2 + +print("funbody using 0mq") + +context = zmq.Context() +socket = context.socket(zmq.REP) +socket.bind("tcp://*:2346") + +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u = "[0.0, 0.0, 0.0]" +init_simtime_ym = "[0.0, 0.0, 0.0]" + +u = concore.initval(init_simtime_u) +ym = concore2.initval(init_simtime_ym) + +while concore2.simtime < concore.maxtime: + msg = socket.recv_json() + if msg["action"] == "fun": + u = msg["params"]["u"] + concore.simtime = u[0] + u = u[1:] + concore.write(concore.oport['U2'], "u", u) + print(u) + old2 = concore2.simtime + while concore2.unchanged() or concore2.simtime <= old2: + ym = concore2.read(concore.iport['Y2'], "ym", init_simtime_ym) + ym_full = [concore2.simtime] + ym + print(f"Replying with {ym_full}") + socket.send_json({"ym": ym_full}) + print(f"funbody u={u} ym={ym} time={concore2.simtime}") + else: + print("undefined action: " + str(msg.get("action", "None"))) + socket.send_json({"error": "undefined action"}) + break + +print("retry=" + str(concore.retrycount)) \ No newline at end of file diff --git a/0mq/funcall_zmq.dir/concore2.py b/0mq/funcall_zmq.dir/concore2.py new file mode 100644 index 0000000..e3ec817 --- /dev/null +++ b/0mq/funcall_zmq.dir/concore2.py @@ -0,0 +1,113 @@ +import time +import os +from ast import literal_eval +import sys +import re + +#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") + +try: + iport = literal_eval(open("concore.iport").read()) +except: + iport = dict() +try: + oport = literal_eval(open("concore.oport").read()) +except: + oport = dict() + + +s = '' +olds = '' +delay = 1 +retrycount = 0 +inpath = "./in" #must be rel path for local +outpath = "./out" + +#9/21/22 +try: + sparams = open(inpath+"1/concore.params").read() + if sparams[0] == '"': #windows keeps "" need to remove + sparams = sparams[1:] + sparams = sparams[0:sparams.find('"')] + if sparams != '{': + print("converting sparams: "+sparams) + sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" + print("converted sparams: " + sparams) + try: + params = literal_eval(sparams) + except: + print("bad params: "+sparams) +except: + params = dict() +#9/30/22 +def tryparam(n,i): + try: + return params[n] + except: + return i + + +#9/12/21 +def default_maxtime(default): + global maxtime + try: + maxtime = literal_eval(open(inpath+"1/concore.maxtime").read()) + except: + maxtime = default +default_maxtime(100) + +def unchanged(): + global olds,s + if olds==s: + s = '' + return True + else: + olds = s + return False + +def read(port, name, initstr): + global s,simtime,retrycount + time.sleep(delay) + try: + infile = open(inpath+str(port)+"/"+name); + ins = infile.read() + except: + ins = initstr + while len(ins)==0: + time.sleep(delay) + ins = infile.read() + retrycount += 1 + s += ins + inval = literal_eval(ins) + simtime = max(simtime,inval[0]) + return inval[1:] + +def write(port, name, val, delta=0): + global outpath,simtime + if isinstance(val,str): + time.sleep(2*delay) + elif isinstance(val,list)==False: + print("mywrite must have list or str") + quit() + try: + with open(outpath+str(port)+"/"+name,"w") as outfile: + if isinstance(val,list): + outfile.write(str([simtime+delta]+val)) + simtime += delta + else: + outfile.write(val) + except: + print("skipping"+outpath+str(port)+"/"+name); + +def initval(simtime_val): + global simtime + val = literal_eval(simtime_val) + simtime = val[0] + return val[1:] + diff --git a/0mq/funcall_zmq.py b/0mq/funcall_zmq.py new file mode 100644 index 0000000..dfbb0de --- /dev/null +++ b/0mq/funcall_zmq.py @@ -0,0 +1,39 @@ +# funcall2_zmq.py +import zmq +import time +import concore +import concore2 + +print("funcall using 0mq") + +context = zmq.Context() +socket = context.socket(zmq.REQ) +socket.connect("tcp://localhost:2346") + +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u = "[0.0, 0.0, 0.0]" +init_simtime_ym = "[0.0, 0.0, 0.0]" + +u = concore.initval(init_simtime_u) +ym = concore2.initval(init_simtime_ym) + +while concore2.simtime < concore.maxtime: + while concore.unchanged(): + u = concore.read(concore.iport['U'], "u", init_simtime_u) + message = { + "action": "fun", + "params": {"u": [concore.simtime] + u} + } + socket.send_json(message) + response = socket.recv_json() + ym = response["ym"] + concore2.simtime = ym[0] + ym = ym[1:] + concore2.write(concore.oport['Y'], "ym", ym) + print(f"funcall 0mq u={u} ym={ym} time={concore2.simtime}") +print("retry=" + str(concore.retrycount)) \ No newline at end of file diff --git a/0mq/test0mq3.graphml b/0mq/test0mq3.graphml new file mode 100644 index 0000000..4bc62b4 --- /dev/null +++ b/0mq/test0mq3.graphml @@ -0,0 +1,459 @@ + + + + + + + + + + + + PZ:pmpymax.py + + + + + + + + + + + CZ:cpymax.py + + + + + + + + + + + F1:funcall_zmq.py + + + + + + + + + + + F2:funbody_zmq.py + + + + + + + + + + U + + + + + + + + + + + + Y + + + + + + + + + + + + U2 + + + + + + + + + + + + Y2 + + + + + + + + 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 + + + 1666487497309 + + ADD_EDGE + W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= + + + DEL_EDGE + WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== + + 4957bb66f70bda073e7edafdad81f6b4 + + + 1666487500685 + + ADD_EDGE + W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== + + + DEL_EDGE + WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== + + c8d5e89e2630a4a0aa607594e14861d1 + + + 1666487596231 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4Ijo2MDEsInkiOjIwNC43NzM2MjI4MjYyMzMxMn1d + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjAxLCJ5IjoyMDQuNzczNjIyODI2MjMzMTJ9LHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX1d + + c7aeac0c4601154d11c4c4068f631c62 + + + 1666487606788 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjE5Mi4zMjAxMjcwNjgyNTY0fV0= + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjE5Mi4zMjAxMjcwNjgyNTY0fSx7IngiOi0xMzcuNzc2MjAzNTQ5NDIzODMsInkiOjkxLjMyMDEyNzA2ODI1NjQxfV0= + + 600af97eb5c4cc3a573f65c724b85ae9 + + + 1666488874534 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjI0Ni4zMjAxMjcwNjgyNTY0fSx7IngiOjM0Mi4yMjM3OTY0NTA1NzYyLCJ5IjoyMDkuMzIwMTI3MDY4MjU2NH1d + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQyLjIyMzc5NjQ1MDU3NjIsInkiOjIwOS4zMjAxMjcwNjgyNTY0fSx7IngiOjM0Ni4yMjM3OTY0NTA1NzYyLCJ5IjoyNDYuMzIwMTI3MDY4MjU2NH1d + + ea3cf1656cbb3323791a747bcb8f624c + + + 1666810512066 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + 33c0759e9ca1d4d92639a94477c9b052 + + + 1666810533063 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjExMSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsLnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + 06d61b24bc2485f9464f3e2751d1409a + + + 1748868954808 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5My5weSIsdHJ1ZV0= + + 4afd9af5e90936e999770a941ab0ace6 + + + 1748868975001 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1MCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcS5weSIsdHJ1ZV0= + + 38c7cf57be2a0a3b4b1bafb14e9d29fb + + + 1748868991559 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5My5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2MSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcS5weSIsdHJ1ZV0= + + 16982a4aa4703d98fc301e30aed0d25a + + + \ No newline at end of file diff --git a/demo/controllerFile.py b/demo/controllerFile.py index 38e45da..702c163 100644 --- a/demo/controllerFile.py +++ b/demo/controllerFile.py @@ -1,34 +1,43 @@ import numpy as np import concore +import ast ysp = 3.0 -#//controller function// def controller(ym): - if ym[0] < ysp: - return 1.01 * ym - else: - return 0.9 * ym + if ym[0] < ysp: + return 1.01 * ym + else: + return 0.9 * ym -#//main// -concore.default_maxtime(150) ##maps to-- for i in range(0,150): +concore.default_maxtime(150) concore.delay = 0.02 init_simtime_u = "[0.0, 0.0]" init_simtime_ym = "[0.0, 0.0]" -u = np.array([concore.initval(init_simtime_u)]).T -while(concore.simtime 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: + 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 + + file_path = os.path.join(outpath+str(file_port_num), name) + + 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: - print("skipping"+outpath+str(port)+"/"+name); + except Exception as e: + print(f"Error writing to {file_path}: {e}") -def initval(simtime_val): +def initval(simtime_val_str): global simtime - val = literal_eval(simtime_val) - simtime = val[0] - return val[1:] + 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/0mq/funbody_zmq.py b/0mq/funbody_zmq.py index b3ecd63..576f692 100644 --- a/0mq/funbody_zmq.py +++ b/0mq/funbody_zmq.py @@ -8,7 +8,7 @@ context = zmq.Context() socket = context.socket(zmq.REP) -socket.bind("tcp://*:2346") +socket.bind("tcp://*:2356") concore.delay = 0.07 concore2.delay = 0.07 diff --git a/0mq/funbody_zmq2.dir/concore2.py b/0mq/funbody_zmq2.dir/concore2.py new file mode 100644 index 0000000..65bd955 --- /dev/null +++ b/0mq/funbody_zmq2.dir/concore2.py @@ -0,0 +1,254 @@ +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 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: + 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 + + file_path = os.path.join(outpath+str(file_port_num), name) + + 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/0mq/funbody_zmq2.py b/0mq/funbody_zmq2.py new file mode 100644 index 0000000..fce7b13 --- /dev/null +++ b/0mq/funbody_zmq2.py @@ -0,0 +1,68 @@ +# funbody2_zmq.py +import time +import concore +import concore2 + +print("funbody using ZMQ via concore") + +# ZMQ settings +ZMQ_PORT_NAME = "FUNBODY_REP_PORT" +ZMQ_BIND_ADDRESS = "tcp://*:2355" + +# Initialize ZMQ REP port using concore +concore.init_zmq_port( + port_name=ZMQ_PORT_NAME, + port_type="bind", + address=ZMQ_BIND_ADDRESS, + socket_type_str="REP" +) + +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" + +u_data_values = concore.initval(init_simtime_u_str) +ym_data_values = concore2.initval(init_simtime_ym_str) + +print(f"Initial u_data_values: {u_data_values}, ym_data_values: {ym_data_values}") +print(f"Max time: {concore.maxtime}") + +while concore2.simtime < concore.maxtime: + received_u_data = concore.read(ZMQ_PORT_NAME, "u_signal", init_simtime_u_str) + + if not (isinstance(received_u_data, list) and len(received_u_data) > 0): + print(f"Error or invalid data received via ZMQ: {received_u_data}. Skipping iteration.") + time.sleep(concore.delay) + continue + + received_time = received_u_data[0] + if isinstance(received_time, (int, float)): + concore.simtime = received_time + u_data_values = received_u_data[1:] + else: + print(f"Warning: Received ZMQ data's first element is not time: {received_u_data}. Using data part as is.") + u_data_values = received_u_data[1:] if len(received_u_data) > 1 else [] + + # Assuming concore.oport['U2'] is a file port (e.g., to pmpymax.py) + if 'U2' in concore.oport: + concore.write(concore.oport['U2'], "u", u_data_values) + + old_concore2_simtime = concore2.simtime + while concore2.unchanged() or concore2.simtime <= old_concore2_simtime: + # Assuming concore.iport['Y2'] is a file port (e.g., from pmpymax.py) + ym_data_values = concore2.read(concore.iport['Y2'], "ym", init_simtime_ym_str) + # time.sleep(concore2.delay) # Optional delay + + ym_full_to_send = [concore2.simtime] + ym_data_values + + concore.write(ZMQ_PORT_NAME, "ym_signal", ym_full_to_send) + + print(f"funbody u={u_data_values} ym={ym_data_values} time={concore2.simtime}") + +print("funbody retry=" + str(concore.retrycount)) \ No newline at end of file diff --git a/0mq/funcall_zmq.dir/concore2.py b/0mq/funcall_zmq.dir/concore2.py index e3ec817..7b0b3b4 100644 --- a/0mq/funcall_zmq.dir/concore2.py +++ b/0mq/funcall_zmq.dir/concore2.py @@ -3,6 +3,7 @@ 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 @@ -12,15 +13,60 @@ with open("concorekill.bat","w") as fpid: fpid.write("taskkill /F /PID "+str(os.getpid())+"\n") -try: - iport = literal_eval(open("concore.iport").read()) -except: - iport = dict() -try: - oport = literal_eval(open("concore.oport").read()) -except: - oport = dict() +# --- 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}") +# --- 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 = '' @@ -28,86 +74,182 @@ retrycount = 0 inpath = "./in" #must be rel path for local outpath = "./out" +simtime = 0 #9/21/22 try: - sparams = open(inpath+"1/concore.params").read() - if sparams[0] == '"': #windows keeps "" need to remove - sparams = sparams[1:] - sparams = sparams[0:sparams.find('"')] - if sparams != '{': - print("converting sparams: "+sparams) - sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" - print("converted sparams: " + sparams) - try: - params = literal_eval(sparams) - except: - print("bad params: "+sparams) -except: + 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): - try: - return params[n] - except: - return i +def tryparam(n, i): + return params.get(n, i) #9/12/21 def default_maxtime(default): global maxtime - try: - maxtime = literal_eval(open(inpath+"1/concore.maxtime").read()) - except: - maxtime = default + 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: + global olds, s + if olds == s: s = '' return True - else: - olds = s - return False + 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 = "" -def read(port, name, initstr): - global s,simtime,retrycount - time.sleep(delay) try: - infile = open(inpath+str(port)+"/"+name); - ins = infile.read() - except: - ins = initstr - while len(ins)==0: + 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) - ins = infile.read() + 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 - s += ins - inval = literal_eval(ins) - simtime = max(simtime,inval[0]) - return inval[1:] - -def write(port, name, val, delta=0): - global outpath,simtime - if isinstance(val,str): - time.sleep(2*delay) - elif isinstance(val,list)==False: - print("mywrite must have list or str") - quit() + + if len(ins) == 0: + print(f"Max retries reached for {file_path}, using default value.") + return default_return_val + + s += ins try: - with open(outpath+str(port)+"/"+name,"w") as outfile: - if isinstance(val,list): - outfile.write(str([simtime+delta]+val)) - simtime += delta - else: + 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: + 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 + + file_path = os.path.join(outpath+str(file_port_num), name) + + 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: - print("skipping"+outpath+str(port)+"/"+name); + except Exception as e: + print(f"Error writing to {file_path}: {e}") -def initval(simtime_val): +def initval(simtime_val_str): global simtime - val = literal_eval(simtime_val) - simtime = val[0] - return val[1:] + 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/0mq/funcall_zmq.py b/0mq/funcall_zmq.py index dfbb0de..f0c2f33 100644 --- a/0mq/funcall_zmq.py +++ b/0mq/funcall_zmq.py @@ -8,7 +8,7 @@ context = zmq.Context() socket = context.socket(zmq.REQ) -socket.connect("tcp://localhost:2346") +socket.connect("tcp://localhost:2356") concore.delay = 0.07 concore2.delay = 0.07 diff --git a/0mq/funcall_zmq2.dir/concore2.py b/0mq/funcall_zmq2.dir/concore2.py new file mode 100644 index 0000000..7b0b3b4 --- /dev/null +++ b/0mq/funcall_zmq2.dir/concore2.py @@ -0,0 +1,255 @@ +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}") + +# --- 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: + 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 + + file_path = os.path.join(outpath+str(file_port_num), name) + + 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/0mq/funcall_zmq2.py b/0mq/funcall_zmq2.py new file mode 100644 index 0000000..baff34b --- /dev/null +++ b/0mq/funcall_zmq2.py @@ -0,0 +1,65 @@ +# funcall2_zmq.py +import time +import concore +import concore2 + +print("funcall using ZMQ via concore") + +# ZMQ settings +ZMQ_PORT_NAME = "FUNCALL_REQ_PORT" +ZMQ_SERVER_ADDRESS = "tcp://localhost:2355" + +# Initialize ZMQ REQ port using concore +concore.init_zmq_port( + port_name=ZMQ_PORT_NAME, + port_type="connect", + address=ZMQ_SERVER_ADDRESS, + socket_type_str="REQ" +) + +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" + +u = concore.initval(init_simtime_u_str) +ym = concore2.initval(init_simtime_ym_str) + +print(f"Initial u: {u}, ym: {ym}, concore.simtime: {concore.simtime}, concore2.simtime: {concore2.simtime}") +print(f"Max time: {concore.maxtime}") + +while concore2.simtime < concore.maxtime: + while concore.unchanged(): + # Assuming concore.iport['U'] is a file port (e.g., from cpymax.py) + u = concore.read(concore.iport['U'], "u", init_simtime_u_str) + # time.sleep(concore.delay) # Optional: if file reads are too fast in a loop + + data_to_send_u = [concore.simtime] + u + + concore.write(ZMQ_PORT_NAME, "u_signal", data_to_send_u) + + received_ym_data = concore.read(ZMQ_PORT_NAME, "ym_signal", init_simtime_ym_str) + + if isinstance(received_ym_data, list) and len(received_ym_data) > 0: + response_time = received_ym_data[0] + if isinstance(response_time, (int, float)): + concore2.simtime = response_time + ym = received_ym_data[1:] + else: + print(f"Warning: Received ZMQ data's first element is not time: {received_ym_data}. Using as is.") + ym = received_ym_data + else: + print(f"Warning: Received unexpected ZMQ data format: {received_ym_data}. Using default ym.") + ym = concore2.initval(init_simtime_ym_str) + + # Assuming concore.oport['Y'] is a file port (e.g., to cpymax.py) + concore2.write(concore.oport['Y'], "ym", ym) + + print(f"funcall ZMQ u={u} ym={ym} time={concore2.simtime}") + +print("funcall retry=" + str(concore.retrycount)) \ No newline at end of file diff --git a/0mq/test0mq4.graphml b/0mq/test0mq4.graphml new file mode 100644 index 0000000..4206ece --- /dev/null +++ b/0mq/test0mq4.graphml @@ -0,0 +1,483 @@ + + + + + + + + + + + + PZ:pmpymax.py + + + + + + + + + + + CZ:cpymax.py + + + + + + + + + + + F1:funcall_zmq2.py + + + + + + + + + + + F2:funbody_zmq2.py + + + + + + + + + + U + + + + + + + + + + + + Y + + + + + + + + + + + + U2 + + + + + + + + + + + + Y2 + + + + + + + + 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 + + + 1666487497309 + + ADD_EDGE + W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= + + + DEL_EDGE + WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== + + 4957bb66f70bda073e7edafdad81f6b4 + + + 1666487500685 + + ADD_EDGE + W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== + + + DEL_EDGE + WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== + + c8d5e89e2630a4a0aa607594e14861d1 + + + 1666487596231 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4Ijo2MDEsInkiOjIwNC43NzM2MjI4MjYyMzMxMn1d + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjAxLCJ5IjoyMDQuNzczNjIyODI2MjMzMTJ9LHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX1d + + c7aeac0c4601154d11c4c4068f631c62 + + + 1666487606788 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjE5Mi4zMjAxMjcwNjgyNTY0fV0= + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjE5Mi4zMjAxMjcwNjgyNTY0fSx7IngiOi0xMzcuNzc2MjAzNTQ5NDIzODMsInkiOjkxLjMyMDEyNzA2ODI1NjQxfV0= + + 600af97eb5c4cc3a573f65c724b85ae9 + + + 1666488874534 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjI0Ni4zMjAxMjcwNjgyNTY0fSx7IngiOjM0Mi4yMjM3OTY0NTA1NzYyLCJ5IjoyMDkuMzIwMTI3MDY4MjU2NH1d + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQyLjIyMzc5NjQ1MDU3NjIsInkiOjIwOS4zMjAxMjcwNjgyNTY0fSx7IngiOjM0Ni4yMjM3OTY0NTA1NzYyLCJ5IjoyNDYuMzIwMTI3MDY4MjU2NH1d + + ea3cf1656cbb3323791a747bcb8f624c + + + 1666810512066 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + 33c0759e9ca1d4d92639a94477c9b052 + + + 1666810533063 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjExMSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsLnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + 06d61b24bc2485f9464f3e2751d1409a + + + 1748868954808 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5My5weSIsdHJ1ZV0= + + 4afd9af5e90936e999770a941ab0ace6 + + + 1748868975001 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1MCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcS5weSIsdHJ1ZV0= + + 38c7cf57be2a0a3b4b1bafb14e9d29fb + + + 1748868991559 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5My5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2MSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcS5weSIsdHJ1ZV0= + + 16982a4aa4703d98fc301e30aed0d25a + + + 1748971661849 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2MSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcS5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + bc5037b25958965e670ba8b2200dbcf3 + + + 1748971670391 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1MCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcS5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcTIucHkiLHRydWVd + + 7bcfd7cb9bf8eaae8a615d108c4264ac + + + \ No newline at end of file diff --git a/concore.py b/concore.py index 51eef7b..7b0b3b4 100644 --- a/concore.py +++ b/concore.py @@ -3,6 +3,7 @@ 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 @@ -12,12 +13,56 @@ 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}") + +# --- 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: - print(f"Error reading {filename}: {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", {}) @@ -33,20 +78,30 @@ def safe_literal_eval(filename, defaultValue): #9/21/22 try: - sparams = open(inpath+"1/concore.params").read() - if sparams[0] == '"': #windows keeps "" need to remove - sparams = sparams[1:] - sparams = sparams[0:sparams.find('"')] - if sparams != '{': - print("converting sparams: "+sparams) - sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" - print("converted sparams: " + sparams) - try: - params = literal_eval(sparams) - except: - print("bad params: "+sparams) -except: + 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) @@ -55,7 +110,8 @@ def tryparam(n, i): #9/12/21 def default_maxtime(default): global maxtime - maxtime = safe_literal_eval(os.path.join(inpath + "1", "concore.maxtime"), default) + maxtime_path = os.path.join(inpath + "1", "concore.maxtime") + maxtime = safe_literal_eval(maxtime_path, default) default_maxtime(100) @@ -67,23 +123,49 @@ def unchanged(): olds = s return False -def read(port, name, initstr): +def read(port_identifier, name, initstr_val): global s, simtime, retrycount - max_retries=5 - time.sleep(delay) - file_path = os.path.join(inpath+str(port), name) + + 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: - print(f"File {file_path} not found, using default value.") - ins = initstr + ins = str(initstr_val) except Exception as e: - print(f"Error reading {file_path}: {e}") - return initstr + 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: @@ -96,44 +178,78 @@ def read(port, name, initstr): if len(ins) == 0: print(f"Max retries reached for {file_path}, using default value.") - return initstr + return default_return_val - s += ins + s += ins try: inval = literal_eval(ins) - simtime = max(simtime, inval[0]) - return inval[1:] + 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 {ins}: {e}") - return initstr + print(f"Error parsing content from {file_path} ('{ins}'): {e}. Returning default.") + return default_return_val -def write(port, name, val, delta=0): +def write(port_identifier, name, val, delta=0): global simtime - file_path = os.path.join(outpath+str(port), name) + + 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: + 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 + + file_path = os.path.join(outpath+str(file_port_num), name) if isinstance(val, str): - time.sleep(2 * delay) + time.sleep(2 * delay) elif not isinstance(val, list): - print("write must have list or str") + 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): - outfile.write(str([simtime + delta] + val)) - simtime += delta - else: + 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): +def initval(simtime_val_str): global simtime try: - val = literal_eval(simtime_val) - simtime = val[0] - return val[1:] + 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: {e}") - return [] + print(f"Error parsing simtime_val_str '{simtime_val_str}': {e}. Returning empty list.") + return [] \ No newline at end of file From 3c2db128a0c0883e965b0ab0d41e9c7007ec920d Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Thu, 5 Jun 2025 01:34:21 +0530 Subject: [PATCH 03/17] For Port Assignment Based On Edge Label, This script will append ZMQ_PORT and PORT_NAME and copy that file from source dir to destination dir --- copy_with_port_portname.py | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 copy_with_port_portname.py diff --git a/copy_with_port_portname.py b/copy_with_port_portname.py new file mode 100644 index 0000000..1211adf --- /dev/null +++ b/copy_with_port_portname.py @@ -0,0 +1,69 @@ +# copythefile.py +import sys +import os + +def create_modified_script(template_script_path, zmq_port_name_val, zmq_port_val, output_dir): + + try: + with open(template_script_path, 'r') as f: + lines = f.readlines() + except FileNotFoundError: + print(f"Error: Template script '{template_script_path}' not found.") + sys.exit(1) + except Exception as e: + print(f"Error reading template script '{template_script_path}': {e}") + sys.exit(1) + + definitions = [ + '\n', + f'ZMQ_PORT_NAME = "{zmq_port_name_val}"\n', + f'ZMQ_PORT = "{zmq_port_val}"\n', + '\n' + ] + + insert_index = 0 + for i, line in enumerate(lines): + stripped_line = line.strip() + if stripped_line.startswith('import ') or stripped_line.startswith('from '): + insert_index = i + 1 + elif insert_index > 0 and stripped_line and not stripped_line.startswith('#'): + break + if insert_index == 0 and lines and lines[0].startswith('#!'): + insert_index = 1 + + modified_lines = lines[:insert_index] + definitions + lines[insert_index:] + + # Determine output filename + base_template_name = os.path.basename(template_script_path) + template_root, template_ext = os.path.splitext(base_template_name) + output_filename = f"{template_root}{template_ext}" + output_script_path = os.path.join(output_dir, output_filename) + + try: + if not os.path.exists(output_dir): + os.makedirs(output_dir) + print(f"Created output directory: {output_dir}") + + with open(output_script_path, 'w') as f: + f.writelines(modified_lines) + + print(f"Successfully created '{output_script_path}' with:") + print(f" ZMQ_PORT_NAME = \"{zmq_port_name_val}\"") + print(f" ZMQ_PORT = \"{zmq_port_val}\"") + + except Exception as e: + print(f"Error writing output script '{output_script_path}': {e}") + sys.exit(1) + +if __name__ == "__main__": + if len(sys.argv) != 5: + print("Usage: python3 copy_with_port_portname.py ") + print("Example: python3 copy_with_port_portname.py FUNBODY_REP_1 \"2355\" \"./templates/funbody_base.py\" \"./generated_scripts/\"") + sys.exit(1) + + new_port_name_arg = sys.argv[1] + new_bind_address_arg = sys.argv[2] + template_script_path_arg = sys.argv[3] + output_directory_arg = sys.argv[4] + + create_modified_script(template_script_path_arg, new_port_name_arg, new_bind_address_arg, output_directory_arg) \ No newline at end of file From 7ca304abc7e1f45dea06b0609699200a56bc36a0 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Thu, 5 Jun 2025 23:26:41 +0530 Subject: [PATCH 04/17] added a function that will run the copy_with_port_portname script with arguments --- copy_with_port_portname.py | 52 +++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/copy_with_port_portname.py b/copy_with_port_portname.py index 1211adf..083f72d 100644 --- a/copy_with_port_portname.py +++ b/copy_with_port_portname.py @@ -1,9 +1,59 @@ # copythefile.py import sys import os +import subprocess +import logging + +logging.basicConfig( + level=logging.INFO, + format='%(message)s', + datefmt='%Y-%m-%d %H:%M:%S' +) + +def run_copy_script(template_script_path_arg, new_port_name_arg, new_zmq_port_arg, output_directory_arg, python_exe): + base_template_name = os.path.basename(template_script_path_arg) + template_root, template_ext = os.path.splitext(base_template_name) + output_filename = f"{template_root}{template_ext}" + expected_output_path = os.path.join(output_directory_arg, output_filename) + + if os.path.exists(expected_output_path): + logging.info(f"Specialized script '{expected_output_path}' already exists. Skipping generation.") + return output_filename + + copy_script_path = os.path.join(".","copy_with_port_portname.py") + + cmd = [ + python_exe, + copy_script_path, + new_port_name_arg, + new_zmq_port_arg, + template_script_path_arg, + output_directory_arg + ] + logging.info(f"Running: {' '.join(cmd)}") + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True, encoding='utf-8') + logging.info(f"Successfully generated '{output_filename}' using copy_with_port_portname.py.") + if result.stdout: logging.debug(f"copy_with_port_portname.py stdout:\n{result.stdout}") + if result.stderr: logging.warning(f"copy_with_port_portname.py stderr:\n{result.stderr}") + return output_filename + except subprocess.CalledProcessError as e: + logging.error(f"Error calling copy_with_port_portname.py for '{template_script_path_arg}' with port_name '{new_port_name_arg}':") + logging.error(f"Command: {' '.join(e.cmd)}") + logging.error(f"Return code: {e.returncode}") + logging.error(f"Stdout: {e.stdout}") + logging.error(f"Stderr: {e.stderr}") + return None + except FileNotFoundError: + logging.error(f"Error: Python executable or copy_with_port_portname.py script not found.") + logging.error(f"Attempted command: {' '.join(cmd)}") + return None + except Exception as e: + logging.error(f"An unexpected error occurred while trying to run copy_script: {e}") + return None -def create_modified_script(template_script_path, zmq_port_name_val, zmq_port_val, output_dir): +def create_modified_script(template_script_path, zmq_port_name_val, zmq_port_val, output_dir): try: with open(template_script_path, 'r') as f: lines = f.readlines() From 8c2f90ec7c1843960f257eecff095f041d4d45ec Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Sat, 7 Jun 2025 00:03:16 +0530 Subject: [PATCH 05/17] Added A function to close all ports of zeromq running for a particular instance of concore --- concore.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/concore.py b/concore.py index 7b0b3b4..a06ecf8 100644 --- a/concore.py +++ b/concore.py @@ -54,6 +54,13 @@ def init_zmq_port(port_name, port_type, address, socket_type_str): 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): From 86b2f17264a141901913430679cdbd89fb7cfcba Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Sun, 8 Jun 2025 03:14:56 +0530 Subject: [PATCH 06/17] Added the functionality to view results of zmq edges also, and along with that improved copy_port_portname.py as per requirements --- concore.py | 9 +-- copy_with_port_portname.py | 125 +++++++++++++++++++++++++------------ 2 files changed, 89 insertions(+), 45 deletions(-) diff --git a/concore.py b/concore.py index a06ecf8..2f4d7c8 100644 --- a/concore.py +++ b/concore.py @@ -214,16 +214,17 @@ def write(port_identifier, name, val, delta=0): 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: - file_port_num = int(port_identifier) + 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 - file_path = os.path.join(outpath+str(file_port_num), name) - if isinstance(val, str): time.sleep(2 * delay) elif not isinstance(val, list): diff --git a/copy_with_port_portname.py b/copy_with_port_portname.py index 083f72d..7307289 100644 --- a/copy_with_port_portname.py +++ b/copy_with_port_portname.py @@ -3,6 +3,7 @@ import os import subprocess import logging +import json logging.basicConfig( level=logging.INFO, @@ -10,50 +11,62 @@ datefmt='%Y-%m-%d %H:%M:%S' ) -def run_copy_script(template_script_path_arg, new_port_name_arg, new_zmq_port_arg, output_directory_arg, python_exe): - base_template_name = os.path.basename(template_script_path_arg) +def run_specialization_script(template_script_path, output_dir, edge_params_list, python_exe, copy_script_path): + """ + Calls the copy script to generate a specialized version of a node's script. + Returns the basename of the generated script on success, None on failure. + """ + # The new copy script generates a standardized filename, e.g., "original.py" + base_template_name = os.path.basename(template_script_path) template_root, template_ext = os.path.splitext(base_template_name) output_filename = f"{template_root}{template_ext}" - expected_output_path = os.path.join(output_directory_arg, output_filename) + expected_output_path = os.path.join(output_dir, output_filename) + # If the specialized file already exists, we don't need to regenerate it. if os.path.exists(expected_output_path): - logging.info(f"Specialized script '{expected_output_path}' already exists. Skipping generation.") + logging.info(f"Specialized script '{expected_output_path}' already exists. Using existing.") return output_filename - - copy_script_path = os.path.join(".","copy_with_port_portname.py") + + # Convert the list of parameters to a JSON string for command line argument + edge_params_json_str = json.dumps(edge_params_list) cmd = [ python_exe, copy_script_path, - new_port_name_arg, - new_zmq_port_arg, - template_script_path_arg, - output_directory_arg + template_script_path, + output_dir, + edge_params_json_str # Pass the JSON string as the last argument ] - logging.info(f"Running: {' '.join(cmd)}") + logging.info(f"Running specialization for '{base_template_name}': {' '.join(cmd)}") try: result = subprocess.run(cmd, capture_output=True, text=True, check=True, encoding='utf-8') - logging.info(f"Successfully generated '{output_filename}' using copy_with_port_portname.py.") - if result.stdout: logging.debug(f"copy_with_port_portname.py stdout:\n{result.stdout}") - if result.stderr: logging.warning(f"copy_with_port_portname.py stderr:\n{result.stderr}") + logging.info(f"Successfully generated specialized script '{output_filename}'.") + if result.stdout: logging.debug(f"copy_with_port_portname.py stdout:\n{result.stdout.strip()}") + if result.stderr: logging.warning(f"copy_with_port_portname.py stderr:\n{result.stderr.strip()}") return output_filename except subprocess.CalledProcessError as e: - logging.error(f"Error calling copy_with_port_portname.py for '{template_script_path_arg}' with port_name '{new_port_name_arg}':") + logging.error(f"Error calling specialization script for '{template_script_path}':") logging.error(f"Command: {' '.join(e.cmd)}") logging.error(f"Return code: {e.returncode}") - logging.error(f"Stdout: {e.stdout}") - logging.error(f"Stderr: {e.stderr}") - return None - except FileNotFoundError: - logging.error(f"Error: Python executable or copy_with_port_portname.py script not found.") - logging.error(f"Attempted command: {' '.join(cmd)}") + logging.error(f"Stdout: {e.stdout.strip()}") + logging.error(f"Stderr: {e.stderr.strip()}") return None except Exception as e: - logging.error(f"An unexpected error occurred while trying to run copy_script: {e}") + logging.error(f"An unexpected error occurred while trying to run specialization script: {e}") return None -def create_modified_script(template_script_path, zmq_port_name_val, zmq_port_val, output_dir): +def create_modified_script(template_script_path, output_dir, edge_params_json_str): + """ + Creates a modified Python script by injecting ZMQ port and port name + definitions from a JSON object. + + Args: + template_script_path (str): The path to the source template script. + output_dir (str): The directory to save the new script in. + edge_params_json_str (str): A JSON string representing a list of + edge parameter dictionaries. + """ try: with open(template_script_path, 'r') as f: lines = f.readlines() @@ -64,28 +77,60 @@ def create_modified_script(template_script_path, zmq_port_name_val, zmq_port_val print(f"Error reading template script '{template_script_path}': {e}") sys.exit(1) - definitions = [ - '\n', - f'ZMQ_PORT_NAME = "{zmq_port_name_val}"\n', - f'ZMQ_PORT = "{zmq_port_val}"\n', - '\n' - ] + try: + edge_params_list = json.loads(edge_params_json_str) + except json.JSONDecodeError as e: + print(f"Error: Invalid JSON string provided for edge parameters: {e}") + print(f"Received: {edge_params_json_str}") + sys.exit(1) + # --- Generate definitions from the list of edge parameters --- + definitions = ['\n# --- ZMQ Port and Name Definitions (Auto-generated by mkconcore.py) ---\n'] + print(f"Generating definitions for {len(edge_params_list)} edge(s):") + + for params in edge_params_list: + port = params.get("port") + port_name = params.get("port_name") + source_label = params.get("source_node_label", "UNKNOWN_SOURCE") + target_label = params.get("target_node_label", "UNKNOWN_TARGET") + + # Sanitize labels to be valid Python variable parts + safe_source = "".join(c if c.isalnum() else '_' for c in source_label) + safe_target = "".join(c if c.isalnum() else '_' for c in target_label) + + # Create unique variable names + port_var_name = f"PORT_{safe_source}_{safe_target}" + port_name_var_name = f"PORT_NAME_{safe_source}_{safe_target}" + + definitions.append(f'{port_name_var_name} = "{port_name}"\n') + definitions.append(f'{port_var_name} = "{port}"\n') + + print(f" - {port_name_var_name} = \"{port_name}\"") + print(f" - {port_var_name} = \"{port}\"") + + definitions.append('# --- End of Auto-generated Definitions ---\n\n') + + # --- Insert definitions into the script --- insert_index = 0 for i, line in enumerate(lines): stripped_line = line.strip() + # Find the last import statement to insert after if stripped_line.startswith('import ') or stripped_line.startswith('from '): insert_index = i + 1 + # Stop searching after the first non-import, non-comment line after imports are found elif insert_index > 0 and stripped_line and not stripped_line.startswith('#'): break + # Handle case where script starts with shebang if insert_index == 0 and lines and lines[0].startswith('#!'): insert_index = 1 modified_lines = lines[:insert_index] + definitions + lines[insert_index:] - # Determine output filename + # --- Determine and create output file --- base_template_name = os.path.basename(template_script_path) template_root, template_ext = os.path.splitext(base_template_name) + + # Standardized output filename for a node with one or more specializations output_filename = f"{template_root}{template_ext}" output_script_path = os.path.join(output_dir, output_filename) @@ -97,23 +142,21 @@ def create_modified_script(template_script_path, zmq_port_name_val, zmq_port_val with open(output_script_path, 'w') as f: f.writelines(modified_lines) - print(f"Successfully created '{output_script_path}' with:") - print(f" ZMQ_PORT_NAME = \"{zmq_port_name_val}\"") - print(f" ZMQ_PORT = \"{zmq_port_val}\"") + print(f"Successfully created specialized script: '{output_script_path}'") except Exception as e: print(f"Error writing output script '{output_script_path}': {e}") sys.exit(1) if __name__ == "__main__": - if len(sys.argv) != 5: - print("Usage: python3 copy_with_port_portname.py ") - print("Example: python3 copy_with_port_portname.py FUNBODY_REP_1 \"2355\" \"./templates/funbody_base.py\" \"./generated_scripts/\"") + if len(sys.argv) != 4: + print("\nUsage: python3 copy_with_port_portname.py ''\n") + print("Example JSON: '[{\"port\": \"2355\", \"port_name\": \"FUNBODY_REP_1\", \"source_node_label\": \"nodeA\", \"target_node_label\": \"nodeB\"}]'") + print("Note: The JSON string must be enclosed in single quotes in shell.\n") sys.exit(1) - new_port_name_arg = sys.argv[1] - new_bind_address_arg = sys.argv[2] - template_script_path_arg = sys.argv[3] - output_directory_arg = sys.argv[4] + template_script_path_arg = sys.argv[1] + output_directory_arg = sys.argv[2] + json_params_arg = sys.argv[3] - create_modified_script(template_script_path_arg, new_port_name_arg, new_bind_address_arg, output_directory_arg) \ No newline at end of file + create_modified_script(template_script_path_arg, output_directory_arg, json_params_arg) \ No newline at end of file From 3df68859ff9877cac5f233abde998888a358ef06 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Sun, 8 Jun 2025 23:55:52 +0530 Subject: [PATCH 07/17] Added Some Studies that i created while testing ZeroMQ --- 0mq/distributed_client.graphml | 592 ++++++++++++++ 0mq/distributed_server.graphml | 520 ++++++++++++ 0mq/firstNode.py | 45 ++ 0mq/funbody.dir/concore2.py | 284 +++++-- 0mq/funbody2.dir/concore2.py | 284 +++++-- .../concore2.py | 18 +- 0mq/funbody_distributed.py | 67 ++ 0mq/funbody_zmq.dir copy/concore2.py | 263 ++++++ 0mq/funbody_zmq.py | 85 +- 0mq/funbody_zmq2.dir/concore2.py | 19 +- 0mq/funbody_zmq2.py | 16 +- 0mq/funcall.dir/concore2.py | 284 +++++-- 0mq/funcall2.dir/concore2.py | 284 +++++-- 0mq/funcall_distributed.dir/concore2.py | 263 ++++++ 0mq/funcall_distributed.py | 63 ++ 0mq/funcall_zmq.dir/concore2.py | 18 +- 0mq/funcall_zmq.py | 76 +- 0mq/funcall_zmq2.dir/concore2.py | 18 +- 0mq/funcall_zmq2.py | 16 +- 0mq/secondNode.py | 33 + 0mq/semicyclic.graphml | 760 ++++++++++++++++++ 0mq/test0mq4.graphml | 138 +++- 0mq/test0mqbody2.graphml | 222 +++-- 0mq/test0mqcall.graphml | 308 +++++-- 0mq/thirdNode.py | 34 + 25 files changed, 4218 insertions(+), 492 deletions(-) create mode 100644 0mq/distributed_client.graphml create mode 100644 0mq/distributed_server.graphml create mode 100644 0mq/firstNode.py rename 0mq/{funbody_zmq.dir => funbody_distributed.dir}/concore2.py (94%) create mode 100644 0mq/funbody_distributed.py create mode 100644 0mq/funbody_zmq.dir copy/concore2.py create mode 100644 0mq/funcall_distributed.dir/concore2.py create mode 100644 0mq/funcall_distributed.py create mode 100644 0mq/secondNode.py create mode 100644 0mq/semicyclic.graphml create mode 100644 0mq/thirdNode.py diff --git a/0mq/distributed_client.graphml b/0mq/distributed_client.graphml new file mode 100644 index 0000000..033f176 --- /dev/null +++ b/0mq/distributed_client.graphml @@ -0,0 +1,592 @@ + + + + + + + + + + + + CZ:cpymax.py + + + + + + + + + + + F1:funcall_zmq2.py + + + + + + + + + + + IN: + + + + + + + + + + Y + + + + + + + + + + + + U + + + + + + + + + + + + 0x2405_U3 + + + + + + + + 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 + + + 1666487497309 + + ADD_EDGE + W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= + + + DEL_EDGE + WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== + + 4957bb66f70bda073e7edafdad81f6b4 + + + 1666487500685 + + ADD_EDGE + W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== + + + DEL_EDGE + WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== + + c8d5e89e2630a4a0aa607594e14861d1 + + + 1666810339519 + + ADD_EDGE + W3sibGFiZWwiOiJVMiIsInNvdXJjZSI6ImFjZWUyZTJjLTFhOTEtNDg1OC1hYzdjLWNhMmNiM2YxZjQ3MCIsInRhcmdldCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjotOS40NzQ2NTYxODQ2MTU5NmUtOCwiYmVuZFdlaWdodCI6MC41MDAwMDAwMDAwMDA5Nzc3LCJiZW5kUG9pbnQiOnsieCI6NDkxLjU4ODIyNDQ2NjEyMTEsInkiOjEwMC42MzA4MzY3OTg1ODUxfX0sInNvdXJjZUlEIjoiZGIzMWJlM2YtM2U1OC00YzM2LTk3OWQtNDFmYjI4YWVmZTY4IiwidGFyZ2V0SUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImU2ZWZhMmIyLWI0NDItNDAwNi05NzQ5LTdlM2IyZDUxMzJmYiJ9XQ== + + + DEL_EDGE + WyJlNmVmYTJiMi1iNDQyLTQwMDYtOTc0OS03ZTNiMmQ1MTMyZmIiXQ== + + ead3ddf695580bca36da4698dfe89256 + + + 1666810339519 + + ADD_EDGE + W3sibGFiZWwiOiJZMiIsInNvdXJjZSI6IjA0YmZkMWI4LTkzYWYtNDQxZi1iNDZhLTMyMGZkMTA3NDBjOSIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjozMC41NjQzMTU2MDk0NTE4NjQsImJlbmRXZWlnaHQiOjAuNTE0MzI5NzI5MzYyMTU2MywiYmVuZFBvaW50Ijp7IngiOjQyMi43NzE0OTAyODczNTc2NiwieSI6NjQuMDU1NTI3OTI5NTQ0ODd9fSwic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInR5cGUiOiJvcmRpbiIsImlkIjoiOTE3MzNmNmItM2RlMy00MGFmLWJmMTQtMmJiNmNiYzQ5MGUyIn1d + + + DEL_EDGE + WyI5MTczM2Y2Yi0zZGUzLTQwYWYtYmYxNC0yYmI2Y2JjNDkwZTIiXQ== + + a86191957747741919dd1f5e71c2e56c + + + 1666810339519 + + ADD_NODE + WyJGMjpmdW5ib2R5LnB5Iix7IndpZHRoIjoxMjAsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsiaWQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJsYWJlbCI6IkYyOmZ1bmJvZHkucHkiLCJ0eXBlIjoib3JkaW4iLCJzdHlsZSI6eyJ3aWR0aCI6MTIwLCJoZWlnaHQiOjUwLCJvcGFjaXR5IjoxLCJzaGFwZSI6InJlY3RhbmdsZSIsImJhY2tncm91bmRDb2xvciI6IiNmZmNjMDAiLCJib3JkZXJDb2xvciI6IiMwMDAiLCJib3JkZXJXaWR0aCI6MX19LCJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== + + + DEL_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== + + b3ce34b6dc8f697e5b8fdf374ec42075 + + + 1666810343268 + + ADD_NODE + WyJQWjpwbXB5bWF4LnB5Iix7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJpZCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiUFo6cG1weW1heC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyJd + + + DEL_NODE + WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciXQ== + + ab4fb226f0c49b8ded66436938762af7 + + + 1666810375461 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjExMSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsLnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + f5e56f793b1dfd259251f6b15ecf0e6a + + + 1748979732766 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcTIucHkiLHRydWVd + + 9e9aaedf5e2f34cef7d06d52891d6a76 + + + 1749058687416 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4IjotMzg4LCJ5IjoxMC43NzM2MjI4MjYyMzMxMDh9XQ== + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fSx7IngiOjEwMCwieSI6OTQuNzczNjIyODI2MjMzMTF9XQ== + + 7cb1d108692b66ae85dd0ffdcf639baf + + + 1749058691778 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTE3Ny43NzYyMDM1NDk0MjM4MywieSI6MTM2LjMyMDEyNzA2ODI1NjR9XQ== + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3Ny43NzYyMDM1NDk0MjM4MywieSI6MTM2LjMyMDEyNzA2ODI1NjR9LHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9XQ== + + 1ce2563fc9ee71151cb6a722255fd762 + + + 1749058702356 + + DEL_NODE + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiXQ== + + + ADD_NODE + WyJJTjoiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotNjMyLCJ5IjotMTQzfSx7fSwiNDA4YTVkNjUtZTc2My00NjcyLTlkYTgtZGVjOTEzNjFkY2RkIl0= + + 26f5f23f693921ed1b1ee5d52e1e75b6 + + + 1749058707709 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6LTU5OCwieSI6OTl9XQ== + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTU5OCwieSI6OTl9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 6ae6b59a08af5a7047a97a5ad388c270 + + + 1749058713842 + + DEL_EDGE + WyIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6IjQwOGE1ZDY1LWU3NjMtNDY3Mi05ZGE4LWRlYzkxMzYxZGNkZCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYifV0= + + cc747ad0ecc75c44cc3b6f6f9e9ae92c + + + 1749058727442 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTU5OCwieSI6OTl9LHsieCI6LTYxMiwieSI6LTEwMn1d + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYxMiwieSI6LTEwMn0seyJ4IjotNTk4LCJ5Ijo5OX1d + + fa49a13771e334eebbf112917f89d058 + + + 1749058754860 + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6IjQwOGE1ZDY1LWU3NjMtNDY3Mi05ZGE4LWRlYzkxMzYxZGNkZCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwidHlwZSI6Im9yZGluIiwic291cmNlIjoiYzI1ZDZiNjItNWQ2Ni00MDliLTk0YjEtZTZmZmI1ZjBmMTViIiwidGFyZ2V0IjoiNDA4YTVkNjUtZTc2My00NjcyLTlkYTgtZGVjOTEzNjFkY2RkIiwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLCJiZW5kV2VpZ2h0IjowLjUsImJlbmRQb2ludCI6eyJ4IjotNTI0Ljg0NzY3NTkxNDkzNTQsInkiOi01OC4xMTMxODg1ODY4ODM0NDZ9fSwiaWQiOiIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYifV0= + + + DEL_EDGE + WyIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYiXQ== + + 7f0f25f333a2a6cfc15a70a1634323f1 + + + 1749058756916 + + DEL_EDGE + WyJjNTQzMjlmMy0xMmQ1LTQ2ZTAtOTE3Zi02MGQ3NmI3OTQ1ZmIiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJjNTQzMjlmMy0xMmQ1LTQ2ZTAtOTE3Zi02MGQ3NmI3OTQ1ZmIifV0= + + fc1f4b789ad989f3e60a17bbe3a5bd5a + + + 1749058765759 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYxMiwieSI6LTEwMn0seyJ4IjotNjMyLCJ5IjotMTQzfV0= + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYzMiwieSI6LTE0M30seyJ4IjotNjEyLCJ5IjotMTAyfV0= + + 4209fecec5c91f476c4539fa06418efd + + + 1749058768670 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fSx7IngiOi00ODcsInkiOjUwLjc3MzYyMjgyNjIzMzExfV0= + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTQ4NywieSI6NTAuNzczNjIyODI2MjMzMTF9LHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fV0= + + 63797cc5d0c6dc2da5ef71e99504bd45 + + + 1749066909379 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9ZMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + 1ad516ce46689ac6f15b5532ff42ab86 + + + 1749070198710 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + f6a8e5aa88fff9e10e187a6f5d1b6b33 + + + 1749070471512 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + 9b54fffa96ec88de939b11febe6746d0 + + + 1749070605367 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + ae211e5c6a9ff5b2487f0e107ea136f1 + + + 1749325857360 + + UPDATE_EDGE + WyIwMjg4Nzc2NS1lNTA5LTQ3MjgtYWE1ZC1hZTBiYmJhMjkxMzQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyIwMjg4Nzc2NS1lNTA5LTQ3MjgtYWE1ZC1hZTBiYmJhMjkxMzQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwNV9VMyIsdHJ1ZV0= + + d42101a2e57f7e1fc75f9b867262a6a8 + + + \ No newline at end of file diff --git a/0mq/distributed_server.graphml b/0mq/distributed_server.graphml new file mode 100644 index 0000000..852b689 --- /dev/null +++ b/0mq/distributed_server.graphml @@ -0,0 +1,520 @@ + + + + + + + + + + + + PZ:pmpymax.py + + + + + + + + + + + F2:funbody_distributed.py + + + + + + + + + + + OUT: + + + + + + + + + + Y2 + + + + + + + + + + + + U2 + + + + + + + + + + + + 0x2405_U3 + + + + + + + + 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 + + + 1666487497309 + + ADD_EDGE + W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= + + + DEL_EDGE + WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== + + 4957bb66f70bda073e7edafdad81f6b4 + + + 1666487500685 + + ADD_EDGE + W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== + + + DEL_EDGE + WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== + + c8d5e89e2630a4a0aa607594e14861d1 + + + 1666810445211 + + ADD_EDGE + W3sibGFiZWwiOiJZIiwic291cmNlIjoiNTIzNjQxYTQtOTc1NS00NWVkLTlhMjUtYTExNDc2ZGUzN2EwIiwidGFyZ2V0IjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjI5LjE1NTExMDY3Mjg3NDI5NCwiYmVuZFdlaWdodCI6MC41MTMxNjc2Njk2NTEzNTEyLCJiZW5kUG9pbnQiOnsieCI6LTUwLjM1NTE2Njc0NzA3LCJ5Ijo1OC4xODI0NTg4NjkxNTA4NH19LCJzb3VyY2VJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInRhcmdldElEIjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwidHlwZSI6Im9yZGluIiwiaWQiOiI4YTE1ZmMyOC02ZjA5LTQ3MmYtYTk3Ni1jZmYzOWY3MzFjNjAifV0= + + + DEL_EDGE + WyI4YTE1ZmMyOC02ZjA5LTQ3MmYtYTk3Ni1jZmYzOWY3MzFjNjAiXQ== + + cfc129abe20d32f8c156301489dcc705 + + + 1666810445211 + + ADD_EDGE + W3sibGFiZWwiOiJVIiwic291cmNlIjoiZDA0MDg0OGYtNmE5NC00YWMyLWE0ZTItYTg4NzliNWY3ZmZiIiwidGFyZ2V0IjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjAuMDAwMDE0ODc2MzcxMTExNjM4NDIsImJlbmRXZWlnaHQiOjAuNTAwMDAwMDAxMjIyMTMzNiwiYmVuZFBvaW50Ijp7IngiOjExLjYxMTg5ODIyNTI4ODk2OCwieSI6OTMuNDg5ODc5MjQ2Nzg1Mzl9fSwic291cmNlSUQiOiJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInR5cGUiOiJvcmRpbiIsImlkIjoiZTAxY2FiN2MtYzQ0Ni00OGRhLWI4OGUtN2Y5NjIwY2NkMjY5In1d + + + DEL_EDGE + WyJlMDFjYWI3Yy1jNDQ2LTQ4ZGEtYjg4ZS03Zjk2MjBjY2QyNjkiXQ== + + 9fbba2442b7019a76634710caf98a549 + + + 1666810445211 + + ADD_NODE + WyJGMTpmdW5jYWxsLnB5Iix7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJpZCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiRjE6ZnVuY2FsbC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCJd + + + DEL_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiXQ== + + de44f1ff4f2107a20e234361711eec91 + + + 1666810453165 + + ADD_NODE + WyJDWjpjcHltYXgucHkiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotMTM3Ljc3NjIwMzU0OTQyMzgzLCJ5Ijo5MS4zMjAxMjcwNjgyNTY0MX0seyJpZCI6ImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSIsImxhYmVsIjoiQ1o6Y3B5bWF4LnB5IiwidHlwZSI6Im9yZGluIiwic3R5bGUiOnsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9fSwiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIl0= + + + DEL_NODE + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiXQ== + + f1cb4196a5082cef004f9ee186c7f04b + + + 1666810462415 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + 9e9b34686b3aec97cf26547fcd7ae633 + + + 1748979705408 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + 299aef4ea2931f8b9a6b7f10361b0022 + + + 1749058646821 + + DEL_NODE + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiXQ== + + + ADD_NODE + WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTQzLCJ5IjoyNzF9LHt9LCI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiXQ== + + 51cf4c5701b1a8a637c1b373dcd09c59 + + + 1749058651133 + + SET_POS + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTQzLCJ5IjoyNzF9XQ== + + + SET_POS + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiLHsieCI6MTQzLCJ5IjoyNzF9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 440d3083c9a571e9660685eaeefae6fb + + + 1749058659847 + + DEL_EDGE + WyJmYzY1ZTg0OC04OTJmLTQyZWQtYWU0OS1iYjhlYmQzODVmYjAiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6IjUyZTk3NDkyLWNjZWEtNDhhMi05ZGVkLWUyMzVlMjQ1MDM1OCIsImxhYmVsIjoiMHgyNDAwX1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJmYzY1ZTg0OC04OTJmLTQyZWQtYWU0OS1iYjhlYmQzODVmYjAifV0= + + 615e0be29af2a4940efea41e374438bb + + + 1749070207801 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + a8472011e18e50a782b19383b3b1a41d + + + 1749070480095 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + 4a9c6467598df6924c76f002eccbb822 + + + 1749070617114 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + 2b2ace96e5b5dad90e06fbac4e20b915 + + + 1749322194657 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + dfbb291ab07456ce0005d5c6d1d6a18a + + + 1749325840799 + + UPDATE_EDGE + WyJlOTJlM2E5ZC1lOWEwLTQ5YzgtOWYyMC1iNWQ1MTM3M2EzZjYiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyJlOTJlM2E5ZC1lOWEwLTQ5YzgtOWYyMC1iNWQ1MTM3M2EzZjYiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwNV9VMyIsdHJ1ZV0= + + 385fc34934650be854756424f6fac52e + + + 1749406730989 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjIxMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X2Rpc3RyaWJ1dGVkLnB5Iix0cnVlXQ== + + 3eae38f7266c77d8368676cbdc9b3ba5 + + + \ No newline at end of file diff --git a/0mq/firstNode.py b/0mq/firstNode.py new file mode 100644 index 0000000..acc08a9 --- /dev/null +++ b/0mq/firstNode.py @@ -0,0 +1,45 @@ +# firstNode.py (Client/Orchestrator) +import concore +import time + +# --- ZMQ Initialization --- +# This REQ socket connects to Node B (F2) +concore.init_zmq_port( + port_name=f"0x{PORT_F1_F2}_{PORT_NAME_F1_F2}", + port_type="connect", + address="tcp://localhost:" + PORT_F1_F2, + socket_type_str="REQ" +) +# This REQ socket connects to Node C (F3) +concore.init_zmq_port( + port_name=f"0x{PORT_F1_F3}_{PORT_NAME_F1_F3}", + port_type="connect", + address="tcp://localhost:" + PORT_F1_F3, + socket_type_str="REQ" +) + +current_value = 0.0 + +while current_value <= 100: + # --- Step 1: Communicate with Node B --- + print(f"Node A: Sending value {current_value:.2f} to Node B.") + concore.write(f"0x{PORT_F1_F2}_{PORT_NAME_F1_F2}", "value", [current_value]) + + # Wait for the reply from Node B + value_from_b = concore.read(f"0x{PORT_F1_F2}_{PORT_NAME_F1_F2}", "value", [current_value]) + processed_by_b = value_from_b[0] + print(f"Node A: Received processed value {processed_by_b:.2f} from Node B.") + + # --- Step 2: Communicate with Node C --- + print(f"Node A: Sending value {processed_by_b:.2f} to Node C.") + concore.write(f"0x{PORT_F1_F3}_{PORT_NAME_F1_F3}", "value", [processed_by_b]) + + # Wait for the reply from Node C + value_from_c = concore.read(f"0x{PORT_F1_F3}_{PORT_NAME_F1_F3}", "value", [processed_by_b]) + current_value = value_from_c[0] + print(f"Node A: Received final value {current_value:.2f} from Node C.") + print("-" * 20) + time.sleep(1) # Slow down the loop for readability + +print("\nNode A: Value exceeded 100. Terminating.") +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/funbody.dir/concore2.py b/0mq/funbody.dir/concore2.py index e3ec817..a018ddf 100644 --- a/0mq/funbody.dir/concore2.py +++ b/0mq/funbody.dir/concore2.py @@ -3,6 +3,7 @@ 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 @@ -12,15 +13,67 @@ with open("concorekill.bat","w") as fpid: fpid.write("taskkill /F /PID "+str(os.getpid())+"\n") -try: - iport = literal_eval(open("concore.iport").read()) -except: - iport = dict() -try: - oport = literal_eval(open("concore.oport").read()) -except: - oport = dict() +# --- 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 = '' @@ -28,86 +81,183 @@ retrycount = 0 inpath = "./in" #must be rel path for local outpath = "./out" +simtime = 0 #9/21/22 try: - sparams = open(inpath+"1/concore.params").read() - if sparams[0] == '"': #windows keeps "" need to remove - sparams = sparams[1:] - sparams = sparams[0:sparams.find('"')] - if sparams != '{': - print("converting sparams: "+sparams) - sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" - print("converted sparams: " + sparams) - try: - params = literal_eval(sparams) - except: - print("bad params: "+sparams) -except: + 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): - try: - return params[n] - except: - return i +def tryparam(n, i): + return params.get(n, i) #9/12/21 def default_maxtime(default): global maxtime - try: - maxtime = literal_eval(open(inpath+"1/concore.maxtime").read()) - except: - maxtime = default + 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: + global olds, s + if olds == s: s = '' return True - else: - olds = s - return False + 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 -def read(port, name, initstr): - global s,simtime,retrycount - time.sleep(delay) try: - infile = open(inpath+str(port)+"/"+name); - ins = infile.read() - except: - ins = initstr - while len(ins)==0: + 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) - ins = infile.read() + 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 - s += ins - inval = literal_eval(ins) - simtime = max(simtime,inval[0]) - return inval[1:] - -def write(port, name, val, delta=0): - global outpath,simtime - if isinstance(val,str): - time.sleep(2*delay) - elif isinstance(val,list)==False: - print("mywrite must have list or str") - quit() + + if len(ins) == 0: + print(f"Max retries reached for {file_path}, using default value.") + return default_return_val + + s += ins try: - with open(outpath+str(port)+"/"+name,"w") as outfile: - if isinstance(val,list): - outfile.write(str([simtime+delta]+val)) - simtime += delta - else: + 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: - print("skipping"+outpath+str(port)+"/"+name); + except Exception as e: + print(f"Error writing to {file_path}: {e}") -def initval(simtime_val): +def initval(simtime_val_str): global simtime - val = literal_eval(simtime_val) - simtime = val[0] - return val[1:] + 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/0mq/funbody2.dir/concore2.py b/0mq/funbody2.dir/concore2.py index e3ec817..a018ddf 100644 --- a/0mq/funbody2.dir/concore2.py +++ b/0mq/funbody2.dir/concore2.py @@ -3,6 +3,7 @@ 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 @@ -12,15 +13,67 @@ with open("concorekill.bat","w") as fpid: fpid.write("taskkill /F /PID "+str(os.getpid())+"\n") -try: - iport = literal_eval(open("concore.iport").read()) -except: - iport = dict() -try: - oport = literal_eval(open("concore.oport").read()) -except: - oport = dict() +# --- 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 = '' @@ -28,86 +81,183 @@ retrycount = 0 inpath = "./in" #must be rel path for local outpath = "./out" +simtime = 0 #9/21/22 try: - sparams = open(inpath+"1/concore.params").read() - if sparams[0] == '"': #windows keeps "" need to remove - sparams = sparams[1:] - sparams = sparams[0:sparams.find('"')] - if sparams != '{': - print("converting sparams: "+sparams) - sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" - print("converted sparams: " + sparams) - try: - params = literal_eval(sparams) - except: - print("bad params: "+sparams) -except: + 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): - try: - return params[n] - except: - return i +def tryparam(n, i): + return params.get(n, i) #9/12/21 def default_maxtime(default): global maxtime - try: - maxtime = literal_eval(open(inpath+"1/concore.maxtime").read()) - except: - maxtime = default + 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: + global olds, s + if olds == s: s = '' return True - else: - olds = s - return False + 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 -def read(port, name, initstr): - global s,simtime,retrycount - time.sleep(delay) try: - infile = open(inpath+str(port)+"/"+name); - ins = infile.read() - except: - ins = initstr - while len(ins)==0: + 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) - ins = infile.read() + 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 - s += ins - inval = literal_eval(ins) - simtime = max(simtime,inval[0]) - return inval[1:] - -def write(port, name, val, delta=0): - global outpath,simtime - if isinstance(val,str): - time.sleep(2*delay) - elif isinstance(val,list)==False: - print("mywrite must have list or str") - quit() + + if len(ins) == 0: + print(f"Max retries reached for {file_path}, using default value.") + return default_return_val + + s += ins try: - with open(outpath+str(port)+"/"+name,"w") as outfile: - if isinstance(val,list): - outfile.write(str([simtime+delta]+val)) - simtime += delta - else: + 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: - print("skipping"+outpath+str(port)+"/"+name); + except Exception as e: + print(f"Error writing to {file_path}: {e}") -def initval(simtime_val): +def initval(simtime_val_str): global simtime - val = literal_eval(simtime_val) - simtime = val[0] - return val[1:] + 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/0mq/funbody_zmq.dir/concore2.py b/0mq/funbody_distributed.dir/concore2.py similarity index 94% rename from 0mq/funbody_zmq.dir/concore2.py rename to 0mq/funbody_distributed.dir/concore2.py index 7b0b3b4..a018ddf 100644 --- a/0mq/funbody_zmq.dir/concore2.py +++ b/0mq/funbody_distributed.dir/concore2.py @@ -54,6 +54,13 @@ def init_zmq_port(port_name, port_type, address, socket_type_str): 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): @@ -207,16 +214,17 @@ def write(port_identifier, name, val, delta=0): 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 - + return try: - file_port_num = int(port_identifier) + 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 - file_path = os.path.join(outpath+str(file_port_num), name) - if isinstance(val, str): time.sleep(2 * delay) elif not isinstance(val, list): diff --git a/0mq/funbody_distributed.py b/0mq/funbody_distributed.py new file mode 100644 index 0000000..eaae295 --- /dev/null +++ b/0mq/funbody_distributed.py @@ -0,0 +1,67 @@ +# funbody2_zmq.py +import time +import concore +import concore2 + +print("funbody using ZMQ via concore") + +# Initialize ZMQ REP port using concore +concore.init_zmq_port( + port_name=PORT_NAME_F2_OUT, + port_type="bind", + address= "tcp://0.0.0.0:" + PORT_F2_OUT, + socket_type_str="REP" +) + + +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" + +u_data_values = concore.initval(init_simtime_u_str) +ym_data_values = concore2.initval(init_simtime_ym_str) + +print(f"Initial u_data_values: {u_data_values}, ym_data_values: {ym_data_values}") +print(f"Max time: {concore.maxtime}") + +while concore2.simtime < concore.maxtime: + received_u_data = concore.read(PORT_NAME_F2_OUT, "u_signal", init_simtime_u_str) + + if not (isinstance(received_u_data, list) and len(received_u_data) > 0): + print(f"Error or invalid data received via ZMQ: {received_u_data}. Skipping iteration.") + time.sleep(concore.delay) + continue + + received_time = received_u_data[0] + if isinstance(received_time, (int, float)): + concore.simtime = received_time + u_data_values = received_u_data[1:] + else: + print(f"Warning: Received ZMQ data's first element is not time: {received_u_data}. Using data part as is.") + u_data_values = received_u_data[1:] if len(received_u_data) > 1 else [] + + # Assuming concore.oport['U2'] is a file port (e.g., to pmpymax.py) + if 'U2' in concore.oport: + concore.write(concore.oport['U2'], "u", u_data_values) + + old_concore2_simtime = concore2.simtime + while concore2.unchanged() or concore2.simtime <= old_concore2_simtime: + # Assuming concore.iport['Y2'] is a file port (e.g., from pmpymax.py) + ym_data_values = concore2.read(concore.iport['Y2'], "ym", init_simtime_ym_str) + # time.sleep(concore2.delay) # Optional delay + + ym_full_to_send = [concore2.simtime] + ym_data_values + + concore.write(PORT_NAME_F2_OUT, "ym_signal", ym_full_to_send) + + print(f"funbody u={u_data_values} ym={ym_data_values} time={concore2.simtime}") + +print("funbody retry=" + str(concore.retrycount)) + +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/funbody_zmq.dir copy/concore2.py b/0mq/funbody_zmq.dir copy/concore2.py new file mode 100644 index 0000000..a018ddf --- /dev/null +++ b/0mq/funbody_zmq.dir copy/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/0mq/funbody_zmq.py b/0mq/funbody_zmq.py index 576f692..6a6b353 100644 --- a/0mq/funbody_zmq.py +++ b/0mq/funbody_zmq.py @@ -1,45 +1,66 @@ # funbody2_zmq.py -import zmq -import time +import time import concore import concore2 -print("funbody using 0mq") +print("funbody using ZMQ via concore") -context = zmq.Context() -socket = context.socket(zmq.REP) -socket.bind("tcp://*:2356") +# Initialize ZMQ REP port using concore +concore.init_zmq_port( + port_name=PORT_NAME_F2_F1, + port_type="bind", + address= "tcp://*:" + PORT_F2_F1, + socket_type_str="REP" +) -concore.delay = 0.07 -concore2.delay = 0.07 +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 concore2.inpath = concore.inpath concore2.outpath = concore.outpath -concore2.simtime = 0 -concore.default_maxtime(100) -init_simtime_u = "[0.0, 0.0, 0.0]" -init_simtime_ym = "[0.0, 0.0, 0.0]" +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" -u = concore.initval(init_simtime_u) -ym = concore2.initval(init_simtime_ym) +u_data_values = concore.initval(init_simtime_u_str) +ym_data_values = concore2.initval(init_simtime_ym_str) + +print(f"Initial u_data_values: {u_data_values}, ym_data_values: {ym_data_values}") +print(f"Max time: {concore.maxtime}") while concore2.simtime < concore.maxtime: - msg = socket.recv_json() - if msg["action"] == "fun": - u = msg["params"]["u"] - concore.simtime = u[0] - u = u[1:] - concore.write(concore.oport['U2'], "u", u) - print(u) - old2 = concore2.simtime - while concore2.unchanged() or concore2.simtime <= old2: - ym = concore2.read(concore.iport['Y2'], "ym", init_simtime_ym) - ym_full = [concore2.simtime] + ym - print(f"Replying with {ym_full}") - socket.send_json({"ym": ym_full}) - print(f"funbody u={u} ym={ym} time={concore2.simtime}") + received_u_data = concore.read(PORT_NAME_F2_F1, "u_signal", init_simtime_u_str) + + if not (isinstance(received_u_data, list) and len(received_u_data) > 0): + print(f"Error or invalid data received via ZMQ: {received_u_data}. Skipping iteration.") + time.sleep(concore.delay) + continue + + received_time = received_u_data[0] + if isinstance(received_time, (int, float)): + concore.simtime = received_time + u_data_values = received_u_data[1:] else: - print("undefined action: " + str(msg.get("action", "None"))) - socket.send_json({"error": "undefined action"}) - break + print(f"Warning: Received ZMQ data's first element is not time: {received_u_data}. Using data part as is.") + u_data_values = received_u_data[1:] if len(received_u_data) > 1 else [] + + # Assuming concore.oport['U2'] is a file port (e.g., to pmpymax.py) + if 'U2' in concore.oport: + concore.write(concore.oport['U2'], "u", u_data_values) + + old_concore2_simtime = concore2.simtime + while concore2.unchanged() or concore2.simtime <= old_concore2_simtime: + # Assuming concore.iport['Y2'] is a file port (e.g., from pmpymax.py) + ym_data_values = concore2.read(concore.iport['Y2'], "ym", init_simtime_ym_str) + # time.sleep(concore2.delay) # Optional delay + + ym_full_to_send = [concore2.simtime] + ym_data_values + + concore.write(PORT_NAME_F2_F1, "ym_signal", ym_full_to_send) + + print(f"funbody u={u_data_values} ym={ym_data_values} time={concore2.simtime}") + +print("funbody retry=" + str(concore.retrycount)) -print("retry=" + str(concore.retrycount)) \ No newline at end of file +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/funbody_zmq2.dir/concore2.py b/0mq/funbody_zmq2.dir/concore2.py index 65bd955..a018ddf 100644 --- a/0mq/funbody_zmq2.dir/concore2.py +++ b/0mq/funbody_zmq2.dir/concore2.py @@ -54,6 +54,14 @@ def init_zmq_port(port_name, port_type, address, socket_type_str): 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: @@ -206,16 +214,17 @@ def write(port_identifier, name, val, delta=0): 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 - + return try: - file_port_num = int(port_identifier) + 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 - file_path = os.path.join(outpath+str(file_port_num), name) - if isinstance(val, str): time.sleep(2 * delay) elif not isinstance(val, list): diff --git a/0mq/funbody_zmq2.py b/0mq/funbody_zmq2.py index fce7b13..04d9487 100644 --- a/0mq/funbody_zmq2.py +++ b/0mq/funbody_zmq2.py @@ -5,15 +5,11 @@ print("funbody using ZMQ via concore") -# ZMQ settings -ZMQ_PORT_NAME = "FUNBODY_REP_PORT" -ZMQ_BIND_ADDRESS = "tcp://*:2355" - # Initialize ZMQ REP port using concore concore.init_zmq_port( - port_name=ZMQ_PORT_NAME, + port_name=PORT_NAME_F2_OUT, port_type="bind", - address=ZMQ_BIND_ADDRESS, + address= "tcp://*:" + PORT_F2_OUT, socket_type_str="REP" ) @@ -34,7 +30,7 @@ print(f"Max time: {concore.maxtime}") while concore2.simtime < concore.maxtime: - received_u_data = concore.read(ZMQ_PORT_NAME, "u_signal", init_simtime_u_str) + received_u_data = concore.read(PORT_NAME_F2_OUT, "u_signal", init_simtime_u_str) if not (isinstance(received_u_data, list) and len(received_u_data) > 0): print(f"Error or invalid data received via ZMQ: {received_u_data}. Skipping iteration.") @@ -61,8 +57,10 @@ ym_full_to_send = [concore2.simtime] + ym_data_values - concore.write(ZMQ_PORT_NAME, "ym_signal", ym_full_to_send) + concore.write(PORT_NAME_F2_OUT, "ym_signal", ym_full_to_send) print(f"funbody u={u_data_values} ym={ym_data_values} time={concore2.simtime}") -print("funbody retry=" + str(concore.retrycount)) \ No newline at end of file +print("funbody retry=" + str(concore.retrycount)) + +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/funcall.dir/concore2.py b/0mq/funcall.dir/concore2.py index e3ec817..a018ddf 100644 --- a/0mq/funcall.dir/concore2.py +++ b/0mq/funcall.dir/concore2.py @@ -3,6 +3,7 @@ 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 @@ -12,15 +13,67 @@ with open("concorekill.bat","w") as fpid: fpid.write("taskkill /F /PID "+str(os.getpid())+"\n") -try: - iport = literal_eval(open("concore.iport").read()) -except: - iport = dict() -try: - oport = literal_eval(open("concore.oport").read()) -except: - oport = dict() +# --- 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 = '' @@ -28,86 +81,183 @@ retrycount = 0 inpath = "./in" #must be rel path for local outpath = "./out" +simtime = 0 #9/21/22 try: - sparams = open(inpath+"1/concore.params").read() - if sparams[0] == '"': #windows keeps "" need to remove - sparams = sparams[1:] - sparams = sparams[0:sparams.find('"')] - if sparams != '{': - print("converting sparams: "+sparams) - sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" - print("converted sparams: " + sparams) - try: - params = literal_eval(sparams) - except: - print("bad params: "+sparams) -except: + 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): - try: - return params[n] - except: - return i +def tryparam(n, i): + return params.get(n, i) #9/12/21 def default_maxtime(default): global maxtime - try: - maxtime = literal_eval(open(inpath+"1/concore.maxtime").read()) - except: - maxtime = default + 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: + global olds, s + if olds == s: s = '' return True - else: - olds = s - return False + 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 -def read(port, name, initstr): - global s,simtime,retrycount - time.sleep(delay) try: - infile = open(inpath+str(port)+"/"+name); - ins = infile.read() - except: - ins = initstr - while len(ins)==0: + 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) - ins = infile.read() + 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 - s += ins - inval = literal_eval(ins) - simtime = max(simtime,inval[0]) - return inval[1:] - -def write(port, name, val, delta=0): - global outpath,simtime - if isinstance(val,str): - time.sleep(2*delay) - elif isinstance(val,list)==False: - print("mywrite must have list or str") - quit() + + if len(ins) == 0: + print(f"Max retries reached for {file_path}, using default value.") + return default_return_val + + s += ins try: - with open(outpath+str(port)+"/"+name,"w") as outfile: - if isinstance(val,list): - outfile.write(str([simtime+delta]+val)) - simtime += delta - else: + 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: - print("skipping"+outpath+str(port)+"/"+name); + except Exception as e: + print(f"Error writing to {file_path}: {e}") -def initval(simtime_val): +def initval(simtime_val_str): global simtime - val = literal_eval(simtime_val) - simtime = val[0] - return val[1:] + 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/0mq/funcall2.dir/concore2.py b/0mq/funcall2.dir/concore2.py index e3ec817..a018ddf 100644 --- a/0mq/funcall2.dir/concore2.py +++ b/0mq/funcall2.dir/concore2.py @@ -3,6 +3,7 @@ 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 @@ -12,15 +13,67 @@ with open("concorekill.bat","w") as fpid: fpid.write("taskkill /F /PID "+str(os.getpid())+"\n") -try: - iport = literal_eval(open("concore.iport").read()) -except: - iport = dict() -try: - oport = literal_eval(open("concore.oport").read()) -except: - oport = dict() +# --- 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 = '' @@ -28,86 +81,183 @@ retrycount = 0 inpath = "./in" #must be rel path for local outpath = "./out" +simtime = 0 #9/21/22 try: - sparams = open(inpath+"1/concore.params").read() - if sparams[0] == '"': #windows keeps "" need to remove - sparams = sparams[1:] - sparams = sparams[0:sparams.find('"')] - if sparams != '{': - print("converting sparams: "+sparams) - sparams = "{'"+re.sub(';',",'",re.sub('=',"':",re.sub(' ','',sparams)))+"}" - print("converted sparams: " + sparams) - try: - params = literal_eval(sparams) - except: - print("bad params: "+sparams) -except: + 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): - try: - return params[n] - except: - return i +def tryparam(n, i): + return params.get(n, i) #9/12/21 def default_maxtime(default): global maxtime - try: - maxtime = literal_eval(open(inpath+"1/concore.maxtime").read()) - except: - maxtime = default + 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: + global olds, s + if olds == s: s = '' return True - else: - olds = s - return False + 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 -def read(port, name, initstr): - global s,simtime,retrycount - time.sleep(delay) try: - infile = open(inpath+str(port)+"/"+name); - ins = infile.read() - except: - ins = initstr - while len(ins)==0: + 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) - ins = infile.read() + 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 - s += ins - inval = literal_eval(ins) - simtime = max(simtime,inval[0]) - return inval[1:] - -def write(port, name, val, delta=0): - global outpath,simtime - if isinstance(val,str): - time.sleep(2*delay) - elif isinstance(val,list)==False: - print("mywrite must have list or str") - quit() + + if len(ins) == 0: + print(f"Max retries reached for {file_path}, using default value.") + return default_return_val + + s += ins try: - with open(outpath+str(port)+"/"+name,"w") as outfile: - if isinstance(val,list): - outfile.write(str([simtime+delta]+val)) - simtime += delta - else: + 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: - print("skipping"+outpath+str(port)+"/"+name); + except Exception as e: + print(f"Error writing to {file_path}: {e}") -def initval(simtime_val): +def initval(simtime_val_str): global simtime - val = literal_eval(simtime_val) - simtime = val[0] - return val[1:] + 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/0mq/funcall_distributed.dir/concore2.py b/0mq/funcall_distributed.dir/concore2.py new file mode 100644 index 0000000..a018ddf --- /dev/null +++ b/0mq/funcall_distributed.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/0mq/funcall_distributed.py b/0mq/funcall_distributed.py new file mode 100644 index 0000000..5f869c6 --- /dev/null +++ b/0mq/funcall_distributed.py @@ -0,0 +1,63 @@ +# funcall2_zmq.py +import time +import concore +import concore2 + +print("funcall using ZMQ via concore") + +# Initialize ZMQ REQ port using concore +concore.init_zmq_port( + port_name = PORT_NAME_IN_F1, + port_type="connect", + address="tcp://192.168.0.107:" + PORT_IN_F1, # Put the IP address which will Reply + socket_type_str="REQ" +) + +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" + +u = concore.initval(init_simtime_u_str) +ym = concore2.initval(init_simtime_ym_str) + +print(f"Initial u: {u}, ym: {ym}, concore.simtime: {concore.simtime}, concore2.simtime: {concore2.simtime}") +print(f"Max time: {concore.maxtime}") + +while concore2.simtime < concore.maxtime: + while concore.unchanged(): + # Assuming concore.iport['U'] is a file port (e.g., from cpymax.py) + u = concore.read(concore.iport['U'], "u", init_simtime_u_str) + # time.sleep(concore.delay) # Optional: if file reads are too fast in a loop + + data_to_send_u = [concore.simtime] + u + + concore.write(PORT_NAME_IN_F1, "u_signal", data_to_send_u) + + received_ym_data = concore.read(PORT_NAME_IN_F1, "ym_signal", init_simtime_ym_str) + + if isinstance(received_ym_data, list) and len(received_ym_data) > 0: + response_time = received_ym_data[0] + if isinstance(response_time, (int, float)): + concore2.simtime = response_time + ym = received_ym_data[1:] + else: + print(f"Warning: Received ZMQ data's first element is not time: {received_ym_data}. Using as is.") + ym = received_ym_data + else: + print(f"Warning: Received unexpected ZMQ data format: {received_ym_data}. Using default ym.") + ym = concore2.initval(init_simtime_ym_str) + + # Assuming concore.oport['Y'] is a file port (e.g., to cpymax.py) + concore2.write(concore.oport['Y'], "ym", ym) + + print(f"funcall ZMQ u={u} ym={ym} time={concore2.simtime}") + +print("funcall retry=" + str(concore.retrycount)) + +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/funcall_zmq.dir/concore2.py b/0mq/funcall_zmq.dir/concore2.py index 7b0b3b4..a018ddf 100644 --- a/0mq/funcall_zmq.dir/concore2.py +++ b/0mq/funcall_zmq.dir/concore2.py @@ -54,6 +54,13 @@ def init_zmq_port(port_name, port_type, address, socket_type_str): 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): @@ -207,16 +214,17 @@ def write(port_identifier, name, val, delta=0): 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 - + return try: - file_port_num = int(port_identifier) + 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 - file_path = os.path.join(outpath+str(file_port_num), name) - if isinstance(val, str): time.sleep(2 * delay) elif not isinstance(val, list): diff --git a/0mq/funcall_zmq.py b/0mq/funcall_zmq.py index f0c2f33..b2f991d 100644 --- a/0mq/funcall_zmq.py +++ b/0mq/funcall_zmq.py @@ -1,39 +1,63 @@ # funcall2_zmq.py -import zmq -import time +import time import concore import concore2 -print("funcall using 0mq") +print("funcall using ZMQ via concore") -context = zmq.Context() -socket = context.socket(zmq.REQ) -socket.connect("tcp://localhost:2356") +# Initialize ZMQ REQ port using concore +concore.init_zmq_port( + port_name = PORT_NAME_F2_F1, + port_type="connect", + address="tcp://localhost:" + PORT_F2_F1, + socket_type_str="REQ" +) -concore.delay = 0.07 -concore2.delay = 0.07 +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 concore2.inpath = concore.inpath concore2.outpath = concore.outpath concore2.simtime = 0 -concore.default_maxtime(100) -init_simtime_u = "[0.0, 0.0, 0.0]" -init_simtime_ym = "[0.0, 0.0, 0.0]" +concore.default_maxtime(100) +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" -u = concore.initval(init_simtime_u) -ym = concore2.initval(init_simtime_ym) +u = concore.initval(init_simtime_u_str) +ym = concore2.initval(init_simtime_ym_str) + +print(f"Initial u: {u}, ym: {ym}, concore.simtime: {concore.simtime}, concore2.simtime: {concore2.simtime}") +print(f"Max time: {concore.maxtime}") while concore2.simtime < concore.maxtime: - while concore.unchanged(): - u = concore.read(concore.iport['U'], "u", init_simtime_u) - message = { - "action": "fun", - "params": {"u": [concore.simtime] + u} - } - socket.send_json(message) - response = socket.recv_json() - ym = response["ym"] - concore2.simtime = ym[0] - ym = ym[1:] + while concore.unchanged(): + # Assuming concore.iport['U'] is a file port (e.g., from cpymax.py) + u = concore.read(concore.iport['U'], "u", init_simtime_u_str) + # time.sleep(concore.delay) # Optional: if file reads are too fast in a loop + + data_to_send_u = [concore.simtime] + u + + concore.write(PORT_NAME_F2_F1, "u_signal", data_to_send_u) + + received_ym_data = concore.read(PORT_NAME_F2_F1, "ym_signal", init_simtime_ym_str) + + if isinstance(received_ym_data, list) and len(received_ym_data) > 0: + response_time = received_ym_data[0] + if isinstance(response_time, (int, float)): + concore2.simtime = response_time + ym = received_ym_data[1:] + else: + print(f"Warning: Received ZMQ data's first element is not time: {received_ym_data}. Using as is.") + ym = received_ym_data + else: + print(f"Warning: Received unexpected ZMQ data format: {received_ym_data}. Using default ym.") + ym = concore2.initval(init_simtime_ym_str) + + # Assuming concore.oport['Y'] is a file port (e.g., to cpymax.py) concore2.write(concore.oport['Y'], "ym", ym) - print(f"funcall 0mq u={u} ym={ym} time={concore2.simtime}") -print("retry=" + str(concore.retrycount)) \ No newline at end of file + + print(f"funcall ZMQ u={u} ym={ym} time={concore2.simtime}") + +print("funcall retry=" + str(concore.retrycount)) + +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/funcall_zmq2.dir/concore2.py b/0mq/funcall_zmq2.dir/concore2.py index 7b0b3b4..a018ddf 100644 --- a/0mq/funcall_zmq2.dir/concore2.py +++ b/0mq/funcall_zmq2.dir/concore2.py @@ -54,6 +54,13 @@ def init_zmq_port(port_name, port_type, address, socket_type_str): 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): @@ -207,16 +214,17 @@ def write(port_identifier, name, val, delta=0): 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 - + return try: - file_port_num = int(port_identifier) + 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 - file_path = os.path.join(outpath+str(file_port_num), name) - if isinstance(val, str): time.sleep(2 * delay) elif not isinstance(val, list): diff --git a/0mq/funcall_zmq2.py b/0mq/funcall_zmq2.py index baff34b..13c6584 100644 --- a/0mq/funcall_zmq2.py +++ b/0mq/funcall_zmq2.py @@ -5,15 +5,11 @@ print("funcall using ZMQ via concore") -# ZMQ settings -ZMQ_PORT_NAME = "FUNCALL_REQ_PORT" -ZMQ_SERVER_ADDRESS = "tcp://localhost:2355" - # Initialize ZMQ REQ port using concore concore.init_zmq_port( - port_name=ZMQ_PORT_NAME, + port_name = PORT_NAME_IN_F1, port_type="connect", - address=ZMQ_SERVER_ADDRESS, + address="tcp://localhost:" + PORT_IN_F1, socket_type_str="REQ" ) @@ -41,9 +37,9 @@ data_to_send_u = [concore.simtime] + u - concore.write(ZMQ_PORT_NAME, "u_signal", data_to_send_u) + concore.write(PORT_NAME_IN_F1, "u_signal", data_to_send_u) - received_ym_data = concore.read(ZMQ_PORT_NAME, "ym_signal", init_simtime_ym_str) + received_ym_data = concore.read(PORT_NAME_IN_F1, "ym_signal", init_simtime_ym_str) if isinstance(received_ym_data, list) and len(received_ym_data) > 0: response_time = received_ym_data[0] @@ -62,4 +58,6 @@ print(f"funcall ZMQ u={u} ym={ym} time={concore2.simtime}") -print("funcall retry=" + str(concore.retrycount)) \ No newline at end of file +print("funcall retry=" + str(concore.retrycount)) + +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/secondNode.py b/0mq/secondNode.py new file mode 100644 index 0000000..dcb2b49 --- /dev/null +++ b/0mq/secondNode.py @@ -0,0 +1,33 @@ +# secondNode.py (Server B) +import concore + +# --- ZMQ Initialization --- +# This REP socket binds and waits for Node A to connect and send a request. +concore.init_zmq_port( + port_name=f"0x{PORT_F1_F2}_{PORT_NAME_F1_F2}", + port_type="bind", + address="tcp://*:" + PORT_F1_F2, + socket_type_str="REP" +) + +print("Node B server started. Waiting for requests...") + +while True: + # Wait to receive a request from Node A + received_data = concore.read(f"0x{PORT_F1_F2}_{PORT_NAME_F1_F2}", "value", [0.0]) + received_value = received_data[0] + + print(f"Node B: Received {received_value:.2f} from Node A.") + + # Process the value + new_value = received_value + 0.01 + print(f"Node B: Sending back processed value {new_value:.2f}.") + + # Send the reply back to Node A + concore.write(f"0x{PORT_F1_F2}_{PORT_NAME_F1_F2}", "value", [new_value]) + + if new_value > 100: + break + +print("\nNode B: Terminating.") +concore.terminate_zmq() \ No newline at end of file diff --git a/0mq/semicyclic.graphml b/0mq/semicyclic.graphml new file mode 100644 index 0000000..c6de060 --- /dev/null +++ b/0mq/semicyclic.graphml @@ -0,0 +1,760 @@ + + + + + + + + + + + + F1:firstNode.py + + + + + + + + + + + F2:secondNode.py + + + + + + + + + + + F3:thirdNode.py + + + + + + + + + + 0x1234_U1 + + + + + + + + + + + + 0x1235_U2 + + + + + + + + 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 + + + 1666487497309 + + ADD_EDGE + W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= + + + DEL_EDGE + WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== + + 4957bb66f70bda073e7edafdad81f6b4 + + + 1666487500685 + + ADD_EDGE + W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== + + + DEL_EDGE + WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== + + c8d5e89e2630a4a0aa607594e14861d1 + + + 1666487596231 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4Ijo2MDEsInkiOjIwNC43NzM2MjI4MjYyMzMxMn1d + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjAxLCJ5IjoyMDQuNzczNjIyODI2MjMzMTJ9LHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX1d + + c7aeac0c4601154d11c4c4068f631c62 + + + 1666487606788 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjE5Mi4zMjAxMjcwNjgyNTY0fV0= + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjE5Mi4zMjAxMjcwNjgyNTY0fSx7IngiOi0xMzcuNzc2MjAzNTQ5NDIzODMsInkiOjkxLjMyMDEyNzA2ODI1NjQxfV0= + + 600af97eb5c4cc3a573f65c724b85ae9 + + + 1666488874534 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQ2LjIyMzc5NjQ1MDU3NjIsInkiOjI0Ni4zMjAxMjcwNjgyNTY0fSx7IngiOjM0Mi4yMjM3OTY0NTA1NzYyLCJ5IjoyMDkuMzIwMTI3MDY4MjU2NH1d + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQyLjIyMzc5NjQ1MDU3NjIsInkiOjIwOS4zMjAxMjcwNjgyNTY0fSx7IngiOjM0Ni4yMjM3OTY0NTA1NzYyLCJ5IjoyNDYuMzIwMTI3MDY4MjU2NH1d + + ea3cf1656cbb3323791a747bcb8f624c + + + 1666810512066 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + 33c0759e9ca1d4d92639a94477c9b052 + + + 1666810533063 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjExMSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsLnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + 06d61b24bc2485f9464f3e2751d1409a + + + 1748868954808 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5My5weSIsdHJ1ZV0= + + 4afd9af5e90936e999770a941ab0ace6 + + + 1748868975001 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1MCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcS5weSIsdHJ1ZV0= + + 38c7cf57be2a0a3b4b1bafb14e9d29fb + + + 1748868991559 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5My5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2MSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcS5weSIsdHJ1ZV0= + + 16982a4aa4703d98fc301e30aed0d25a + + + 1748971661849 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2MSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcS5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + bc5037b25958965e670ba8b2200dbcf3 + + + 1748971670391 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1MCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcS5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcTIucHkiLHRydWVd + + 7bcfd7cb9bf8eaae8a615d108c4264ac + + + 1749318672556 + + ADD_EDGE + W3sibGFiZWwiOiJZMiIsInNvdXJjZSI6ImFmYjAzNDY1LTlkYTUtNGM5Yy1iNTU3LTY3YmExNWEwOWM4YyIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjo1Ni4yNDgxODU0MzEzMjI1MiwiYmVuZFdlaWdodCI6MC41Nzk3MjkyNTM1NjY5MjUzLCJiZW5kUG9pbnQiOnsieCI6NDA2LjE4NTQ4NTgzMjY5OTA0LCJ5IjozNS43MjY5MDYwMTkwMjY1N319LCJzb3VyY2VJRCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsInRhcmdldElEIjoiZGIzMWJlM2YtM2U1OC00YzM2LTk3OWQtNDFmYjI4YWVmZTY4IiwidHlwZSI6Im9yZGluIiwiaWQiOiIwODkwMzhiYi01N2FlLTQxNzctOTIyYy1hODlhZTUzNmI0OTIifV0= + + + DEL_EDGE + WyIwODkwMzhiYi01N2FlLTQxNzctOTIyYy1hODlhZTUzNmI0OTIiXQ== + + 3990ececb72b73c95733b084e3cc7123 + + + 1749318672556 + + ADD_EDGE + W3sibGFiZWwiOiJVMiIsInNvdXJjZSI6Ijk2MzAwMjYyLTViZTItNGJkYS1iMzFlLTg0ZjFlNTQ3NTAyMCIsInRhcmdldCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjotMi4wOTQwNjk0NzAzMjY0MjA3ZS03LCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwMDAwMjI5NDQsImJlbmRQb2ludCI6eyJ4Ijo1MDMuODM4MjI0NDY2MDkwNCwieSI6MTAwLjYwNjY3Mzk1NTc4MjMzfX0sInNvdXJjZUlEIjoiZGIzMWJlM2YtM2U1OC00YzM2LTk3OWQtNDFmYjI4YWVmZTY4IiwidGFyZ2V0SUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0eXBlIjoib3JkaW4iLCJpZCI6Ijg3NDdjODdmLWQyMTAtNDNlMy1iNDkyLTk1MWUyNWU0ZjczNSJ9XQ== + + + DEL_EDGE + WyI4NzQ3Yzg3Zi1kMjEwLTQzZTMtYjQ5Mi05NTFlMjVlNGY3MzUiXQ== + + bc22fd0050cd9fc5356061967027baea + + + 1749318672556 + + ADD_NODE + WyJQWjpwbXB5bWF4LnB5Iix7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJpZCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiUFo6cG1weW1heC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyJd + + + DEL_NODE + WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciXQ== + + 7a0221fd2f4d6714160cb1dadda127a4 + + + 1749318672556 + + ADD_EDGE + W3sibGFiZWwiOiJVIiwic291cmNlIjoiMTc5YTFlNzItMmU2Zi00NDBhLWFjMzItNDkyNWIwNmM4NDgwIiwidGFyZ2V0IjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjAuMDAwMDI3OTU5OTI5MzQyNjgwMjEyLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwMDA2MDA2MTEsImJlbmRQb2ludCI6eyJ4Ijo1MDIuMTExODk4NzI4MzI3NDUsInkiOjIwNi41MTEwNDYwNjE2NDI4fX0sInNvdXJjZUlEIjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwidGFyZ2V0SUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0eXBlIjoib3JkaW4iLCJpZCI6Ijg4OGQ2YTQ5LTQxOTMtNDMxYi04ZGRkLTY2ZDkxOWQyMmUxYyJ9XQ== + + + DEL_EDGE + WyI4ODhkNmE0OS00MTkzLTQzMWItOGRkZC02NmQ5MTlkMjJlMWMiXQ== + + 49b2893c7c3877d7d726ef11cb1b488b + + + 1749318672556 + + ADD_EDGE + W3sibGFiZWwiOiJZIiwic291cmNlIjoiOTY4M2RjZDMtYjJjNC00ZmRiLTgxOTMtNDIzMzdkMGViM2VhIiwidGFyZ2V0IjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjU0LjgyNzk4OTUzNTk2MjUyLCJiZW5kV2VpZ2h0IjowLjU3MjM4MjA2MDg3MzY3MjUsImJlbmRQb2ludCI6eyJ4Ijo0MTAuNzMxNDI0MTY5MzA0OTQsInkiOjE0My41NzI0MTkzMDc0NDYzOH19LCJzb3VyY2VJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInRhcmdldElEIjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkZDgxOTE0NS01MTA3LTQ5ZmQtYmI3OC0wODI0MmNmODljNjEifV0= + + + DEL_EDGE + WyJkZDgxOTE0NS01MTA3LTQ5ZmQtYmI3OC0wODI0MmNmODljNjEiXQ== + + dd0af86450207de6e25e796f240fe912 + + + 1749318672556 + + ADD_NODE + WyJDWjpjcHltYXgucHkiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjozNDIuMjIzNzk2NDUwNTc2MiwieSI6MjA5LjMyMDEyNzA2ODI1NjR9LHsiaWQiOiJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLCJsYWJlbCI6IkNaOmNweW1heC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMjIsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSJd + + + DEL_NODE + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiXQ== + + 2e04cc361b16f90c6fb64ee6325740f3 + + + 1749318672556 + + ADD_NODE + WyJGMTpmdW5jYWxsX3ptcTIucHkiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4Ijo2MDEsInkiOjIwNC43NzM2MjI4MjYyMzMxMn0seyJpZCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiRjE6ZnVuY2FsbF96bXEyLnB5IiwidHlwZSI6Im9yZGluIiwic3R5bGUiOnsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9fSwiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIl0= + + + DEL_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiXQ== + + 005221fcf3c3cd5137a54ed1e14a866e + + + 1749318672556 + + ADD_NODE + WyJGMjpmdW5ib2R5X3ptcTIucHkiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjozMzYuMDE4NjM3MDg1NTg2NjUsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX0seyJpZCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiRjI6ZnVuYm9keV96bXEyLnB5IiwidHlwZSI6Im9yZGluIiwic3R5bGUiOnsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9fSwiZGIzMWJlM2YtM2U1OC00YzM2LTk3OWQtNDFmYjI4YWVmZTY4Il0= + + + DEL_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== + + 44570216570ee4c15fd928f792f94d7f + + + 1749318681043 + + DEL_NODE + WyJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiXQ== + + + ADD_NODE + WyJGMTpmaXJzdE5vZGUucHkiLHsid2lkdGgiOjEyOCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4Ijo5MSwieSI6MTAyfSx7fSwiY2Q0ZjA1NjUtMjI4ZS00NTRjLWFjZWQtYTA2OGM1MWRhNGU5Il0= + + e6cc6e04b9199acd990c213567fc7f5c + + + 1749318695675 + + DEL_NODE + WyI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiXQ== + + + ADD_NODE + WyJGMjpzZWNvbmROb2RlLnB5Iix7IndpZHRoIjoxNTQsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6Mzc4LCJ5IjoyNzR9LHt9LCI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiXQ== + + 82cdd148cca83ffa4cf77913aa7c34b5 + + + 1749318699837 + + SET_POS + WyI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiLHsieCI6MTEwLCJ5IjoxMTB9LHsieCI6Mzg0LCJ5IjoyNDJ9XQ== + + + SET_POS + WyI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiLHsieCI6Mzg0LCJ5IjoyNDJ9LHsieCI6MTEwLCJ5IjoxMTB9XQ== + + 188acf262a649e90a949e38a63235320 + + + 1749318708081 + + DEL_NODE + WyI1MWU0MjNmMi1hNTMwLTRkMjYtYTg4My00ZGVmZGYzYzVkMGYiXQ== + + + ADD_NODE + WyJGMzp0aGlyZE5vZGUucHkiLHsid2lkdGgiOjEzNCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjozNzYsInkiOi00OX0se30sIjUxZTQyM2YyLWE1MzAtNGQyNi1hODgzLTRkZWZkZjNjNWQwZiJd + + 114b3ba9ee328482f15477d7e9258154 + + + 1749318711764 + + SET_POS + WyI1MWU0MjNmMi1hNTMwLTRkMjYtYTg4My00ZGVmZGYzYzVkMGYiLHsieCI6MTEwLCJ5IjoxMTB9LHsieCI6Mzc2LCJ5IjotNDl9XQ== + + + SET_POS + WyI1MWU0MjNmMi1hNTMwLTRkMjYtYTg4My00ZGVmZGYzYzVkMGYiLHsieCI6Mzc2LCJ5IjotNDl9LHsieCI6MTEwLCJ5IjoxMTB9XQ== + + 96f3d5361de38f5b38a5d0fd6706f641 + + + 1749318713866 + + DEL_EDGE + WyI3ZjBlYWI5Zi0yMTUyLTQ1ZjgtODJlNi05NjEzODY4MzdhNjUiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLCJ0YXJnZXRJRCI6IjQ2YmQ3ZjZlLTE5YzEtNGUyZS04Y2QwLTVhNmFmM2M0NzA5MSIsImxhYmVsIjoiMHgxMjM0X1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI3ZjBlYWI5Zi0yMTUyLTQ1ZjgtODJlNi05NjEzODY4MzdhNjUifV0= + + 854cb9b399afdd31e878682fd203bc4e + + + 1749318725650 + + DEL_EDGE + WyJiMTM0YjdlMC1jYjkyLTQyOWQtYTE3Ny1hNzQ2ZjIzZTNkYmIiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiLCJ0YXJnZXRJRCI6IjUxZTQyM2YyLWE1MzAtNGQyNi1hODgzLTRkZWZkZjNjNWQwZiIsImxhYmVsIjoiMHgxMjM1X1UyIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJiMTM0YjdlMC1jYjkyLTQyOWQtYTE3Ny1hNzQ2ZjIzZTNkYmIifV0= + + 7857de46290ae0ae191e06f17512ed9a + + + 1749318735430 + + DEL_EDGE + WyJkOTIzYjZmOC0xMzMxLTRiOTMtYjI3Zi02ZTk0Mjc5OTQyNGUiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI1MWU0MjNmMi1hNTMwLTRkMjYtYTg4My00ZGVmZGYzYzVkMGYiLCJ0YXJnZXRJRCI6ImNkNGYwNTY1LTIyOGUtNDU0Yy1hY2VkLWEwNjhjNTFkYTRlOSIsImxhYmVsIjoiMHgxMjM2X1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJkOTIzYjZmOC0xMzMxLTRiOTMtYjI3Zi02ZTk0Mjc5OTQyNGUifV0= + + bc781021d33b4dc0502af8183fea5cdb + + + 1749318750730 + + SET_POS + WyI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiLHsieCI6Mzg0LCJ5IjoyNDJ9LHsieCI6Mzc4LCJ5IjoyNzR9XQ== + + + SET_POS + WyI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiLHsieCI6Mzc4LCJ5IjoyNzR9LHsieCI6Mzg0LCJ5IjoyNDJ9XQ== + + 8b9404801550cec3a09afef7cd50c913 + + + 1749318762309 + + SET_POS + WyJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6OTEsInkiOjEwMn1d + + + SET_POS + WyJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLHsieCI6OTEsInkiOjEwMn0seyJ4IjoxMDAsInkiOjEwMH1d + + 2db82a56f25b69a256e0c7d14227f08d + + + 1749324626651 + + ADD_EDGE + W3sibGFiZWwiOiIweDEyMzVfVTIiLCJzb3VyY2UiOiI2MTViZTQxMi1iNDMwLTQzNzItYTA0Yi1iNDNmNjk1NzM0OTUiLCJ0YXJnZXQiOiI1MWU0MjNmMi1hNTMwLTRkMjYtYTg4My00ZGVmZGYzYzVkMGYiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjotMC4wMzU1MjAzNTg0OTk0MjUwMywiYmVuZFdlaWdodCI6MC41MDAwMDA3MzgwNDA1NTA4LCJiZW5kUG9pbnQiOnsieCI6Mzc2Ljg4NDUyNzc4MDk2ODcsInkiOjk5Ljk5OTk5OTM5MTcwNzMyfX0sInNvdXJjZUlEIjoiNDZiZDdmNmUtMTljMS00ZTJlLThjZDAtNWE2YWYzYzQ3MDkxIiwidGFyZ2V0SUQiOiI1MWU0MjNmMi1hNTMwLTRkMjYtYTg4My00ZGVmZGYzYzVkMGYiLCJ0eXBlIjoib3JkaW4iLCJpZCI6IjAxZmQ4ZGYzLWU4ZWMtNDVmOC1iOTlkLTY4ZGNiNjZhMDYyNSJ9XQ== + + + DEL_EDGE + WyIwMWZkOGRmMy1lOGVjLTQ1ZjgtYjk5ZC02OGRjYjY2YTA2MjUiXQ== + + 2f2e4b26b791be0394e33c8fc7569982 + + + 1749324631928 + + UPDATE_EDGE + WyJmMmFkYzU0OS0xNTIyLTRhM2EtYWJjZi1kMmM0MTFjYmMwYjUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MTIzNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJmMmFkYzU0OS0xNTIyLTRhM2EtYWJjZi1kMmM0MTFjYmMwYjUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MTIzNF9VMSIsdHJ1ZV0= + + 156ec0a2daad8c0c3a38b89c57aa9c50 + + + 1749324646397 + + ADD_EDGE + W3sibGFiZWwiOiIweDEyMzRfVTEiLCJzb3VyY2UiOiIxYWYyOTZhZC04ZDdmLTQ0ZjEtOGRkYS0yYjRkMjZhYzY4OGIiLCJ0YXJnZXQiOiI0NmJkN2Y2ZS0xOWMxLTRlMmUtOGNkMC01YTZhZjNjNDcwOTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjA0Nzg1Mjk5Mzk0MzY0OTgzNSwiYmVuZFdlaWdodCI6MC40OTk3MjA3NzQwMjk2NDY0MywiYmVuZFBvaW50Ijp7IngiOjI1NS4yNTI2NTA5MTk0NDYsInkiOjIwMC41MDAwMDEwNDQ2NzEyNX19LCJzb3VyY2VJRCI6ImNkNGYwNTY1LTIyOGUtNDU0Yy1hY2VkLWEwNjhjNTFkYTRlOSIsInRhcmdldElEIjoiNDZiZDdmNmUtMTljMS00ZTJlLThjZDAtNWE2YWYzYzQ3MDkxIiwidHlwZSI6Im9yZGluIiwiaWQiOiJmMmFkYzU0OS0xNTIyLTRhM2EtYWJjZi1kMmM0MTFjYmMwYjUifV0= + + + DEL_EDGE + WyJmMmFkYzU0OS0xNTIyLTRhM2EtYWJjZi1kMmM0MTFjYmMwYjUiXQ== + + a03366277b8ab8b2241cd9b67857df54 + + + 1749324652309 + + DEL_EDGE + WyI5MGZmYThhOC00Yjg5LTQzZmItYWMxYy1iY2NkMjRmNWUxNWIiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLCJ0YXJnZXRJRCI6IjQ2YmQ3ZjZlLTE5YzEtNGUyZS04Y2QwLTVhNmFmM2M0NzA5MSIsImxhYmVsIjoiMHgxMjM0X1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI5MGZmYThhOC00Yjg5LTQzZmItYWMxYy1iY2NkMjRmNWUxNWIifV0= + + f39b5ddb66988d2bc1aac805dc5ed4ff + + + 1749324661797 + + ADD_EDGE + W3sibGFiZWwiOiIweDEyMzZfVTMiLCJzb3VyY2UiOiJjMDhlYjQ0OC0yYjZmLTQ5ZWItOGZlYS02MWMwOTllYWRlYjEiLCJ0YXJnZXQiOiJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjotMC4wMTA3NjE2ODYyMzk3Njc2OTgsImJlbmRXZWlnaHQiOjAuNDk5OTI0NTI4Mzc2NzE3MjUsImJlbmRQb2ludCI6eyJ4IjoyMDkuOTMzNTM2ODcwMjg1ODgsInkiOjM5LjAwMDAwMDA1NzIzMjg3NH19LCJzb3VyY2VJRCI6IjUxZTQyM2YyLWE1MzAtNGQyNi1hODgzLTRkZWZkZjNjNWQwZiIsInRhcmdldElEIjoiY2Q0ZjA1NjUtMjI4ZS00NTRjLWFjZWQtYTA2OGM1MWRhNGU5IiwidHlwZSI6Im9yZGluIiwiaWQiOiIwZTIwOGM0OC0xZTQxLTQ1NzAtOTUxOS0xZjJjZTdhY2VkYWUifV0= + + + DEL_EDGE + WyIwZTIwOGM0OC0xZTQxLTQ1NzAtOTUxOS0xZjJjZTdhY2VkYWUiXQ== + + 36fd9c94737647dc64c1cbd858f17a71 + + + 1749324663715 + + SET_POS + WyJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLHsieCI6OTEsInkiOjEwMn0seyJ4IjoxMDcsInkiOjExM31d + + + SET_POS + WyJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLHsieCI6MTA3LCJ5IjoxMTN9LHsieCI6OTEsInkiOjEwMn1d + + b9eb92a0be11f002aa9195078b2e4335 + + + 1749324664642 + + SET_POS + WyJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLHsieCI6MTA3LCJ5IjoxMTN9LHsieCI6OTksInkiOjkyfV0= + + + SET_POS + WyJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLHsieCI6OTksInkiOjkyfSx7IngiOjEwNywieSI6MTEzfV0= + + fc44d62c1d80232d1c1338985ec1f417 + + + 1749324666770 + + DEL_EDGE + WyI3Y2ViYTQxZS00YWNhLTRmYWEtYmU0Yy0xOGYyMjQ3NDNhYzgiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJjZDRmMDU2NS0yMjhlLTQ1NGMtYWNlZC1hMDY4YzUxZGE0ZTkiLCJ0YXJnZXRJRCI6IjUxZTQyM2YyLWE1MzAtNGQyNi1hODgzLTRkZWZkZjNjNWQwZiIsImxhYmVsIjoiMHgxMjM1X1UyIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI3Y2ViYTQxZS00YWNhLTRmYWEtYmU0Yy0xOGYyMjQ3NDNhYzgifV0= + + 00bc1b6fd722b4e6618ffc9f83206e6d + + + \ No newline at end of file diff --git a/0mq/test0mq4.graphml b/0mq/test0mq4.graphml index 4206ece..ef6b503 100644 --- a/0mq/test0mq4.graphml +++ b/0mq/test0mq4.graphml @@ -2,7 +2,7 @@ - + @@ -17,7 +17,7 @@ - + CZ:cpymax.py @@ -28,10 +28,10 @@ - + - F1:funcall_zmq2.py + F1:funcall_zmq.py @@ -42,7 +42,7 @@ - F2:funbody_zmq2.py + F2:funbody_zmq.py @@ -54,7 +54,7 @@ U - + @@ -66,7 +66,7 @@ Y - + @@ -78,7 +78,7 @@ U2 - + @@ -90,7 +90,19 @@ Y2 - + + + + + + + + + + + 0x1234_U3 + + @@ -479,5 +491,113 @@ 7bcfd7cb9bf8eaae8a615d108c4264ac + + 1749405667763 + + DEL_EDGE + WyI0ZDNkNDNjMC0yYmMzLTQ0NDctODgzYS1mYjAyYjI2ZWJkNDIiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiMHgxMjM0X1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI0ZDNkNDNjMC0yYmMzLTQ0NDctODgzYS1mYjAyYjI2ZWJkNDIifV0= + + 837a51f51a8a374cba2c9ef8b8092462 + + + 1749405684095 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjAxLCJ5IjoyMDQuNzczNjIyODI2MjMzMTJ9LHsieCI6NjAzLCJ5IjozMDYuNzczNjIyODI2MjMzMX1d + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjAzLCJ5IjozMDYuNzczNjIyODI2MjMzMX0seyJ4Ijo2MDEsInkiOjIwNC43NzM2MjI4MjYyMzMxMn1d + + 916e93c225b2ece30179d329085e51d3 + + + 1749405686595 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzQyLjIyMzc5NjQ1MDU3NjIsInkiOjIwOS4zMjAxMjcwNjgyNTY0fSx7IngiOjI2MC4yMjM3OTY0NTA1NzYyLCJ5IjozMTEuMzIwMTI3MDY4MjU2NH1d + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MjYwLjIyMzc5NjQ1MDU3NjIsInkiOjMxMS4zMjAxMjcwNjgyNTY0fSx7IngiOjM0Mi4yMjM3OTY0NTA1NzYyLCJ5IjoyMDkuMzIwMTI3MDY4MjU2NH1d + + ec064d1ca492b3c62e01e9653d3742c2 + + + 1749405711784 + + ADD_EDGE + W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiMHgxMjM0X1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwidHlwZSI6Im9yZGluIiwic291cmNlIjoiZjQ4YjA1YWQtYWJmMi00YmVjLTk2ZjUtMjI5ZjY3YTBiNmI1IiwidGFyZ2V0IjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLCJiZW5kV2VpZ2h0IjowLjUsImJlbmRQb2ludCI6eyJ4Ijo0ODUuNzEzOTY5ODQ4MzQ3NCwieSI6MjE2LjM1NTY1NzYzNTc2ODN9fSwiaWQiOiI0ZDNkNDNjMC0yYmMzLTQ0NDctODgzYS1mYjAyYjI2ZWJkNDIifV0= + + + DEL_EDGE + WyI0ZDNkNDNjMC0yYmMzLTQ0NDctODgzYS1mYjAyYjI2ZWJkNDIiXQ== + + e154e83cc14ebdad21484178af33f2da + + + 1749405713782 + + DEL_EDGE + WyJhM2VkNTQzMC0wZTIwLTQxNmEtODE4OC01OTA2ZDAxNzYzNjUiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiMHgxMjM0X1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJhM2VkNTQzMC0wZTIwLTQxNmEtODE4OC01OTA2ZDAxNzYzNjUifV0= + + 49e8c4ceae4a8e0ad4307c028a1c3aa4 + + + 1749405909129 + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiMHgxMjM0X1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwidHlwZSI6Im9yZGluIiwic291cmNlIjoiZjlhOTJkZDMtZDAyNC00MWQ2LTk4NjktN2QwZWVkN2Q2NDBkIiwidGFyZ2V0IjoiZGIzMWJlM2YtM2U1OC00YzM2LTk3OWQtNDFmYjI4YWVmZTY4IiwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLCJiZW5kV2VpZ2h0IjowLjUsImJlbmRQb2ludCI6eyJ4Ijo0NTMuMjk2MDgwMDE3MDcwMTUsInkiOjE5MS4zNTU2NTc2MzU3NjgzfX0sImlkIjoiYTNlZDU0MzAtMGUyMC00MTZhLTgxODgtNTkwNmQwMTc2MzY1In1d + + + DEL_EDGE + WyJhM2VkNTQzMC0wZTIwLTQxNmEtODE4OC01OTA2ZDAxNzYzNjUiXQ== + + 0ee542e0a45c8fd2aeb96d80ad1213b1 + + + 1749405910993 + + DEL_EDGE + WyI1MzhjMTExYy1hZjNmLTQ0MjgtYTQyMy1hNThjYTg3MjJlMDkiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiMHgxMjM0X1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI1MzhjMTExYy1hZjNmLTQ0MjgtYTQyMy1hNThjYTg3MjJlMDkifV0= + + 72dc7bacfcd3ba72d7816cd544af76cd + + + 1749406018861 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcS5weSIsdHJ1ZV0= + + aa81002d2e8b9cbdeb150e2710cf3dbb + + + 1749406093511 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcS5weSIsdHJ1ZV0= + + 6455bbb0a3114ec3ba44920b64bd0266 + \ No newline at end of file diff --git a/0mq/test0mqbody2.graphml b/0mq/test0mqbody2.graphml index cd69805..458857a 100644 --- a/0mq/test0mqbody2.graphml +++ b/0mq/test0mqbody2.graphml @@ -2,7 +2,7 @@ - + @@ -17,10 +17,21 @@ - + - F2:funbody2.py + F2:funbody_zmq2.py + + + + + + + + + + + OUT: @@ -32,7 +43,7 @@ Y2 - + @@ -44,14 +55,25 @@ U2 - + + + + + + + + + + + 0x2405_U3 + + 1664644923582 - mark DEL_NODE WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciXQ== @@ -60,11 +82,10 @@ ADD_NODE WyJQWjpwbXB5bWF4LnB5Iix7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0se30sImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyJd - ea1f3ba8fe573453400ffda5fad41219 + a53a7f7273a40c7970938b6de1829249 1664644939781 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH1d @@ -73,11 +94,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH0seyJ4IjoxMDAsInkiOjEwMH1d - 4d28b3ac41cd2913a677da0a4b65b424 + 3d4a875a8a6ea281598aa70364b0ea82 1664644951652 - mark DEL_NODE WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiXQ== @@ -86,11 +106,10 @@ ADD_NODE WyJDWjpjcHltYXgucHkiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotMTM3Ljc3NjIwMzU0OTQyMzgzLCJ5Ijo5MS4zMjAxMjcwNjgyNTY0MX0se30sImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSJd - 7d1c82d143a33ca11a4f968849bad104 + 5ed7e3d12fd25656b2ad03e29c307d65 1664644958838 - mark SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfV0= @@ -99,11 +118,10 @@ SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfSx7IngiOjEwMCwieSI6MTAwfV0= - 2e1ad74435543de42a296bb9a0620e63 + 35c613c8203b65e1f44e066b3d783143 1664644988539 - mark DEL_NODE WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiXQ== @@ -112,11 +130,10 @@ ADD_NODE WyJGMTpmdW5jYWxsLnB5Iix7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0se30sImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCJd - ed42ad47c94f87d676c7c83ce9ded915 + 33d0b0cc4d3dbe3c42323e33f06993e9 1664645002278 - mark DEL_NODE WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== @@ -125,11 +142,10 @@ ADD_NODE WyJGMjpmdW5ib2R5LnB5Iix7IndpZHRoIjoxMjAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHt9LCJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== - 0f42a42f08b5d6633750c6cd0a52cd7f + 8d0d4a735631afe6241c66143fb29db8 1664645010353 - mark SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MTEwLCJ5IjoxMTB9LHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d @@ -138,11 +154,10 @@ SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX0seyJ4IjoxMTAsInkiOjExMH1d - 9ed03855520c803cecdd1d7497a92151 + 8a01a9ca8b3706bc3b1ce4de33669b6d 1664645015576 - mark DEL_EDGE WyIwZjk1MWZiYy0wZDNmLTQzYzAtYmJmMC04NjViYzQ3ZjEyMGUiXQ== @@ -151,11 +166,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiVSIsInN0eWxlIjp7InRoaWNrbmVzcyI6MSwiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInNoYXBlIjoic29saWQifSwiaWQiOiIwZjk1MWZiYy0wZDNmLTQzYzAtYmJmMC04NjViYzQ3ZjEyMGUifV0= - 725908dc36e7bc154d1d8dd0e98a412d + 14416fc2e3c48db65e2b5e1012027ee0 1664645043815 - mark DEL_EDGE WyIzY2ZiNDBjZC01NTdhLTQ4NTAtOTNhNi1mZGMwOWNkMDA1ZjAiXQ== @@ -164,11 +178,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiVTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiM2NmYjQwY2QtNTU3YS00ODUwLTkzYTYtZmRjMDljZDAwNWYwIn1d - 9f18da8775e24b7f2f9902f2842eb63e + 326a920ffd7e662bc64ca95c086fb9de 1664645057658 - mark DEL_EDGE WyI3MTRkYjk4OS01NjcyLTQwM2ItYWU3Ni1mZDlhMjA4OTM0NzUiXQ== @@ -177,11 +190,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiVTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiNzE0ZGI5ODktNTY3Mi00MDNiLWFlNzYtZmQ5YTIwODkzNDc1In1d - 3e1c6e41350aaf47123ec7cf25e1b62c + 4593337e9924ae4b23dc5c5576c31394 1664645068951 - mark DEL_EDGE WyJhOGFlNzg5MC1iMmJiLTQyNzMtODc1My0wMTgxY2ViNDg2YzEiXQ== @@ -190,11 +202,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiWTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiYThhZTc4OTAtYjJiYi00MjczLTg3NTMtMDE4MWNlYjQ4NmMxIn1d - 269c6a2baeea1b2785ce71ff56f4a76d + 568d8b7a109ffacc4b912095793cb2ca 1664645081283 - mark DEL_EDGE WyI1NWI5OWFiNi1hN2Q2LTRjNjctYWI0ZS1hOGUyOTM5YzFiMGYiXQ== @@ -203,11 +214,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiWTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiNTViOTlhYjYtYTdkNi00YzY3LWFiNGUtYThlMjkzOWMxYjBmIn1d - 3c7cb858225e79ecf43defb7b70197a6 + 0d0aa0179f22f9d73a11f8ccfbcc145e 1664645089735 - mark SET_POS WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX1d @@ -216,11 +226,10 @@ SET_POS WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4IjoxMDAsInkiOjEwMH1d - b6b4fcd96e508461f87e4513dbd0170e + 1c19591402c0f2daca7d2b4a8af5e956 1664645092868 - mark DEL_EDGE WyI3OWE1NDdmNS02NzBhLTQ1ZjYtYTc4My02ZGI4ZmYwZTY1NTkiXQ== @@ -229,11 +238,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSIsImxhYmVsIjoiWSIsInN0eWxlIjp7InRoaWNrbmVzcyI6MSwiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInNoYXBlIjoic29saWQifSwiaWQiOiI3OWE1NDdmNS02NzBhLTQ1ZjYtYTc4My02ZGI4ZmYwZTY1NTkifV0= - f2a382cf010520ed6d8d1167488af14c + 3c913497d8aa8f1c79bbdc03c3feec16 1664645142026 - mark SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfSx7IngiOi0xNzAuNDQxMDYwODg1NDY2OTUsInkiOjkwLjAxMzUzMjc3NDgxNDY5fV0= @@ -242,11 +250,10 @@ SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9LHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfV0= - 5fc1c53a84494c7b3b749c475cf09d33 + ecbd46b28ecaf800c8da0d2ada69b4de 1664645149601 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH0seyJ4Ijo3NTQuNDAxODgxNDA3MTk2NSwieSI6OTkuMTM1NzM0OTcxOTM2NjR9XQ== @@ -255,11 +262,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NzU0LjQwMTg4MTQwNzE5NjUsInkiOjk5LjEzNTczNDk3MTkzNjY0fSx7IngiOjQwNC4yMzQ2MTA3NjQ4MTQyLCJ5IjotODkuMDEzODQzMjgzNjcxNzh9XQ== - 627a3a19a5e310402ab0c81e854bb1aa + ea35c112764d7964f8b7e35e9a18efbd 1664645223291 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NzU0LjQwMTg4MTQwNzE5NjUsInkiOjk5LjEzNTczNDk3MTkzNjY0fSx7IngiOjY3Ni4wMDYyMjM4MDA2OTMsInkiOjEwMC40NDIzMjkyNjUzNzgzNn1d @@ -268,11 +274,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6Njc2LjAwNjIyMzgwMDY5MywieSI6MTAwLjQ0MjMyOTI2NTM3ODM2fSx7IngiOjc1NC40MDE4ODE0MDcxOTY1LCJ5Ijo5OS4xMzU3MzQ5NzE5MzY2NH1d - 65480a229a142f0b48daa6727b8aae7b + d669d3d37a4693ad860a18c69999b31f 1664645228453 - mark SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX0seyJ4IjozMzYuMDE4NjM3MDg1NTg2NjUsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d @@ -281,11 +286,10 @@ SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d - 1359e922778d54bbfc88d8040c764247 + f7eb6af4003cb4eff19f39421fc00174 1664645231883 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6Njc2LjAwNjIyMzgwMDY5MywieSI6MTAwLjQ0MjMyOTI2NTM3ODM2fSx7IngiOjU4Ny4xNTc4MTE4NDY2NTU2LCJ5IjoxMDAuNDQyMzI5MjY1Mzc4MzZ9XQ== @@ -294,11 +298,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJ4Ijo2NzYuMDA2MjIzODAwNjkzLCJ5IjoxMDAuNDQyMzI5MjY1Mzc4MzZ9XQ== - ef15c4c7e39dcf45dee8b9e5d071d32f + 49dd0c2013be6e39c2f11ea967dbcab4 1664645237206 - mark SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9LHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9XQ== @@ -307,11 +310,10 @@ SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9XQ== - a8ef099b87ae2a958e58d7b138deb5f5 + 009fc03903a9ae6003caea49a6575ddb 1666487497309 - mark ADD_EDGE W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= @@ -320,11 +322,10 @@ DEL_EDGE WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== - 6a68923268af161e7e8346570af341ba + 4957bb66f70bda073e7edafdad81f6b4 1666487500685 - mark ADD_EDGE W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== @@ -333,11 +334,10 @@ DEL_EDGE WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== - afaa886c1e4907765760ae91632e1871 + c8d5e89e2630a4a0aa607594e14861d1 1666810445211 - mark ADD_EDGE W3sibGFiZWwiOiJZIiwic291cmNlIjoiNTIzNjQxYTQtOTc1NS00NWVkLTlhMjUtYTExNDc2ZGUzN2EwIiwidGFyZ2V0IjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjI5LjE1NTExMDY3Mjg3NDI5NCwiYmVuZFdlaWdodCI6MC41MTMxNjc2Njk2NTEzNTEyLCJiZW5kUG9pbnQiOnsieCI6LTUwLjM1NTE2Njc0NzA3LCJ5Ijo1OC4xODI0NTg4NjkxNTA4NH19LCJzb3VyY2VJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInRhcmdldElEIjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwidHlwZSI6Im9yZGluIiwiaWQiOiI4YTE1ZmMyOC02ZjA5LTQ3MmYtYTk3Ni1jZmYzOWY3MzFjNjAifV0= @@ -346,11 +346,10 @@ DEL_EDGE WyI4YTE1ZmMyOC02ZjA5LTQ3MmYtYTk3Ni1jZmYzOWY3MzFjNjAiXQ== - e6899a4a1e46f06e241808fedb6942ce + cfc129abe20d32f8c156301489dcc705 1666810445211 - mark ADD_EDGE W3sibGFiZWwiOiJVIiwic291cmNlIjoiZDA0MDg0OGYtNmE5NC00YWMyLWE0ZTItYTg4NzliNWY3ZmZiIiwidGFyZ2V0IjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjAuMDAwMDE0ODc2MzcxMTExNjM4NDIsImJlbmRXZWlnaHQiOjAuNTAwMDAwMDAxMjIyMTMzNiwiYmVuZFBvaW50Ijp7IngiOjExLjYxMTg5ODIyNTI4ODk2OCwieSI6OTMuNDg5ODc5MjQ2Nzg1Mzl9fSwic291cmNlSUQiOiJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInR5cGUiOiJvcmRpbiIsImlkIjoiZTAxY2FiN2MtYzQ0Ni00OGRhLWI4OGUtN2Y5NjIwY2NkMjY5In1d @@ -359,11 +358,10 @@ DEL_EDGE WyJlMDFjYWI3Yy1jNDQ2LTQ4ZGEtYjg4ZS03Zjk2MjBjY2QyNjkiXQ== - 7ac674c0802aeff613b1f0b989427ec9 + 9fbba2442b7019a76634710caf98a549 1666810445211 - mark ADD_NODE WyJGMTpmdW5jYWxsLnB5Iix7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJpZCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiRjE6ZnVuY2FsbC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCJd @@ -372,11 +370,10 @@ DEL_NODE WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiXQ== - bd81ac85ca97ad8607020554364e59b0 + de44f1ff4f2107a20e234361711eec91 1666810453165 - mark ADD_NODE WyJDWjpjcHltYXgucHkiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotMTM3Ljc3NjIwMzU0OTQyMzgzLCJ5Ijo5MS4zMjAxMjcwNjgyNTY0MX0seyJpZCI6ImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSIsImxhYmVsIjoiQ1o6Y3B5bWF4LnB5IiwidHlwZSI6Im9yZGluIiwic3R5bGUiOnsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9fSwiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIl0= @@ -385,11 +382,10 @@ DEL_NODE WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiXQ== - a1e7c2a7f9a5da8636e9eb957887686d + f1cb4196a5082cef004f9ee186c7f04b 1666810462415 - mark UPDATE_NODE WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5LnB5Iix0cnVlXQ== @@ -398,7 +394,115 @@ UPDATE_NODE WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= - 6d6f211aebd7b1a130a1360f884c258b + 9e9b34686b3aec97cf26547fcd7ae633 + + + 1748979705408 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + 299aef4ea2931f8b9a6b7f10361b0022 + + + 1749058646821 + + DEL_NODE + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiXQ== + + + ADD_NODE + WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTQzLCJ5IjoyNzF9LHt9LCI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiXQ== + + 51cf4c5701b1a8a637c1b373dcd09c59 + + + 1749058651133 + + SET_POS + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTQzLCJ5IjoyNzF9XQ== + + + SET_POS + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiLHsieCI6MTQzLCJ5IjoyNzF9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 440d3083c9a571e9660685eaeefae6fb + + + 1749058659847 + + DEL_EDGE + WyJmYzY1ZTg0OC04OTJmLTQyZWQtYWU0OS1iYjhlYmQzODVmYjAiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6IjUyZTk3NDkyLWNjZWEtNDhhMi05ZGVkLWUyMzVlMjQ1MDM1OCIsImxhYmVsIjoiMHgyNDAwX1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJmYzY1ZTg0OC04OTJmLTQyZWQtYWU0OS1iYjhlYmQzODVmYjAifV0= + + 615e0be29af2a4940efea41e374438bb + + + 1749070207801 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + a8472011e18e50a782b19383b3b1a41d + + + 1749070480095 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + 4a9c6467598df6924c76f002eccbb822 + + + 1749070617114 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + 2b2ace96e5b5dad90e06fbac4e20b915 + + + 1749322194657 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + dfbb291ab07456ce0005d5c6d1d6a18a + + + 1749325840799 + + UPDATE_EDGE + WyJlOTJlM2E5ZC1lOWEwLTQ5YzgtOWYyMC1iNWQ1MTM3M2EzZjYiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyJlOTJlM2E5ZC1lOWEwLTQ5YzgtOWYyMC1iNWQ1MTM3M2EzZjYiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwNV9VMyIsdHJ1ZV0= + + 385fc34934650be854756424f6fac52e \ No newline at end of file diff --git a/0mq/test0mqcall.graphml b/0mq/test0mqcall.graphml index cf5b799..033f176 100644 --- a/0mq/test0mqcall.graphml +++ b/0mq/test0mqcall.graphml @@ -2,11 +2,11 @@ - + - + CZ:cpymax.py @@ -17,10 +17,21 @@ - + - F1:funcall2.py + F1:funcall_zmq2.py + + + + + + + + + + + IN: @@ -32,7 +43,7 @@ Y - + @@ -44,14 +55,25 @@ U - + + + + + + + + + + + 0x2405_U3 + + 1664644923582 - mark DEL_NODE WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciXQ== @@ -60,11 +82,10 @@ ADD_NODE WyJQWjpwbXB5bWF4LnB5Iix7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0se30sImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyJd - ea1f3ba8fe573453400ffda5fad41219 + a53a7f7273a40c7970938b6de1829249 1664644939781 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH1d @@ -73,11 +94,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH0seyJ4IjoxMDAsInkiOjEwMH1d - 4d28b3ac41cd2913a677da0a4b65b424 + 3d4a875a8a6ea281598aa70364b0ea82 1664644951652 - mark DEL_NODE WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiXQ== @@ -86,11 +106,10 @@ ADD_NODE WyJDWjpjcHltYXgucHkiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotMTM3Ljc3NjIwMzU0OTQyMzgzLCJ5Ijo5MS4zMjAxMjcwNjgyNTY0MX0se30sImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSJd - 7d1c82d143a33ca11a4f968849bad104 + 5ed7e3d12fd25656b2ad03e29c307d65 1664644958838 - mark SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfV0= @@ -99,11 +118,10 @@ SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfSx7IngiOjEwMCwieSI6MTAwfV0= - 2e1ad74435543de42a296bb9a0620e63 + 35c613c8203b65e1f44e066b3d783143 1664644988539 - mark DEL_NODE WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiXQ== @@ -112,11 +130,10 @@ ADD_NODE WyJGMTpmdW5jYWxsLnB5Iix7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0se30sImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCJd - ed42ad47c94f87d676c7c83ce9ded915 + 33d0b0cc4d3dbe3c42323e33f06993e9 1664645002278 - mark DEL_NODE WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== @@ -125,11 +142,10 @@ ADD_NODE WyJGMjpmdW5ib2R5LnB5Iix7IndpZHRoIjoxMjAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHt9LCJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== - 0f42a42f08b5d6633750c6cd0a52cd7f + 8d0d4a735631afe6241c66143fb29db8 1664645010353 - mark SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MTEwLCJ5IjoxMTB9LHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d @@ -138,11 +154,10 @@ SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX0seyJ4IjoxMTAsInkiOjExMH1d - 9ed03855520c803cecdd1d7497a92151 + 8a01a9ca8b3706bc3b1ce4de33669b6d 1664645015576 - mark DEL_EDGE WyIwZjk1MWZiYy0wZDNmLTQzYzAtYmJmMC04NjViYzQ3ZjEyMGUiXQ== @@ -151,11 +166,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiVSIsInN0eWxlIjp7InRoaWNrbmVzcyI6MSwiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInNoYXBlIjoic29saWQifSwiaWQiOiIwZjk1MWZiYy0wZDNmLTQzYzAtYmJmMC04NjViYzQ3ZjEyMGUifV0= - 725908dc36e7bc154d1d8dd0e98a412d + 14416fc2e3c48db65e2b5e1012027ee0 1664645043815 - mark DEL_EDGE WyIzY2ZiNDBjZC01NTdhLTQ4NTAtOTNhNi1mZGMwOWNkMDA1ZjAiXQ== @@ -164,11 +178,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiVTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiM2NmYjQwY2QtNTU3YS00ODUwLTkzYTYtZmRjMDljZDAwNWYwIn1d - 9f18da8775e24b7f2f9902f2842eb63e + 326a920ffd7e662bc64ca95c086fb9de 1664645057658 - mark DEL_EDGE WyI3MTRkYjk4OS01NjcyLTQwM2ItYWU3Ni1mZDlhMjA4OTM0NzUiXQ== @@ -177,11 +190,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiVTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiNzE0ZGI5ODktNTY3Mi00MDNiLWFlNzYtZmQ5YTIwODkzNDc1In1d - 3e1c6e41350aaf47123ec7cf25e1b62c + 4593337e9924ae4b23dc5c5576c31394 1664645068951 - mark DEL_EDGE WyJhOGFlNzg5MC1iMmJiLTQyNzMtODc1My0wMTgxY2ViNDg2YzEiXQ== @@ -190,11 +202,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsImxhYmVsIjoiWTIiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiYThhZTc4OTAtYjJiYi00MjczLTg3NTMtMDE4MWNlYjQ4NmMxIn1d - 269c6a2baeea1b2785ce71ff56f4a76d + 568d8b7a109ffacc4b912095793cb2ca 1664645081283 - mark DEL_EDGE WyI1NWI5OWFiNi1hN2Q2LTRjNjctYWI0ZS1hOGUyOTM5YzFiMGYiXQ== @@ -203,11 +214,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiWTEiLCJzdHlsZSI6eyJ0aGlja25lc3MiOjEsImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJzaGFwZSI6InNvbGlkIn0sImlkIjoiNTViOTlhYjYtYTdkNi00YzY3LWFiNGUtYThlMjkzOWMxYjBmIn1d - 3c7cb858225e79ecf43defb7b70197a6 + 0d0aa0179f22f9d73a11f8ccfbcc145e 1664645089735 - mark SET_POS WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX1d @@ -216,11 +226,10 @@ SET_POS WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4IjoxMDAsInkiOjEwMH1d - b6b4fcd96e508461f87e4513dbd0170e + 1c19591402c0f2daca7d2b4a8af5e956 1664645092868 - mark DEL_EDGE WyI3OWE1NDdmNS02NzBhLTQ1ZjYtYTc4My02ZGI4ZmYwZTY1NTkiXQ== @@ -229,11 +238,10 @@ ADD_EDGE W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6ImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSIsImxhYmVsIjoiWSIsInN0eWxlIjp7InRoaWNrbmVzcyI6MSwiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInNoYXBlIjoic29saWQifSwiaWQiOiI3OWE1NDdmNS02NzBhLTQ1ZjYtYTc4My02ZGI4ZmYwZTY1NTkifV0= - f2a382cf010520ed6d8d1167488af14c + 3c913497d8aa8f1c79bbdc03c3feec16 1664645142026 - mark SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfSx7IngiOi0xNzAuNDQxMDYwODg1NDY2OTUsInkiOjkwLjAxMzUzMjc3NDgxNDY5fV0= @@ -242,11 +250,10 @@ SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9LHsieCI6OTcuNDEwNzY5MjcwMDg2NjksInkiOi05MS42MDMwNzQwMTM1ODUxfV0= - 5fc1c53a84494c7b3b749c475cf09d33 + ecbd46b28ecaf800c8da0d2ada69b4de 1664645149601 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NDA0LjIzNDYxMDc2NDgxNDIsInkiOi04OS4wMTM4NDMyODM2NzE3OH0seyJ4Ijo3NTQuNDAxODgxNDA3MTk2NSwieSI6OTkuMTM1NzM0OTcxOTM2NjR9XQ== @@ -255,11 +262,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NzU0LjQwMTg4MTQwNzE5NjUsInkiOjk5LjEzNTczNDk3MTkzNjY0fSx7IngiOjQwNC4yMzQ2MTA3NjQ4MTQyLCJ5IjotODkuMDEzODQzMjgzNjcxNzh9XQ== - 627a3a19a5e310402ab0c81e854bb1aa + ea35c112764d7964f8b7e35e9a18efbd 1664645223291 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NzU0LjQwMTg4MTQwNzE5NjUsInkiOjk5LjEzNTczNDk3MTkzNjY0fSx7IngiOjY3Ni4wMDYyMjM4MDA2OTMsInkiOjEwMC40NDIzMjkyNjUzNzgzNn1d @@ -268,11 +274,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6Njc2LjAwNjIyMzgwMDY5MywieSI6MTAwLjQ0MjMyOTI2NTM3ODM2fSx7IngiOjc1NC40MDE4ODE0MDcxOTY1LCJ5Ijo5OS4xMzU3MzQ5NzE5MzY2NH1d - 65480a229a142f0b48daa6727b8aae7b + d669d3d37a4693ad860a18c69999b31f 1664645228453 - mark SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX0seyJ4IjozMzYuMDE4NjM3MDg1NTg2NjUsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d @@ -281,11 +286,10 @@ SET_POS WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsieCI6Mzk0LjgxNTM4MDI5MDQ2NDMsInkiOjEwMC45Mzc2OTI0NDUzMDM0MX1d - 1359e922778d54bbfc88d8040c764247 + f7eb6af4003cb4eff19f39421fc00174 1664645231883 - mark SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6Njc2LjAwNjIyMzgwMDY5MywieSI6MTAwLjQ0MjMyOTI2NTM3ODM2fSx7IngiOjU4Ny4xNTc4MTE4NDY2NTU2LCJ5IjoxMDAuNDQyMzI5MjY1Mzc4MzZ9XQ== @@ -294,11 +298,10 @@ SET_POS WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJ4Ijo2NzYuMDA2MjIzODAwNjkzLCJ5IjoxMDAuNDQyMzI5MjY1Mzc4MzZ9XQ== - ef15c4c7e39dcf45dee8b9e5d071d32f + 49dd0c2013be6e39c2f11ea967dbcab4 1664645237206 - mark SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9LHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9XQ== @@ -307,11 +310,10 @@ SET_POS WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTE3MC40NDEwNjA4ODU0NjY5NSwieSI6OTAuMDEzNTMyNzc0ODE0Njl9XQ== - a8ef099b87ae2a958e58d7b138deb5f5 + 009fc03903a9ae6003caea49a6575ddb 1666487497309 - mark ADD_EDGE W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= @@ -320,11 +322,10 @@ DEL_EDGE WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== - 6a68923268af161e7e8346570af341ba + 4957bb66f70bda073e7edafdad81f6b4 1666487500685 - mark ADD_EDGE W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== @@ -333,11 +334,10 @@ DEL_EDGE WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== - afaa886c1e4907765760ae91632e1871 + c8d5e89e2630a4a0aa607594e14861d1 1666810339519 - mark ADD_EDGE W3sibGFiZWwiOiJVMiIsInNvdXJjZSI6ImFjZWUyZTJjLTFhOTEtNDg1OC1hYzdjLWNhMmNiM2YxZjQ3MCIsInRhcmdldCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjotOS40NzQ2NTYxODQ2MTU5NmUtOCwiYmVuZFdlaWdodCI6MC41MDAwMDAwMDAwMDA5Nzc3LCJiZW5kUG9pbnQiOnsieCI6NDkxLjU4ODIyNDQ2NjEyMTEsInkiOjEwMC42MzA4MzY3OTg1ODUxfX0sInNvdXJjZUlEIjoiZGIzMWJlM2YtM2U1OC00YzM2LTk3OWQtNDFmYjI4YWVmZTY4IiwidGFyZ2V0SUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImU2ZWZhMmIyLWI0NDItNDAwNi05NzQ5LTdlM2IyZDUxMzJmYiJ9XQ== @@ -346,11 +346,10 @@ DEL_EDGE WyJlNmVmYTJiMi1iNDQyLTQwMDYtOTc0OS03ZTNiMmQ1MTMyZmIiXQ== - c513a6555bbc7f569db6b7618105b78f + ead3ddf695580bca36da4698dfe89256 1666810339519 - mark ADD_EDGE W3sibGFiZWwiOiJZMiIsInNvdXJjZSI6IjA0YmZkMWI4LTkzYWYtNDQxZi1iNDZhLTMyMGZkMTA3NDBjOSIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjozMC41NjQzMTU2MDk0NTE4NjQsImJlbmRXZWlnaHQiOjAuNTE0MzI5NzI5MzYyMTU2MywiYmVuZFBvaW50Ijp7IngiOjQyMi43NzE0OTAyODczNTc2NiwieSI6NjQuMDU1NTI3OTI5NTQ0ODd9fSwic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInR5cGUiOiJvcmRpbiIsImlkIjoiOTE3MzNmNmItM2RlMy00MGFmLWJmMTQtMmJiNmNiYzQ5MGUyIn1d @@ -359,11 +358,10 @@ DEL_EDGE WyI5MTczM2Y2Yi0zZGUzLTQwYWYtYmYxNC0yYmI2Y2JjNDkwZTIiXQ== - b33c2827ee23b0e9057528015febad17 + a86191957747741919dd1f5e71c2e56c 1666810339519 - mark ADD_NODE WyJGMjpmdW5ib2R5LnB5Iix7IndpZHRoIjoxMjAsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsiaWQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJsYWJlbCI6IkYyOmZ1bmJvZHkucHkiLCJ0eXBlIjoib3JkaW4iLCJzdHlsZSI6eyJ3aWR0aCI6MTIwLCJoZWlnaHQiOjUwLCJvcGFjaXR5IjoxLCJzaGFwZSI6InJlY3RhbmdsZSIsImJhY2tncm91bmRDb2xvciI6IiNmZmNjMDAiLCJib3JkZXJDb2xvciI6IiMwMDAiLCJib3JkZXJXaWR0aCI6MX19LCJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== @@ -372,11 +370,10 @@ DEL_NODE WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== - 1e39894291be950a14dd7ab1b7759234 + b3ce34b6dc8f697e5b8fdf374ec42075 1666810343268 - mark ADD_NODE WyJQWjpwbXB5bWF4LnB5Iix7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJpZCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiUFo6cG1weW1heC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyJd @@ -385,11 +382,10 @@ DEL_NODE WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciXQ== - 0658fdad3d7279fd8e56299941d04582 + ab4fb226f0c49b8ded66436938762af7 1666810375461 - mark UPDATE_NODE WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjExMSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsLnB5Iix0cnVlXQ== @@ -398,7 +394,199 @@ UPDATE_NODE WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= - 2f5c9fab25c4a17d6b2906bbda9aab3c + f5e56f793b1dfd259251f6b15ecf0e6a + + + 1748979732766 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcTIucHkiLHRydWVd + + 9e9aaedf5e2f34cef7d06d52891d6a76 + + + 1749058687416 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4IjotMzg4LCJ5IjoxMC43NzM2MjI4MjYyMzMxMDh9XQ== + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fSx7IngiOjEwMCwieSI6OTQuNzczNjIyODI2MjMzMTF9XQ== + + 7cb1d108692b66ae85dd0ffdcf639baf + + + 1749058691778 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTE3Ny43NzYyMDM1NDk0MjM4MywieSI6MTM2LjMyMDEyNzA2ODI1NjR9XQ== + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3Ny43NzYyMDM1NDk0MjM4MywieSI6MTM2LjMyMDEyNzA2ODI1NjR9LHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9XQ== + + 1ce2563fc9ee71151cb6a722255fd762 + + + 1749058702356 + + DEL_NODE + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiXQ== + + + ADD_NODE + WyJJTjoiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotNjMyLCJ5IjotMTQzfSx7fSwiNDA4YTVkNjUtZTc2My00NjcyLTlkYTgtZGVjOTEzNjFkY2RkIl0= + + 26f5f23f693921ed1b1ee5d52e1e75b6 + + + 1749058707709 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6LTU5OCwieSI6OTl9XQ== + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTU5OCwieSI6OTl9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 6ae6b59a08af5a7047a97a5ad388c270 + + + 1749058713842 + + DEL_EDGE + WyIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6IjQwOGE1ZDY1LWU3NjMtNDY3Mi05ZGE4LWRlYzkxMzYxZGNkZCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYifV0= + + cc747ad0ecc75c44cc3b6f6f9e9ae92c + + + 1749058727442 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTU5OCwieSI6OTl9LHsieCI6LTYxMiwieSI6LTEwMn1d + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYxMiwieSI6LTEwMn0seyJ4IjotNTk4LCJ5Ijo5OX1d + + fa49a13771e334eebbf112917f89d058 + + + 1749058754860 + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6IjQwOGE1ZDY1LWU3NjMtNDY3Mi05ZGE4LWRlYzkxMzYxZGNkZCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwidHlwZSI6Im9yZGluIiwic291cmNlIjoiYzI1ZDZiNjItNWQ2Ni00MDliLTk0YjEtZTZmZmI1ZjBmMTViIiwidGFyZ2V0IjoiNDA4YTVkNjUtZTc2My00NjcyLTlkYTgtZGVjOTEzNjFkY2RkIiwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLCJiZW5kV2VpZ2h0IjowLjUsImJlbmRQb2ludCI6eyJ4IjotNTI0Ljg0NzY3NTkxNDkzNTQsInkiOi01OC4xMTMxODg1ODY4ODM0NDZ9fSwiaWQiOiIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYifV0= + + + DEL_EDGE + WyIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYiXQ== + + 7f0f25f333a2a6cfc15a70a1634323f1 + + + 1749058756916 + + DEL_EDGE + WyJjNTQzMjlmMy0xMmQ1LTQ2ZTAtOTE3Zi02MGQ3NmI3OTQ1ZmIiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJjNTQzMjlmMy0xMmQ1LTQ2ZTAtOTE3Zi02MGQ3NmI3OTQ1ZmIifV0= + + fc1f4b789ad989f3e60a17bbe3a5bd5a + + + 1749058765759 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYxMiwieSI6LTEwMn0seyJ4IjotNjMyLCJ5IjotMTQzfV0= + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYzMiwieSI6LTE0M30seyJ4IjotNjEyLCJ5IjotMTAyfV0= + + 4209fecec5c91f476c4539fa06418efd + + + 1749058768670 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fSx7IngiOi00ODcsInkiOjUwLjc3MzYyMjgyNjIzMzExfV0= + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTQ4NywieSI6NTAuNzczNjIyODI2MjMzMTF9LHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fV0= + + 63797cc5d0c6dc2da5ef71e99504bd45 + + + 1749066909379 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9ZMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + 1ad516ce46689ac6f15b5532ff42ab86 + + + 1749070198710 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + f6a8e5aa88fff9e10e187a6f5d1b6b33 + + + 1749070471512 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + 9b54fffa96ec88de939b11febe6746d0 + + + 1749070605367 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + ae211e5c6a9ff5b2487f0e107ea136f1 + + + 1749325857360 + + UPDATE_EDGE + WyIwMjg4Nzc2NS1lNTA5LTQ3MjgtYWE1ZC1hZTBiYmJhMjkxMzQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyIwMjg4Nzc2NS1lNTA5LTQ3MjgtYWE1ZC1hZTBiYmJhMjkxMzQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwNV9VMyIsdHJ1ZV0= + + d42101a2e57f7e1fc75f9b867262a6a8 \ No newline at end of file diff --git a/0mq/thirdNode.py b/0mq/thirdNode.py new file mode 100644 index 0000000..3cb28cf --- /dev/null +++ b/0mq/thirdNode.py @@ -0,0 +1,34 @@ +# thirdNode.py (Server C) +import concore + +# --- ZMQ Initialization --- +# This REP socket binds and waits for Node A to connect and send a request. +concore.init_zmq_port( + port_name=f"0x{PORT_F1_F3}_{PORT_NAME_F1_F3}", + port_type="bind", + address="tcp://*:" + PORT_F1_F3, + socket_type_str="REP" +) + +print("Node C server started. Waiting for requests...") + +while True: + # Wait to receive a request from Node A + received_data = concore.read(f"0x{PORT_F1_F3}_{PORT_NAME_F1_F3}", "value", [0.0]) + received_value = received_data[0] + + print(f"Node C: Received {received_value:.2f} from Node A.") + + # Process the value + new_value = received_value + 0.01 + print(f"Node C: Sending back final value {new_value:.2f}.") + + # Send the reply back to Node A + concore.write(f"0x{PORT_F1_F3}_{PORT_NAME_F1_F3}", "value", [new_value]) + + # Check the value to know when to shut down gracefully. + if new_value > 100: + break + +print("\nNode C: Terminating.") +concore.terminate_zmq() \ No newline at end of file From 834cdf1d4749ea707167ffc6390d49c7cb9d105d Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Mon, 9 Jun 2025 00:15:21 +0530 Subject: [PATCH 08/17] Added a file only communication based study for testing --- 0mq/comm_node.dir/concore2.py | 263 +++++++++++++++++ 0mq/comm_node.py | 25 ++ 0mq/fileOnlyCommunication.graphml | 460 ++++++++++++++++++++++++++++++ concore.py | 2 +- 4 files changed, 749 insertions(+), 1 deletion(-) create mode 100644 0mq/comm_node.dir/concore2.py create mode 100644 0mq/comm_node.py create mode 100644 0mq/fileOnlyCommunication.graphml diff --git a/0mq/comm_node.dir/concore2.py b/0mq/comm_node.dir/concore2.py new file mode 100644 index 0000000..a018ddf --- /dev/null +++ b/0mq/comm_node.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/0mq/comm_node.py b/0mq/comm_node.py new file mode 100644 index 0000000..edba31d --- /dev/null +++ b/0mq/comm_node.py @@ -0,0 +1,25 @@ +import concore +import concore2 + +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u = "[0.0, 0.0, 0.0]" +init_simtime_ym = "[0.0, 0.0, 0.0]" + +u = concore.initval(init_simtime_u) +ym = concore2.initval(init_simtime_ym) +while(concore2.simtime + + + + + + + + + + + PZ:pmpymax.py + + + + + + + + + + + CZ:cpymax.py + + + + + + + + + + + F1:comm_node.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 + + + \ No newline at end of file diff --git a/concore.py b/concore.py index 2f4d7c8..a018ddf 100644 --- a/concore.py +++ b/concore.py @@ -214,7 +214,7 @@ def write(port_identifier, name, val, delta=0): 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) From b7c21e8d9d2d4872db7096f9fd89c1eede3b64eb Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Mon, 9 Jun 2025 00:22:17 +0530 Subject: [PATCH 09/17] Successfully Integrated zmq node detection and extraction of hexadecimal port and name, then setting them in the variable names as PORT_[SOURCE_NODE]_[DESTINATION_NODE] and PORT_NAME_[SOURCE_NODE]_[DESTINATION_NODE], these variables can be used in the source files when Ports and Portnames are not decided for zeromq connection, and also the port is accessible through iport and oport files. --- mkconcore.py | 343 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 237 insertions(+), 106 deletions(-) diff --git a/mkconcore.py b/mkconcore.py index a608ffb..c05e8aa 100644 --- a/mkconcore.py +++ b/mkconcore.py @@ -5,6 +5,8 @@ import os import shutil import stat +import copy_with_port_portname +import numpy as np MKCONCORE_VER = "22-09-18" @@ -122,66 +124,165 @@ nodes_text = soup.find_all('node') # Store the edges and nodes in a dictionary +edge_label_regex = re.compile(r"0x([a-fA-F0-9]+)_(\S+)") edges_dict = dict() nodes_dict = dict() +node_id_to_label_map = dict() # Helper to get clean node labels from GraphML ID for node in nodes_text: - node_key = node.get_text() - length = len(node.find_all('data')) - for i in range(length): - try: - data = node.find_all('data')[i] - node_label = prefixedgenode + data.find('y:NodeLabel').text #3/23/21 - nodes_dict[node['id']] = re.sub(r'(\s+|\n)', ' ', node_label) - except IndexError: - logging.debug('IndexError: A node with no valid properties encountered and ignored') - except AttributeError: - logging.debug('AttributeError: A node with no valid properties encountered and ignored') + try: + data = node.find('data', recursive=False) + if data: + node_label_tag = data.find('y:NodeLabel') + if node_label_tag: + node_label = prefixedgenode + node_label_tag.text + nodes_dict[node['id']] = re.sub(r'(\s+|\n)', ' ', node_label) + node_id_to_label_map[node['id']] = node_label.split(':')[0] + except (IndexError, AttributeError): + logging.debug('A node with no valid properties encountered and ignored') for edge in edges_text: - length = len(edge.find_all('data')) - for i in range(length): - try: - data = edge.find_all('data')[i] - edge_label = prefixedgenode + data.find('y:EdgeLabel').text # 3/23/21 - if edges_dict.get(edge_label) != None: - targets = edges_dict[edge_label][1] - else: - targets = [] - targets.append(nodes_dict[edge['target']]) - edges_dict[edge_label] = [nodes_dict[edge['source']], targets] - except IndexError: - logging.debug('An edge with no valid properties encountered and ignored') - except AttributeError: - logging.debug('AttributeError: An edge with no valid properties encountered and ignored') + try: + data = edge.find('data', recursive=False) + if data: + edge_label_tag = data.find('y:EdgeLabel') + if edge_label_tag: + raw_label = edge_label_tag.text + edge_label = prefixedgenode + raw_label + # Filter out ZMQ edges from the file-based edge dictionary by checking the raw label + if not edge_label_regex.match(raw_label): + if edge_label not in edges_dict: + edges_dict[edge_label] = [nodes_dict[edge['source']], []] + edges_dict[edge_label][1].append(nodes_dict[edge['target']]) + except (IndexError, AttributeError, KeyError): + logging.debug('An edge with no valid properties or missing node encountered and ignored') -# Print the edges_dict -#logging.info(edges_dict) ############## Mark's Docker -import numpy as np - -i=0 -nodes_num=dict() -for node in nodes_dict: - nodes_num[nodes_dict[node]] = i - i=i+1 +logging.info("Building graph adjacency matrix...") +nodes_num = {label: i for i, label in enumerate(nodes_dict.values())} -m=np.zeros((len(nodes_dict),len(nodes_dict))) +m = np.zeros((len(nodes_dict), len(nodes_dict))) for edges in edges_dict: - for dest in (edges_dict[edges])[1]: - m[nodes_num[edges_dict[edges][0]]][nodes_num[dest]] = 1 + source_node_label = edges_dict[edges][0] + for dest_node_label in edges_dict[edges][1]: + try: + source_idx = nodes_num[source_node_label] + dest_idx = nodes_num[dest_node_label] + m[source_idx][dest_idx] = 1 + except KeyError as e: + logging.error(f"KeyError while building matrix. Label '{e}' not found in node map.") + continue mp = np.eye(len(nodes_dict)) ms = np.zeros((len(nodes_dict),len(nodes_dict))) - -for i in range(0,len(nodes_dict)): +for i in range(len(nodes_dict)): mp = mp@m ms += mp - if (ms == 0).any(): logging.warning("Unreachable nodes detected") +# --- START: New logic for script specialization (Aggregation) --- +python_executable = sys.executable +mkconcore_dir = os.path.dirname(os.path.abspath(__file__)) +copy_script_py_path = os.path.join(mkconcore_dir, "copy_with_port_portname.py") +if not os.path.exists(copy_script_py_path): + copy_script_py_path = os.path.join(CONCOREPATH, "copy_with_port_portname.py") + +if not os.path.exists(copy_script_py_path): + logging.warning(f"copy_with_port_portname.py not found. Script specialization will be skipped.") + copy_script_py_path = None + +# Dictionary to aggregate edge parameters for each node that needs specialization +# Key: node_id (from GraphML), Value: list of edge parameter dicts +node_edge_params = {} +edge_label_regex = re.compile(r"0x([^_]+)_(\S+)") + +logging.info("Aggregating ZMQ edge parameters for nodes...") +if copy_script_py_path: + for edge_element in soup.find_all('edge'): + try: + edge_label_tag = edge_element.find('y:EdgeLabel') + if not edge_label_tag or not edge_label_tag.text: + continue + + raw_edge_label = edge_label_tag.text + match = edge_label_regex.match(raw_edge_label) + + if match: + hex_port_val, port_name_val = match.groups() + # Convert hex port value to decimal string + try: + decimal_port_str = str(int(hex_port_val, 16)) + except ValueError: + logging.error(f"Invalid hex value '{hex_port_val}' in edge label. Using as is.") + decimal_port_str = hex_port_val + + source_node_id = edge_element['source'] + target_node_id = edge_element['target'] + + # Get clean labels for use in variable names + source_node_label = node_id_to_label_map.get(source_node_id, "UNKNOWN_SOURCE") + target_node_label = node_id_to_label_map.get(target_node_id, "UNKNOWN_TARGET") + + logging.info(f"Found ZMQ edge '{raw_edge_label}' from '{source_node_label}' to '{target_node_label}'") + + edge_param_data = { + "port": decimal_port_str, + "port_name": port_name_val, + "source_node_label": source_node_label, + "target_node_label": target_node_label + } + + # Add this edge's data to both the source and target nodes for specialization + if source_node_id in nodes_dict: + if source_node_id not in node_edge_params: + node_edge_params[source_node_id] = [] + node_edge_params[source_node_id].append(edge_param_data) + + if target_node_id in nodes_dict: + if target_node_id not in node_edge_params: + node_edge_params[target_node_id] = [] + node_edge_params[target_node_id].append(edge_param_data) + except Exception as e: + logging.warning(f"Error processing edge for parameter aggregation: {e}") + +# --- Now, run the specialization for each node that has aggregated parameters --- +if node_edge_params: + logging.info("Running script specialization process...") + specialized_scripts_output_dir = os.path.abspath(os.path.join(outdir, "src")) + os.makedirs(specialized_scripts_output_dir, exist_ok=True) + + for node_id, params_list in node_edge_params.items(): + current_node_full_label = nodes_dict[node_id] + try: + container_name, original_script = current_node_full_label.split(':', 1) + except ValueError: + continue # Skip if label format is wrong + + if not original_script or "." not in original_script: + continue # Skip if not a script file + + template_script_full_path = os.path.join(sourcedir, original_script) + if not os.path.exists(template_script_full_path): + logging.error(f"Cannot specialize: Original script '{template_script_full_path}' not found in '{sourcedir}'.") + continue + + new_script_basename = copy_with_port_portname.run_specialization_script( + template_script_full_path, + specialized_scripts_output_dir, + params_list, + python_executable, + copy_script_py_path + ) + + if new_script_basename: + # Update nodes_dict to point to the new comprehensive specialized script + nodes_dict[node_id] = f"{container_name}:{new_script_basename}" + logging.info(f"Node ID '{node_id}' ('{container_name}') updated to use specialized script '{new_script_basename}'.") + else: + logging.error(f"Failed to generate specialized script for node ID '{node_id}'. It will retain its original script.") + #not right for PM2_1_1 and PM2_1_2 volswr = len(nodes_dict)*[''] i = 0 @@ -202,31 +303,46 @@ volsro[nodes_num[dest]] += ' -v '+volIndirPair+':ro' i += 1 -#copy sourcedir into ./src -for node in nodes_dict: - containername,sourcecode = nodes_dict[node].split(':') - if len(sourcecode)!=0 and sourcecode.find(".")!=-1: #3/28/21 - dockername,langext = sourcecode.split(".") - try: - fsource = open(sourcedir+"/"+sourcecode) - except: - logging.error(f"{sourcecode} not found in {sourcedir}") - quit() - with open(outdir+"/src/"+sourcecode,"w") as fcopy: - fcopy.write(fsource.read()) - fsource.close() - if concoretype == "docker": # 3/30/21 - try: - fsource = open(sourcedir+"/Dockerfile."+dockername) - with open(outdir+"/src/Dockerfile."+dockername,"w") as fcopy: - fcopy.write(fsource.read()) - logging.info(f"Using custom Dockerfile for {dockername}") - except: - logging.info(f"Using default Dockerfile for {dockername}") - fsource.close() - if os.path.isdir(sourcedir+"/"+dockername+".dir"): - shutil.copytree(sourcedir+"/"+dockername+".dir",outdir+"/src/"+dockername+".dir") +# copy sourcedir into ./src +# --- Modified file copying loop --- +logging.info("Processing files for nodes...") +for node_id_key in list(nodes_dict.keys()): + node_label_from_dict = nodes_dict[node_id_key] + try: + containername, sourcecode = node_label_from_dict.split(':', 1) + except ValueError: + continue + + if not sourcecode: + continue + + if "." in sourcecode: + dockername, langext = os.path.splitext(sourcecode) + else: + dockername, langext = sourcecode, "" + + script_target_path = os.path.join(outdir, "src", sourcecode) + + # If the script was specialized, it's already in outdir/src. If not, copy from sourcedir. + if node_id_key not in node_edge_params: + script_source_path = os.path.join(sourcedir, sourcecode) + if os.path.exists(script_source_path): + shutil.copy2(script_source_path, script_target_path) + else: + logging.error(f"Script '{sourcecode}' not found in sourcedir '{sourcedir}'") + + # The rest of the file handling (Dockerfiles, .dir) uses 'dockername', + # which is now derived from the specialized script name, maintaining consistency. + if concoretype == "docker": + custom_dockerfile = f"Dockerfile.{dockername}" + if os.path.exists(os.path.join(sourcedir, custom_dockerfile)): + shutil.copy2(os.path.join(sourcedir, custom_dockerfile), os.path.join(outdir, "src", custom_dockerfile)) + dir_for_node = f"{dockername}.dir" + if os.path.isdir(os.path.join(sourcedir, dir_for_node)): + shutil.copytree(os.path.join(sourcedir, dir_for_node), os.path.join(outdir, "src", dir_for_node), dirs_exist_ok=True) + + #copy proper concore.py into /src try: if concoretype=="docker": @@ -346,48 +462,63 @@ fcopy.write(fsource.read()) fsource.close() +# --- Generate iport and oport mappings --- +logging.info("Generating iport/oport mappings...") +node_port_mappings = {label: {'iport': {}, 'oport': {}} for label in nodes_dict.values()} +# 1. Process file-based inputs +node_labels_by_index = {i: label for label, i in nodes_num.items()} +for i, in_dirs in enumerate(indir): + if i in node_labels_by_index: + node_label = node_labels_by_index[i] + for pair in in_dirs: + volname, portnum = pair.split(INDIRNAME) + node_port_mappings[node_label]['iport'][volname] = int(portnum) +# 2. Process file-based outputs +for edge_label, (source_label, target_labels) in edges_dict.items(): + if source_label in node_port_mappings: + out_count = len(node_port_mappings[source_label]['oport']) + 1 + node_port_mappings[source_label]['oport'][edge_label] = out_count +# 3. Augment with bidirectional ZMQ connections +logging.info("Augmenting port maps with ZMQ connections...") +for edge_element in soup.find_all('edge'): + try: + edge_label_tag = edge_element.find('y:EdgeLabel') + if not edge_label_tag or not edge_label_tag.text: continue + match = edge_label_regex.match(edge_label_tag.text) + if match: + hex_port_val, port_name_val = match.groups() + # Convert hex port value to decimal string + try: + decimal_port_str = str(int(hex_port_val, 16)) + except ValueError: + logging.error(f"Invalid hex value '{hex_port_val}' in edge label. Using as is.") + decimal_port_str = hex_port_val + + source_label = nodes_dict.get(edge_element['source']) + target_label = nodes_dict.get(edge_element['target']) + if source_label and target_label: + node_port_mappings[source_label]['iport'][port_name_val] = decimal_port_str + node_port_mappings[source_label]['oport'][port_name_val] = decimal_port_str + node_port_mappings[target_label]['iport'][port_name_val] = decimal_port_str + node_port_mappings[target_label]['oport'][port_name_val] = decimal_port_str + logging.info(f" - Added ZMQ port '{port_name_val}:{decimal_port_str}' to both iport/oport for nodes '{source_label}' and '{target_label}'") + except Exception as e: + logging.warning(f"Error processing ZMQ edge for port map: {e}") + +# 4. Write final iport/oport files +logging.info("Writing .iport and .oport files...") +for node_label, ports in node_port_mappings.items(): + try: + containername, sourcecode = node_label.split(':', 1) + if not sourcecode or "." not in sourcecode: continue + dockername = os.path.splitext(sourcecode)[0] + with open(os.path.join(outdir, "src", f"{dockername}.iport"), "w") as fport: + fport.write(str(ports['iport']).replace("'" + prefixedgenode, "'")) + with open(os.path.join(outdir, "src", f"{dockername}.oport"), "w") as fport: + fport.write(str(ports['oport']).replace("'" + prefixedgenode, "'")) + except ValueError: + continue -#generate input portmap file -i=0 -for node in nodes_dict: - containername,sourcecode = nodes_dict[node].split(':') - iportmap_dict = dict() - for pair in indir[i]: - volname,portnum = pair.split(INDIRNAME) - iportmap_dict[volname] = int(portnum) - if len(sourcecode)!=0 and sourcecode.find(".")!=-1: #3/28/21 - dockername,langext = sourcecode.split(".") - if os.path.exists(outdir+"/src/"+dockername+".iport"): - logging.warning(f"{dockername} has multiple instantiations ; iport/oport may be invalid") - with open(outdir+"/src/"+dockername+".iport", "w") as fport: - if prefixedgenode == "": # 5/18/21 - fport.write(str(iportmap_dict)) - else: - fport.write(str(iportmap_dict).replace("'"+prefixedgenode,"'")) - i=i+1 - -#generate output portmap file -outcount = len(nodes_dict)*[0] -#wrong, this aliases single dict for all elements: oportmap = len(nodes_dict)*[dict()] -#instead, need to use a loop to initialize: -oportmap_dict = [] -for node in nodes_dict: - oportmap_dict += [dict()] -for edges in edges_dict: - containername,sourcecode = edges_dict[edges][0].split(':') - outcount[nodes_num[edges_dict[edges][0]]] += 1 - oportmap_dict[nodes_num[edges_dict[edges][0]]][edges] = outcount[nodes_num[edges_dict[edges][0]]] -i=0 -for node in nodes_dict: - containername,sourcecode = nodes_dict[node].split(':') - if len(sourcecode)!=0 and sourcecode.find(".")!=-1: #3/28/21 - dockername,langext = sourcecode.split(".") - with open(outdir+"/src/"+dockername+".oport", "w") as fport: - if prefixedgenode == "": # 5/18/21 - fport.write(str(oportmap_dict[i])) - else: - fport.write(str(oportmap_dict[i]).replace("'"+prefixedgenode,"'")) - i=i+1 #if docker, make docker-dirs, generate build, run, stop, clear scripts and quit if (concoretype=="docker"): From c87cf2f62f0bba6bf518b073a2e81b60ad578949 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Wed, 11 Jun 2025 16:21:17 +0530 Subject: [PATCH 10/17] Added A Functionality to see the ZMQ edge results also even if it is not communicating through file based communication --- .../concore2.py | 0 0mq/test0mq4.graphml | 152 ++++++++++++++++-- concore.py | 2 +- 3 files changed, 143 insertions(+), 11 deletions(-) rename 0mq/{funbody_zmq.dir copy => funbody_zmq.dir}/concore2.py (100%) diff --git a/0mq/funbody_zmq.dir copy/concore2.py b/0mq/funbody_zmq.dir/concore2.py similarity index 100% rename from 0mq/funbody_zmq.dir copy/concore2.py rename to 0mq/funbody_zmq.dir/concore2.py diff --git a/0mq/test0mq4.graphml b/0mq/test0mq4.graphml index ef6b503..08ada0f 100644 --- a/0mq/test0mq4.graphml +++ b/0mq/test0mq4.graphml @@ -2,11 +2,11 @@ - + - + PZ:pmpymax.py @@ -17,7 +17,7 @@ - + CZ:cpymax.py @@ -28,7 +28,7 @@ - + F1:funcall_zmq.py @@ -39,7 +39,7 @@ - + F2:funbody_zmq.py @@ -54,7 +54,7 @@ U - + @@ -66,7 +66,7 @@ Y - + @@ -78,7 +78,7 @@ U2 - + @@ -90,7 +90,7 @@ Y2 - + @@ -102,7 +102,7 @@ 0x1234_U3 - + @@ -599,5 +599,137 @@ 6455bbb0a3114ec3ba44920b64bd0266 + + 1749634829919 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MjYwLjIyMzc5NjQ1MDU3NjIsInkiOjMxMS4zMjAxMjcwNjgyNTY0fSx7IngiOjI2MS4yMjM3OTY0NTA1NzYyLCJ5IjozODguMzIwMTI3MDY4MjU2NH1d + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MjYxLjIyMzc5NjQ1MDU3NjIsInkiOjM4OC4zMjAxMjcwNjgyNTY0fSx7IngiOjI2MC4yMjM3OTY0NTA1NzYyLCJ5IjozMTEuMzIwMTI3MDY4MjU2NH1d + + 6db1c3f5876e499e3af23bc64c8c5bb0 + + + 1749634829941 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjAzLCJ5IjozMDYuNzczNjIyODI2MjMzMX0seyJ4Ijo2MDQsInkiOjM4My43NzM2MjI4MjYyMzMxfV0= + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjA0LCJ5IjozODMuNzczNjIyODI2MjMzMX0seyJ4Ijo2MDMsInkiOjMwNi43NzM2MjI4MjYyMzMxfV0= + + cbf7736ec743327ba43b837143224398 + + + 1749634835985 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MjYxLjIyMzc5NjQ1MDU3NjIsInkiOjM4OC4zMjAxMjcwNjgyNTY0fSx7IngiOjMzNS4yMjM3OTY0NTA1NzYyLCJ5IjozODAuMzIwMTI3MDY4MjU2NH1d + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzM1LjIyMzc5NjQ1MDU3NjIsInkiOjM4MC4zMjAxMjcwNjgyNTY0fSx7IngiOjI2MS4yMjM3OTY0NTA1NzYyLCJ5IjozODguMzIwMTI3MDY4MjU2NH1d + + bcd1d06be8ec425b80883b7e8ed78ebb + + + 1749634843769 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjA0LCJ5IjozODMuNzczNjIyODI2MjMzMX0seyJ4Ijo2MDUsInkiOjM3NS43NzM2MjI4MjYyMzMxfV0= + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjA1LCJ5IjozNzUuNzczNjIyODI2MjMzMX0seyJ4Ijo2MDQsInkiOjM4My43NzM2MjI4MjYyMzMxfV0= + + d22a89c1436e739adc827b2c9c5ed9fb + + + 1749638394047 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjA1LCJ5IjozNzUuNzczNjIyODI2MjMzMX0seyJ4Ijo2MDYuMTA2NjIzNzgzOTc3NiwieSI6Mzg0LjYyNjYxMzA5ODA1NDQ2fV0= + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjA2LjEwNjYyMzc4Mzk3NzYsInkiOjM4NC42MjY2MTMwOTgwNTQ0Nn0seyJ4Ijo2MDUsInkiOjM3NS43NzM2MjI4MjYyMzMxfV0= + + 98a2cdaa9c637e3b1f80e191689ef228 + + + 1749638406118 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzM1LjIyMzc5NjQ1MDU3NjIsInkiOjM4MC4zMjAxMjcwNjgyNTY0fSx7IngiOjM1NS4xNDMwMjQ1NjIxNzQyLCJ5IjozODEuNDI2NzUwODUyMjM0fV0= + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6MzU1LjE0MzAyNDU2MjE3NDIsInkiOjM4MS40MjY3NTA4NTIyMzR9LHsieCI6MzM1LjIyMzc5NjQ1MDU3NjIsInkiOjM4MC4zMjAxMjcwNjgyNTY0fV0= + + 461addecc2f83c39d144dd59fe140d7a + + + 1749638411387 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjA2LjEwNjYyMzc4Mzk3NzYsInkiOjM4NC42MjY2MTMwOTgwNTQ0Nn0seyJ4Ijo2MDEuNjgwMTI4NjQ4MDY3LCJ5IjozODIuNDEzMzY1NTMwMDk5MX1d + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6NjAxLjY4MDEyODY0ODA2NywieSI6MzgyLjQxMzM2NTUzMDA5OTF9LHsieCI6NjA2LjEwNjYyMzc4Mzk3NzYsInkiOjM4NC42MjY2MTMwOTgwNTQ0Nn1d + + a65da086d27f4b89fde06386803b6c83 + + + 1749638417166 + + SET_POS + WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJ4Ijo1OTEuNTg0MzA2OTgyNTY2MiwieSI6MTAxLjU0ODk1MzA0OTM1NjAzfV0= + + + SET_POS + WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTkxLjU4NDMwNjk4MjU2NjIsInkiOjEwMS41NDg5NTMwNDkzNTYwM30seyJ4Ijo1ODcuMTU3ODExODQ2NjU1NiwieSI6MTAwLjQ0MjMyOTI2NTM3ODM2fV0= + + f084c23a413d578cc6f24c99f4abf593 + + + 1749638421768 + + SET_POS + WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTkxLjU4NDMwNjk4MjU2NjIsInkiOjEwMS41NDg5NTMwNDkzNTYwM30seyJ4Ijo1OTAuNDc3NjgzMTk4NTg4NSwieSI6OTQuOTA5MjEwMzQ1NDkwMDJ9XQ== + + + SET_POS + WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLHsieCI6NTkwLjQ3NzY4MzE5ODU4ODUsInkiOjk0LjkwOTIxMDM0NTQ5MDAyfSx7IngiOjU5MS41ODQzMDY5ODI1NjYyLCJ5IjoxMDEuNTQ4OTUzMDQ5MzU2MDN9XQ== + + 7351dd339614af3284a27265645c683e + + + 1749638428404 + + SET_POS + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsieCI6MzM0LjkxMjAxMzMwMTYwODk3LCJ5Ijo5MC45NzgwNzgzODk1MDQ0fV0= + + + SET_POS + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MzM0LjkxMjAxMzMwMTYwODk3LCJ5Ijo5MC45NzgwNzgzODk1MDQ0fSx7IngiOjMzNi4wMTg2MzcwODU1ODY2NSwieSI6MTAwLjkzNzY5MjQ0NTMwMzQxfV0= + + e6e0b6e82708953b8f2a3a53d75d7480 + + + 1749638434730 + + SET_POS + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MzM0LjkxMjAxMzMwMTYwODk3LCJ5Ijo5MC45NzgwNzgzODk1MDQ0fSx7IngiOjMzMi42OTg3NjU3MzM2NTM3LCJ5Ijo5NC4yOTc5NDk3NDE0Mzc0fV0= + + + SET_POS + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsieCI6MzMyLjY5ODc2NTczMzY1MzcsInkiOjk0LjI5Nzk0OTc0MTQzNzR9LHsieCI6MzM0LjkxMjAxMzMwMTYwODk3LCJ5Ijo5MC45NzgwNzgzODk1MDQ0fV0= + + 5308877f34d57a16e83da8243a43a98f + \ No newline at end of file diff --git a/concore.py b/concore.py index a018ddf..e90c750 100644 --- a/concore.py +++ b/concore.py @@ -214,7 +214,7 @@ def write(port_identifier, name, val, delta=0): 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) From efd7896fafabcf9a7a9ae495848c64ec6cae2c9a Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Fri, 13 Jun 2025 18:13:21 +0530 Subject: [PATCH 11/17] Implemented ZeroMQ socket timeouts & retry logic fordropped connections. --- concore.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/concore.py b/concore.py index e90c750..ce3ab0a 100644 --- a/concore.py +++ b/concore.py @@ -20,12 +20,38 @@ def __init__(self, port_type, address, zmq_socket_type): self.socket = self.context.socket(zmq_socket_type) self.port_type = port_type # "bind" or "connect" self.address = address + + self.socket.setsockopt(zmq.RCVTIMEO, 2000) + self.socket.setsockopt(zmq.SNDTIMEO, 2000) + self.socket.setsockopt(zmq.LINGER, 0) + 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}") + + def send_json_with_retry(self, message): + for attempt in range(5): + try: + self.socket.send_json(message) + return + except zmq.Again: + print(f"Send timeout (attempt {attempt + 1}/5)") + time.sleep(0.5) + print("Failed to send after retries.") + return + + def recv_json_with_retry(self): + for attempt in range(5): + try: + return self.socket.recv_json() + except zmq.Again: + print(f"Receive timeout (attempt {attempt + 1}/5)") + time.sleep(0.5) + print("Failed to receive after retries.") + return None # Global ZeroMQ ports registry zmq_ports = {} @@ -143,7 +169,7 @@ def read(port_identifier, name, initstr_val): if isinstance(port_identifier, str) and port_identifier in zmq_ports: zmq_p = zmq_ports[port_identifier] try: - message = zmq_p.socket.recv_json() + message = zmq_p.recv_json_with_retry() return message except zmq.error.ZMQError as e: print(f"ZMQ read error on port {port_identifier} (name: {name}): {e}. Returning default.") @@ -209,7 +235,7 @@ def write(port_identifier, name, val, delta=0): if isinstance(port_identifier, str) and port_identifier in zmq_ports: zmq_p = zmq_ports[port_identifier] try: - zmq_p.socket.send_json(val) + zmq_p.send_json_with_retry(val) except zmq.error.ZMQError as e: print(f"ZMQ write error on port {port_identifier} (name: {name}): {e}") except Exception as e: From 15dfcf7f10c80cdf79782ab2f25e68f4e43ca7a0 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Wed, 18 Jun 2025 03:42:11 +0530 Subject: [PATCH 12/17] Added A ZeroMQ Study for Quick Measurements based on adding 10 in sum untill 100 --- measurements/A.py | 76 +++++++++ measurements/B.py | 60 +++++++ measurements/C.py | 62 +++++++ measurements/ZeroMQOnly.graphml | 280 ++++++++++++++++++++++++++++++++ 4 files changed, 478 insertions(+) create mode 100644 measurements/A.py create mode 100644 measurements/B.py create mode 100644 measurements/C.py create mode 100644 measurements/ZeroMQOnly.graphml 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 From e1a0bf357b699ec3162c02045e538aa6c56d44f8 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Wed, 18 Jun 2025 22:50:17 +0530 Subject: [PATCH 13/17] Added A file only communication Study for Quick Measurements based on adding 10 in sum untill 100 --- measurements/comm_node_test.dir/concore2.py | 263 ++++++++++ measurements/comm_node_test.py | 68 +++ measurements/cpymax_test.py | 78 +++ measurements/fileOnlyCommunication.graphml | 508 ++++++++++++++++++++ measurements/pmpymax_test.py | 57 +++ 5 files changed, 974 insertions(+) create mode 100644 measurements/comm_node_test.dir/concore2.py create mode 100644 measurements/comm_node_test.py create mode 100644 measurements/cpymax_test.py create mode 100644 measurements/fileOnlyCommunication.graphml create mode 100644 measurements/pmpymax_test.py 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) From f831a2e8b189e3588ac3848c06b1534a850ce168 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Thu, 7 Aug 2025 11:35:50 +0530 Subject: [PATCH 14/17] Measurements Folder Added --- measurements/CPU/Figure5.png | Bin 0 -> 38492 bytes measurements/CPU/client_cpu.graphml | 185 +++++ measurements/CPU/funbody_cpu.py | 88 +++ measurements/CPU/funcall_cpu.py | 74 ++ measurements/CPU/plot_fig5.py | 42 ++ measurements/CPU/receiver_usage.csv | 32 + measurements/CPU/sender_usage.csv | 26 + measurements/CPU/server_cpu.graphml | 293 ++++++++ measurements/Latency/cpymax.py | 29 + .../Latency/distributed_client.graphml | 640 ++++++++++++++++++ .../Latency/distributed_server.graphml | 520 ++++++++++++++ .../Latency/figure3_latency_comparison.png | Bin 0 -> 208612 bytes measurements/Latency/funbody_distributed.py | 67 ++ measurements/Latency/funcall_distributed.py | 83 +++ measurements/Latency/mediator_latencies.csv | 101 +++ measurements/Latency/plot_fig3(1).py | 53 ++ measurements/Latency/plot_fig3(2).py | 38 ++ measurements/Latency/pmpymax.py | 15 + measurements/Latency/zeromq_latencies.csv | 95 +++ measurements/Latency/zmq_violin.png | Bin 0 -> 40664 bytes measurements/Throughput/Figure_4.png | Bin 0 -> 26235 bytes ... 2025-07-07 at 12.43.32\342\200\257AM.png" | Bin 0 -> 235625 bytes measurements/Throughput/client.graphml | 185 +++++ .../Throughput/funbody_throughput_test.py | 40 ++ .../Throughput/funcall_throughput_test.py | 57 ++ measurements/Throughput/plot_fig4.py | 34 + measurements/Throughput/server.graphml | 221 ++++++ measurements/readme.md | 59 ++ ... 2025-07-07 at 12.43.32\342\200\257AM.png" | Bin 0 -> 235625 bytes measurements/throughput_test/client.graphml | 173 +++++ .../throughput_test/client_cpu.graphml | 185 +++++ measurements/throughput_test/concore.py | 289 ++++++++ measurements/throughput_test/funbody_cpu.py | 71 ++ .../funbody_throughput_test.py | 40 ++ measurements/throughput_test/funcall_cpu.py | 63 ++ .../funcall_throughput_test.py | 57 ++ measurements/throughput_test/plot.py | 34 + measurements/throughput_test/plot_fig5.py | 42 ++ measurements/throughput_test/server.graphml | 221 ++++++ .../throughput_test/server_cpu.graphml | 245 +++++++ 40 files changed, 4397 insertions(+) create mode 100644 measurements/CPU/Figure5.png create mode 100644 measurements/CPU/client_cpu.graphml create mode 100644 measurements/CPU/funbody_cpu.py create mode 100644 measurements/CPU/funcall_cpu.py create mode 100644 measurements/CPU/plot_fig5.py create mode 100644 measurements/CPU/receiver_usage.csv create mode 100644 measurements/CPU/sender_usage.csv create mode 100644 measurements/CPU/server_cpu.graphml create mode 100644 measurements/Latency/cpymax.py create mode 100644 measurements/Latency/distributed_client.graphml create mode 100644 measurements/Latency/distributed_server.graphml create mode 100644 measurements/Latency/figure3_latency_comparison.png create mode 100644 measurements/Latency/funbody_distributed.py create mode 100644 measurements/Latency/funcall_distributed.py create mode 100644 measurements/Latency/mediator_latencies.csv create mode 100644 measurements/Latency/plot_fig3(1).py create mode 100644 measurements/Latency/plot_fig3(2).py create mode 100644 measurements/Latency/pmpymax.py create mode 100644 measurements/Latency/zeromq_latencies.csv create mode 100644 measurements/Latency/zmq_violin.png create mode 100644 measurements/Throughput/Figure_4.png create mode 100644 "measurements/Throughput/Screenshot 2025-07-07 at 12.43.32\342\200\257AM.png" create mode 100644 measurements/Throughput/client.graphml create mode 100644 measurements/Throughput/funbody_throughput_test.py create mode 100644 measurements/Throughput/funcall_throughput_test.py create mode 100644 measurements/Throughput/plot_fig4.py create mode 100644 measurements/Throughput/server.graphml create mode 100644 measurements/readme.md create mode 100644 "measurements/throughput_test/Screenshot 2025-07-07 at 12.43.32\342\200\257AM.png" create mode 100644 measurements/throughput_test/client.graphml create mode 100644 measurements/throughput_test/client_cpu.graphml create mode 100644 measurements/throughput_test/concore.py create mode 100644 measurements/throughput_test/funbody_cpu.py create mode 100644 measurements/throughput_test/funbody_throughput_test.py create mode 100644 measurements/throughput_test/funcall_cpu.py create mode 100644 measurements/throughput_test/funcall_throughput_test.py create mode 100644 measurements/throughput_test/plot.py create mode 100644 measurements/throughput_test/plot_fig5.py create mode 100644 measurements/throughput_test/server.graphml create mode 100644 measurements/throughput_test/server_cpu.graphml diff --git a/measurements/CPU/Figure5.png b/measurements/CPU/Figure5.png new file mode 100644 index 0000000000000000000000000000000000000000..5b91b62e7c9fddac1471e4b7675724ba8be7730c GIT binary patch literal 38492 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 literal 0 HcmV?d00001 diff --git a/measurements/CPU/client_cpu.graphml b/measurements/CPU/client_cpu.graphml new file mode 100644 index 0000000..495721d --- /dev/null +++ b/measurements/CPU/client_cpu.graphml @@ -0,0 +1,185 @@ + + + + + + + + + + + + B:funbody_cpu.py + + + + + + + + + + + OUT: + + + + + + + + + + 0x2306_U1 + + + + + + + + 1751825758771 + + DEL_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + + ADD_NODE + WyJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMzMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NDg3LCJ5IjozMTN9LHt9LCI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + e425a002ed1453f66a4fb1dad3ad2923 + + + 1751825761336 + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDg3LCJ5IjozMTN9XQ== + + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6NDg3LCJ5IjozMTN9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + d7861c7337345a2010806e89311d85bf + + + 1751825767651 + + DEL_NODE + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + + ADD_NODE + WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTA3LCJ5IjoxMDJ9LHt9LCIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + 19b85e105d5758f18c55915fbce84663 + + + 1751825770936 + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTA3LCJ5IjoxMDJ9XQ== + + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTA3LCJ5IjoxMDJ9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 03b8818572c5800d88c583073a1ef559 + + + 1751825773370 + + DEL_EDGE + WyI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLCJ0YXJnZXRJRCI6IjIxOTZjMTQ2LTE4MGMtNGQxNC1iYmFhLTM0MGY3NmUxNDgwOSIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQifV0= + + 1dd8b4edaeed282d75d1daeb3195b728 + + + 1751826367735 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + ca298c11df338ea36bce176af0fe3b69 + + + 1751826515156 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + c6ee9fdcb90f48bc1de9bdc44b7da91f + + + 1751826596605 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + b79566da6d5ea6c2cf2cbb618da677d2 + + + 1751826901740 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + ba871dc0f4bc75adee32e34c87854508 + + + 1751827730897 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 8bb2b4d5cd9d445722b307d6bdb3d9fd + + + 1751828973865 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 3609737de0e0d000c3d43a620f592090 + + + 1751872486908 + + UPDATE_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsid2lkdGgiOjIzMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsid2lkdGgiOjIzMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJCOmZ1bmJvZHlfY3B1LnB5Iix0cnVlXQ== + + a0691587adb56f1c913b278379ea8cd5 + + + \ No newline at end of file diff --git a/measurements/CPU/funbody_cpu.py b/measurements/CPU/funbody_cpu.py new file mode 100644 index 0000000..cdbb0a2 --- /dev/null +++ b/measurements/CPU/funbody_cpu.py @@ -0,0 +1,88 @@ +# funbody_throughput_test.py (MODIFIED FOR RESOURCE MONITORING & CORRECTED) +import time +import concore +import os +import json +import threading +import psutil +import csv + +# --- MONITORING FUNCTION (to be run in a separate thread) --- +def monitor_resources(stop_event, output_list): + """Monitors this script's CPU and memory usage.""" + process = psutil.Process(os.getpid()) + while not stop_event.is_set(): + cpu_percent = process.cpu_percent(interval=0.5) + memory_mb = process.memory_info().rss / (1024 * 1024) + output_list.append({'cpu_percent': cpu_percent, 'memory_mb': memory_mb}) + +print("funbody (Receiver) using ZMQ REP socket for Throughput & Resource Test.") + +TEST_DURATION = 10 +message_count = 0 +test_started = False +resource_records = [] +start_time = 0 + +# --- Start Monitoring --- +stop_monitoring = threading.Event() +monitor_thread = threading.Thread(target=monitor_resources, args=(stop_monitoring, resource_records)) +monitor_thread.start() + +# --- Main Throughput Test Logic (CORRECTED) --- +concore.init_zmq_port( + port_name=PORT_NAME_B_OUT, + port_type="bind", + address="tcp://0.0.0.0:" + PORT_B_OUT, # Bind to all interfaces on the specified port + socket_type_str="REP" +) + +print(f"Receiver waiting for messages on port {PORT_B_OUT}...") +while True: + # Wait for a message + message_str = concore.read(PORT_NAME_B_OUT, "stream", "{}") + + # Send an acknowledgment immediately after receiving + concore.write(PORT_NAME_B_OUT, "reply", "{}") # ADDED: Send acknowledgment + + if message_str is None: + continue # Or break, depending on desired behavior on timeout + + try: + # Since concore.read now handles JSON parsing, this might not be needed + # but we keep it for validation of the message structure. + message_dict = message_str if isinstance(message_str, dict) else json.loads(message_str) + except (json.JSONDecodeError, TypeError): + continue + + if isinstance(message_dict, dict) and 'type' in message_dict: + if message_dict['type'] == 'control': + if message_dict['value'] == 'START' and not test_started: + print("START signal received.") + test_started = True + start_time = time.perf_counter() + elif message_dict['value'] == 'STOP' and test_started: + print("STOP signal received.") + break # Exit the loop to end the test + elif message_dict['type'] == 'data' and test_started: + message_count += 1 + +# --- Stop Monitoring and Save Results --- +stop_monitoring.set() +monitor_thread.join() +concore.terminate_zmq() + +if message_count > 0: + end_time = time.perf_counter() + duration = end_time - start_time + throughput = message_count / duration if duration > 0 else 0 + print(f"\n--- TEST COMPLETE ---") + print(f"Received {message_count} messages in {duration:.2f} seconds.") + print(f"THROUGHPUT RESULT: {throughput:.2f} messages/second") + +if resource_records: + with open('receiver_usage.csv', 'w', newline='') as f: + writer = csv.DictWriter(f, fieldnames=['cpu_percent', 'memory_mb']) + writer.writeheader() + writer.writerows(resource_records) + print("Receiver resource usage saved to receiver_usage.csv") \ No newline at end of file diff --git a/measurements/CPU/funcall_cpu.py b/measurements/CPU/funcall_cpu.py new file mode 100644 index 0000000..500b486 --- /dev/null +++ b/measurements/CPU/funcall_cpu.py @@ -0,0 +1,74 @@ +# funcall_throughput_test.py (MODIFIED FOR RESOURCE MONITORING & CORRECTED) +import time +import concore +import os +import json +import threading +import psutil +import csv + +# --- MONITORING FUNCTION (to be run in a separate thread) --- +def monitor_resources(stop_event, output_list): + """Monitors this script's CPU and memory usage.""" + process = psutil.Process(os.getpid()) + while not stop_event.is_set(): + # Get CPU (as a percentage) and Memory (RSS in MB) + cpu_percent = process.cpu_percent(interval=0.5) + memory_mb = process.memory_info().rss / (1024 * 1024) + output_list.append({'cpu_percent': cpu_percent, 'memory_mb': memory_mb}) + +print("funcall (Sender) using ZMQ REQ socket for Throughput & Resource Test.") + +TEST_DURATION = 10 +message_count = 0 +resource_records = [] + +# --- Start Monitoring --- +stop_monitoring = threading.Event() +monitor_thread = threading.Thread(target=monitor_resources, args=(stop_monitoring, resource_records)) +monitor_thread.start() + +# --- Main Throughput Test Logic (CORRECTED) --- +concore.init_zmq_port( + port_name=PORT_NAME_IN_A, + port_type="connect", + address="tcp://192.168.0.109:" + PORT_IN_A, # Use 127.0.0.1 for local, or the receiver's IP + socket_type_str="REQ" +) +print(f"Sender starting. Will send data for {TEST_DURATION} seconds.") + +# Send START signal and wait for reply +start_signal = json.dumps({"type": "control", "value": "START"}) +concore.write(PORT_NAME_IN_A, "stream", start_signal) +concore.read(PORT_NAME_IN_A, "reply", "{}") # ADDED: Wait for acknowledgment + +time.sleep(1) +start_time = time.perf_counter() + +# Loop for the test duration +while (time.perf_counter() - start_time) < TEST_DURATION: + data_message = json.dumps({"type": "data", "value": message_count}) + concore.write(PORT_NAME_IN_A, "stream", data_message) + concore.read(PORT_NAME_IN_A, "reply", "{}") # ADDED: Wait for acknowledgment + message_count += 1 + +time.sleep(1) + +# Send STOP signal and wait for reply +stop_signal = json.dumps({"type": "control", "value": "STOP"}) +concore.write(PORT_NAME_IN_A, "stream", stop_signal) +concore.read(PORT_NAME_IN_A, "reply", "{}") # ADDED: Wait for acknowledgment + +print(f"Sender finished. Sent approximately {message_count} messages.") + +# --- Stop Monitoring and Save Results --- +stop_monitoring.set() +monitor_thread.join() +concore.terminate_zmq() + +if resource_records: + with open('sender_usage.csv', 'w', newline='') as f: + writer = csv.DictWriter(f, fieldnames=['cpu_percent', 'memory_mb']) + writer.writeheader() + writer.writerows(resource_records) + print("Sender resource usage saved to sender_usage.csv") \ No newline at end of file diff --git a/measurements/CPU/plot_fig5.py b/measurements/CPU/plot_fig5.py new file mode 100644 index 0000000..2990a9d --- /dev/null +++ b/measurements/CPU/plot_fig5.py @@ -0,0 +1,42 @@ +import pandas as pd +import seaborn as sns +import matplotlib.pyplot as plt + +# Load all data and calculate averages +try: + avg_cpu_sender_zmq = pd.read_csv('sender_usage.csv')['cpu_percent'].mean() + avg_mem_sender_zmq = pd.read_csv('sender_usage.csv')['memory_mb'].mean() + + # In a real test, you would also measure the receiver. For simplicity, we plot sender. + # avg_cpu_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['cpu_percent'].mean() + # avg_mem_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['memory_mb'].mean() + + # Create placeholder data for Mediator until you run the test + avg_cpu_sender_mediator = 25.5 # Example value + avg_mem_sender_mediator = 60.2 # Example value + +except FileNotFoundError: + print("One or more CSV files not found. Using placeholder data.") + # Placeholder data for plotting if you haven't run the experiment yet + avg_cpu_sender_zmq, avg_mem_sender_zmq = 15.0, 45.0 + avg_cpu_sender_mediator, avg_mem_sender_mediator = 25.5, 60.2 + +# Prepare data for plotting +data = { + 'Protocol': ['Mediator', 'ZeroMQ', 'Mediator', 'ZeroMQ'], + 'Metric': ['CPU Usage (%)', 'CPU Usage (%)', 'Memory Usage (MB)', 'Memory Usage (MB)'], + 'Value': [avg_cpu_sender_mediator, avg_cpu_sender_zmq, avg_mem_sender_mediator, avg_mem_sender_zmq] +} +df_plot = pd.DataFrame(data) + +# Create the grouped bar chart +plt.figure(figsize=(10, 7)) +sns.barplot(x='Metric', y='Value', hue='Protocol', data=df_plot, palette={'Mediator': '#F44336', 'ZeroMQ': '#4CAF50'}) + +plt.title('Figure 5: Resource Utilization During Throughput Test (Sender)', fontsize=16) +plt.xlabel('Performance Metric', fontsize=12) +plt.ylabel('Average Usage', fontsize=12) +plt.legend(title='Protocol') +plt.grid(axis='y', linestyle='--', alpha=0.7) + +plt.show() diff --git a/measurements/CPU/receiver_usage.csv b/measurements/CPU/receiver_usage.csv new file mode 100644 index 0000000..d49f1f0 --- /dev/null +++ b/measurements/CPU/receiver_usage.csv @@ -0,0 +1,32 @@ +cpu_percent,memory_mb +0.0,17.375 +0.0,17.375 +0.0,17.375 +2.0,17.375 +0.0,17.375 +0.0,17.375 +4.0,17.375 +0.0,17.375 +0.0,17.5 +34.0,17.625 +38.0,17.625 +40.0,17.625 +38.0,17.625 +36.0,17.625 +40.0,17.625 +40.0,17.625 +38.0,17.625 +40.0,17.625 +40.0,17.625 +40.0,17.625 +40.0,17.625 +42.0,17.625 +40.0,17.625 +40.0,17.625 +42.0,17.625 +38.0,17.625 +40.0,17.625 +42.0,17.625 +37.6,17.625 +0.0,17.625 +0.0,17.625 diff --git a/measurements/CPU/sender_usage.csv b/measurements/CPU/sender_usage.csv new file mode 100644 index 0000000..ff7fa9f --- /dev/null +++ b/measurements/CPU/sender_usage.csv @@ -0,0 +1,26 @@ +cpu_percent,memory_mb +0.3,17.15625 +0.0,16.609375 +27.5,17.046875 +23.8,17.078125 +24.3,17.078125 +23.6,17.078125 +23.9,16.75 +23.7,16.734375 +23.9,15.859375 +23.6,15.84375 +22.7,15.78125 +23.3,15.796875 +23.1,15.8125 +23.2,15.8125 +22.0,15.46875 +22.4,15.46875 +23.7,11.578125 +22.8,11.578125 +23.0,11.578125 +22.9,11.5625 +22.6,11.5625 +23.3,11.59375 +0.3,11.578125 +0.0,11.578125 +0.4,10.453125 diff --git a/measurements/CPU/server_cpu.graphml b/measurements/CPU/server_cpu.graphml new file mode 100644 index 0000000..9359a5d --- /dev/null +++ b/measurements/CPU/server_cpu.graphml @@ -0,0 +1,293 @@ + + + + + + + + + + + + A:funcall_cpu.py + + + + + + + + + + + IN: + + + + + + + + + + 0x2311_U1 + + + + + + + + 1751825545123 + + DEL_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + + ADD_NODE + WyJBOmZ1bmNhbGxfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMjMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHt9LCIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + 0f6a06a5f49f1d83657221f267bbf65e + + + 1751825547451 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjEwMCwieSI6MTAwfV0= + + c07fdf0b5fbc290aea42a3bd74c45a6b + + + 1751825549601 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjUzMC4wMDIxOTE0MDExMDk5LCJ5IjoyOTIuMDAwOTc4NDg2MDc3fV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + 55cb72ce7faf50386f9f71afe1e576fb + + + 1751825564072 + + DEL_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + + ADD_NODE + WyJJbjoiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjoxOTUuMDAwNDg0MTQ2NzU2OCwieSI6OTAuOTk5OTU0MTMzNDY1MTR9LHt9LCJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + d13798fff2bf40cbacc6bc0f73cc3e5a + + + 1751825566634 + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJbjoiLHRydWVd + + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJTjoiLHRydWVd + + 1292dab0cd809e0bc822a88cbe296a4f + + + 1751825570934 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fV0= + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjEwMCwieSI6MTAwfV0= + + 71a0470230ca5a52edc2cb9ff06f3d28 + + + 1751825572700 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjE5NS4wMDA0ODQxNDY3NTY4LCJ5Ijo5MC45OTk5NTQxMzM0NjUxNH1d + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTk1LjAwMDQ4NDE0Njc1NjgsInkiOjkwLjk5OTk1NDEzMzQ2NTE0fSx7IngiOjE5Mi4wMDA0Njg4NTc5MTE5LCJ5Ijo5NC45OTk5NzQ1MTg1OTE3N31d + + 86c56976fc63f27dc9485ecc73f2de2d + + + 1751825576935 + + DEL_EDGE + WyI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLCJ0YXJnZXRJRCI6IjI0YmUwYzEzLTVkOGMtNGY5MC1iMGJiLTFlMDcyN2IwNDJkNyIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUifV0= + + e3d7f90d81fe934dfa3c417169de8824 + + + 1751826381936 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + 39ad7e349fa9310a7b969d4ebab5282e + + + 1751826525320 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 8efbfe0ae1b0204fce1d374693fa71a4 + + + 1751826583001 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 28d360705ea6c4b2c2fe71ddd4ac747b + + + 1751826587218 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + 4688004b0c03d91e2da0b196f1c26a63 + + + 1751826894632 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + 8cbf36e069285329a3e6c103fadd2d15 + + + 1751827827801 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 474cb438a743ffd7c3e75d28317657f3 + + + 1751828982344 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 4ec6d444cdddc40c1917aba4da2ee7d0 + + + 1751872426393 + + UPDATE_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsid2lkdGgiOjIyMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJBOmZ1bmNhbGxfdGhyb3VnaHB1dF90ZXN0LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsid2lkdGgiOjIyMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJBOmZ1bmNhbGxfY3B1LnB5Iix0cnVlXQ== + + 72b043d710aeb2d0db300c844fe93875 + + + 1751873444149 + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwN19VMSIsdHJ1ZV0= + + 1e572e7163ea8ea7366929b360f9c466 + + + 1751874079320 + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwN19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwOF9VMSIsdHJ1ZV0= + + 10c8509625f2ef89d457feb1f2e446c0 + + + 1751880120514 + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwOF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwOV9VMSIsdHJ1ZV0= + + de8502fb8c760c95583f8b1c86af7ba4 + + + 1751880331938 + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwOV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMxMF9VMSIsdHJ1ZV0= + + 5e9de785196d432fb24f4e6ef3e3563a + + + 1751880478763 + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMxMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI5OGRkOGRkYi0xNDQxLTQ3NjItOGEwOS04MWUwYTliOGVmMmQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMxMV9VMSIsdHJ1ZV0= + + 169fdabd56823b7ad4dfcb02668b2355 + + + \ No newline at end of file diff --git a/measurements/Latency/cpymax.py b/measurements/Latency/cpymax.py new file mode 100644 index 0000000..5c767ea --- /dev/null +++ b/measurements/Latency/cpymax.py @@ -0,0 +1,29 @@ +import concore +import time +concore.delay = 0.01 +#Nsim = 100 +init_simtime_u = "[0.0, 0.0, 0.0]" +init_simtime_ym = "[0.0, 0.0, 0.0]" +minElasped = 10000000 +maxElasped = 0 +sumElasped = 0 +u = concore.initval(init_simtime_u) +wallclock1 = time.perf_counter() +while(concore.simtime + + + + + + + + + + + CZ:cpymax.py + + + + + + + + + + + F1:funcall_distributed.py + + + + + + + + + + + IN: + + + + + + + + + + Y + + + + + + + + + + + + U + + + + + + + + + + + + 0x2400_U3 + + + + + + + + 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 + + + 1666487497309 + + ADD_EDGE + W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= + + + DEL_EDGE + WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== + + 4957bb66f70bda073e7edafdad81f6b4 + + + 1666487500685 + + ADD_EDGE + W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== + + + DEL_EDGE + WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== + + c8d5e89e2630a4a0aa607594e14861d1 + + + 1666810339519 + + ADD_EDGE + W3sibGFiZWwiOiJVMiIsInNvdXJjZSI6ImFjZWUyZTJjLTFhOTEtNDg1OC1hYzdjLWNhMmNiM2YxZjQ3MCIsInRhcmdldCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjotOS40NzQ2NTYxODQ2MTU5NmUtOCwiYmVuZFdlaWdodCI6MC41MDAwMDAwMDAwMDA5Nzc3LCJiZW5kUG9pbnQiOnsieCI6NDkxLjU4ODIyNDQ2NjEyMTEsInkiOjEwMC42MzA4MzY3OTg1ODUxfX0sInNvdXJjZUlEIjoiZGIzMWJlM2YtM2U1OC00YzM2LTk3OWQtNDFmYjI4YWVmZTY4IiwidGFyZ2V0SUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImU2ZWZhMmIyLWI0NDItNDAwNi05NzQ5LTdlM2IyZDUxMzJmYiJ9XQ== + + + DEL_EDGE + WyJlNmVmYTJiMi1iNDQyLTQwMDYtOTc0OS03ZTNiMmQ1MTMyZmIiXQ== + + ead3ddf695580bca36da4698dfe89256 + + + 1666810339519 + + ADD_EDGE + W3sibGFiZWwiOiJZMiIsInNvdXJjZSI6IjA0YmZkMWI4LTkzYWYtNDQxZi1iNDZhLTMyMGZkMTA3NDBjOSIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmNDQzMzYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjozMC41NjQzMTU2MDk0NTE4NjQsImJlbmRXZWlnaHQiOjAuNTE0MzI5NzI5MzYyMTU2MywiYmVuZFBvaW50Ijp7IngiOjQyMi43NzE0OTAyODczNTc2NiwieSI6NjQuMDU1NTI3OTI5NTQ0ODd9fSwic291cmNlSUQiOiJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciLCJ0YXJnZXRJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInR5cGUiOiJvcmRpbiIsImlkIjoiOTE3MzNmNmItM2RlMy00MGFmLWJmMTQtMmJiNmNiYzQ5MGUyIn1d + + + DEL_EDGE + WyI5MTczM2Y2Yi0zZGUzLTQwYWYtYmYxNC0yYmI2Y2JjNDkwZTIiXQ== + + a86191957747741919dd1f5e71c2e56c + + + 1666810339519 + + ADD_NODE + WyJGMjpmdW5ib2R5LnB5Iix7IndpZHRoIjoxMjAsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MzM2LjAxODYzNzA4NTU4NjY1LCJ5IjoxMDAuOTM3NjkyNDQ1MzAzNDF9LHsiaWQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJsYWJlbCI6IkYyOmZ1bmJvZHkucHkiLCJ0eXBlIjoib3JkaW4iLCJzdHlsZSI6eyJ3aWR0aCI6MTIwLCJoZWlnaHQiOjUwLCJvcGFjaXR5IjoxLCJzaGFwZSI6InJlY3RhbmdsZSIsImJhY2tncm91bmRDb2xvciI6IiNmZmNjMDAiLCJib3JkZXJDb2xvciI6IiMwMDAiLCJib3JkZXJXaWR0aCI6MX19LCJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== + + + DEL_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiXQ== + + b3ce34b6dc8f697e5b8fdf374ec42075 + + + 1666810343268 + + ADD_NODE + WyJQWjpwbXB5bWF4LnB5Iix7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTg3LjE1NzgxMTg0NjY1NTYsInkiOjEwMC40NDIzMjkyNjUzNzgzNn0seyJpZCI6ImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyIsImxhYmVsIjoiUFo6cG1weW1heC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMzYsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImJkOTJmOWQ4LTdkNjMtNDJiMi05NjhiLTM5MDllZjRjNzIzNyJd + + + DEL_NODE + WyJiZDkyZjlkOC03ZDYzLTQyYjItOTY4Yi0zOTA5ZWY0YzcyMzciXQ== + + ab4fb226f0c49b8ded66436938762af7 + + + 1666810375461 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjExMSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsLnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + f5e56f793b1dfd259251f6b15ecf0e6a + + + 1748979732766 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsMi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcTIucHkiLHRydWVd + + 9e9aaedf5e2f34cef7d06d52891d6a76 + + + 1749058687416 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJ4IjotMzg4LCJ5IjoxMC43NzM2MjI4MjYyMzMxMDh9XQ== + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fSx7IngiOjEwMCwieSI6OTQuNzczNjIyODI2MjMzMTF9XQ== + + 7cb1d108692b66ae85dd0ffdcf639baf + + + 1749058691778 + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9LHsieCI6LTE3Ny43NzYyMDM1NDk0MjM4MywieSI6MTM2LjMyMDEyNzA2ODI1NjR9XQ== + + + SET_POS + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLHsieCI6LTE3Ny43NzYyMDM1NDk0MjM4MywieSI6MTM2LjMyMDEyNzA2ODI1NjR9LHsieCI6LTEzNy43NzYyMDM1NDk0MjM4MywieSI6OTEuMzIwMTI3MDY4MjU2NDF9XQ== + + 1ce2563fc9ee71151cb6a722255fd762 + + + 1749058702356 + + DEL_NODE + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiXQ== + + + ADD_NODE + WyJJTjoiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotNjMyLCJ5IjotMTQzfSx7fSwiNDA4YTVkNjUtZTc2My00NjcyLTlkYTgtZGVjOTEzNjFkY2RkIl0= + + 26f5f23f693921ed1b1ee5d52e1e75b6 + + + 1749058707709 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6LTU5OCwieSI6OTl9XQ== + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTU5OCwieSI6OTl9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 6ae6b59a08af5a7047a97a5ad388c270 + + + 1749058713842 + + DEL_EDGE + WyIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6IjQwOGE1ZDY1LWU3NjMtNDY3Mi05ZGE4LWRlYzkxMzYxZGNkZCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYifV0= + + cc747ad0ecc75c44cc3b6f6f9e9ae92c + + + 1749058727442 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTU5OCwieSI6OTl9LHsieCI6LTYxMiwieSI6LTEwMn1d + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYxMiwieSI6LTEwMn0seyJ4IjotNTk4LCJ5Ijo5OX1d + + fa49a13771e334eebbf112917f89d058 + + + 1749058754860 + + ADD_EDGE + W3sic291cmNlSUQiOiJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLCJ0YXJnZXRJRCI6IjQwOGE1ZDY1LWU3NjMtNDY3Mi05ZGE4LWRlYzkxMzYxZGNkZCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwidHlwZSI6Im9yZGluIiwic291cmNlIjoiYzI1ZDZiNjItNWQ2Ni00MDliLTk0YjEtZTZmZmI1ZjBmMTViIiwidGFyZ2V0IjoiNDA4YTVkNjUtZTc2My00NjcyLTlkYTgtZGVjOTEzNjFkY2RkIiwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLCJiZW5kV2VpZ2h0IjowLjUsImJlbmRQb2ludCI6eyJ4IjotNTI0Ljg0NzY3NTkxNDkzNTQsInkiOi01OC4xMTMxODg1ODY4ODM0NDZ9fSwiaWQiOiIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYifV0= + + + DEL_EDGE + WyIxMDhhZjJhMy1jOWQ3LTQwNWYtODg5MC1kOTFmOWU5NjYzZTYiXQ== + + 7f0f25f333a2a6cfc15a70a1634323f1 + + + 1749058756916 + + DEL_EDGE + WyJjNTQzMjlmMy0xMmQ1LTQ2ZTAtOTE3Zi02MGQ3NmI3OTQ1ZmIiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiMHgyNDAwX1kzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJjNTQzMjlmMy0xMmQ1LTQ2ZTAtOTE3Zi02MGQ3NmI3OTQ1ZmIifV0= + + fc1f4b789ad989f3e60a17bbe3a5bd5a + + + 1749058765759 + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYxMiwieSI6LTEwMn0seyJ4IjotNjMyLCJ5IjotMTQzfV0= + + + SET_POS + WyI0MDhhNWQ2NS1lNzYzLTQ2NzItOWRhOC1kZWM5MTM2MWRjZGQiLHsieCI6LTYzMiwieSI6LTE0M30seyJ4IjotNjEyLCJ5IjotMTAyfV0= + + 4209fecec5c91f476c4539fa06418efd + + + 1749058768670 + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fSx7IngiOi00ODcsInkiOjUwLjc3MzYyMjgyNjIzMzExfV0= + + + SET_POS + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsieCI6LTQ4NywieSI6NTAuNzczNjIyODI2MjMzMTF9LHsieCI6LTM4OCwieSI6MTAuNzczNjIyODI2MjMzMTA4fV0= + + 63797cc5d0c6dc2da5ef71e99504bd45 + + + 1749066909379 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9ZMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + 1ad516ce46689ac6f15b5532ff42ab86 + + + 1749070198710 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + f6a8e5aa88fff9e10e187a6f5d1b6b33 + + + 1749070471512 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + 9b54fffa96ec88de939b11febe6746d0 + + + 1749070605367 + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NTNjM2Y1Zi02NjY4LTRhYmEtYTUzNi0wYWVhMWM2NDNkYzgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + ae211e5c6a9ff5b2487f0e107ea136f1 + + + 1749325857360 + + UPDATE_EDGE + WyIwMjg4Nzc2NS1lNTA5LTQ3MjgtYWE1ZC1hZTBiYmJhMjkxMzQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyIwMjg4Nzc2NS1lNTA5LTQ3MjgtYWE1ZC1hZTBiYmJhMjkxMzQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwNV9VMyIsdHJ1ZV0= + + d42101a2e57f7e1fc75f9b867262a6a8 + + + 1751707047236 + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE1OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiLHsid2lkdGgiOjE5MywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMTpmdW5jYWxsX2Rpc3RyaWJ1dGVkLnB5Iix0cnVlXQ== + + ad7e56eb4e9610939329b1542aa0e868 + + + 1751708835442 + + UPDATE_EDGE + WyIxMWYyMGJhOC1lYWU5LTQ3YjktYTA0OC05NjBmODRlYWJhOWEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwNV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyIxMWYyMGJhOC1lYWU5LTQ3YjktYTA0OC05NjBmODRlYWJhOWEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + 16b71f5be7fb830dc4cb9ceea3f11ff0 + + + 1751709251435 + + UPDATE_EDGE + WyIxMWYyMGJhOC1lYWU5LTQ3YjktYTA0OC05NjBmODRlYWJhOWEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyIxMWYyMGJhOC1lYWU5LTQ3YjktYTA0OC05NjBmODRlYWJhOWEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + 8957f77c22449c1f4caabb7ca68ead37 + + + 1751709403095 + + UPDATE_EDGE + WyIxMWYyMGJhOC1lYWU5LTQ3YjktYTA0OC05NjBmODRlYWJhOWEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyIxMWYyMGJhOC1lYWU5LTQ3YjktYTA0OC05NjBmODRlYWJhOWEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + e85d0bc31c27cb6e02aeacdb333eaa29 + + + \ No newline at end of file diff --git a/measurements/Latency/distributed_server.graphml b/measurements/Latency/distributed_server.graphml new file mode 100644 index 0000000..852b689 --- /dev/null +++ b/measurements/Latency/distributed_server.graphml @@ -0,0 +1,520 @@ + + + + + + + + + + + + PZ:pmpymax.py + + + + + + + + + + + F2:funbody_distributed.py + + + + + + + + + + + OUT: + + + + + + + + + + Y2 + + + + + + + + + + + + U2 + + + + + + + + + + + + 0x2405_U3 + + + + + + + + 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 + + + 1666487497309 + + ADD_EDGE + W3sibGFiZWwiOiJZMSIsInNvdXJjZSI6IjdiNjljNmU2LTY0ZDEtNGQxZC1hODVkLThmODIwZGVhZTkyZSIsInRhcmdldCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiNmZjZkMDAiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjoyNS4wMTU2MDQ0Mzg0NDI0NywiYmVuZFdlaWdodCI6MC41MDcyNjEyODIxMTY0NTQyLCJiZW5kUG9pbnQiOnsieCI6MTg1Ljk0OTI3NTk2OTkwNjY3LCJ5Ijo2Ny4wNTc5Mjg3NTI0OTY3Mn19LCJzb3VyY2VJRCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInRhcmdldElEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidHlwZSI6Im9yZGluIiwiaWQiOiJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkifV0= + + + DEL_EDGE + WyJkYWRmMjgyOS1lMDEwLTRlMGQtYTNhNy1iYTdkYjg3OWM2NDkiXQ== + + 4957bb66f70bda073e7edafdad81f6b4 + + + 1666487500685 + + ADD_EDGE + W3sibGFiZWwiOiJVMSIsInNvdXJjZSI6IjZhYzczNmNiLWUyZmUtNGI4Mi04NzQ1LTUyZjkzNGYyZGYxMCIsInRhcmdldCI6ImRiMzFiZTNmLTNlNTgtNGMzNi05NzlkLTQxZmIyOGFlZmU2OCIsInN0eWxlIjp7ImJhY2tncm91bmRDb2xvciI6IiM3YzRkZmYiLCJ0aGlja25lc3MiOjEsInNoYXBlIjoic29saWQifSwiYmVuZERhdGEiOnsiYmVuZERpc3RhbmNlIjowLjAwMDAyNzg2ODE3Mzg2NTQ2NDAzLCJiZW5kV2VpZ2h0IjowLjUwMDAwMDAwNDAzMDUwNjYsImJlbmRQb2ludCI6eyJ4IjoyNDUuNzU5MzE4NTQyNzk0OTQsInkiOjk4LjU4MDQzNDE0NjM5NTE4fX0sInNvdXJjZUlEIjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwidGFyZ2V0SUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0eXBlIjoib3JkaW4iLCJpZCI6ImRlYzYzYTI5LWY1NWEtNGNmNy04OWIwLWQ3NjY2YzcyMmFkOSJ9XQ== + + + DEL_EDGE + WyJkZWM2M2EyOS1mNTVhLTRjZjctODliMC1kNzY2NmM3MjJhZDkiXQ== + + c8d5e89e2630a4a0aa607594e14861d1 + + + 1666810445211 + + ADD_EDGE + W3sibGFiZWwiOiJZIiwic291cmNlIjoiNTIzNjQxYTQtOTc1NS00NWVkLTlhMjUtYTExNDc2ZGUzN2EwIiwidGFyZ2V0IjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjI5LjE1NTExMDY3Mjg3NDI5NCwiYmVuZFdlaWdodCI6MC41MTMxNjc2Njk2NTEzNTEyLCJiZW5kUG9pbnQiOnsieCI6LTUwLjM1NTE2Njc0NzA3LCJ5Ijo1OC4xODI0NTg4NjkxNTA4NH19LCJzb3VyY2VJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInRhcmdldElEIjoiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIiwidHlwZSI6Im9yZGluIiwiaWQiOiI4YTE1ZmMyOC02ZjA5LTQ3MmYtYTk3Ni1jZmYzOWY3MzFjNjAifV0= + + + DEL_EDGE + WyI4YTE1ZmMyOC02ZjA5LTQ3MmYtYTk3Ni1jZmYzOWY3MzFjNjAiXQ== + + cfc129abe20d32f8c156301489dcc705 + + + 1666810445211 + + ADD_EDGE + W3sibGFiZWwiOiJVIiwic291cmNlIjoiZDA0MDg0OGYtNmE5NC00YWMyLWE0ZTItYTg4NzliNWY3ZmZiIiwidGFyZ2V0IjoiZjU2ZjhiMjQtNDFhNi00NWI0LTg4MmItNjU5NjA0MGI2YWYwIiwic3R5bGUiOnsiYmFja2dyb3VuZENvbG9yIjoiIzgyNzcxNyIsInRoaWNrbmVzcyI6MSwic2hhcGUiOiJzb2xpZCJ9LCJiZW5kRGF0YSI6eyJiZW5kRGlzdGFuY2UiOjAuMDAwMDE0ODc2MzcxMTExNjM4NDIsImJlbmRXZWlnaHQiOjAuNTAwMDAwMDAxMjIyMTMzNiwiYmVuZFBvaW50Ijp7IngiOjExLjYxMTg5ODIyNTI4ODk2OCwieSI6OTMuNDg5ODc5MjQ2Nzg1Mzl9fSwic291cmNlSUQiOiJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiLCJ0YXJnZXRJRCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsInR5cGUiOiJvcmRpbiIsImlkIjoiZTAxY2FiN2MtYzQ0Ni00OGRhLWI4OGUtN2Y5NjIwY2NkMjY5In1d + + + DEL_EDGE + WyJlMDFjYWI3Yy1jNDQ2LTQ4ZGEtYjg4ZS03Zjk2MjBjY2QyNjkiXQ== + + 9fbba2442b7019a76634710caf98a549 + + + 1666810445211 + + ADD_NODE + WyJGMTpmdW5jYWxsLnB5Iix7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTAwLCJ5Ijo5NC43NzM2MjI4MjYyMzMxMX0seyJpZCI6ImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCIsImxhYmVsIjoiRjE6ZnVuY2FsbC5weSIsInR5cGUiOiJvcmRpbiIsInN0eWxlIjp7IndpZHRoIjoxMTEsImhlaWdodCI6NTAsIm9wYWNpdHkiOjEsInNoYXBlIjoicmVjdGFuZ2xlIiwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfX0sImY1NmY4YjI0LTQxYTYtNDViNC04ODJiLTY1OTYwNDBiNmFmMCJd + + + DEL_NODE + WyJmNTZmOGIyNC00MWE2LTQ1YjQtODgyYi02NTk2MDQwYjZhZjAiXQ== + + de44f1ff4f2107a20e234361711eec91 + + + 1666810453165 + + ADD_NODE + WyJDWjpjcHltYXgucHkiLHsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjotMTM3Ljc3NjIwMzU0OTQyMzgzLCJ5Ijo5MS4zMjAxMjcwNjgyNTY0MX0seyJpZCI6ImQ5NWY3ODg3LTQyYmYtNGUxMi1hMDIyLTAyMTg2OTcwMWM2YSIsImxhYmVsIjoiQ1o6Y3B5bWF4LnB5IiwidHlwZSI6Im9yZGluIiwic3R5bGUiOnsid2lkdGgiOjEyMiwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9fSwiZDk1Zjc4ODctNDJiZi00ZTEyLWEwMjItMDIxODY5NzAxYzZhIl0= + + + DEL_NODE + WyJkOTVmNzg4Ny00MmJmLTRlMTItYTAyMi0wMjE4Njk3MDFjNmEiXQ== + + f1cb4196a5082cef004f9ee186c7f04b + + + 1666810462415 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEyMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + 9e9b34686b3aec97cf26547fcd7ae633 + + + 1748979705408 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjEzMCwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5Mi5weSIsdHJ1ZV0= + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + 299aef4ea2931f8b9a6b7f10361b0022 + + + 1749058646821 + + DEL_NODE + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiXQ== + + + ADD_NODE + WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTQzLCJ5IjoyNzF9LHt9LCI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiXQ== + + 51cf4c5701b1a8a637c1b373dcd09c59 + + + 1749058651133 + + SET_POS + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTQzLCJ5IjoyNzF9XQ== + + + SET_POS + WyI1MmU5NzQ5Mi1jY2VhLTQ4YTItOWRlZC1lMjM1ZTI0NTAzNTgiLHsieCI6MTQzLCJ5IjoyNzF9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 440d3083c9a571e9660685eaeefae6fb + + + 1749058659847 + + DEL_EDGE + WyJmYzY1ZTg0OC04OTJmLTQyZWQtYWU0OS1iYjhlYmQzODVmYjAiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLCJ0YXJnZXRJRCI6IjUyZTk3NDkyLWNjZWEtNDhhMi05ZGVkLWUyMzVlMjQ1MDM1OCIsImxhYmVsIjoiMHgyNDAwX1UzIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiJmYzY1ZTg0OC04OTJmLTQyZWQtYWU0OS1iYjhlYmQzODVmYjAifV0= + + 615e0be29af2a4940efea41e374438bb + + + 1749070207801 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMF9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + a8472011e18e50a782b19383b3b1a41d + + + 1749070480095 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMV9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + 4a9c6467598df6924c76f002eccbb822 + + + 1749070617114 + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwMl9VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyI2NjJjMmRkNS05YmNkLTQwZDItODJjZC1lNDViMDUxYWVlNmEiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + 2b2ace96e5b5dad90e06fbac4e20b915 + + + 1749322194657 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + dfbb291ab07456ce0005d5c6d1d6a18a + + + 1749325840799 + + UPDATE_EDGE + WyJlOTJlM2E5ZC1lOWEwLTQ5YzgtOWYyMC1iNWQ1MTM3M2EzZjYiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwM19VMyIsdHJ1ZV0= + + + UPDATE_EDGE + WyJlOTJlM2E5ZC1lOWEwLTQ5YzgtOWYyMC1iNWQ1MTM3M2EzZjYiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjQwNV9VMyIsdHJ1ZV0= + + 385fc34934650be854756424f6fac52e + + + 1749406730989 + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjE2OSwiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X3ptcTIucHkiLHRydWVd + + + UPDATE_NODE + WyJkYjMxYmUzZi0zZTU4LTRjMzYtOTc5ZC00MWZiMjhhZWZlNjgiLHsid2lkdGgiOjIxMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJGMjpmdW5ib2R5X2Rpc3RyaWJ1dGVkLnB5Iix0cnVlXQ== + + 3eae38f7266c77d8368676cbdc9b3ba5 + + + \ No newline at end of file diff --git a/measurements/Latency/figure3_latency_comparison.png b/measurements/Latency/figure3_latency_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..6aa3ca811bec5a4e7b9d6e071060346e0e1cd646 GIT binary patch literal 208612 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

G!qkLos@g6$N9H6T82|&Ms zD%N!@^+|b2fx@f=w8i)Vcub7$urGxI-uzwIH&sKMLR5|-K6Ah>YGgCS0VW}kA5;yi zh7&)bt3Qi-2k{%k$;tc+ZyX+rc?kEC8x##_vjPz3EM%Bf?LQo51&h~K>&g?c?xw81 zwxNSZ8&kOl!VX{^P+(EHGJ;gph}Le57auQJbrWz~N!7>~nH1IT#H%=0-c;x}oA&Lm zlIh#DRonj>4grX;ea&_TnbhMZW_aB2o&Nc|&#ylbr&G$w1D3H-D^h5F&*wV|g?}{h zO1uDJz8!z3{)0V@6meBJLJ?p*X$RvwC7NtUID@iWSsKDQeEQY`)!t649@1W0(6I^< z7!Yh8W2Nz!cOeB#*yGIWq$lKzfENl&cg42>Ais-HWVu0x#NN>ar|hK#w3KcJ3qbJ- z)x6!HaDG_6eM3X>qkOMvkQam!ov@IKxY$4X4AOUk*=|UNUQ+d(A{9p3A(UN8U>_Rw zro841FyN=X1Sp748=>+dZsW7M0|PW)Qi9E6EKWi@vw9|R0ursSU!f}u(k9MT}*VzpatSrL7vX3i3p(@Xa&2n6e*O9Yy zMhM+00vXu}oTLJMQKwGhM!;T00J3VjV;QU~Vw7f2TezOEqBfvP$ot6T??lnIO>qSC zlb^tUJkyS*le+~Qqtizz2=WO54N87{VbwMf1T)J3c`AXqj74XAUTFl2q7_LY3c`)N zxyAKjkHoDr$!kHaaK1bdvT+WbvMT93mBzh^3oZvd(z3;CW^`JNo|I`4J$ILhZ^FJw!UyaS!qo$Cu@MG}bP)+Jc(ah=M3Cr>wy#}oz5D$16cX7I) zFi?sW>r=7!^@C+$01+!t^gjMAz({Enap4fvD%oHEgoNmdK}zPyoA8cPB&unV7QwVh zpUHgxA^g>sHffZl?9UD7aknTz<7OtI6D9mj%>b_qBI0}rtRP~z)wg-DcI`nt)SW70KB#It?eL>!f8&I;yaM;xN$G5)^a;0Sj zlNU$aRpfA)!_iIKfK-+4#0b5@BRg9LT_Sp`OrkApNb5X&`bwT(^m;UIArjzln> zR+wv-53mU0Tq<)>)9HPP7ji9c8?MlsYq!Ega!<&j99Y-TJ|wx3^WcIA7+a(5FhiQa058D0)gZ(3C4r^Av_@EGRTTBt4NTmEBd1P5x zq{&;J$~#c+K>y%$-_vIt6vRQ7u~&9pc|_LP$fIgSnOlzi_9=MQGU{*~I)-@OI(47~ zWM1P1-p5Dn&s~K$N4l9I?QYXS0~MOa39?HreyVA3Ryx)dXtz||Zj^Sh&|+loF4-xm z5bZuUXXTE+qhL;}8ZHH*BZZ_>k8-AyBMW_Ks=(zby_`C>1Ptc)Cx?Jm)44eJVGA%; z34%vvUz4mXOO56ozkDP(#UQ@O64^qi-M;H-Zguli!_gf)m{K|P&3%GA*%E~QeVXtr3%e$PL2V!T;f2a*5SVlY zq%XY8i+}$dW4T6%$Y<~-mLVYuZae7j_BrOF*-K$74`IPOqoy<4t5c}AXq+T2U(3sy@qlm4jz-fWfW&LWan^tV*teE z4oig)wlXVy67v-|?^0i~ny9gZ%H! z0{QPApR5wySpm=~%Y z^KQB!;(0e6q!_Yj*387!jFi7y4NNJyPytIsyBbVmpu@VJpR%4Jk&gCpj^meZ8y3lw10X^AFCV222_V2*he`NELC2YPHpInf!%RB$1QimM=nsJ!R4s zaBayuH%b}L93j0?a)H9UQwk)!9HKr2imyO}5p9EaKsk#v%5<)CKoCW51td!~RhgK2 z`RlZWHwDogY@?@zEP$;83p}6efa?S$7dZRN$`eSpLKy^#X$74iE7sHTOJ;6>fc(j< z{dfcPuR}NmEvf$jB}o+VOUSXp4>N0b3Sngc(MsI2I9~4RGRw%B=L@GM90^DL**m8B zp4GYa_MJl2#f}758-`KB*2keE{+V+mWmsuMWgpA~_;m^5c3H5vc zr3_2o*5~G2E?TW}2I3XMxfRr*Qa0p@BpVPF|0mC%SqgHV421ux7!27*NjQ*+w0uqG z1j=C8VZU>lzVJPka)s%lZ^4{YK{drrwt6H?&&Z)BnT_#NT~WjO{)FP z8X1Q~7{612tJO*}9O}pn8H@+<`ZjWs34bD{2sew=hLoh^53CNNk#Or+qA&n8t3aHT#_Ae;=2UOQ^Q=y{D-4H}=CuK2! zDPw_y(=`sD{Y~J3@&Nrj>qg;IA=rZxi{LJil?Bmv5YxqK)Bx#KU&euQ0)vL)A_n>a z10u?l7vbyD+vA!awgb>UKn{-5T3$I4nMvxJP*+IFVtHxFcuqy1v5@5~1ce}5-y0U6O4e9@=RLRH z{aYKI6N9Svb$6`N-(K}PvPT$ZiQ-)!JP@A>&62OrQlB&|(uG(?rrwP?$%R#OCRp9w zhQuU!`plWO-YIcooCJ!l&UP-*8wL#Y!)s`nJgQoNLbieSGsEG}HqRA#AiZYkP%HlH zLXUxmh?a3M$(&zaUT&Wq4ouCf1eIo)bQp-nLa361;_#S`uNp)kJxP!H_NwJ5>)Wt3 zmJar_EQ$k=u{yJVk!hSFMwnGY39DoU&o_;uwWgm1MwfGTIN=yws|t!uRjYB-gx*8I z77`YR8Sg znj+5K*?I@fQ6i6VIRTzp^gR8=7)O83!V289z`MTE=}SOb$M6xKb@rLtEFK=ucs)`1 z65~h?sT0Gg6RNu(^**uU5tMv1I9{djZj0SI2(}XyQ6rloj8}$sp?gVkLIZu9Z0M6} zi`4_mSNANqJ(xO`!kZd2BY`72z7IZwoZ8KDjiYWobl%6%bnC1_ReH>!z&k-d+}YW= z1_8J2(j856gn<+NPMCNw%>l}P77Rdp6<~|xv#7ssV~eO4Y_!=I#x?rX(7b@LP)6+y z)+oiJoVl^y+j;;(f< z468`5RF+3H0qS1S1JH5b0>LZ$AH6zU(YL<0mk0AbGvZCfy01UA;jz|r-#x^NW9@uy5 zCvXKyrg3NMP{7G!FTSyLxIaikMN$ORK-P|?W{ZiH?JPQaPab%>0 zEs(=YWy3Z8=6$HoJo>{HtD43|fBp8*^GXlC9gc2FaZRG+FV!z0!U%@_2pKcJYgMAUx4fH?*JcrtuITA-vTQ2O0t+i2n~HUYYW{M~v)3%)IM2+7dRh5eV0&c| zL?+Czj$#bvrG8qWQJ5{p%r!LBKe@8Q~1O%FB-}K z_6Jq}6*eLoAHErh}>M}EV1iE%%r%OV~jW~}VJHIEADXp}2r#85^q!K$Sg%j+36 zC#}d;v4#jJ#LRs|a&~t%?5x{tQqJ1k;-vOL7UZbq=u7AIWBbJ5#JGzhbZ*3p%({MQ z$OmjA{2GY)nzuYc)h}#NY!J`73!9fXUth`jV#L%9Q=Y8BcH2qF81TxKhmHGzNQ*Iw zY!>Pd^dkm(8sm|Ht~C40+m6mRCF;Q1jvzYC>T32T1t4;;Nn|ZZQ{2(fQA{g;o`rl) z0UX1$pvqcr0QWo&y&7On)?>gQ-vbk0FNp+Yk;tG0)tx7XLW?^=R(Gl8*|k%ns|ekO z=!2lWz=7C*5)AzC!w+2njPWoy3bSiVi=R=?#X^p?6=o`P>KsTE#rJ)K>lWNdDYD1U zow<1NGumh|V!%~nsmE&qrBJ^3IDvvpI2r770w!|~*|=5t=rJHDgoid;Tj%FB;7RcW zIOJ$O1zq1+tl-EqU@Ir+hB56RZ(H^}5Evfr0)pgi9UWqn400Hs)9nAahutykdJ=-4 z-HnYM!)J(^ccRdL%dsN6qB5j#wE|}+Cmy;LMUS7ZVkGJcfc9rlZQMt@$3Z=+#06Ox zR-0uZc2|Hv!*OdO586H3uTom}6JIqUn*0tfW)_ZYBr|QZ&!Bq3{Y+=0gd<(&Vhvb7 zd)#Qw?zk0XlSO7Dyl6?F3GokDY&67MV)&a>bh%L*k_g7VSoUMRl2d}v1spR9!?qoH$QcQ=C1V5#xfq5s3R(1Rl&T5bBWQ*SdzJl4Fo%FXXAbT9|cr zM>Lu-uvAlX13^M}fN-Xc68s{qCh`3A(Vp|#tOh$*AiqZqv~$d1HfCxcx1n@V>l@@b z_HC3IRSed|h69;zanFAq*Mm8SR4BjKlR?oEYoc2O7iLxS+#mb?5`HA=d5iUe7MFx! zmsRYp(#3Bf-!yw%+O`Lex@D+^m)i?BvE!>6@zku8v(@F<=jV zG7yO<;c7Qz1Of70du@_uhkphuV9Unk*rV>S`tyjn1_0(5Hi#&?6U7^IPtY!1a((!8)_+YhkVb?&w>Zg|7+~dK{2!th?B($2^Dyj6EhJZEQ-rg=U5Mn z5rqT84l&5H;{4GNV^0b=@C|kI&pO@vH++B4kCOTTD>K1)J{ zqnRH)=<)8i<$vc?ix2n)ML^o=)2DCvA-^cG603bhE6V3v9N^c8SQL%o^?V)KE}oWm z2F~#IgFdK1imMwl?Utque(9yK!e4NDH1mUskw!;087&PvfMJO0$D#KmTA`&74*0#C zQ*`kTSaSpSj8LL8$ImGBmu*RPF-zJWq?~HwfnQAe@Fq&O9|oEMIG(D{E2Y62N%Z02 zVf%aG2;QQ43Ny%WYQ5t8Bpp*zEFCXzv*6&Ld~TW=`Q|+A%=jjDDu>i_Zh3|v!nk5q z+N+;aTd31Fbw8lUEgOVqq9}Bm`x%78_VJQHlrQCo$Clpgt&s1Q!vjF=bs6m<@W5&c zm6o|0Ik+${+=`z(U)uU~R)j60dg1FY#>0iPa1h8vdm!fGz}WI`yvJygf3>ef?@wD! zDUk`7_T^25c$zGJM2Jwi%3O#QLEQlQy#6tc{JKISUC^NniDShhPOGsAwMBaw%Kln@ za1|u*HQou2zt8RhLbIfQujO%8G^qM4y{QtjS*ot0LNB42G1(|#8Q?Z&JNS<;A7-Tm zh{!a(1VREwFP(?`IZ=zcPk5_z0RuOC>A|o;+rVX;2Cxq)x^`8`_g%I zh{lf6Vw4W$_|#*TnYc{4gV^`W!!49ZyJ!HFCEG`v=RYvqaFD|C5jsLjnC^LZuTK~# z4o67YzT3YUagGP7Sfpn=6>EXc&%518sp8WzEC2C397>aEJA%(mbfDV3@Hewkn$F}q zEZn<#=}TJBQ;jSdKs)2Er0j>n9p&xH%w?!A_c~-Fc-p^z*1WS13({R@{68q&+238G zxp*bQ{PL@kuBmu7iF@|8Rd)ZVIRft8u-{I*uL0u!Hj?qP#r}I?nv}^kUEC{_- zN+?)T&z`R@N=~C~Y}V3+tYAm6V>YG(;?#78TqLV8zDp`EON=013T0nwr$aiOH33Lz73sO8P(@`paW_$OK((2O|Eh>7ALe8 zU;yZ(r9RNt%O8)L#FtKp#!|vK%%0x_O5W*Zz`qt(Bh@7AdD8WcE$MWA*u98PGXDIl z2^}1dA|o^Y%Y0Ky@6}0jgKQq6*&#D3;+UZ5{rcs*5n9Ah`CEB&?vt*t5@q!10SvpD z`^=}zoU`lK&+YpU9H3Kqr6lejH`glx7qE{_&j|HIATV28aB1YC4hvt)pQ~{PA_L7O zOR_Q+h!$&n5{eQz;COLmANX{^Izbrq#g3z%hy^8{%elI~y8zMcyCqJPEuO8X0gO#X zBScteS-ZdLG=#Z(RB&Ck;|h(el!I~N4iu(5)$2ZjMpm$22C|2Zw-cTzYshHY5N7UV z0o=60-Th3P5313ztd8-Y@%!Asr+AGG;$qDD?-+ZDcX+iF9X*JAZ;Z~t4Y96$VB+)J zeKz=;1Y?*N>Y8VySB||#T4hS7p+j^52JwvJ<~z3cEZ~z3Yx;|D#QEv>&>?9Ql){G{ z3AlXb);oaHKSgF;pN{{LT{C8O&AbzaP?Ea)pWr6^kFQDi=&OlEuYYNoCa9G_wZqJ!`X~pzCd$&2mYrDT zG}N*TvOB9b*!O*&;m1X6ZXwpOO|PaWkIeYBzw#tgnYHgD)0<@nL`RH36J$3E5`#bDD4S>H;ZGVYPB%}2U?T$LQy5>C{See3w!q%VXMwjz9gzj=n*TX*i5PwD2d zQ~-|3)-_%NP@nIBtfTfgH-GH_>aWYMHlNU+7f`jvF{nGcc&ejSPS4)kZdbMBRNOo1 zZ39qy31@gbRtIS~Z9U0j?*0-tPq#~PhIFj6UlK9Wpl9M|vA{4~_X=(@OKjcWVTEO( zVrXdCo;2lBXqS3sTWS2B6%)Sk{q~MpPo0~_{i^zGG{-FjN=R0=e)7z4nYoSi88+(F z(c3a~Um0@10CkFOCN`63Btf?@f7R3T*uoyFv9q;3FWPsYG1y9|p>D?r)k}>|K^B}( zWt%Lp2q??Y`^*8>HA+M~3Fj4mX_J~}HoHf$V7UIm(Xp|kxn&td$>C%8>-J?AL^rDiw$Y z+*{Rhsv|Sb=c~B+*J%00u;C08PssnT zCiXvw53=@>B&P*h*@Ul|At!hK@%<3I)hTGM!WVkP`)$?toqypQf?-#$0-!XuSLZkyBhFbV+v#2?Ma;_B zvZ0DcA5}_L1wFqBc5%fWCpwKF-kqzXppo&vp@jN!HHZ4+#}X40_k8>?KBx`>L;|X6 zeflbs_H+2n=R!C5SNcpK2^(RHG$}fMal0Ccw^0ZRFT)lX`mluX{_Ps#HcGBniA#YI zjwGa9QTbo*1R;=WJF`qGZya|iQSYSf`RiQK0DuR(t1a=WRyE$JZL)V67Di#c$BP&A z1fEIxsggrWxru-v|ttAHkIm+uw;>&SQT+UuQj z3u7YcCEsCXpEt@Bc|-53>!39oEUG?unKu2v6zZP&hR z6vqshz&0*&EPPXMNCA)`9`B~Evv*xapkWJubV3qleki*wu4PgiE#p2J<7BkzfTs{K zt$l^KzvphU{uQ&1{b)m40ZnT37voon>bv2zlGP!&`67_5Plt@p8Tj(ytl&J4gzM(L zhi0e~H?PbP1ErYo>3$jpUtc3ML{{GOOk$$wvQycSf$-yyo&Rg_K5QvDmS&>HUx5|I zi?LEK?8>cN+@(nUd%k|2-C3Y*l;OuaFq=cG`1ovp-mrCjM=jvw+Ha+x+BN!PB!;#& z;xN!_HJbDH1KheZ>ZG~RtL04%Bp_N>3;`9^dSf)r#SNW+ef8F(9P$9tc*HUoQBi{B za{H=X;fSEnXqOelLJ>=-3)u{oDZUB!M^UvDl#*ZI1or^dZG7pZdg}a$6Xxqs1}KHL zf4c#5p9E~i#>_<9d4n|J%(m6~Pp1^*!E!7YhXnIVFC=Mm{X*oe*{CoA8-DCO#8cM1 z3J7v$Dx?1PBS@Fv{N?S>CP3UfzjRLE+M<@mtcybqdM`p~LWFE%<&E*E81xPSy$TNv zXd070_|x)ggK5Bgooqv^Fng1~merCHB!o-$I^A{)$3SVq+dYS|pT*EIoDjOX^p-Zu z6m}ubVZ-h54k&lXOKS$*1=Bj4oTHf^CK%aIZP(d*j=f8M6K*-NzQ>Q86jqd|?p0&% z90)t!p3~$wVZ?;xd)-`OM{FlEXV2}E{xJ)gvZkGh_}b_^}9V47eo!9qJZGmd12HDYC; z*crA#UIoZT-)0qQCw2+xRAMrU}yb186cyuR|}nDPz5f zW$X1jh;OYuH(ArpHKz!OvozV`_;e$f0g)CHaEV>pX^SUDtl=rshX{Y8hgk0L3w9&b z78}#C>(oD9`847i=vgWi2k{GTf}@r|C$haM=$G%OZoIbKpg0}PKaB;?)zPX04V&f) zBR$Af>A)qNJJDM9s$X;Q;sb;{jw0n)&H<;vWzb$45Oxvu6Hy?Z!`=SGVjt*H)!0Tv z21um7;aHbPj6LKGG)9wRP%BVUJkQXu?1oOlHs~QY?sM9*Wfoi|55oS_I>W_7c+s>6 z5fvgHlOmCzM^f(_-2%v(0!4D)T_4xbpU7-%;Jv^*Ai*BdG|0>kun{5nZy*4xRJ?*F zU?qwldc155?uNSGiap?rs;#{b@SYquQkB|&MTcm9aqy3 zHa2hB@`Gg$Hm~u|QuL{!t@D9YjSgHXizbx^8pQtVSd<@PdSIf?I*8p~dbdkK+w&7j zYHMHNDFt)VfI|UVAm{aUKL);#A8?U)CN z-9@Ea0igk)r@0&_P}1KMg$!?upP$z{@<|ImQJE+PrSV9D3H_t*zyCh*Gm29fGG}+< zsl;$J7cP9%L6ac5fY*g2v4TEybO8ahAnMoW?ZfWWKKGy59Xwc-N&?iJrFpto4=*rI z0JD&}wAur@90hK52=ExknJ7Yt7MtUeBtTfATA&?v^pPtpLNd|I0iBuuE9iTxG=Kwn zn1A7gr9m>ph8$HLDm4X4o{8g-MMvy9eBc1K>9xE2G_SrmQv^zmr!vm=L6q7`hrXQ{ zexX3>4DtsSq#XY{Zy$rQ#W3RWmSqp=PDC+VxmDzrP1%)lY)-7U@?YDV<~m!bR2ca zg$}^CH@WMf7SQz>6drTdw*3cZ2!ko!*h!bzWn#r?Y>BlYoE5&%P#gzi&tUO+NuWq{^o|&hGuJ#w74=q`Ai4!%MrAsP z>s@5v0HVuM7>@dj=O9Wz8(VZ15EkTj>3F*jls)H(BIS4=Zg_L5{m6tWyb&fRc=oA- z?@+=D5;!6lBjRR0qXtEK#n>n$d~+3|@+Y`=>^|tRV)-OV29Yb$4Le661uFb$tk)cJ zQSnxAx_Llj9vAkJkKQ5nXBp1eJ8-Nz1cAz{dMVgQIQN{`-2wxs3e5A(Lf7Y4{74CJ zTS`Sbfdjk_)oLD;Aw?wJrrkn00HyzzoEJITfn5?THi12Ah)P*G0rsGm=aL{_2wPf_ zDIcEM`=)9J$?56Sr_4FTa)4lO*xy->~YCwVK!c%e>q$vNG7nbEmKB-r7vI8L;jLBN%@=B z6lWrsbFa`Ln8LUAVlaX$$6*Y)t!_KIWsY-*Li@hh=a1t=Nj5eG2cXvQC@n*+;pkn0 zVqAC{aJ1kJneNMBfrSs?Y`dCM?NqrVuaQFKyVn^-E9h`V3&v^)sByhcXawlu#&O)8 zWrrBqiLYbV?KKOxWnQ>V|r({eBNml}PS#oS<>SME8B< zK#N!P0D*)d8*mvs4KnJ+DT)XvzQ^l4-XB7?n#BTT!bSz&3 zi8Vs#w8?B(*#FR)L^M^5@NYV0^VO=>5&h4hh8U)ah{bs5#dd;4j5h*A>5D)qOnai{ zUk9%1l0q=HT{*`6?Vkl}TjBW}W(mpxFk`f>mzBdQjd^!2vVCke!l?l$%ALT6jZvRm zR-Pjb-Bb#$b%wtkN`hH%Zf}MXGhu%j&9dkTL9k!#@_Ihrubxdfu=oFIAt4iCqJixY zER)Y5*UNwJ0DelDJDkuoGf5H9cvtv7-SQr%0*Qi7FwP{v?Pf*wAX(72P>N6|@CaGY zRR)QK)3ODNO>!r+>k77)Ad|uVykPxnub~C)Q2{jwryX+qA9tL&<1SUm9FP>0;h2O< zztIJ4!vn#i6$)g{6|)?nb7KR}0}rKWUjll|wG7|zOcn{a_=ETy4UGGIN+L`^yng!a zoHxW<6aerjJ)U+I`RpNg)^{H(DR7jNHm-+r6EkW-XHnuUC?O#SWlD^EaU|RD>@KEwBw~kIQ=)LYYbsH4oLHCxCQq z|K^qOAp4XM7Nvld9nQsp9u&Wl8X$&)mPPlZuAc(%t5{@6eVSLOr5r1@=9)Unl3ZHAWUZL2nc+Ha+}6cF~lkGyIfH;3Eze&C=3R&2kKgI=>#vB zG80n%Jm%Rp$4Q>i0Cz0tSO6z-ftbAN%gf$o%n;e}57(e=MngKMI*YHqifg u7Hxloi+?|iKf=YoAI1L%;o`=`f9SX0e^`G>&WN{Vx^9C}&KH0G_P+xKCAo+I literal 0 HcmV?d00001 diff --git a/measurements/Latency/funbody_distributed.py b/measurements/Latency/funbody_distributed.py new file mode 100644 index 0000000..eaae295 --- /dev/null +++ b/measurements/Latency/funbody_distributed.py @@ -0,0 +1,67 @@ +# funbody2_zmq.py +import time +import concore +import concore2 + +print("funbody using ZMQ via concore") + +# Initialize ZMQ REP port using concore +concore.init_zmq_port( + port_name=PORT_NAME_F2_OUT, + port_type="bind", + address= "tcp://0.0.0.0:" + PORT_F2_OUT, + socket_type_str="REP" +) + + +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" + +u_data_values = concore.initval(init_simtime_u_str) +ym_data_values = concore2.initval(init_simtime_ym_str) + +print(f"Initial u_data_values: {u_data_values}, ym_data_values: {ym_data_values}") +print(f"Max time: {concore.maxtime}") + +while concore2.simtime < concore.maxtime: + received_u_data = concore.read(PORT_NAME_F2_OUT, "u_signal", init_simtime_u_str) + + if not (isinstance(received_u_data, list) and len(received_u_data) > 0): + print(f"Error or invalid data received via ZMQ: {received_u_data}. Skipping iteration.") + time.sleep(concore.delay) + continue + + received_time = received_u_data[0] + if isinstance(received_time, (int, float)): + concore.simtime = received_time + u_data_values = received_u_data[1:] + else: + print(f"Warning: Received ZMQ data's first element is not time: {received_u_data}. Using data part as is.") + u_data_values = received_u_data[1:] if len(received_u_data) > 1 else [] + + # Assuming concore.oport['U2'] is a file port (e.g., to pmpymax.py) + if 'U2' in concore.oport: + concore.write(concore.oport['U2'], "u", u_data_values) + + old_concore2_simtime = concore2.simtime + while concore2.unchanged() or concore2.simtime <= old_concore2_simtime: + # Assuming concore.iport['Y2'] is a file port (e.g., from pmpymax.py) + ym_data_values = concore2.read(concore.iport['Y2'], "ym", init_simtime_ym_str) + # time.sleep(concore2.delay) # Optional delay + + ym_full_to_send = [concore2.simtime] + ym_data_values + + concore.write(PORT_NAME_F2_OUT, "ym_signal", ym_full_to_send) + + print(f"funbody u={u_data_values} ym={ym_data_values} time={concore2.simtime}") + +print("funbody retry=" + str(concore.retrycount)) + +concore.terminate_zmq() \ No newline at end of file diff --git a/measurements/Latency/funcall_distributed.py b/measurements/Latency/funcall_distributed.py new file mode 100644 index 0000000..779324f --- /dev/null +++ b/measurements/Latency/funcall_distributed.py @@ -0,0 +1,83 @@ +# funcall_distributed.py (MODIFIED FOR LATENCY MEASUREMENT) +import time +import concore +import concore2 +import csv # <--- ADDED: Import CSV library + +print("funcall using ZMQ via concore") + +# This assumes PORT_NAME_IN_F1, PORT_IN_F1 are defined elsewhere before this script runs +concore.init_zmq_port( + port_name=PORT_NAME_IN_F1, + port_type="connect", + address="tcp://192.168.0.109:" + PORT_IN_F1, # The IP address of the machine running funbody + socket_type_str="REQ" +) + +# Standard concore initializations +concore.delay = 0.07 +concore2.delay = 0.07 +concore2.inpath = concore.inpath +concore2.outpath = concore.outpath +concore2.simtime = 0 +concore.default_maxtime(100) # Recommend increasing this for more data points, e.g., 1000 +init_simtime_u_str = "[0.0, 0.0, 0.0]" +init_simtime_ym_str = "[0.0, 0.0, 0.0]" + +u = concore.initval(init_simtime_u_str) +ym = concore2.initval(init_simtime_ym_str) + +# --- ADDED: Initialize a list to store latency values --- +zeromq_latencies = [] + +print(f"Initial u: {u}, ym: {ym}, concore.simtime: {concore.simtime}, concore2.simtime: {concore2.simtime}") +print(f"Max time: {concore.maxtime}") + +while concore2.simtime < concore.maxtime: + while concore.unchanged(): + u = concore.read(concore.iport['U'], "u", init_simtime_u_str) + + data_to_send_u = [concore.simtime] + u + + # --- MODIFIED: Add timing logic around the ZMQ communication --- + start_time = time.perf_counter() + + concore.write(PORT_NAME_IN_F1, "u_signal", data_to_send_u) + received_ym_data = concore.read(PORT_NAME_IN_F1, "ym_signal", init_simtime_ym_str) + + end_time = time.perf_counter() + latency_ms = (end_time - start_time) * 1000 + zeromq_latencies.append(latency_ms) + # --- END OF MODIFICATION --- + + if isinstance(received_ym_data, list) and len(received_ym_data) > 0: + response_time = received_ym_data[0] + if isinstance(response_time, (int, float)): + concore2.simtime = response_time + ym = received_ym_data[1:] + else: + print(f"Warning: Received ZMQ data's first element is not time: {received_ym_data}. Using as is.") + ym = received_ym_data + else: + print(f"Warning: Received unexpected ZMQ data format: {received_ym_data}. Using default ym.") + ym = concore2.initval(init_simtime_ym_str) + + concore2.write(concore.oport['Y'], "ym", ym) + + print(f"funcall ZMQ u={u} ym={ym} time={concore2.simtime} | ZMQ Latency: {latency_ms:.4f} ms") + +print("funcall retry=" + str(concore.retrycount)) + +# --- ADDED: Save the collected latencies to a CSV file --- +# Discard the first few values as a "warm-up" +warmup_period = 5 +if len(zeromq_latencies) > warmup_period: + with open('zeromq_latencies.csv', 'w', newline='') as f: + writer = csv.writer(f) + writer.writerow(['Latency (ms)']) + for latency in zeromq_latencies[warmup_period:]: + writer.writerow([latency]) + print("Latency data saved to zeromq_latencies.csv") +# --- END OF ADDITION --- + +concore.terminate_zmq() \ No newline at end of file diff --git a/measurements/Latency/mediator_latencies.csv b/measurements/Latency/mediator_latencies.csv new file mode 100644 index 0000000..618fbf0 --- /dev/null +++ b/measurements/Latency/mediator_latencies.csv @@ -0,0 +1,101 @@ +Latency (ms) +5245.0712 +4292.6035 +5471.5328 +6784.5448 +4148.7699 +4148.7946 +6868.8192 +5651.1521 +3795.7884 +5313.8401 +3804.8735 +3801.4054 +4862.9434 +1630.0796 +1912.6233 +3656.5687 +2980.7533 +4971.3710 +3137.9639 +2381.5444 +6698.4732 +4161.3355 +4601.2923 +2362.8777 +3683.4259 +4666.3839 +2773.5096 +5063.5470 +3599.0420 +4062.4594 +3597.4401 +7278.4173 +4479.7542 +2913.4336 +5733.8174 +2668.7345 +4813.2954 +1560.4948 +2507.7209 +4795.2919 +5607.6999 +4757.0524 +4326.5276 +4048.3445 +2282.2170 +3420.2337 +3809.0418 +6085.6833 +5015.4274 +1855.4398 +4986.1260 +3922.3766 +3484.6170 +5417.5144 +6046.4993 +5896.9202 +3241.1737 +4036.1814 +4996.8951 +5963.3177 +3781.2386 +4221.5115 +2840.4975 +2705.6901 +5718.7887 +6534.3600 +4391.9848 +6005.2993 +5042.4540 +3532.3204 +5042.0934 +6807.0548 +4446.2609 +6846.9655 +1708.7055 +5732.8538 +4630.5706 +4051.4890 +4637.6412 +1518.6466 +4170.4922 +5035.6689 +6716.8411 +3722.5947 +3287.2596 +3747.3644 +5873.1032 +4993.1267 +3705.3597 +5269.9011 +4645.6163 +5952.9675 +3446.9204 +4008.5068 +3911.8378 +2304.7276 +4944.1804 +4891.5829 +4507.6702 +4148.1193 \ No newline at end of file diff --git a/measurements/Latency/plot_fig3(1).py b/measurements/Latency/plot_fig3(1).py new file mode 100644 index 0000000..6f441d1 --- /dev/null +++ b/measurements/Latency/plot_fig3(1).py @@ -0,0 +1,53 @@ +import pandas as pd +import seaborn as sns +import matplotlib.pyplot as plt + +def generate_comparison_plot(): + """ + Loads latency data for ZeroMQ and Mediator protocols, + and generates a comparative violin plot. + """ + try: + # Load the ZeroMQ latency data + df_zmq = pd.read_csv('zeromq_latencies.csv') + df_zmq['Protocol'] = 'ZeroMQ' + + # Load the Mediator latency data + df_mediator = pd.read_csv('mediator_latencies.csv') + df_mediator['Protocol'] = 'Mediator' + + except FileNotFoundError as e: + print(f"Error: Could not find a required CSV file. Make sure both 'zeromq_latencies.csv' and 'mediator_latencies.csv' are in the same directory.") + print(f"Details: {e}") + return + + # Combine both dataframes into a single one for plotting + df_combined = pd.concat([df_zmq, df_mediator], ignore_index=True) + + # Create the violin plot + print("Generating plot...") + plt.figure(figsize=(10, 8)) + sns.violinplot( + x='Protocol', + y='Latency (ms)', + data=df_combined, + palette={'ZeroMQ': '#4CAF50', 'Mediator': '#F44336'} + ) + + # Add plot details for the research paper + plt.title('Figure 3: Latency Distribution of Distributed Protocols', fontsize=16, pad=20) + plt.xlabel('Communication Protocol', fontsize=12) + plt.ylabel('Round-Trip Latency (ms)', fontsize=12) + plt.xticks(fontsize=12) + plt.yticks(fontsize=12) + plt.grid(True, which='major', linestyle='--', linewidth='0.5', color='grey') + + # Save the figure for your paper + plt.savefig('figure3_latency_comparison.png', dpi=300) + print("Plot saved as 'figure3_latency_comparison.png'") + + # Display the plot + plt.show() + +if __name__ == '__main__': + generate_comparison_plot() \ No newline at end of file diff --git a/measurements/Latency/plot_fig3(2).py b/measurements/Latency/plot_fig3(2).py new file mode 100644 index 0000000..70240a6 --- /dev/null +++ b/measurements/Latency/plot_fig3(2).py @@ -0,0 +1,38 @@ +import pandas as pd +import seaborn as sns +import matplotlib.pyplot as plt + +# Load the collected data +try: + df_zmq = pd.read_csv('zeromq_latencies.csv') + df_zmq['Protocol'] = 'ZeroMQ' # Add a column to identify the protocol +except FileNotFoundError: + print("Error: zeromq_latencies.csv not found. Please run the experiment first.") + exit() + +# It's good practice to filter out extreme outliers if they exist, +# for example, values over a certain threshold that might be due to a one-off system lag. +# For now, we will plot all the data. + +# Create the plot +plt.figure(figsize=(8, 7)) +sns.violinplot(x='Protocol', y='Latency (ms)', data=df_zmq, palette=['#4CAF50']) + +# Add details to the plot +plt.title('Latency Distribution of ZeroMQ Protocol', fontsize=16) +plt.xlabel('') +plt.ylabel('Round-Trip Latency (ms)', fontsize=12) +plt.grid(True, linestyle='--', alpha=0.6) +plt.xticks(fontsize=12) + +# Calculate and print statistics to include in your paper +median_val = df_zmq['Latency (ms)'].median() +mean_val = df_zmq['Latency (ms)'].mean() +std_val = df_zmq['Latency (ms)'].std() + +print(f"ZeroMQ Latency Stats:") +print(f" - Median: {median_val:.4f} ms") +print(f" - Mean: {mean_val:.4f} ms") +print(f" - Std Dev: {std_val:.4f} ms") + +plt.show() \ No newline at end of file diff --git a/measurements/Latency/pmpymax.py b/measurements/Latency/pmpymax.py new file mode 100644 index 0000000..9454f30 --- /dev/null +++ b/measurements/Latency/pmpymax.py @@ -0,0 +1,15 @@ +import concore + +concore.delay = 0.01 +#Nsim = 100 +init_simtime_u = "[0.0, 0.0, 0.0]" +init_simtime_ym = "[0.0, 0.0, 0.0]" + +ym = concore.initval(init_simtime_ym) +while(concore.simtimeIKf%mEl5IeCjk}-5J<4a;i3UH$d~(i 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

XY}1S>b-jOij}uH>$;|f{zpHp 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νcisp>_=&=1ZQN1RU+?|A(%( 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

jDR4&>onZMjlP@sw2eyY_+ zkThr1n>WboXVARhUxWFaAibB6!5M}VQOap}XweaJu z72&La$CVVOpP5G#4&;w93<fd@cOn`Xye|!mDPW`J3AUh-UbOK-GKs-iu zp2<=L=8tStVlvA#c>>;%xXq2#(HbhxoW$j7>{uG}KG%d4M1&?5GA@2D0j3Q#fR;7V zl?is6(xqCtK^ZIu-wZ-4=Du>(rb@uMYXUarizss(l>$IQ;-5%GASP|AhmB#e3Hks) z7@pr{Sp&M=c^jjSL@`3Lp2NBg1!?byEXdX3)=J6_(@wf|Im>v6y0K%m(KfW&C1RoR z?49(XBG$pM$LjnF5LgbqI30ZQqVI>w)F?GLSxB?!Uh=$Y0RSBIfKwTlRchMjPg}bX z)NUoU@N{FX5kR*)6KSUGiZK!_^wuzywVpKaqQ8J?U+iDHErS#;n{F-d>R9sN3k!7l zsSUc?aKjWR)vTgH{Z}6#eSC8-Di>F3NFu!CeoU##=bt89XEa+p4C-ik2b=&0aj9DS zXk=?;rK964Qf69!ivSv>o0+HeFjj^nXX{nl9bdJ7Jxmhz4Ya<(ZwDv>SGNee{Dv&n zO?C5Gi*;$nHw(Sc<`nL{LI^4b&&4nG*J`~dqq2e)C`wQ=uk0^wg)5#3x>Wr%^DI|? zt44VjI_olcq1tJy64XUAI74nKBY|iHyaPO?IQtEofXzy8^me>PGLJlXZhCeM7`#hs zSBqrC5OYajtL*SSeQs$QPUoiLXW?i0@5jY|UJ2muOt{!M4cnfXvc+-G10uNc_~cW} zXqCt%`iu`@1qDw{DWDIWY^GXrP&$nk+k@m7J_F;ef!PW*q{_rXS$vfm6D!D0r@yKT zWCNiv^GO(Y!D*`#X^t7bLM7`co^RS^zNWo>k+A}gJu>pwhv)26x(-tFtd>C(?zER0j z`~?MryWILDPjde9{z*<0LblZ2jDX7}CZ4)%O|pRd(CW!N{wnFHW5!;sc$7UfyBw|T zQNd>j>Ll=)E$d0M?PLt3H0;-)h%gnwCo;-j$*0<$_L2-Bd~n99% zc1yTXy3=VvRW{^+;hv^>_nbL%1BjHUExKi(D}!K}jii|yf--%F z$FRGe;NFbh4Cwd&@kQbI&*4sgFp$7Uzy$jd!?$X`HE=Z~ct{;q&=||NTHSl}4(PEw zJ1^p^rM4mJ$o?=F6mwhjc{WUWj5vMj%i9FxL!?uw_TU>%vtE zrEeBP!H;jr*fl%NbUN!zwVUPuHd@67E#0!)(+{l0*w7A7 z{|n-Ee?SU0lqtZj%YbMY?K+AQr)=_9lWvKZ6aWUwwx)# z+ZTtL+YOtD?EV)P^gnRW=QF+(yisahsw@2UTVhl|nHqGhJPJU?#O0!EVyR&6E`V;1 znf}_%aS+f&6)2Pt7ZR$_<31y`^?dcc)Ia0HGxsQk6nqs|scg0SkF=B8lFtmgViOB8@U-NE5*4!AcayCy^Y` z3@exe*t3mL4G8j$MyAknNrOMOCfX=_yoL|LjGMLCYYZ%G>mK*QVqgOleRUS({Cqu-X@>mmC;<{yHzg9XUR)#?bcwHdo z)83f`so5Ue*XYPhG#MivL4e7%^t5mNNt}*9u z=(J`zST$PaT-_158m%{kt0Wcwi?sV6-tNEeCak3Yf!0yvGHJ9dZdKtL|LaCQTc&~m zL6r7e{?oXA87|pzHw!913u3n^H9#I}faG>m9?Vd0?W)#NU;@pW{0Hhj`ECQs^uUr+ z6nKbbIHU~)3-rlP6y4KpU0niZ!F7 z*bik`;YO+x`r5?HM-P~hAxF7vymEm74FK6L?FC8Uu3=;sacu~D z_RrD}jLa~nzZA@29!0N14qX4E=)==jL)Y>?H(_|>%mSNL=cbr@gCcmYE4b^srwHu-qKLVGY^M zlm3^n!uaViIcf=ir>?h2K`yztp~0={jQ8a6{%YExcwi^+h+`C#Gvc8oNBML!Bv^KN zt$Eo%w0836iW>$CiILt+Q=`UxtBn(WxF$W#axs zX~kba<9qu%iqW9a%zmp#7=ww&1jF6+Q25YOICh>IHV`jgJE)rfbw!`j^8X?1Eug9j zx4mxzlu&6=x?$5H-6gfjz3Eay8l)QpX_4H(rc1iJLApb_ySqES#d+_2?>Xms-fzel z4jH;-J!`G`%xBL3{Qd8)?J=xvz}`7P#CG7GTbCeafTF2{w?Uok`I$se^GZqEH7z4N zo}60${9_aQ7V<~?s->iOIUMqmOIIe^s8-hYhF?9M)G)Xm`c;Nvq@h66Uou7-vaWU$ zfHPWaZ+0bY9O!y#b$fY~bSI(xS&z2TP&L2udjjXpbhe^Cu=!8ikvdAMd1{M1Et@+7 z&ZcvlNz&~>xIef;Z{y&{WpTC>u{sMCbPJ<7z!M%ooE3>{ovE+T?8_EYVyf%X9pGZ_ zezhpdAnnr#*MA!-qXRh9D~lC1)*7{4YFUe$;7rcS(sr=#8?a;_1xSHS(%j1;;m?kK zobnd5W$mz5JplfBqt1@67}!GRtBziAJt*u06syRKU_8nt`TdNITFZ;KKcK;BHqW!Q z8gIi-S`&3Wn_$zTHStzN=&G)@d{#{J_-sV3M6Ul7XuN*Nz62`rwR@E_U7x%Ha&D|3 zPluLzE>2sqZxi&u{4$L0BlqIXgRV+$Ie9dVqfvx$03{MpFiZK0r;1Wl0Jw`n&4Ua8 zwUG)%!l0oj#NK@{t+i!qw8GgDu(xMMBse+p_Y!iC-Zgx;~}VJ;DS> zT6lMFJ)2Awr5BOWq~hw0Wz`2p=>~eEm?(^Ld&M^Z*vFsZu7N~e-mfg(^})sP>lpx~ zWx;7YIrOIz-yd_eHe&=ZwtXLdvHp}(CV%mKGd+}hfb`QjM4q40C_JO*x7TyRjUZg6 z!aSH&!(HV{!qmOHU&3pA@t6_%m~r>W)c`{l`_{9G8FwLi;xbvaoP6Dfbe<-&4aQDx zHeFy4U$gQT?Nk~DB!lM7yJZ?uFADbOWz-`*cGMxnsvDpF=%0fMZn7UtGMLz;bS zu5ZY00C{dv&))PJfupVB3;Aa=8$3sw=?_DCJ@GA~`xYO(d|iOeLf#8wloigE z;l0MKUr#hipE~!!{~Sviiwh(S1}tu@2iYvRo&3}|E>YQ=#$=S$ zv2KZWD-rua3!o<6KN4{1fTFZS2muJF*X9klSAF^U9GCCicXP3p%LS2DC@|+~IA*H6 z_xp_N;`ehjKwXF%zEg-+LtnxRZ3I)T@*kRDoHOfT7qf^)2!!OY!!b%jF{X^}&dh224GK?Io23(Uu4_6nl8rsPG0nW5!dy){Ua7|v>I0I(s4q=R z&y0I=I}+c%7HY|L2h0$nqG&Z&?n}7$3x6M*G$gT8(?Jp!uX$`%=SmIpqJw@-S6aji zP;y#ME{2VG8R2a#gprEwUYC5YNupD=l;EY}a9OC+Dg^Libu+xU`TTQ?R##N8e@ZDI z)5}G@;m6WDAS9&{V4l?hfc0=Z(xo2%(CS>Q{0xoBaV71U=EvO8fMu-K%UpsbbDA9h zlsr~dm9GFmy#X$ZZ}Y>Yes2Z>8nbq-oi(4&CeG>Cfy8oUzj&G;sY~M@IsI}IF=}hK z^aY2%k*o4aa#RZ993J!pzxrvt(Jm=IT+E*PnpP2uQRue01B46y_(Xv_@j5FPCC&_- zNpNYOHoE>~h2}(n4f)5}wSn!+kc|DgamQL&^YmVB{xtqFbB*)FHt4DHm4e{xTv|?F z2qACRaUsCTS9?gvc)4$kZ1YRpqlgvYs|1b1RtS*j%0i~apnyqkXL#rBGZ{ESZ3x_O zz{s;L0OQLU#!b`BCaQN4F~4cJ1%~hDw`7lJMq&IOCWA?W2Hd4@Y%jX;93RZuL-yWX zkcHT=6v@tIn)02)RzAoH}Z|adlvCRH>?94GiAZVt_K9CzE#onNO>pbP>=E*#8*7G{&C-oaE_Tv;BXTot_g$i|;=L*yV|L z%*Q~`;vM+@3C?a7&4*iBDBJ;@uX_Orsn)g{pV>sAJKsN9VMG?tUvp?!Iv@CGF*qmK6+tae~Y4nn~~)MyEeOKa8w&GQla7pH^q_=(_5ZaS65Bw zIyTr?4XfDF{9w7ekRa}!Hpo~TIJke4&%ph_93M53>D;@;NIdAM7Ho2rt6W3`;TWB( zbF``n(aTd`8}*xohe#oyzC>QLY%>0nR{0|#iuc&F_1%8dK2N$kv4FXg!E*r#huYae z1t#wi;4Jw<0=X^9V08-0*lt-G0Uzi+BI$?LY2?CGCV#OoU4KYBAf5Y$(9 zJ{9ofS2R@y-Ix;Gn;X>09%=MQcRe}Qy100bCgISpx+nM-U;5){!Hp3`Qs?bw8drf6wB~)5i?8m}we~-T?FISzR+emB zb7obheyj&L&szy?&&SMqIeA&FRRC`c}cm@-Z3Otp4oos*+EO3)kZz?S!uHKR9R z^|+f1BoT3W4KRZN(kyGaNdXhJBz09=Dw9DfRYYVj=nk0c=6eSg>~4_?vxku^D+3UB zMf93?*`DLo8|l`AQY%SusVhmGx;obCIlXNqE1hlob9LFFUSiPL4@vNqqk*PJd5`0F z50%jd`9ltC!ZHv4Wpr4syjjg+gtgp1clLo&{9=p5w*U}8UnXq_8GN+LRV`xNG%R&G z8;fc8`BOFIUiV8rEyedtjEtX+f?}0~<(Fi2E(Epo0~fx_r|{FTU&yq(SRiqE){TKA z#T%KXD@D7lahx>-hW@1YcZ(da5NJMCreti4g;OUd&>L4Uk?n>AnvUfLhC7C0i(295 z4#>U})Co>zZl>w3`(MrEfAq|skbh+%f9#q&y9cW3BvE#RHcC-YQiWq+cY#v7Kxvr> z3`mrii!E96rdU(I@_%8oAfkdm1K#jqVwbxHyRpzTvlvTL0=8bgZ9Nq{$AxY}CG+`m z_1`GZ0=3ZE8{J(I3%ret=1TPIvX!$!CYv0S-Gd$fwMX$ke_CAr_^2RI12^#f2*^?7 z1Yyz!2GBUEh1FpHQ4$mT{3Gh}w;Cu5RZRke6j265K_KY*VjL<4{d0e;yn|REB))*v z1#|+nu3#j$gCD=?;Q^QAtUOwvs#*h`rZ(O<85Dp-Lw3dsIMGf7{uBOMYZVC);Q^}Z z7^8mdiv{;|vR^jn7>IhbEG*&1Ae)uvoMR25Y$!k)M-f%}yQD)3rTW6FJ}sr@t-AQ? zsEr!9gig0oVNJvrHPFR=J4mZdz*};*`1ALal;$ZBj9#`s})T)8P=ne=IgF(R9 zN6px?5SFNh55XCq|E&r1KMVZ(jU6t4iJhbyRj* z`o|?e|DTtD|9A;@!8w1b&Qw&Ckdcu*7z2Kl&R$1!6)>gh$9EXu<7jxvx7Y+VlGeij zC4_fs-r|NBxZw7j8X&K)sdp8+q0rs`L;LnmAou@kasbf#|G|u}K5n?~>D5~;P(?)$ zc!`nWorI;vT`WSZvbHl+i{UH$62q`PGL7IA@dg&v1#&y3b*F;?+;xMEcaSOV6*Yl> z3k3hvniD}Xz+qwkp|Xb0eMn1*_$--vDA!Gl?+=;V>afHOGT{tIvs7fUc@!-T zSOT1ZNDFXS^M7SQ!GHEnC_2;t}J~J9w1K!mO}PD%SkfqAI5p`>x4FrvvtDs7IBfo zp8Vx&)a4mFDY!e|E#mg}CGKl4I_&!Z^o*K};y2XU*gj|C9l>}A{xm+jsZL1{V;?`t zQZ&3MpUdV@>54qn`-(Nl0}9@=x>*zzQ|c${Q)7P7q-py z=YxbF1QVg~OY>#$k@ld@oM;%U5&M8J%EVGMZnrh#^l828A+Of*o~v|{M*QvP4ts(G ztzsT4(U*V#az!?*RJVnGeDp-$!8)8}bjlW(le{=%A8}@hD-Ra2>4zn5Q%ab;Ru-QX zZGg(8PWA5VRXE)baou}~pZ_3x6YK^;|J5cX z&7aLE;E7E&M|ae6Ng^PnVwZ!x)q}e6T~b*ottLyyo0(n12LuI58^76HCt}m#-z93GTz5@ zi_;{-(nS1@K}a6qe_wS5Y6VEk=qn`1^SbgVB!OETTo4mXev~>qhiswY>jxjuQILq& z<*y~TWg<$?64+M(b?N<_njg{e^?#g)!-yaivx{7Oe_0e@rM~{xvLGUk$QJE>uzE)( zAnprN&P`!*Zh;}mXWJ4%$oQPgjz1>{s3?Y;&dc;-^t=oO5&X(79@55-`Rh9ge6s>B zWRD7AgvtBl6vh^`JxKATKtnNKORE^n{RI^$SDI$aD~ zFo^Cyt%1ek8o($74<^^m$%7zbYoPFSXlBcs0LV(`ni);9dBEi_9f+Fgvh4?Ki|uSA zNH(KJHLUD-%t2=5@~?MIlEm-vEnH@aN<{gLl9MK8i+KgoTkFOD1ce{-rHcheq_G_Z zk^s>qFet-&Op(oTi8V4W)eY>izqG>nw`cbW@~Fo%b}F!JvSq1~=I^IHGB}jpFjJ*V zOdQ%{ekU-pfIO@e?kj&R>zo9^+{+rqK95>_VvF0XPpfJJeh=wVzcOtav-bJ>sy=y) zNr^T+pfA^_ow6#uZ?{=8K0DKbGqPzYuayjL+x1B`q`GwMz6iXk9JQ4`=M6{E8}+87 z;+%+&3gyl;p7{I6DsVo=3}qfVT`y{I;7;V~kCp|b<*QK{lufdQ@641qNi(pj)7iW< zwi6QxG@GScN}Z6LfcAVhar^Il5>kH;aMWC0+ix?y%Z?2zcsftu5w0oEu(dMMD39l? z_4#C_w->o7EtP5INim|Jn_zdvrQEOgdPoqYHPO`npQua?Zr0C@q7YQQLjL25!G!Dr zgCDR^&X9=&a%Ff@i1Gya9e-}3h>oj5PjySTRW45Jge@=qKchSl2MCo0+2e$y36oPe zo$;brPxvzpP)#z+VFU~qogk)j`Ez~IV}*WSW_B05q}5DTUvXa@eUHCKNZ=7LeY{WX z#zVicv9aO191INseCSHDC<6+TY#Dku5y{C`p)i>7Ppo{gfQYouZhtb6ASbvD<~Aqj zJ^rRZ7$EykuRsB{0#*xbgN1$04%qahA%RX}pT%3QKK#TU&FOMv!rRGFn50~eY`ZmK zwc8z|*c^tA|8c&TDT4pup(EzcG;L_N{tx>oI_2XhyMSf=nWK_uU0~a?rD;5o`M=Fj zT1KyiQa=pKn?d2;LX=TDNW|M|dQm74Ne{~<8|5|y0lfe8CLlj9!{g$PXi8L2reOY* z3T);^ky(ZFEJTyQn4Vn#@lgI(UO+e>Bu$Pm$_+9tFLJfW(yk!T-pTa$V3kdWU@8Z^ zo0(!-N^{89kzA62>l7}K)#V=@UBi$<3Yh$t^$|iHDm&zZ5kZCWw*YZ@l?*0d`}Qr4 z6y1N=7)ZP{fDOk76mzR3dL?E)9KeS*su(yQNwFCt1g8ZZiP7W?qu`_u>4;p5MJsXA znZ0c&?^_KS5RVUt?Nty6rD&4++m;}i5{;ED^*I;v(QFLvW<*o$J^Cv|G5iNpU+A`c z5`I(wG+dGkgJ)RQMClX}X|1=n7uSjo0##G%4OhK89N^iZhcIO%9it=5b6v^gca8cN zx&gJ3FMwrnEg-~FW!vcHULR`yz7Bvi*#K0lW53*HhE42qMgR`%wOH!8(1;c1Uw64) zTn2L~W?QH=U^o4w_}$h4x14R_K}>C&cZ*^q)!j8RGEzS-VZ6G;`` zN2Uu9)Y%J&Sc`t==P%<3>m1;o^_QX2 zO}?F$Mz)`g^l9A*I$eHO#>Ubz?oU2te8_fVY(CQZ+KiZ)lJfh5**Jam3<00rP+uH( zuNDA}pmp%0-TCcz`{V&AV_=2YwX`9xZ)GLPsj0r_WwU+|`>;?_X1ZI;+R>%|Z|NZc zzE>Q2CI!su#ry=12z>ZfNdXonj6#OfsI)3LPYTvPP2`jR*^-F_$yF1s7@k#9+a}(P zSx1ebXHN$b%Im-+{airmo>^V}j)GQ2N29zen1EdxehwAy|j8H_)GRwKT+u<`&H z>MAyIk`}!?@L?O^Ywh#Ut9;|U>=U@2la-uXx>R>_@qSl>?_BNQw!>`!uQ<$16qL;P zf!M8&RP&LW#ENj}FH9@YC*@EO@&Xnb?bV{D(Q2friJG^(G=(@~uK16bxOz9IyA*9; z(~kAHyN-=S7g_BI^*ANB1=`EoUvzYmrmBcjjeADn!1Z2aFd{;L%xZ zACU7)6qoI8n^GrPWid8Vb}s7Stz0?2GD6>tQ~g;?N~8qTKiPqQ+CIo==5bNC5DQF1 z$MWm$vBc=u4{`|sFruLQF}pG28un}+7(plcl{G@r2{754A2 za)c!QYsN+*ostP;Oz>@3Z03PQ8kP~93qJGi<-e$eOfOQ`B>I=zQfX)hd2n6c_7&o@}OTm1U;3O0*xcJD`OB01q^$va&h?k@U)u~Kla z$_5^?*9>4naRod+w;t)}%he?4%QRXp7yA}~BUuKiIN-3zaX_(X0}P+Wdm&|Eo!N7D zOjTR!j}%!6j=W+zKHEt)f6Jtk-;&~)wiy(h%~hZChDDS zBa@N}Wgop<;sJs{9|5=9DX&ze&_7Yu*1^wg4j(-;B5?&U z4&vl@Ib}}dvG;?=>8W_F1>w;339oX~rPDip zMwEIPg_(V!mP;@O+`Bfc>Tv2M$uCsl2Y~g|cJ7^FbMX7~{knsXPE>XsLVz^LNMys` zNgoiBJGgEREeX+C;gAM8tY(L&p4(VS1i#y_>hI|Z%1h?3h#Oy_7UGXLw>_#Ayj4`=;NmB28_QI#Pg)5Q7w z%|7bcQK6O30^`vcf67@q%fv;N;9d8D>UhsCx9#$P`uoAYvx%7LshpqqF|Hv8o)0$; zodb#1qH{nq&UZ4R{K3l8HOu!a&V>AKhE=kF^&L?mNep*X+ZtdO^`}JmcX?K#gT}0r z&)NCjOvUTAWCi!Fldm*OXG<>~vfWKh>6)~yk6b(ni89Wq1+N16ZGMfepYLAve5qh^ z*YQ4gE}Jw;DIk#CJp(kCuM?TV6NTW%gS?+_FKuRe-4~o+UED1R^6wHi68O*uqwYSb{@mL>CbediFuPkBA`!uWal)9EJ`DXiu~^R~c@l9}uIt~x_9@$KTv z>qaOOW&3)0Z#lOGo4MQN3Z8n8?pLvfKliuwCklCq75-_PMs(^lvJ1F;+vHjjV;m^58IXGCEv#2DP>~+eX z+yd)sWmZid4rkkA*VZDVfCui~d2^IevNMNW=zh&c(kFHVe^CeE8M$vPLUXflz1Sk$ zW&?&cnuwAVQ+aAQyL~`T4pTqzIj-GP&*jfso{1gr?@S zbF~7th{CJ?WixS5R|Q3SjRG;W53U$owC{3Jfa3|?yWUUg&2*n%dEGD$CL`G$UGVeU zy*jvezM$ojYw)bL;!VF$OuCu0_1k^LSZ!()Uv=rvjnH_=8oYz+N?>_Hto4uk{Ox~k zyH{@6V`f1m8)pE4!h4Ffr!!^-EJhewu1`lu(|_)T%}>X%)Szc95=OmLq;UaOm8y#1i$)DyQT+wWJMSMuC||1}@SS_s~Mc^z(6Gz^dGK zK%n#f;NiYV_W}^lQn`l%sI|ZaIhD8cYM+1?&Js|FoB6kV&nArCC(6jkxJpt2=IDzX zT%4I^^$3vsk3+vx{P7^((zIU6L5Oo;OHvcT$!Dx7~&+pI`Mtc9QsPUTiLEv}6@WMgIZA{ax_|BSufsy0k zj#Z6e?gCob($$T&V3nA0V&#pEy zTiEwyn(rltZKpzUAr$E%?DzR@D+@SDQS!(4zssa;Rizv-w+_|{T9#IV*yA}YIUXf4 zN7p~kuDccLp{nzkokKY9LqFPz4_T$JyCI+3&KZpA1PVTM7&jSzmsS^IKC}f(C8fJd z**qXbx(S{RiLOtZ6}?V;sF=_hnUy$bxGCHU&|(Ng@d2>`ypDnhKAwf9+nf8bj>_b3 zZXeL`>@LJ{wGDKfmV6Z=0V68Y0fKJok>byy{bLlbKZd+BdCRDgZNY1|iQe;)l9w3H z(GRY2ml{Y56}aw_Y|IBt*5-cyRH!vZ zUZ1}f{8~d5(wn!)`nw*LG4Yuepz8?Ygf7i(Si;=QvNLf`oW2brN8?)hC zMzDwbp%d$beDfJjk%U}M`4G!o2LptK4q({hIVHdEE`ksm_M8=$ndmT` z$p~cD>De&X+%O`yv9YmOtXOvajctpdFIy-}B2Ar^AK(4mckv#267k8*|1 zO+T3=?I^8E5{ap)E{wA_EKd$#Qp+&yGsUdxpAF$-zeG%TA|(izlNgI~@JD(ww!ty^|qLhd&u=VhWv#rop0czzwfeiOz1Y7XWWafFk zlT)^4Q_s8jSw~0ohkMe&nJoa6rNX_TH919f@V?1#8)`dY<%w^)ziU2MTR}xmZf=z7 zhch{pe4@|Xsu%RZp-J&@22pUEQa%l~IQZ}rpR@hWW9VZl(?lx+i#no*V7-@?9yPhd z+@#yBz_5vV`k7kwg5ZAe{w+RBcYC~5Jq8aC=f9j9QYz8EF=rfny&OC;eXj%*giVH0 zyuw#E4q?M$8`n$@6pS&RqA`={^IQOM!dT+X`zL6iqmXSg|5rYa(1&>kg$EsnPsv1; zx)=-=^i#w;8ID)|;N3w## z^3g%-a6BFZ<5_27=T$|+!>z2HmF?Mgx;n?DmE2z!zxhr^mM4}st(^0g7p!Wu(0f~3 zh&S7{J9A1kg_FzJGE=@<6U~l;+3y62cKUoGt=pq3qJO>TsIOaVmowh!3`XSZ_IoAU zwuZ6y(u>4S>j>QzQ7T8&-ezF-8}-{Zj;2PpP!LlmG>t%GUqhN-#^I*Z-d?%l)s%WV zBr?fyb4ZC19iw2Crq$fOwjN=Jsp+; zu4qT{7ya>qgTy1nzuhH`lb_b%#@np~Yro*nqzX?3ZxnTc$oEg4 zbUEZ`#~d8Jb-QQ2`tI2%lUBK&j8;?8CPV+{injJZ&2ykGnWb~us{QC*M}6r|Ab0bu zc#iX-LB`KO@?X-EWe$ZoBFN)R;yPSfD$t2La~iSriq)LMMmBH)7Ov2c`uryM9ecGW zF>kRIG;AAL7$tdru5MCiu68m>n>UY{G7bAnGVR40*>g+vLwJdQSnnn}CXGyC%4F!M z^Ua$nXUPDD7g6C!pV3Gb!dJB-_#{1a=L9w_R(yx^1dTW9Jl?-|5!hPUUY+b7I2cfk z{m2Kr&euw`x<7l+UwKP4Ql2t8yt*J&titZ|z){_p*6ZN6I63!xh%f(X<_a8z%x0FC zi@&XIe}5)h=dgFXf_OoVof$?aDScFXXibS04FhK1ZaQr?A~JSkmfIv%fr>W}%`Ik> z6J(g7C_(14+=jb_2)<7-a7Y8Zm?W;3!;{`pRaH?9t<{g`sj{R@OSouZ4XR`72393xDcfLcDy}aio zd}!)_Hb^V%b3;j0;3zsP+VB7&>BEiQqiLgEdjwyQ6PU7L{g$QEW&w+O(6MECAH^p- zr27Jahgjh~ovhw2{W)Im%s^Q33Hr+1pwrcz!nJGLP2$q_>c+#Z^GQ_XjXU-&A#|GQ z+Dmv;>&X*zZ7DHfsB703Rj2Q9flfn@-Ol*j;@YebK_Ksf?!&dJZ8v2M@FP%) zTwPzC2{WR1^>tcn?IXs-fB1#6{B42hUC#tNb?5EHUez6s`qpSor25G@-W=zPmFE0! zwQoY1wHC;<(flsA-nj7tPIJ|bW_{PodXdpOc)6R~h9FWK$N4~oMt-CU|^=LdEoq||7sDc>#Fdu1+x9@{geZOU^m-7B1v}{;|^e1!yHMaZAbxQQ(K(V z^SEp!j;#K;4zZtX!Sbp)w%UfmpCG$Bh(~-y#6y_t>NC6t85jU z#P3=I@sGZ{zTgDV0DkIK4vE6g91FfP`)(|~@Zq*(Wzeidsfc-vJVr+!EP%FG)+a&i zVE_c1*8Op_ney@vWgd4f<@i4w9$wAe)E(5$%--(A_upQjq7(6I%n<)@U*8CAwq;Yj zY4<=By`q4g17)TVi?kW^Ot4~V-NBE3qv`{jGoH<2)?gslkY->a#)aYC{_$DfDk$w7`hMwwe{Qr9%jbm3M~ zmj;vxMe?BpGj*CqGpIz0{I)z(`-x>1RdR%?oF-U)k`_$5kza?2x;YVw$*{bFF2kbVA=J86+2?xkez0 z#&nR*_Wc}WV5&b9dAJ6AWOpY*k@|SJQXZaoHtodhUTZbbYqK7H0!&jHX~)C$dzz9U zShMnuaI5bV$z)b1OTNE+UHWj@DL6;EXHhj5eF}%9OAXV-@zs&(2Uwh} zCQ#ec-&`C_v@MpLl`;&5!4Og3Uh6m5Zx__cW7bh0bIF|Yl}lS>xUbTU>(e^@bd=!F zOvnlee%bt+?&0X)Qalnfnp5 z{?pO)ABigpezs*OND#&Z?AGruf6Xw$qkzi$cLl>TjE<~SH(D|K{ZHaPJ>8a8yg$&# zQW@H^E78+gEgX2=rd^1;e-(0PhG}Ndl8l|{`-xo1$r9<|ps34G{Qi{d3^GK9Fk1EQ zPRYYunHb}_{&=z^v99?kxOQJ117~ZKyK##d5qm(Gdv?=|N&%f5Un zxvwT;Lw|9w6CiY{Wlp2}wX#JlRS%#O7ZGtp194mW3-zlc`EknGktkqL|MIMP=jN;* zC{+y*@qJaOi(;o+D6+iI;4KHLcmAHh_&;>rLE(wTD3^0c&SN2(cm|Nb<8X3V=eYs3 zxIMrn8Y@>++T>ow}39I^} zj}HWBd|y3hxjV>KC!+-Kk3v1}+J2ur83cJYCFmykU!)JVR{lOwP@&OPsIR%%Hx9`$ z4k#fgiT)@pg-ONJb}Q%Z~s8z@}*#0TVa1gIUTsCntO zan_I(2~+jDsqugElC2j#hvuILJoJhv(c)x&=*0HT5kr$zU^c#eZ3CXe?`OfG``yJ2 zxMi3FtYOm!Uy3@Vdq0yc!#b0Z5r!{=L9QT}08m=N!~Ecxvq!1g1DHS>%m}0JOr>XO z7k~BIk0}Ct#JNUwkDFm6pG&Z%zTNo?-ZsDSp6I(gTG`9O=h*bP3c|@`tWFsfMP|dA z*1cWEmHZ_zJP(ZeI2<%Kcr>Yf-ge^e_GY@bIpmfXFmXNI43S6UH5wpza64!`k-NOc z<1CSoZkeFg5ngCLBMlxtsIt_y&elDgC;!!Bbpe2qw?rpuY>j3RiTn8A<+_LOI%|n4 z%T}Ld6HHLX#R%(Vik_W^*K<#3yE2eD$=K~a&WyCI_{1?>K!au<=!$Mr`FHZm=vxT) z^h5bGZ`O8zk9>X6dNo@?u`*mEvu52K?DOcRckcu!QVk!^*f-}pFY%i&IO;l!ux@Pi zBR7O?sHOgFEOo@^ue$6YKeZs`%hN&@K!ZmO?iIp2q0Cp#B-~8|t5Ow%M3oYbCGt!Q zak~=Pse&IlRWNcjD$ETHmAozIYNgm1B8>X>bc8@3a@hFff6Zw-Y1IobQhp)kdv z5ZMCdM1qjX1#STQylMOw-k=F=flS*QuzWyJkRq9+eU}d}4lQrC3ve`)IS~LkeI}$U zJN~0jyN{^!Dl-kpo|A+F`7$FY1aU(HBQOn~(WOhO$&#(y9ff+DQ`&*lr|O-{?#8Pc zaV9PRw@Uf(b|M}(NnqbcMdg%a&=1$AHW5@^`qF2!!k`M5UY2^BfYS$fdx2tzu&HOc ziCycV#({ef7x$gz>gszk8}q4J_R2iV9|0@V%ImB&V0PM8Hu-@-0x-bXQ(|FuNU{0Z zg^$ZQ&>czL$?@94^L}dM?bYD&b^Y{aIyIr=DjT}eC~&*@ zoEO{K!<&BAMZD0epVtiY+`cm`b|%SxV;VQvb6+l}SAxj-SD#1WLkXjy%5#ve{&`R7 zZXcnl$lI7tRQwxvnTbb~xBh7ONp``@?Bt&<2J*nyfpdL{yn}#2J*A1DqfYG7(bYzB zm9E>7FK-4TUA&B-lO$l~dy{J0)lsO;ySLgsVeFKI5BbWypJsg>ETwtDN0L+LG8KqK zU_JvhFOWX@7x0xa&RPPcr(xyfmlNllO;vq6*)O{G3=3mp(FZc;>Xlfz-)Do$OW$Vr1-~5AO2Tl`{!A zw_s!Izc0Fol^4*_{9+c%QpEX1hSz4b*m>!I2@Xt=&A_krQiQouyo9&SUAN$C`|Y^8 zA0)v#>m{^G$e|$eGB2sEKV@0!4W>~hQ@K&x>FR8W%~lhI+G|9aKtcD#lGevB@i&)| z@;w&G`Ceb6%wRjRA7<1`J;q8NG_yQ=%cab|Z%k~vFEqG1`pV55!XUCLHx4ecdQ4pm zDybgLAIF+A)XS{m2efU#D<6OM0Xu{7IMD7{{QQpKV~hO-UxMAS6x_?&-8aeK=cRNh zR$8QbeOsA4QYT#eYm~5YQnT1|oXSB8|H2{5nuCIo=|%tBlDUh;=DQn5BnNjIK3DzX z#QfHi;qs2bC)~-0w>B3sC9>7B|JGi4jz9vA1sr=9weKV=68L#}XFdR0jy^zOXv50( z>Rw*Ef-*52ZHJ7#S@yTsbVj#1WFBrHE-;j$kmp(Q?GvRtImXFWCIc1PNURKq_BazV z@!BI?=-U%a>3D#$p?d+oX(jF(&4KjayWhOB!H(T2Yyj-8JKbKpg5@-lU!4)!0 zW3g_M7&y6P1#z5^J&^eFIkfaxD~~M6En_>1Mh&#glF@=~15W*_BGCT(Kj~=B9$Sc* zp*aZ-Cg_>pXyRy5Sg}s22EWrr;NfH%jPvJ&eav_Ro&4sAz5b|bxfLqie?td%wO@Y1X&)Dm zG9C`6r9_sD!ZXEmIY5y-AjGE$7~EjuILwg`LU~KSh!yr`xcONC4nB=CA~KTnK_cv` ziH);t3Sd9<%hF)*r(f*v_9cK8lC(<~_&30kMzjpdyn;zG0lL@6k$LBrZBVIq{Jxl2iU=n(R7rf!20w87vbu8> zur=CX?gb>jL}(N>A?<|R=?t0G8uXdFBvLy6=~@uHni!wG7Y3KK12BdI1#J4vNsSIG(AjFx!OJPeF(uf6QGu5WfJ1G(d&#^7WE2{V)*AUI}8FHrZn6@7c z4~?!StwzaPY*&~F_sB@lJe8k73M?K|q?PJ-w)3av1os}fw{e>tps>eXUmVEuI_{@1 zYS-%6drp*o*Q&8m1n$8WO5xVgO6T`|9>>B27`ahl${K*wkyXx9$v|178v?L_n>$5K znE-s7eDjFaXaJ0ef-U4KPA#99DTB-O0>+?LOrji`E0@s=%e=gFnl9VmoGxBsOGKlg ziSqtNLV|?!?7x5eEgLNK5glUAa`uKk(-hW3=vmU)-D_gXWcpAh7^`Ii2p&a=XdH{hhFGDZnf9IyJ?&yBWocW_0Hr%Uk#+ zw`gbzNFH+7|c{lFm(ET%BS^!?o6y z7US7!>vy&khP~Sa2ZyPxA3iNU(P(g~7}H_>@5TAArTV>q>=jIwIT=;t;;aVt($pgh zDwj!S+3`|@9zDClo_}4APh59m%}mQtsJBBr7+#POAq4gvIu`{7N)BxiRU3b^WRj7S z19=JKrrG5YH8BLh`*~X?YqU~#1gDlbJ(b!)RW`kIncy^^3@bGPoK~LDDHK2HPhf#? zZcU}X?2qN0sH;gpedei&pz#fUtpGS2>gtMu?_TKTp6Uj`OR;`pQGru{^pPUFqC!ll zot@YtdnS|W0uL$UCIXqVYQVEI6n}PMQ1D?_rJ#3u>E+KgI=*=8-D`VXadGAJ6WrN? zGaaXUM3>Wr(CfV&0D}i`4CpkP?jcPUzeN7+J*!s7=t9!#K@cnoc?SV=vrM$j!dj#- z!I@mYppwWIEbUR|IPHw?%;_TJ4s)ojs_#NlQ>9=G5UT6X4^pOMnXhl3h#D&cFBc07 z3k=zY>NNqELS6o$^NxxI060DAi&>)gd9#Q}VQFaOiE%ru%XO)H zeRqZn=B|ri#^}i54ajj80V6(-FTaW>`9w|8rbm1E;~D^tHtU%p(Pw&mZ-;IzA{N>9 z0!JEeJ^h_!Zg(%~XnHANo*UV;4frOeO$kwrWEY`*OrB;Hqx=2U#x-%;cTb{UsjYs^ z8YVcvL}E;m`?;XqAb;zr(}L#%A%M1+vEOa+MI8a2-Ewx^I{c3k5+m#V@!B(`GRrxT ztbl^d%LQK`je`SNYU!(!jja2->yb!#{+u;HKLiGF-Bo79N;LoU3O+t%vwcVg6fDYR zd{~fANfE!FQDQ;6lrU`-mJm;}6_^#l9}Q8~oD@j16`CoO->K!$$BJ%6)5p?iM$?x& zY!Hv;vd``fb@#05W{=n?e*B3ijzujuN_HFZ_5St>+WrF@L zF#kF?AEv7$9j$l5+){LS0Rc3YG*6F2w_9@q0SAIQE2g6#VVXTLOvC`_Gf~>df5g{z zV{2lrZc{>#iD&+JA|9R#a3G0}>kb;9mrO_xTDKqLlv7)x0haE;fCG1yZtY~EDKIlX zKQgj$JFMF9(LPrzhgGtb`FhD;HejPP9PqqZou0?Gd9dH<0EX~>HCk#`S^DmxU9XLl zTl2p4*LtNRL{3fy&_dr>Ox04-)YMnMVMl+SDTYw^{L}zQz&&)i`m5Db(%trQp*bQ6 z3pKXXfH6SGWI?&z*09~-qHt3*Zm`TxJoap*4Cy%VT7`82eq{<0%*nk(O}AQS!5QUk zjF9__T$x@zR9q0)5n3$@Y07WCRkD=dn<;! zn@*^O^sXfCzU2Ue6S-aew!bN4E9ONz_c7Fo|t*4k0tqp-Yh z0rO#DRWQ#34qGN8>%_*r@|py9GxEFF5jgI9#aq35LouSln=*!*GVdbKg*Q>L$P}HT zl?zm&Yzzj40rQe9AWt10&GCby>;hCQ{g-$jjFI&C3DW@z?tBsB%mjSiEizNqWRE)8 z_y_<6n_yDI8;8jNt;2&a&Un)yU0~XEfYdo4{o?jhtNuhfH#a4U9@TpC0Q8&fM^CzG z)%GhpLManIh7d?S_U#7h+}XdGUHA=hZ03@R`WXv4y4GdL#0&%QIVnIYHDnOgAb0$~ zV&v1u?Yyth%@4ke3*}JIi=YjU1${AVL0wg$6qcLQVXmT8rHRRP(j-!@k+j6|)lWRs zR8D90RlYG@%GI=c9|fX^Hd}~Pw7(oSxnFF5y6=+&BbNyIc8v5TFUfiRJr1#Fdw`lm zH4^QUZE`@vYNclJ%W?kSlzje0 zZZO1EMZ3{v>O)nC8zH(xN7HOsSlzCCVTf)Gb#j|M*M<$@+nc60%DF0vz>{0H{)IIF zlCDyqks&Yqp(Z5OQp?F*b@q&{Hss;#z1E1!?o3wE%^7dN&cyGF>p9njh8Hi`t>*bU zr-iw4TK&;>t^uhEZPm>YAl_)c``WSHYOtuX=JMbLXO)E(CGn5doNVOVM#f&RL)FY# zU+>@CO77fEdMC(-k_a)oy@MOHHojSuUyu2w-F`Y~z~0=qjQfq|8WJCh~p@;5+OQ=K?r8)l?- zUT{@r#sG`G{O4bma)h6V5CzxsfX#kBOn#x!9mfM(C4eC>jV@Z{kK=5i9<6hTeb|MY zG+huqOmj|$CX`l_t14HGA|_YqLshOKeQ3~|!K}DwhW!0}yu#~Ix}tq6j11OvHmVGG zf^;ZZ2p)Hj3rklL3d?~cqm z)aI3Wr4`MCp!BRxN8K>kDkma?fVI9ciR2wv8Y~S3WJHjgiwDb~QDD9s=iSh6o4`O* z-rl=LL1k{WF?9>B6<5N>v-fm>z6}nMUO0p(OS~ag4170{gx)nJF&-!rL1lJ-yCN^s zN6ZM+&`YNex$t5ZfNG6LA0e()BJw%G_}6i#dI72^w+;2-lK+pdw+@T4TigGY5CkP8 zr4a#<5)tXL5Ewvdq)P;(8G1laq(iBpl^A4bq#I-asiBAN9=hA_V!!X+zrCO5-M{1h zi$e|$@0t5vYhCB{xz1Bcd-)#69AtH%C`v=xX^2NHSDtax-Fd^STmyZ(!a?-6{PHVc z@0xd^&6Mv&a$CxQ?NPPs=1ipN$lkb5SEA72?aezW#FM{I4a{J&Yj<*VZqcUx(oT)2 zd%ws2u(kkqO3vrP5);RbROecPQPR;Njf&oewZ^l_MIb+YqI?+NVMMk3F{F}@?M3J` zNBF$URQ!RK)3b32>m+&p+Id&yNz+HgziS_HK`Vic;HpF2@z7z)VjcaX_eNdmPXkE8 z-RJ9t>b+AEuL1hy$4PxFlNu!4gi}^dR}c*`j?ZOgs=KzLO(uO8E_PAge0FbpCV=_P z0>U6%c!}A-abmtIh$QgeE)gh8dSLdeiWSQzMDvu)rbmP(!9n*qa(_5~sX@N~B7wxo z%|KFiWm-|A^Gw)wkc$h%Im&~I$U2rxruQ29l9K|XPa!k-l{RB8D<{7ul*KA^-qB_n zWBrcI6e&4mrxVg!iEm!l2xK&$d_K?~!+qZUtK{S9*Qv*EC8Rcn>+}yjNvPF2SsZoT z+&=l~CRs>CUM;7p{Z39!}nV;w67B%a%r#hTv2w>8qN zt>n`iX?)&&F7}BVZ?NoSw~i!`Djj=-4dJhQg;J!%%r*L}z<|uFnVg7!Lyrl1ew$x! z13LY%E5WDzM4|%k&6GZ)mxI8LrDO{`T5xNBH<@#Mf1uKdse`@ZArg>b8Y91Bz!By& zH*BfQZb~Yw18f88VDE*}SEObWFnjeh?Sfqe+BV9IppBbh`)q3J|3IVU-Ru2@TNRFsH9Jf zKhqfIp>dO2PPh24q4YqD<#%>w>li8W^K0^fe3KC`z6sI1x(DS$Z4;zi1k+H6-y#2k#0GMZ3B!X|?Jutl z$LbYwr*5!;f0vJH85L_g&Afa(hV(j#tLjU~g0h(=@=Li5D}*8*+l(#?nTELM6 z+%KVa(ud7oaVv+@o;%e$p5b(BzL~^aEwb*sr5e8HL5@&=d=SVD{K7xc{ zxFD`8R_b^sQ;%LSYwUdmBt>H6O=7lT?c35SoQI8L_#Mg+CGQ0)X3@F!mLVquzY_#~ zZo!E_RCM-hhuBOMqXZ1BPW*;l>6puq0=skR=VBSp4KIKezj^`B1%!M;I$EM~_Z^nY zmJFn%v@%P1RlKP(3-Ta6tVmuf1?1K);miD`cEdo7Sr?Q~Pgb-mUaQs|p8yHFaGS7>pgYE_yg(_on?z4$E&uu)hE6QJS| z5OP`5K1VieXBOt9qC=XDn$;g>yA_vyEbqG=l42CZ#b$^z^qBBN4zT_SplKuk@1wNM zXH^E>mJ%oN(V*-N$$Vb0yBRbk$eEdCq!1VqC?5z(fl!R9(BHU%a@D1%X89=fI6nQY zl_amVG{aTxd#qBjr`~j;Qlq>#x>F>xMBb{%ReYl2Q*T?Hnw*?ZcC;u3;b_U~jq3BE z61qj>P^}%P8_O2-GXG&OL9{OHOF6T!*J@DQoDxLTK3+uN3g342^w;9LCV!mP!6G#G za1AUaibF{~S$ubY*Gp`!jejADYU4D4`IR+R}mK&1k)MJ zm7wBUwH=}BFif?q{Idq0$F@mW-Tr~DheTQMPfR9~|MzyxV~@%m(SnalQYL3zr4KNy z22*lepN{>GiT5OCXJ;99A2_`!Y*4Eg|A30N^sJ3oYiU`TMTHbL@R)SDf=r1juWklI zzn~?v`C(KQA&+pE#7zOAG5?-f5kF!YkD>15-CY8D>U-ht7AlbN#EYXg?^TZTLd&S& zz`(*)9RhUnE?LOhTgwQG7HJb&zpw@Ou;E^nbCBDH%3$S`B4LskUPVjg&%^!{l0)z) zdawT5<(sHT@Guk@E~uZko2yHDt!i;ay%$|5N(s)x+YD4-$*_v1#w zR@*jW_;Nx|redn(4aDJr*=`e(!1Y*xSOA*Gi)d2J(1zf1ATH7^Y|G(R#Kbv9QLbLp zBwuU2C&ZW?ynRhEj4o78)!}Q1659z6EzvUVEl!$F=rZ;>neFJ_M<$EK&iH(%8As*G zXSlj4_=%1S&MkSydWCbT5hAVJZ>nwcBCucRUo^&MuAD4%uLNJMcBdnzOnKxY;bhb5 zWaVSwX{~>;!CziE7Q|(T;kK3bJ`1Uuf}I|mgfezQ59|J{p|8#{S)|gmew}N!jXZEn z=ND8Rq{%|5zu99iS27%K59`6J27*m4|E=_C%ZBv3d2RWzT~ltJZZ19U0XvY+K2L$V{QMqB0#i4 zY;J9maLGM0w%;R9qPCZs5A8t`@{le(9rpe=F;g1ue_p~rNzCvBP$>q+g>WRnlVJI5 zj~Gcl*uKn5RIxR)6zgmIiE4I5+J)|vuH8y@`i0*P#OAFBD|#unnJD82sE9PK@3l2C zXS*w+hsJ@p+OYppw<+Z6Oy(2fh4z?_-O1I{qm4(`Dc*c$3(4mDY)qm{q!VF5VXrrzpzp!GYvl27|W`bxxv@e?PX>!;&gIj;di1O z=6tDgiBR^#b%FRF8rY$#8~g*G-1NlIWBqJBf{)GS4|(5rw8{CiUC2qW`kfM^T3fMY zi^Lb-9vL;rG%0IR($g!t?;@sy^s9ep=8cxXPF?!P#Xf)b?`^n>TcQVn=(oqA1?6m~ zIkF0V9oVSjSTC6A2c*jd7KYuOJz562BZZdz9KpfCcOo5zhPJDWcQAhVyVo^e;LU#7 zx@DswYTvjo<+WVcg8!D9?sorH--4nuy2scVMG*I3`r!vM^`taYlR_zaJ{rDPU8AMf zi=rUHD^g{aA=vUJJ?Wv2Us5nxr4^z@(Sd~%2h+8bm-aRv<)Y=Bm%14na>ZEdB2)~4 zk$V<6VXQcky(ocVHB%qk;Ub<6p~<24=?UDjxkmr_N#jd z-C9-cJTzAeY@|<)vA6YJ17L1{cN;ic;<-xU7(W{p(vW60-u6H3U^}cgt0cS9bV&Zv zjJMq9&(#ER4BO$Od6s2uEs#yZbxrI|iS}#1)3TNj`Uafn>AKZ-9cXXwgU0K`$RuB`abz77 zLS)bl)qJIcX(?&TqmX|NatjPr^$lys1vQm6G@mN1ywT8w%=ojMSMQ9t=n+$%jT7nJ z$Vp-lh4JPvc`UPD80&JD>CFha`}COz0Hl(*KN*~3$|5lkJoNe1`-p~xVV;-J9GrF5cxb^ zEB23jR_}O#-Flq=l=>7ZlY1|!rr;M4ZxA^(rq|=$3#&;u?X>EwgNaS1AK~$J#GM+Z z#;d%E&=Oaf^zUYx*7@jLKx63DyI+NBZiaKL@)b<53jmuzDN*ACi#kHw&uiLw4;rGF7f~cC!`Xav| zqdQ_O|907f2-p|ekejz3J_~5E)Gkf3`k?X)Y3{(26S2>|OFl`|#Z9f6oX$2F`Ic&s zjnOJQOID$_?UQ=yiIwAKm6c$-)wW`)jKX;+G0-%H91@x>8N2| zrj1&T^j-mpQC$C>9A$8(xswDrvZ zkX>LTgIoKW=<1qvGO;jomR_KT`NNJ{`d8s|=;4JEf*KO8>PC0N0DzK6TEo23M@~zs zJ>4nP@QD$A#DrH!`Ou;#^A$o-hVe-?br<1PG8My1F|l6uyI!qJC-DLz4=Us#R&bVH z`JkZSpey~|48*L;vGO(6NnA^&;H~HRYJIpd#Q-HSLFN{OSP%&;gbKt=o}#^NCIYjA zy!DQaZkokry(xRQqW!T}#SVkUae+Am#hXpYp+z^-moDalPFp^@U`M+Im<3>T*vj-c4bA^cp5J(A@&N$oL=vA%f z;eq9^>evMJsz*3nCgEo~sSF|OAl7Us-xm=cQAj9cvT7J1W%YYx?B&Jc>6~JIyq@5{ z9gnW|`cg7h^fptrZVWY3(pNm-(&*YXHc{|Fet;uYm3t>j?+o@V#>grRYN8LUz8S3b zzp5QC|L%c5Kaf*vG8ny4I$*7jL}E7bbAz}zGW%+|r`lc*F<;c|*GS{f=uav)5(QFh zUf>@xYh2^6Vj%cr=mGJV3lly&FrFIO1YiRJ?MJFs`WaH)$l=y}?V_|5RoLmeD-x{! zMETMl-5oMj%{UYi0y>Is>?o@R=#ua>TCW9$b(?4cyRUCw!6qS^%_Lkp=Wo8>i#_n z?F4L!#|{^>XqoCvG(7Uhf=G&@|4!sb_GtM@M=I_~W8@?EKBR^g0LN;VCr~Yrfu9PJr4iI;dVA7O>=8+#W;x`6H#bKipWnX zQa%qDRl6z7PS?pDj7T%?mY_xR+)37K`{udSzAot~7}npF#zeICR4X*?L{jKhI^3SZ ztx0F+EbH5@W3C8;)wq)366Sxc;D5uWz5j%_)exdRiZL$tax8^=^lC#ygR=J~eZ0by z9N7>YtUc14o4`#yN6@4vZugDh@QKylasau=X_CfLEqAIg-w>?%ByBVO87~&bJmQ)= zw_RaV>#_exe*g4hDsLMH1)mM5lw{{%xBA)x)Yncya?}bC9$fWy2U_%Y8o!!V>SVWf zrEUh9qHuh3A1Ge6Gmy>-36w=qmoPjHla~soe|w9f_h5RdCOuQ$D@>%#ht?&*JSSI{ z(9L^i{<>P;uoz!ysXVNmS;WuZi1ptVH5M^@r{#t)kR0~FI+miE%jc9)%`4^!=%^IO_djUWE!&VTcuuG-Jjeah_)?^T_v*4R*o6uX1tH& z3Cx(JZdRwS*v*vNesOK3y%k1EC(<*@_1iOhi`k4AJ zOiaoKy5UbO3WyN8J;(;F4=Ga*G;5DLkfnqm!6#dF- zN5|Rb{G7i*L1iN&0r&27I0~GZRAO8LlEiEBFXVNOzvM(l-BSy7DQ0gRx2+Es^;c(0 z)dx=0L3TI@M~bbx0<0mWQ|a`*WH|X;X;!Vhy~pchk>-ON&1>S zzr2U`S3&6sQYv@nUk5H_B&OiFyXzLEY1U4x&VvEG()O;iBUF++rOyiJ2O~iU9*JlG zNi@bai z;@Tv*lEYu$*GRs8?zZI4+1wE)IgkAElR5rdzI`hriA4N|li3jTdY9fV!=our3DJ7d zi=MC8yBPU@Q-)-mSwK(#tpGk>P+lgToW?82%N0_>`zm#QX+EU|nJv(QEQ3|dvs$rl z+0PY}{7VP06ILMXTrOL<`bD;uEabLUU75{TCYIFoZM(>J>?~-ZE0#up?}-am-;e05W0Wl_B8Stv}J0B5r=9O_QvnCm?Dn2gJS84{>-9R8ZK}(>s#)B z;MJ{ZMFK%(k}Dz)z81tAl<;_)Suh|EO&jv80t3hUG=S8|Q3p|Kuoi*21Lr8*h;olX zt2PaXm|eYq(iH3!Ex}W$h-Lm$xh3fIwsz{JNORw%f2LXUS)#DrkbpZi?~e9y1-Tjz zw$VHp-E9Pc6r#T9L>%^h>`>~=f=Jfi(xSq6&Q!%FxX7l27<7dK6 zI+3;_5|`gkUpeVBGpBwV4r}*hl9)VEk=}ok+Q+98lasOL@^*e0EaAEs_sxtJn_;5Q z{o(84UM&hhQ8F>!w*5%XcXz46VQ$ZDtWa4{&dChsE{pAOnD~4;yf=q1gXv^+j0bYX zVlc*%d#F<}yq-87onmC1p}S79B$hS6y(XRIaCo(UdS^~WIpn#Zmed`iZ{D#*-kW39 zD$vz|UJIpz1B{q7$h{2vooILR^~AU3p}5JluTQT$llXOjy%<@D$kV{xw_H79)^Oq6 zR|Y|Bt@-e}=6fBWs-v&IqU==hobFiq;_Rt$I&rPqx7$y{SN;eq7E-MJdvoO(!G(vI zeR@!~_qjyA*LMb|gzH=!=`zYf`3AB=jajdS=C`lk9xKgnj~5bbqzit?X7=)y3lp&t zq$zbP=o9TDk-M*GpCCAAj(T<&2X0jFG|KpE-rd}}W?sEoBQGK+i8pkL_d0c~L zhC8H!o7^OAS--8uHTkD&EVmY4dlV;WqiS$Cvv_`v(U*@ex4+|kZJyjibS?ebaQO0t z{W`yyN9)7Mb3S-9qxj=kUM&MtS{jNzuZt25XZ6SbK>D zF|z!Rhx-wsq0RYDrTg7D_M&OJc3lz4y?p&6P8Piq(cZr{^x2EJ$NDlA_rnb@7UP8t zrS1pS(Z)%79`?kmS)2($qo@4#8^Z{()p!zz*TO>5qaGzSsFGpOf@qP>UFXPM$S<;R zL@qzOV(cBVs1joF*6r~3819L{Q*=5%6o_5EQrb-?jyXeJKP}L!7I-{yC3QTyRiPWJ z_Hk309{Er4_WbQ992g75-&%3$mg)X@*L$a7D{T`0mM12YWA=vyZ1Jj&9J@Q&6-yN% ztAQSmW1ztGfd-VS|Fxm~W^qx!Zv&}Q-lsSJlr^vT?5a}5Ui)iDRVnyNV0P$8jNQp2 zq*lD^fF@^%qmY@U<`w$04&l&va8MC(ymi*EZ?r#>r;HR7{s~Ubi8|lqS*EV@w3KN8}V7G z9JLy-Yuy^3yWQ}TP96rOxXsG@jin961u%I9f>2i^=XFI6zYfzD745hG4iWv6lM#|( zF%8P@ONjPs{bX?6=cBvH=in!kw?~P{k;d$qG761%?%M8F9{LVg& zd!Myf2shcLw-kWh+=}D7Xdz^|B3XpO)kQg&B>Q(z7z>MA4+hG=uxB1v(EM(8@rBTB z&zy8`fx6ZkuMa`dTD!Nd^X*KYMbl?&pMHI!{P5)FJ;|v7LVJnIANQ6OV{@Bh)#}$rZ^A}g)e7V} z`2WJBTtZ^>IJcieYC~w%pxkl25>bnZGB4a`7awxtAFTM`()-0#<>sXu(fNOV7T?rV zawSp8p}}s=9$~n%savc>Aiad2ug68LW=r#?{lAldM>(vKuP=3QpK%dI zjFD_J6Qqx1vxv&H&Ecct=M*IPz+H^i7I3`=M!~B_aRy=)1o{Xw?wXZIR4^^Z+esn zCC?a$IdY?`b0+Xh^$g6WdIG7`d&_m}|0XBFjZGH>TrzZEpYCr&(`#}On`Y049Y`4W zjJUN^C|JFnqJ5mP!-BZAuk1ynscLM$MEu<0j@8JUU~$@uMi;Au8t&9)_z9LPzVqdO zzXf4D+eZTCE(>$CYWuPff!1buu3?D7doEb`T&I-4eah-BhiE5`j8Mf?)*N`F>VrHJ zztu^6Y1SimdK)YDd@nk5;sLiscTzLv985O|uhW^${$;`W7Z^y!fFqm$FWzi#6+nD- z=Yl-;hd&8_@^%lI{?MX5BR&VOIYHqQx1p*@+T$!D+~mw(-#?b)m_PruX!ByrsbYsU z2o?Q#26473ZFHsfV$?dCS67p6f9svcab}!tJG3q1Z_oe#VyP@5c>g1Irz01>>L0r0 zLtYE8``c|Pvu+;dW6MH^xOLcHSPhQ^p3>jUEY^qrF3PQlyIIM}ZN#(D#h@pYuC$t_E{cgfI8mcWmepJEoJkwcxipv>8! zk9J46!u~v~>`j+b1Kgw~m?Rkhf7AzrwZHw_(p7Pl5QxU+D7ZoyywB^^%X=c6_D@B6 z`Cvai)V0p~+HLja0|hd_QldEB+PKVQ@A^hRF-2r=7}h9N?>NYDYvvOY>H!aPWCyyM!&<^)T`-G0T*&@lC)rWF* zsq*?7+>}nlK zH(Q6hV&}VrkXBt=+sojP5aN@B%Q44h7X6&PX1Ks3mvIp>$Gv-?$+i3jitShV_4(#X ztgexOzla|G4owD#a$S8a>ACk!)M@FYq+S!>G==u*TuXR*x?K1zT|_4PB|a$Tyevb* zZ_mPoHlRhCc!{y4VWjA&HJzm&{uyA zGTrYnRqGgpWVGsrY!{!>Zz_gjhAnF7CDGPJLq2bq?fl?$$e`>A7DW45e=I+i>aS~* zFa4*>rK!aPDXT%^&D0V~q1ll^Nul1UGE?!*&<0PMw7*jWXZ(oL>J~X(@^7wgCpKy` zZsaMAjch0vp0u1omr3wgb93`6L}&b?FQ_G40+Inf?j*a3Dk1$3{sba?$sk-IlH(4y zPUog^C!7;7wMEX9&FbH=FCinGuRy|^Bvah}axVq7n$y}K=8^QZ<}nd6J7Gr{#`&s` zZ#P^b`LPY1kY!)9#ba{%f zQn0KnqlI=2TGEUMw+v4K@MeXP;20SG8XPs|#;s+Xk|()qR_rpHAwNph!{_R{RBgGP zhN>bxuG%If6oAeN#F77H1@iT|^FP2iWxcC#=!51QMGwC|lvP&iJyuoBCVnW$@X&b4|o-dzODq-9OpO%o^?_X$)I6ZR=T3 zaBv#v7g?59f~1iCtW;YWhFm;P!DN2biU%<~8ec7xNymMdf$q9lC@emDBwj?JCOOkCyhK;ML)CHuQcyBs z0?cmH-nj*FWs$}?ydAO>IaAe}u3|?^so|Ez3!!CeCif%xxuQQrOnIH&)UTM{aBRu< z8{Y#6Xa6&kpj+(kP{C9s7HB4rSOVw0PAr^%xFe1)#f)aqt__(_>Lz4I%8~3g>y6Ksy&p+CHN*Uh#TcawHMCLkYlfO& zhcdSU3CVhB-eJplo3}g9RuaApo~YuUs9rzub9>XcstBmq>}&IG7=rNAQej(CJ-xV7 z?Z|kC&fZQ;9SK9eo(=u_-p^?1bUYfxa!~cX($8JlS>WCSujMUiqvN_+H^bHl z#&qD-*sIboU`Rwv+`rw1)W~}=Vr*G%dP)L1o4n3pyok>YG3a`fy1?{rQ@JZDF61C; zle_R(N<-qj>v{WM9z$@FNd3o2V$@_c*;NJ-Lohwfx+Q&pdD`Qot+1l_VUzS)%MW)L z_J@0|HBv`1ZD4$|bigaAekvz6p+BoE!FP^l;Jm=%W(+%zI`{%LOKrwtkAoliya;2! zx06+A{~{9N>)bLch}S|KceVE_upJjgQK&@HCLmpyuTa{*XpXIBp=9VwvZm zZFX6C$F(S*^L2mitzGVHS+e}Qxzt<+{Efy#!Cp9848N{4l4%)q%%Bp4j2nIkJQIy7qQT;%t$GQCDi39?fo}fEb z1@Pn44Q9MZKF_(ZZ0}Y;EyLquK@LewI%6O%exDMClbxL_k|zAbXz8sTVCP?rx$!cd zySMC)v(a`7OuibE(DgtI_KBk3gQw$d_go5WsHq`AVZ!Io?s*7Kja}9=jlxZ zZfE**D^%m>+b;T@m9g@IC&Rb=yAIT&=%_UM6R7r!-1FLzI(Z7n=j%wMhO^Lf;*%jw z;+byYYKv%(dQT0ZpW@*x-{0Q3cam!$H0UX5HLa$9PTKlD{+EnGsoHv{$stBfLcBqv-wR#hOFo zB7_li)JodJ8C_cic~97F7D)O2qnmMw ze)#%){s$`Xnb-LHccjC<_#>{tT#lDqUT+5S(-P+Ti%9~rpA&jZm22G;s+JQH%F(3~ zO4rrcPq|Q6+jPl8TwwAN62f;akIc}w5TlJI$eV51d-w8_&whWA%$kx?XsViSk8wNS zLGc^g0}hd#K~Zx1Q)|0FH~CVl9diraBAC+j9vj9Kf)2bSlP*NyV;gj4hJ7G`6tnEe zp=HbMsM}Dt)~sHRm4S>bg;c!oFlfw2^K}f#avYb!?~@xR`~butSA~LQjnYh%id5$I zkz~BHc8yyRF8x11$L-<>mTAoiU?pK%^{PKhsl0uCcg`!SMJd-M=@{7aot5p!)+X#4 z@gOF>PZ=f4rAf|=yMppyU`T2nE|_X0Cy}G%v9y0MW>+1G!N4RUHQq9?xlTvW3#u@= z9;}Uc048kRBr%V z*9b_OJH|QB)983AV{D;no|<*Io9X_O@-m!9e!}O^c_5kwna7pt*5o9;DDc z*!IAr9mHGbCJg<+Ga<@Q&qI!yC{U>FdSX7%8{Ujmdu>J1#sxYFnVXVis+-Ud)qYuJ zC9JAW?ObuU0=1;HyfSOHfev_gI_HrC?~bp6^G%GKW0NHe9F>> zl-l&aF!d7=iPh^Jlejw(diZu3jCf(RE2wxi2dsn_w_EcZ1p_p4Br&7{P_I=8y%b30 z(&N=Be%1vS_$BK&Jf?@OanSXeyZMJ&tz|!0o(IoX%>_%(G0Ozodu@FVyl#mqT8tL! z?~DwFEG>d3?RdBq`;Ol3m?$EIR@c|PqiBC7J>mkJ&>e-@0UoTYQpb}uLVxmxM&lc1 z0$6;&K%7m?Pe^YX*U3&rNL{XS-Bj&9ici>mhf*$ed~;POr*waSLz{cVVWXEVW~pO! zaENXV9S0_Lblj8xbJ)vy7%^;F<=rvF8(u|oacUT$_f>TeIfJ=UB9toO?#R8Cn~j~& zJ7#d3Ty+pO*Lk0_+W51QKLueYikRlnCZzsPz~}O(j49TK%`v2#AHkHyCwVTHxl8EE ztIJyBb>6Uvm27H)mBXLWVEvP~zZ`>2AzdqKid`G}x?P)Ua?DfsIw(-bK)#QL@z)9< zz$Auc?QoICM`_f9e8n@zkSlFc>%)|tck$c~vX{JzaN}*iYKGj|*z6YHR0mc^YJ{Kj zQoK(r1*2ENm;qM%Eu)Lcsz=36yu*|DLkL@A)E1EqrTDe zX03a`+_c{uf&(vFA5xCuQ0|-8qS5|ogb|sq{;`k6SjT@l!lPOZ(0&A)SWY(w4_b`f zN?)eO#rVNT(%5AQpY;)ntm`FW_5wn`!?cyK2}yG>qpB7+Pn_^_=lFPwB-0d!-@Bpt z6gK-%-o@Wo50K}VCxuQC&kp|*>#A<6el6eXg- z*>kbnXLGwnN>DQd_3J)`Zy#*_Oww>I-%F`hPsTm8d~!#-Y#Uk>QEAlZC263imy|wU zqEl$(n?HrGrK|Qf+(iPNEEyMS!Kv}Xo;9`X#f$JAxwz#If4>q*%%V~195siYCJ>E2 zv*>^%6W2N>hikx9%SfX4x@g ziaPPjDb$8Vd5v`0q9*4kFr6{z38K&mTBV20lmvB4W}Ju%Q;=L14=*k8_17rma?RI^ zP5OdvO9wfsKr}5ziC?;hB3b;VcE{JTq?Bvo!_d0pMcv6?Txd6ZSS#*`*~z{*+RxSz z$|K5_nqul*kp-rtx-II6@?pSiT*JIQdi!>k(%AGqyH-9W%`~tA)}1@@B&o<_9b5|O zGDlC^3F?M&&4pWRrkYke?0^MnHKPBsittfx@&f1Gj!GR!5%D@OlP;~9(F-C~t z>0TLZJLr1Glcsx*c%sP!KVL&nK)Q6x8*?ao0efFqR>EGf(+fa>(pTVkS+suajv;AL zfy<LF!w`8u_&WhW|hk7qYu7rVZ%@COIzv z#Pl6FJ76D@-7IlLDI^ozzRD1>?A1TBvy?ME zH)=7^$10Nhk0j6c)HEjmbD#ncqb3hNY_ahnNqTmH%HVO}7U7dZ_Z%CKhu{|}TRcZ^ z!F;G&=>4|&+*?e~KViS;FIBQ_#C1#ii%Nx6Cd^BsJy{Q{LXs>~C)uR=uaVHcWE6*H z3@>Z@VSfw`f?*9pS=9ddTO!%{8TZ-VI4GD->!CrHeII`^Bkj$^RrP7#MDCfQp$w!K z9NwLUSz;}LXAPp`Lo2A%`+t!}kZgHvFN?aG_|yTt6}Go6SG7q*b)U@T+$j{-n%__3 z9%?--U6ox?2MRu5hi`=W-hlqIj!Eo{=29aZivM59$5QP*qcQsn+-o&#!ryH@(K_MW98uq{n9ULNwuUWV*HvhV1+h1fb*&IiC-N>*CuN7^q}w!+R(;!Eqh#~* zl4QYHp_GdqINqeT$Fo&qp+>hO4P?Vi#@sWPWDi2M{I;&>+KQ_oeW{hnw zL$Wy-bQLz639PxAV`jfC<(Z_FpeT87Yt!3$^(t(3W2(hw6$YO@*h{b?iBby`F10t( z7b4B~7M$s8ZKjN(IFm=CZahA!goQYV7nv|~-?%#Lx;FgXaGr!wZ2rg3^3y}pKSMT0 z9pc|AYZ;eL_puhG>w`IQ>1cAc7urxuRz%fdMP0sE#JTv*EtM%cZ*XxlGo$hgbQL zz~a|`%(?I33alXbfiFQHc9Gxitk|q8&HH$tMt_s>Q7z|&Lllm*A&J=HEeXJYvG0%j zNH`3;b>>f0iJp9V9$SjLvZ3GIb!BVL*8}8LPODS$2<0}2-ka}6C z7T|&gkV9xTqLe#l@u(zpu|id2%UHP13JHZkpLYVJ)-2B+EB$<;vBALFGoj=*y z?d2o`>B6>BtMyvFNF80JE`v9Pd##gM-;-3pvLN($s355|));{9?^m;prw_12NTiwe z4>W|k1Eu(jdzQMdi!#=7%pD6>J1vHu3ZR~yL`hcni)EUi#B-(UPdCH|kx*`YEe0Wv zy?5A!WO~35JP)RP&8|S%n)L}lz{MxG{oUTM2gmh5QN~d7A(y=HgJe|Qp9^vH3DO95 z;Ty4M-Cr1nH3=gnXOr)~iJn1(y$A$n_zFh}WfBBH(sUaV^wAGb01IE0HSVr~Wg z2wxoTz+67%UG1^eNT30_AOFCz&SxK**(-eTw7o&279iA9+VJH!KZ(giiDlHhsTve? z9VCUrvA>`-+-%I?T)qIuHuNx?+vb!vPxiFccoz9%({(O|w?sy^Vb3+c5>js8v9tYheuJ)v}jYEji;yF}v zIE=S@se?+w@C9~>*sz{ddQY2w+YA)C*)8yg)M^b4Qoz0znpgS@rX%^u^P54f2a^6J z^8EBr7dqL97D^$^=)R69LrS;RH4%DryA_*f$*WXNTQVE&`23N6Fi+PZM9oO{9~U7w z1_0Gs%=t&30K$lO5a*LRF_|hvq4aZU^b)SgDlS-^Q~e>3{U1b6kO>Jn`o~tw6UW0b zb{kh*7ILB(&KUB&KnLw@@1zZ=Lc5cc9owpTt67V3!sp`20yCR@O7a40z8Y6pt;U5aN~GgIKcdCt&PX-0VA5> zV`Wkjfw4JrfP6R5Ln}-6DDytys}qjruRT2Q0t0gl#r3`)J_O`V9cZZDj^O<~+|?m< zZ7KeTgv;6wQ=Zf7Xu(I#TEL0e2z}|5w>in_v$sr6MNYmVh!(T|^C;t61R2q+vA`mN zf9;yvj92hNd^wLHTbapj%Aaqtxcz5d*C$QdL}3a<%h3^23GdKIbTXZ5+oP?Csp3e)oXU1jJ_ zv%I9;1*Dy7&1t5zd;Q7Ie#?iGCPx7JXuZ!gXAf;1ih;14&__Ut5}DkdeLXfm_lg(l z*gw8SL6JAMvwKx`5q5%lOI*bSrrTFVhK4%|YI3`i_qFF8m>~&88q}@hv-4=bLb-^P ze7F2JRJ1BS*jUHokI(+TlBZ^0uH@jL9YPCY+pz|U>vc4lqaWZ_6uSDQIa*Ksb7}SD z^c!ro2nQg>#_{(asZldB0v;$oI<5I`ANiQ^h3qft_lUQ=V=RtUO&jl1^h>_=U?hDX zrLB!PUABkbZKjCSdK$eU@b{!|OnbJOME#CNWb!+|N{R&DPG~r@bbf%ZVpuqJL>#t+ z#PioEL3JJdW7aX5H`ETt5NN#~E%kKm!N^J*KEQP9Jj8D2FTuP! zc+1KBCb5-_QeGlT9?3V07mA3vHZR%^Ul+Pv!>@YuHxR(LUJ{1|VY{5~_24VZ*-I55 zYNc~P?`N(x6Zo)#gXBtM-j%$O9N0QNzKklh%zl{zc>*tpjF~PW2F{HMMA3J!` zJy`Oznnae`;?jJpKYt#DPxLR3o`0Ql|ChPha+R5WL7{eO(bT9Lj!^Oppu-^X!h^!R zp9r;5Qs25}8+7~LSvf?iz0{N9IL+5d_j_=Y~Y9IakqK_m=hLyV{6hnIu0xfYY)K7CA9iYFRcYlr}uu4X7eu-73wo}-{F{nU47(Gx%i2eF^;@~=4F>-HukYk$-nw(;G%OtGq?rKC%7 z4*90avZ1_)1XC?35`R8wH71q?-T(g8)QkNC)u`SnMbc!>$vbp9av=7=a~N!LC`G1L zs&TKZ(qcE;tyY{FC*@aWL|&E%&mh&>P=MOJ421XWdcId7+%IFT{ZLCwG(Ppee=|&% zpIFRnyKvZ>p`32=%m?JAC-baXC8&X5Rss8kUyotm^7!~zBzI6G+7#oRJgaQ^?fjYOQwS?Y_!4QDGIjHy7T>zt|Jy)C8h#`X)QIoTRdO(`ol z?KL4!*jHJWS%+g(TH#Ngo<$s~vShy!cDvvhiP=QF5{}RK?>E3jXhtc3YDAAc%3Udn z!}(2#&_5dX2+l)@v4|j(q>9R_gKvT)`Kg-l$%LB=<=Zne8h1rC_?UaWJ+8qP_UtLmEkW(~RoDro}%kk|)uN1SC#tp?u>o&H>IU*J{;!DnJVlWHk_C#muM z6`eSIT70;1pZz+Zul{K&HeE-j0$P@&9(WOY%6f_1&S!3`j^OVgkUhIZ3myGI6u?z1 z%&?!C;DXSjrZfKMD_@*r=&4$kaz84B#xGVW&lq%D@7dLPohT35I8^&(9VB6Og%>U) zy^bEZY?|SW#S>BTyc9xeWdTm+<3M;8@RRHTPWH}|BdXnaR}JxqsQI1|cu%S56q|k5 zGK9r^CS~3jd#UiZ*M~*vl6ygI#(|b$`a#(0a-0H3rbHupJ0(b~Bl1;r?rrLv260e? zxYZclZ~r8-d_TT)cDJK2y2_EAyv~P}1>v2B;3Yd_XjZinKm^n9D+9l9Qo0OaQT95q z%m#WI%loG9vY+84TQkih?!vR|ebIeWw+xTZ+Llib4*vn1jX11TzBO?#Gp04T64oL0cxNN@PC{E(`0Sy3RS<|`cCIRU2lifnRHq5I~g?V?Uc zJ;rno>{%`?`(N{M`h5__`EzktzXE(+F(^y5 zllLc;4}UymqRl4j68D9humw^*O{1cCwS7IP5YU(YY8;4M312j8BNXAi><1=Ga~}U7 z5QqT-0%m4+Q79Dt&3;a1AE3FF^sL*xz~NZ-H+cRlkvvYowB^GOS~)qHVM-F2VLf~v z3}hgD^V4;T{YpvQn&KGN@$(WpUnZB=CyxXkNGv|7n%5XUq(=> z*LqOqF6Aeq27s5HG8juNnA%>a0&^T`BR|!~a}BP@9xSIvj3$cg#PJ&AD`o{>hfVV{+i;!omA1Hxa zgBvwPv6+!g=GR*@#R0TxMtOUhus{J+m`ITjRic*uXK@k=wXQeCC`uCuJ~%N!AfaUq zvj^i7AFkqF2LE{}nWyB&C=zx`SA+SH^uE0;wrkwAG{Y+Ddc?Y#k3>9g4qgZcmiTmzb zOxX%=XR5UHbKs^GxGR}()-c@!yqkLXH#H#TG=^%W$QU~IJyh%OeA^@+GOkS_s;k#2$t?#FM=Jz3jDTY{qX03l|W z@sb?Lq>__>+-a0z(QzwNV>lw@3ddV3+eZx&&JCC zA6;)97RT1Ld7mUifCLFnZ~_Df?he5{(71+R!Gk*l3+@oyp`mei3GNU)xHgSj<4wa? zdA@mP&Uxm{)%?+DQMIe~UVE*3{qCEMI2uQ@u(DwH4V|-QM?cX|lQF1IGP?otP-v*w zagVct=!tFQ`$8f)-Mq!HB`GMwC-45~iCHH4eMY^;7k}~q4XpsEIke1@ckCk|GZPZd zAAH-t;*Ho@%ko|Da558cIS>Vm5x~Y;Z(1%;s;M00z{pYn1adwIK)*Tx4b((8rU;1| zogzg8x3(?SmelhYPryXB4i8@e7eco5rsH;xv7Zo~fH}V<9u?@qAHvoZcc-Hbyy?xD z8i=Ldg(ewZ+B)cucXxMN%pK_`JY_2vzB>`OoIzuQ#o@GA`vB&Lx7Gj``Wz@ZB{O*I zp~dY1@21)6w64mzPuN|{#shyI!kM5}&FeFEy+dCSHQhX}@op8QV$ z;O4}uC|~xR+~?Yl+Xu;|?{BJ^tyZeVR*as@CdmF+V%xp!;r(#FS$013t1{cE>%HLC ziQWsTC}W?QpN{l`RC>dQ3w4a@AK2wJ1Pv)b1?-tD18}%0Q>Hu3iI)+Ja-etL? z&)Gb@T{QIK$3>9u%^=GDhLGpxmzy(F+-P5F8r1&^#(kYpfGh?(8~DgpMHxqBB$YxH z_w|(Oh}gR4Ol7lW?=P)7+#ewMXVV%bN05pi7-fa{m|-e##GJ;lb4lsSk(!v|v4*BDveLO%3iyQ_BW0A?uCVHap`L|LzZ9mUE ztUd^VE4y=@$ABuJ8y7%cz(~oSQ3f!@#_AvGu&enw={1 z0-)phPq!#fhf#N-M=Axr+B#KG02%tDHqaK@^B=kZW7D?99Ucup#V$gRIgaa=JdeHc z6TU*>kSkkXp|MqueI_dm=RFC5?Z2w0il0DsiZ+}6z}uV2I#;~+Ci&-HudmN)dD{D? zqP$jrMaGU|;u#hN7?)`zvS_ZDj|h9;zRL`E1%#I|U0`(K!%-5WWw7WcxA0vU%KL%4 zp-4{`l1vt#tz6`=(8Y8-TAKKEM1$Mu=ciQ5&Vs(twb2eT5wJ zlMO%XdU`r{HMO?;nTdQiF}~s zz1jNMy;*S1-b8uT-b{Pd-g0~Bo~I^7YbWXS*p;DH_O z1QTcS}59e;qtWukhW28QL+hEfN#_H;J(iz zarWB$c_wv*YV}H*^nDBNXH@M?wnvUzC)m9#GnZS)jW2Xyg_hwY@6cK@gGNq^xDN_M zd=1o}8ThsV(*wtn6vQpEuZz)C$U##9XL?Gvn0Euw?zLJRTbD+K& zth4sk#x6+c-#9>3pb)cJ2e`1NoZA54!&iltf&ICtbjWl4M z)^)C|tsVlsnKBf@A+(TP>9GQ|mhbJ`AFz`3kwEmNLA3f%AeVTSLWcvTJw-MHoUpow zD<96PVRCLg(bA@kNyev1Z`U3VD++F^ZvRyxH+SJ~xN1*<1=y{YJHK)maBx5rc^)hCC_QS_Bw`AFF?&-vki9unDN%9^yHerS z3cvc~)HwmU(dT?z9fnMGf6c1GZ|5emnkb6Q&dVXyou9+X3MOsXOg#tDOxR|+%-DLt zO5M^gHA8gs!tj}jGd=d`;kMZT^l2OZ*a+8ox%omvVC-c0>lCe`dJ4NKE)JI$rwz5d zR9D!5_{qtzTA5CrlfKNCA`f62uOU*R!Ee|HqO)BJrEd(?_VxkRvSPQ;4G+P_69^DY zE)^sAzxCpFSbs)$4$}YSWv^X7t@Ea0LP_CNeklYS(~|E8R5-#JwIknjFm5K!<_80t z=`73&+pJPDg1#*i*wknvQ=3KmX%&fedB1KuuHhCTXQn$7Rib;h@~TALk#%#m&OId+ zN~Z#VKkI%Rl$j4;v#0<9_dRO!0cBd8VW6%L5-}aZT_*QUtlOolumL=3G%{SDl{Z@c z{P_qd-@Kx=tp*@mmEX&?YrgNhVTz=G$gea&-VKlM{lSZE{iZ52QyfP^xuq&i0fAMi zFl;=lV(oK*M)|oGu|w}4>C~EBiO<8b_+K^7v2Djf_MWwO0BArRP=%NB_uN$90@CSJ zbz2kc9sM~t^0_N>37ObEQ&S87l4)Y0>=CnJ6RAM`z7GIlE%cpVyH8H&K1!bzbjvU! z5so_ZXis>j@?p+X#IQBg?nmSzP9Z{QGiaDq3q6Gs5cv1Iy}!CYxDuNAS>R7fun4aS z7zW}hpw?dF@0oMdkI=TV>%W;F+9I<|YBQmgOUNNUwIoWxuL6vg*0;2lPo z!q?f%unJ(WH~O65*nRkB21!YCjq3AHb%18!lmF1V)wHyV_Ape#fL8qcTbIBBTwx?X z7YLb>e7n#&IwVe%_WQkm2=j&Y6yy_T2r1jrAlTChmGnUFX+Rt8#d^_fq+)09qvpYW<J?XdVtG~~DJU!D(|Y0@v5ghcK?w9=xd0fNF^2NZ+)p#$Taq_h$!fKNK4 zHg}ydPEy>wA7qADQ}*Rk7S_PV_|6kigXEK#clq!6U5{FII(*u0FI()&*nPyv0io=8 z@+F_4V*7_6wAnjgPj=)=LQC+{$Xs#khY@2%NlI|+E6nIh51YmM$fNiaxA-u;ix{p_ zfpm=uZJS74T!|=Ifc@X7ZhLExc;Ilec(g3++(&wfwqywJ3>zH?+#o&^&(!yE{G-82 z^N`0FkI{wCZ;ARmk26+HDJ%OuJ$v3O-6O#vUm5Zm^x(tp?sD2Cc?FZNMn9P|6wnU} zf6NiDXD{o6aRkKV#>|4{-rhI1Z8OE@4jqz?eFZ^`%w}U=2Mb)icxg;&2hJ<*2)7$} zVMOquIi8EFa~sB8_jlPxb607O-Y$G7_g5)%#5?%9%E(6d8s&_uR_NW{ea!1S6p??_ zJp4+g{uDfbYO`BH=GVpjSLhI7Qc*d-2;yH&LBwBqgfny*bU5B?06XY(NH0Yp{zY&d zZYg->n5ba;va?EA(aW+VrES0HJ&ExigWio4Kz?y}7Qz-pfF4iGV|f7Y7w%Wt_@mp; z;?FC3VO_p>g5Jh+W4w^O$?;Wav!@5Ag*wH-k%Zl(vK+=@?ETXjg2U67J0QE{1!T6H zMWU2V`YQiJNORqiSD625aqvAn_|t~r)gf}eELx|*0;vAFxS(?x#K$Vyc>8_+k|G>I zBdfy%j<~xJ_Cb;7S4#TC6!ht6b^)N1nb!-jU93x!@zqyX>y~OcF!$j4|0;P3U^q{& z(I2hPj0?CjMA;ZC-%Z*Wx{6#wQ)?}zFd3+*x{A%K<3bsffxEjna(-vtkwXO`v{($AmXh7H^_zHlRsjsYPTDqe=;+d+_Yv*Mqplc}y0w4e+ zx9OQ8e25<8%CU8ux9SxHapdqcXV7-NoL57rglD%?k7fn`a7}a&-W@~1DA)*nghi19&;VhT)e^xphXotZf>P(Oi$ z3CchWW==B3_@K-+*lswRX+!c55$m-(+9PAvCJq9hyX(_iq0Y2#Y!_af_#oX+ zDW6$fhn17pc3Ci3By2BS{J#e{q;W%$+1S1A9&J4?B;qjVA5u(9;Skaw zTVaWE38%NyWclIEMwI03dBuNg^Z4~}z5qjhBYDc{Z@HoT*)mWFBcl26hnmz_>A1jk z69l%2Gsvt|xJGQk^1!&ox05CtU&zZuxeW+T90uIAKN5a6iz1h2q~)*FB`uA9J@PAx zT6dxqb*^;Q9JIa?)-xR6SgR8fyAo6?WV*~m&W1;3@~O)9%)S)}Z)=xycdg6fwB33#%5^AZcr_rZ1nmY)WlK5}jXfKEQSsYpcl7 ze>ywrv-|D*q>+U<`<$2zH-CypHa7s3zSlJ(4~OvB);lAHe~>=@+zdN^nyU`}^htWS zT9@B`OWvDn!jpk$Sbm)2w*1J>hF9(ImDHIA^-a^G-oPHWFlCvyt@2oU4)5MOYRD-l ze9(RzWHuxhVCE~Xs8gH!7ViVVIQ%BD@H&LPOTHc-(DD#ubbKAFdxFIpNXXEPQRNoW zAk{#J#dp)_p1IC+(7 zc#M`V6NF+oz*nfUrF#7%$1d49t{yT35N4|*W6Uk#N0lebCT1(GuE&fWuI47~LNI}o znJVZ`#zi5<8`|qCv(*nKSQ1sdX$SkU?@&7cSu?3mEqbo}fk$%7Fns)>n|aR7JMF9Y zGDF39o1=un;47Xbijy;JripeIuHc%?sYx1n=)PThROU((ES(XM!X*G5R_K#w`9(!q z<%nhH>w2!UcSqy6OXLE!^nFGvzs(}j1suT?&64e1jft2d5%!V}%g%(sHb=9ZH7V(C zlc@fjlzf{Jq3lLoyDl7oxMHcXEhQPA{Le2Ov$KM)zms27+iyy>5UX&#Gkj>cX7;?e z-!06-U#>8Cl3TC^7>?O>Av^mOPbBG1ENWn(UwV^$SVjBOeU{4+gUUV(zW4Apw#EIk zXArNmUV^MeN}%5&5r~QP(#Ij52;DuiFQ~_ROqHxunk(l<0x-7RaI4u&Vu*+8U(HM^bRZOd_RUm*Cr<~ z+?AcYk2+=Y@UFSEXK!!(Rx>;uyG%n`c?}Ma#Sgsa_Pg269d|pqH1u-GWMGG_?r?kN z*!=)jnsGsRgix>#@^%B^sNV%&mwQd|H&>zGbErGVTxzNK*N=DxAYF0NfH}G8;6^X| z;W_rTVxX^wxSjvgU?ej80pluvO^x&O9t6Hd$K{#rPI9k`sdQ{ripnntCM#nV@x|SS zVUF{!TpMW>V1qU<*B<TO|gJib4pT_-$nbJW!tj)Ai`A|Hv^@D%DfF;oH$(TeK`+Kwt4WlF>GD{^YM8v zR~%R9nm2Ud!yavxYiJQLV}TFu&t<2gmii}6FJ>H4HNHF6i@P~$ytzZes5s@NE z4c3Er9fdTsDUMDia3DvDj(<#Xj@l~E;gVi8n5P?Y3yljYF*5TjwyjTh49}PE4k`)o zFn=DR&px?tzRE*p*xwfK*R|nmCXSDqUWZ_#_BUUFrmFj&FpED+>ktAVFZed=!q%A8 z4yNlJOgE;r3+p=B(;83l)>GbeTYiy|!QDpK|@5ogy|6 z#ShFBIPB{rYkzxvY2=HE2%#@zSRIkoj{O3G7>|(TAM3MvxAOTe@N(GoSx9M&l6}$` zJ+jM8=K3kle=^^n9K6m}=df*Wc3PXKSX?$#xDC6Ihqm0E4QKeS z&Ruu^&ZyQPc+@A9lcClQ9lm_8&?Mhf;u`8HvR6=T)cwqJWwjH1pzRQ-fcx$Cl_n??Q@wgHN!lu&6JmzVYT+)@{LERKxI6SVNEVM7n zr@rgttvEMVLr{)+ufMPX%z+Po{6y=ch1E3&N0(Q%H6CH9;7?TXHSwvBE$-^BYT{wl z>g3%j?3PqlRcJB454+}u=5=M3dpgX-tE|2e7~4hM!ON@0)4I@%ckcuv#K|QNB>Q`_ z=%@xpX!G?gr_fw(pYXOvw@c@1By{t^(m@5|dC_XOB0w8(-jK_3FgUx(eS3R43I=a{ zW|LZ6U&z^6XJuIH?P|S>%@Lh$<$#_o0{D&MWEM`jDp%B9CN~eBCKoF}tzL<|E2Lp> z&|E+A3&Kp+wQZu=CYk9#SBaqo{OTyq=*<>8pOYUPObS+?#U|Ut+Fu>GlT1o4&z1S8 zDhVLcYmDoe8lC)VP{}}5z>RoJfY-2uDBVT$j?$Hv}WF`fHr`hddK@Zq3HJyp_Lt+vqfeW|C8x z8;>cMB=f7&;iPo6jHeC1y250xrnMS-^tYE^k0S+9R|5F#>76j6+~|kB6}=D@$CG4T zN+rOrjWAQhd*u|XFp7(jQbLFut_4S-$|n;KoEC?@TQX~VF%lP$lO&?wcf1rZH0TZ_rpwT5w)6jk9(tRV8?f`+WHP@;QPbSA3Gnrw~ zu}m&4E3F;TbB3zV!cEtzo|Nu<;sL_UD_!GdR)WS@aQXBK0& z^Rk3$X~%FmLj#3!v$&*!dr#9Dil>>{g+^_)Oh!Jj#!auhWg4I++_HEr!`?7oO8F?MNPBhy*zB&?Y``%QHq}btoZPl3?cr$!XK-^<|)IwSySH<4I$Hh`c0uo zN2(krQAHK*i%Vp6 z>f-Jh-ckB@Cy_kxgs|5m3*2Pl%;P2O(69+%;65St=bukPP)JfkOIi1>MB-74CXnqzKk2LLJdrQG+0h)Mn7r#}QIYJD5kQI?f^? zK!|i!>s}U1x$=sq`b6sq&zJ8-6Xlg$*-_u1E_am2z|pRP4S*- z0KY-z=nGs+hUb%bGRD*76=TkP6L!`HJI@-rSHT)8R-W`v!K$x(S_YWLt z1sWNsBXFU@@xW0c_ihpm>S3G{@g-XC`j^N!%&ZgPty^*O8!dgUtIf_Oe#iPV_UM*u z<&H@Vo9SOhlLOWi?Pcwq)LU7f>K1u;ckFocKGIv-P(P=@L)U4lUD4y$gtGtjxM_;H z$wVx1zrxm5PxVbE>QTVTRcbkl!zv@XC~yDVgDvkw%-Bt{VT0|WS+mQb&OY4ra(M1L zLYh!Jp6hSJ{TJ+8GBDi4Y+RmbR0U(i=40ad2~vvs-*DT}$D;(djtMd>Gc!bRqbX@& zU6i!0_g~@H2Vye&0ld!ZtnllbLaH*m5N)UJzv9h6H+#oy1x-NFrLBnbL!ZraP^AxGoIE!T@ zSzHaxwS$rXZAx0DJXU~FebeFWqP0o*(dH93DL!O|X50OuZOf?jYP){R@6+Q}MES*E z9)C>Co3D$t14x*Q#xw|+ZH+8f0M9YsdmKhGuj_SbsVQW-qhkmE985xfC$#hTVrI)` zTOD)fMblM|MI@kC4V?c@Zg=Fe>U~8c2#yL8OLc#oxD0rQ8mWDo_S{^7MYol%m@L#D zc^5N!d06~%7D8RRdFY&#-?yWp~lb@ zr$F*|x^rSj@)95~_lto#%TK~W`KbK}3NHFwh)vU5&Zz*?>$ur|!{NIkiM6h3DX4jM zU#x2z3=g2^qe}9hs1=L+H3_!PuxE{H*eCP7tJ>i=PXiYh6J%_jnhI>lQilSP8-s!l z4%^%FT{G%j&vOL*!cR+pJy9Q)ImL3X-f#1}aw4;aLy4%u09m>lyytm}ylC?|ZawKj zr;T{fo*+f?STB82k}hb>z-w19&*ZBb(t;r*MMM^y4q9%J4maZw9zho21nn7{j0B27 zQBCb(_nsTMA5uNj4OVNozD_jdDpE^xP0sKIFSOD&V`68Plt3Yfvex5rM6lzp)rHb$hnt;MQyaiB4&>> zR;0<=w?{>m+HW7ckA?i~oyypLz9kkJ_4Ufc;*@0M`#@0@tt^aG6JD)FU8T#>$+8l6 z2DW;p`OS3gs5~~eFK3R=ES{zX|2H_GA zp!Zm}SV^?z0HXD=#^b_)tKrl7R0gVt&+Ufi_r7PS?S>x*KbA0cU6nLXCHyEN{#_ui ziI^`zPvX>DU2hadDouGBkP>82hk$EW>i`Y@rU_vq{G)>MH+CIR8Yov zynrj#y?zuquR&IRwvwT}Y||P`*CqMBDO4&sY& z{V|Li9nZ(CT1f&&jolcHKouF9YUM*66eM{W-1x21Q5>vs`0fxbriCYmF@d5370%cfX zYpEU@HrG=YjQM)wG~6w`wF(5){AzeaeOH2vt!>mYYSy08Ux~+CHRHl~k?Fs{DsN?) zu+@6Qjt&6f)Q@&=#KOfy;)Px|tGe=65~;_LG2f6rVu3pRxj1#ZSHqWw0{Mz>uC9j7 zygJSiV(o^+lvJ7Qf4ky;p_0U)#8E1AYDnR;i~$FICU1csEG1|0EChT!5A7I#^9TfW zNTbSyn9@L@GK%kFG6Y-($MgkI=1nyc8*3^E`_txXCI!}wk9OE`Ql9Vm zaZ;aHptV7mU$b zlKR5?^B)spzc!leRhE7d?^=`-O|*-lDZmJ!K??8HbC}Nfb3cd~9%5rOLL8Cr|x#9_vb4Nn_ z^1&FS(7VJ6s?QAQemrD@qecvdo9SVKR{uy^{I3Lt-;+pDadc3d=T&`gC4RT@Ub<`^ zrA)!k6+Lu^&}#~r9E{k=^s^-&J%JhyU%K3Uxpfwr>)~b@vl`mCiMLOV1L8K|GW}!A zZ-s!=RKr#lwh>x@CP(72Xj*rx!M`3*N{+&!3s(?4ChVwIOJx`)r7&MaFClNCvkE2c zP5Aknq&dEpw( zAwl!y*|pq|oC!|^SoPyri+0U6yXUU2Nu!5?5%1_YW+UGSI_=-b=zrdS$^UbpNj2gB z?7d-BpXESTrG>Z>^ejE}0S^UhGmg&DxQ<%m!jtzgmjj#V*~T&oMS35wz#nq5tykM{ zNZV!wU03psMU#iB8z^{!)o+M*_5NQc^$8`8ULk|SJ|8bfb&Uh6wl&2mj8`OhWq!dH z?6gC%@(t5p4XY0ZRaMi75EQvq5gQv~9BG(IXHVmdZDL$aj15UvEo6{VApOLVoFxCx z2SD^cpZ@xS%2~?_Rf48Hg*!$@vHwbK#Y(r%PuNo$7=&+)k(zRPD@#HqKhXz5vIA+} zL33hI0-&mTk7LnH?Wf7=fN6=Y2BISmMDAW>V31dMF3Kp>T=cMN5FBZ zKNu*TMCpaEl@hh#j$9JT;{!2G(WUY0c~t5*J8Y)fXQBUgBET}|{`eJ>0-yTLA18q+ z+K5Uj+>Jcz%6Q@&U0-_dHeZwHn-?C~s!z%3LzGh#*=Y{o3r_9T>}oLd=PDT$FQ2K? zJ9KXDo925cbcTmPybyQko2YUB_SnaKqxto#D*=>f$0i5{XR&=yOQ^Q+!plua%_)(C z-b}^J(!Sb;(PQOtHjD$T403~xRg8D^EYe$Qp|7f%uOZPYiOSUAHMZVjuOCmc{*1!^ z{qf0=4p=PYM#slfS(i2@fG2;X@S#Qp)a=z?B^*DIAB6H4q8gRZhHEIw9y6JgnfYiP zZ5w7<03@Voh1K>EgCO$3N|n4anYzLddXc~~z=eD9*L%`WSf&NfxwZOiZKk|Flxp}X zv;%TVcc5 zEi&wPKjJt*|k2*I%3VJ^jZLbB+DyhE|P+0D;k; z6epw|H-H@e%s=AZvAItg5Zx>41G$zq%PY+*`-&O6rIN8mA7?&A_=43~ zW3z#wiC%|~^P4NnwkEX`z%YQ}SbVv$wK+-eb{3#~MXq!-pO!u#OIGik8qa~IhRj#q znTc0zer{67hT`_?FqR1deWy&|yaMQk3Oerv@NazPr+hV=+O~aNV=!;NV*LFzE%=;5 zAq7W?xAP?lZ>1O+hxr&Mf!dp#IdR zss1!RH@Ew*t>bQYL>m`3So-k{e$y{?{l>$m+dpZ=%)*koRP)c)SvKJ02+{B6ISl0a z*+KV;gtLH@UW+27s}fwpUWb zgbXXmy9s(`?@XkZj}^>sR_N#HQO#X-dI*s<@;v!yP&#B$`HU`-}k?4;$$XXGB?gBr=pPfs?e-G&O7`DxOz57q8o)_&zCQ0;H z2pag02apmAr8>HKKFq0kku?MV{vx6r`2L1oe%sHm(`KUM4Ewvg-j#>ItIph#HG%^2 zP7<;G&buubi~lnT+(hp8XTY6{mBA$P3pRcR#ra2&d?$kvN5sZ;QES91awYdW&?X^4 zaktyfr{excht0QSQPJKah0_9Xs7MSgJ?n?78}E%*KRwYP#x$J{JvujA{=utdMMHFP z@o8}CoDEyq|9k5C&sTh89uH!HRo9I(GcuS!eOZ=I4AqRQXRc3@?Dn~y+7CHi$)?ca zV#rFxn@zTAqwgpSpNb~P1-&ciWQVc_sUAbHsM46VZiGk1Yu0d}Vm-J)5ON3quZI7+ zO1?cY#+LccYAOWAXNnu#REm6|${-<@Ui}!ahkl=<&cvDrMKv_PfQnx(FTd45R$e)t zVv;K&kS4^&2*)4QqiMv`q%A_iBN^;)0MsD*9}gn`ect~IbvjaXGLSwwD=USo2YeWm zLwA!c0J&*uUr=kO+4La9D-hJemfA`XOHk9%Y4)xFbBU2+VaSQuL-g)`dk_hGyys*B zwirvz*q`kFF`@jQu);4N3pkYmh*vm)`Ebuf0QHLMujJZ-qC(F5icXcxg3abPyjkHt z3J8=5*;L;#Mq~KZPKWRYDN#x&;3Xyu_C{AE8Rb=Di9us$6rl1$5*uRwK1A8&{|WQh z_HdK43bjTD(O2IwC4(i8t>soXs)Qmi+f@w=!(QbuNIR+Vsxd=$cQ@qi9;?VX-ukPm zlEpPK&J7loR%y%(jpp>L>C-(z{A++5Bg+0~qI3`h(?$@R1Y~onGHkE~ISFx+KQ0i& zj5xAPHOcQjCy7;&fr6euD0(2A5())e7HAca%7mmOd5d>%352Vaq@u_I$j*~hzghqL z=>H=8&o&hpf^dRi3u>jP7a)Tds#uAf@#AU!oWf<3S92=M3Q|(VCO=PFOIsD>hULrN zLHj?QJ}-TtuA%Y$Tqqy}a`iFME&}{$(zuvygg=w|ACJuc-q?Qw5;YKOVEBbMa6K_g z=bNMy*E1Gm3X1xt+r$M@&qrRq072?+4YajG6*q^!#8FZ@F*T%knQ|8#w+63Ds|)9! z8R;_%fqAR`AA_QT1w>DCV6?dYG{IBAh?)Nz4h4tiNBp4fcc#@Xy;vW)*Hf% z!t1*@zjNW}en!*v%7jiw23)jZ!Q`xHQFURrEOa3-ac}FU?7!c~qLWl$d~@^R-yr4M z?=VZ3@~(vM3Xn(q67NozezSDfS}ZE5f>aV&dMPaBkOh-8q(EeWmDgqDrX*I%K#w`3 zoOS#0J9VP6uB|Pz9pk@Wsu)pfikQ+6NN>1$GC!(+LO=epqaavN$+>+$N{*{+u{LR% zQ-lE?st5xa0gkW=Y3-UC8q72@$5RRIPshDbjL;xnzvY!Mf*?|?$8KT&KJqaMA@pTK z4S;0lYMG43gc25^~~{ z`S7P~6q4H&3l!Z_rt_;jd4-Z4G0e}C}j@C)q&)e3|mICODwJ8RPS@9p-r<(6G>A2j|np?J?6HH9Q$T zv48BS5JZ08@xef*mD*2Kw7Q01aEFqPN}h#EN)m-3iPhQSIh%enDHRi@B_-rhpu(;l z@m=KvXL|^!S$ZhI^tC_gZL9hlQSDr&B0 zBO)>*Ir=)Xh)Wxqzn(ZTD(#xRP!kK3zrmJLCqv6+H`HSG@@k9tXoQxg$>XoqJ`c;F z^KHKZ1b{%7jiw$wVE*okJR*~h{plkrDuU_T38Rb&8}ClM6Fhj{P&-8PUgt$LMCND0 zvW9xNLj^<+%&PvBM)QBq4u9VK^pU2}?o#6pgiP$QJ!O-F(ptGieS5dhRX_%UHQ-Ja zD~e(q{!&Th8OIgL1>enDF}$P9KfZYkxpY8p_iTHDk^W z0wlB7)t1Y*pYknk3mO}>Tn-o1p$@FC@=0Hwyi(EhG__hb0G1&G7Qc zsz;g;Z$y-ATQ0ci-!sJFM2kFX5FLKTsbG~lug0Fn-PtL4hWx?w`a7nc%>v`KV7k_+ zyW9R@1N65aVgrVy&PZ1ix%4N1AJIgNT8&D)#0EQ7?Y+ZbaO-`W)yEDc{T~oTrw9INGe<;P} zPsnSD#ocG6-~yalZik$x(EZtuQ~wQ)GTTL_WYz9a~RN) z9J~=Z@7xCl24WU%I~2Fa z(=f5|%v{UsPrD=8-6u`vD~$rI4lx@DyB#0934;VO>-Yj>+tWbvi8xR)fPtZjjdIfZ}B|cDd`AXJWy*$m2wPdWBxU zE!}@!eat^sABa&P1HV<^aJB&DE@iAQ3akQiVO|VMkox@LOh@c@F{#XxIa8gJRhv0+ zv5zQ+BmyD0K#H&EI6+$Ol;F-?**a!j20Ha4Egq4#3|7gL9$w8_^fW4#49CwEIhT`@ zdrJTbzPY&(S>WTDj$&!KV{bx~%gAj2R|NXUa5Gr=W((kR8VMbo+4(p|E;&s_x-M5EJ@jpT6yFm4|i}&#I$+$%E{8yDLeZl6p$Cl176$jBW zRw%y#3p_*9>+91^=pbEYLfK-&U`_~0i8AQXN&(M|2LUeFGBS+xAMru<#A}&U*2Gsv zmhYberX~U3}`qxG@s5e@l3oCQ8}=h8tF(HDe$NJi^Yg|5w#?JgB?c!5)8epWnEUk{nXIvr*DSj3u`lttH1>Y0AgGv99f zoXTe<5pxZaP-LMd>A~Mq*9eZ442>!PT7eJE#^oD2?)&!bsU&2F18eBF)!VAoe(nLN zyNl^tpqYEi@ZpY*L4G#fvT##PW@o;{+-XUKt-KjmsDTyl8!L3BW6U1!S=}zzT?`&2 zxnyxcn9C8^kon=dUu3BycX$jYCQf@A8(m(p3(qb!ruK;VQ>hHOzmdBoanFw+6#l^P z#H)sehQ0;$ZF{+zUpIlAHD9L_xe2{neL!ZBdXVLI{GdP^vAET~2f9)KnDRDvs?yVR z@@k>W9bgi0ei8hW5Qk4eRm zi*UqO0$Nvht^ti2f63uKs6<1ufe+Dsxv-jg=U+S*T${%*2aA}PbBDu-k|F&EhO0mK zht{5`KzZ||qQfqOlGRNSBKN2M%NXJZ42yU7-sSLBXO|!bX%RMI{^1a9>jfSf-k&7}_80BK zzrCmpG(K-VuX(+SZzQ}7^tWh{M$MlOigXE zA(y*Uqq>}l)8C{&5~3-BZYAVmX8j3LuBN5gyTE5N?F?DO&LV%X;v8vRXY1cF3oPJf zlU3r+Ta>7?`6=WENP{>%&fiH$-!0p^X4Zbl0%tTWo)b-(Lc1CBN;n;$WeuybFD10U z1j;asbY^TSWbjLpc^;g8F}&)Ut{IDy){wdcvWX;wj!Z6g-&IbBLoSH}r_;(D1}I5C z7h56^&awtGT$hOs4fXW=L(1epXFRJO=o1G0QVp(B5;K1kQQjSeK>|L$!FtXY>h)<- z^nfU{TT0zxD?T+#1aVNqox2}_YCfQu))Chk5Ig|rFkh2B;NG!Dg(feY-_Y(Z6qIl& zX;NR0j3`_y+xS&zHS;cJ`u9&uB=t{c0_+N&)i~qml2&1u2Q786bmVkKz4Jc)NEv=e zU-**v-RlMwHOm3OVklqFt0#e>j2M~+^IG-xl^ojeGEeqygKq0?5p>*1I%SLzWPped z!HP-2FG;EFTFG?R56$wwBVSLLDut74hS>)Mf6~)4<#p{z*kmh+wPf-0)Xi76G;Oeu zY4Kd@{mCcgZ8*cCIMr5b@pf8WQ=cZDRx$24Cd_?@GFSuhvItgyt*eBRGnRybmnFc} z=(f$DJFwwGnPm7EtV9Ln-Y=(|*6FHakf~^^C}GL=8BThLJqfi`y5T zw)#`x5KL~p$|h((s;R$wa)+N)g)vdobxQ^q(Sxf2dcIYZ?}|H27Dw$K(IFy9)eUs| zTcKl@0>T>PooV;Wle;F^A{EYsP-c`oE?YryeBaMK$6T=PSe5|K1a0}BiuB(;en-D} z%kkOrOeX)V)0iPbhMr5ff!_O53AUO8x9Sa8tUtxKDEW=@jx`xCk`Vq&yFZ1_Jkx|M zWnxv(O~VkrcJ5<#bKcJVSuU@jkJ1ut)9S))r&ESA4mEfbyUkO&e@z-3`TAGkAKl^H zz7OR`iH1(`!R*QOQ?T18WpFJ|2lCJ^Z!yLnpM&{6o%43kf=e>wi^<@Tev6If3n4ay zgeB>$bgsnxd7((J_0%S1+ep;Z4xT!hvpzuiex=ZQ=#k!T0c7c&NK}yr9^R8*aPpgp z2y3M0EY1@zAI^qZ4*4US9m>%m-+vNv8&u4dzv2Ay(P=524>s=%^f%P)&u+Fl>7~sk zVuN^AoZ^@39p{vuz^xs}_+Sz%$4eIXUdLI7?19lcr%tU$(z+uT&PTXy!fh2t`;KE5 z;o}{Zn?PjzN&>58Jc3qnq#((_46sFZG$1He%M}4Swr)DBHo7^#KD|(jeymu#jlpwDUajPwzQ*^)s{e39C1pJ6l3z6_O(`qcbwZzB`p7 zi^og-YsBhPJ zhT#!j>R~rClMs3q9NA%9i6?cH*mz93oU!MeBKPfN32~EDsNF3CF!=C6;_*<3igrw` zgoCAaqB5|5630=I5|hxYjU^Ru*${@n)WeFNhu6=oEpA<|+e<4fJC0{28T!{YDIb--6 zYJU?fm~gmQ-;H_jX_4Tu zU+YKvm-#2Cs?DW^Q^2-2S6IOo_`PcF8nZ|)BaHw!I!ynawzhWliQn`5###yHn_Zfd zWQTm_7wB4H1dKu zQ)L&OB;Z17*rN@F_7;Q$<^LaDR~`;!+rBGFX+cp*cFGK8C;J}8J`35mkg=708H7Z# zH^bPo4Kudv+1oMpJtUQEV-16`)bH_r%kS&edvqL*@rQYO?(4p<>%5lpye}8n3f9lr zz^5CGF6Fmc%T2$pcFOr|eucHtc~qpK%TJlW+4%N@^4Z5C#gjuO`bU2GNER|OR9_x% z8EZ8DjLJ>);fM!Mx>0mZtk^inkZy%v$E1MxR=ykn570_b*!xQ74(QJ}_!!yM0dhor zJ(Gi=NUVRONKOf4Hj2qeHOahFFsbA7i{Zrg z-$0{c;IU)wDRPaDk(=4(&W==yva~CAhV))cV5uH z(|-H4AH6Eoz7jzv*q3YP?ad;ool8u36yP?QwzW^?^m1%Ww=GZjZD)V_wAnzxrA;Td z?AQ&iQmn9%ZyPk^0b%*H?t+ZRbYVi(*SLa)Zeyiq=5h@ZR=`pKBA5nnRx;BTN?x%4 z*NKiZc^O^mYAwFj#LP39gF@yy@5wu2YMR0CWJV-Uk3`H}C@9k5e8ipkC**R^+ssEM4hl%;b9y2m z{u>zAi3W9Qb%%y^li7u^S4GN>r~%4aKwcRRcOuUz`KAP`(eAw~ON*nkLpuT2gIa#9 zAmR}raMLqA$*(NqGe~Np-s?4Sq!D)WwSlSxHYZSA;X3(Rk&9m)%T^bG@0+h zD(=-b3Y7t+h#}4zTw2z?*btpKZ@-i(F2Q@!2O7+x#=Z=f*I{;d844|VXoi(qw^G>JgArCbm~x8Wpi*1x;3_?{6kT>QG( zZJ@q-;QhwRq{1~FsHC%U6xw2UU&vy(208SsZ-3$E#*W4K6gh)Mbf#)Rw|2L`AX6^j zgY!V3;nw|0pVq5m^F^~qvkK;d#E{cU%ROs=W2)LXr6gX@>w51oWtS&YHvK%C^d=x+m|& z6KA6HgzC#CnihY`4x-0MZ0j~^V0P8&N6s0|6AuDcjYRV|uMokd{A+}8I?q5r!zS~o zPKwv&RFIC+%j-Eeavjr6Yh9~7h9(M{JLs?G&golMUCE?!YMiNOGo9Vg&Fex200Zb} z8ylUGt{bZ0i}VkSR;F%4DO`_dyz5NfdMv>xg$va$g2|J%cU2_Pseb>rOS;-S*@sjb zT%DP!31w8c5yAwuF!cr3_~zA%1xYru7W zX8834=k2o(g~Z!r#R8uj%i?Q|W$S$MTj8ulYxwJlhKaDaEMTtl-QGEVpkn@w`4PPN zUY07G1m?})toYA|MGJI4fEe|f?Gngxc-QfD{^`YCp(+p)>f3drN?eM8Am7qUr;(fM zJhItUHeUh@(KA&ZJtd5;=TE^%Ybx<%d&>083Ywkk2 z%MNLENdCzqJhJt*R+pn(z#iznOlk-|QBs!%WC8{YUy! zKD?Fw@lpR{rx_g|#A^VZoay*YmoEW{A#LEWD0{WG{nJFfUz_D;*yTQa4*6sPOisS} zAV#NLeS#Y?6IE1-9{7-DUu*6&;T6j6*cY^nE(K)&h^>XUXI<%ezZ3b(icP`ngf%$} z9fZ8YB>j!=+1z=gy?LNT;}t5G>Lp)uA6g;ayo1 zAe(mKt#BPYN|F<^Vx%z*bPakmFYYB&0as&xOTUU@7Gm%2{Hn>~pXb)Q$nqu=AwM%ZF@R@Wma-_{Mgbd*3 zgHunOyzvTmU74qPA)|owVcy#ZoV5dM0%F(N=iL=e`)Aq#C{^Efph!5gh%B>+IK#{( z)LFCp@N0|CY?T{FUm;>>!*RfwFr~gKCDUj`p2v|jr&Zpe&!~YXfqN$76aAMh%+gL9J zd2I>%%$w7z95UO_!(51^hETX5sOcPeuzy8<|D5bJ8s;3eiinQ}5o7Ooi0N#rN0b<*1K^#9ZtxP-in{t`zivj9BEa)p4uh25%~V2X5Ugp9NGO z9^Xqn8&vf^JzJM=bEDzJhuzH?ks#oE zc2~+ORcH+JoE>?(mTD(mGtHaEUVUMSb1-OkP6_!T4b9}*0&YMeM&gfB?TqjH%=NyW zqkN-r-|!7?ntXyKL`Od`3M`u6v9ITPv$1Ddi!VNoeU^4X?y;+u&RJ}n{LV)U8dRQ5 zP2EaBP9!L%-ec@W?WZfO0h`gx-AIr3ObSm+N2WlzXIUi1mVg$3OJ@zU@KkB!=tbt* z*RcbThuwh>EG8IWL0LVn5%+zcb-&0EbnSN4s34Wnx%&f&Q{*h6tTxQU1ub(ng9NME~px`s)JyG7u<}ew& zGg{CmuRA%`jC=>@fq*64iL7dvdv!It4lQ!OeBz?pBLC*CtSmFA+M}?L^?uZo#OL82X<)#O8U~oZAf|^Fc7a1X<6Jq?MzNEc_1)g)NAH7}RXhIaCM{2X9Vut(nRSl=$Y8KifbHQXE?b zt_puN`)n@N21@zz;8|f@sRsbDy4vP*6$lxd*Y+~FMu5E2Qg|;heWqF7K_I6yz03aV zoA47K=1*XL6xYU9at1u`-nb*(eM1}nLejU5Uex*HeNm4YfiRNawac{9Dls@=>DK<; z+@EG+gSqpBqSA`bcBz};;NU*t)S$WOJ|mfPHdcEtZE4O$viMkb-eL^^x}R!W3q|xe z&!#9k-G&`fDR#&Bwat<(^Ur-(vIvHhblGo!8Khd)Rb$Y zq8??jC6k&$MYX#D)Lfo99_p%?iBi20vkSWu=)z#H1-S3ei#a%njEHS5rOqEWn--xB zOS~w<{(=53;9%HH7TvO#kl(73Pni2&>`_2Q(B5Il!pkiskK4`)_{G!wttO#pn@$Cc z#ECuR22vUyT~=pT87C}d>AUsJ$TM}UrFNHykutX4X3X(}XoC)|_S3h8cQ0zr4!8%V z@SPd?+H2^p5#jBw-+}u^e#Gmn?EcyoI4=yUZ@$Pc)|pp)IbSy$w*?=6zyj`ajAD-N z%niI9!{!3}=&4p_0R*a-sqkh&15BC6?A)!BXEo@?!_6?N?chFF@1vj9*8sNpyV7?J zVeziOBrtGs@w1V~_im<**-rBKhPJ;{yjN6_pO?qT>4f(VbVfAm_BoZL5^Kkk%0`qV zCsEJ#){J|}8OSTaqbH+$OPMfIF?ZR#H_8dPaEzfO zF}cuD`rttG3kk%zdKavz8C|>ca-pbn>G z_~53~YNOOqJwabr>Yk)86nQXcv*=4*K_GC0sX|a=NoFDDtXJL3%hP)1XMg&wCGca0 zMm-0*Bs<)K_MK*3GAuZiM}s+e8mGWMyq`EWJ@gBx%0+*Rdhv?6-0{)y=D|U@aTL5+ z<~m)XNZcg^#i}oiv3V_OgdVzc_XM#1ulGVainL7N#rp ze)BXZ5i-!7PVVNHHD25#FO0N058R7NOg!IEg1au~U1rf_^Fexd*ht*pdn_~OtyqO^ zSL&rj@*@?_T>{?r3c1`vJ@42^%7vb2HZ55BpqV*$n^>w^oTTTRe!wkXsM@Y0lcGx; zC-l9PWX$F^Fs`xWuOrCvxRBGQDmE3kF)d@{Vx&KapI`m#yB9HVkKxvq&t4-L-Yxt| zWs##17L%t1RZ9iG*EbL7`?FrOl5G60gg$4F5AvmWJYwK8owV`?f5Ru;+cgyDtI>V+XFTG_fe!)M}M4z_==tZ zx5U*+KW(`Mfd-wdi-N}I%~zbuI*M=!(mLE92`sxD-H5c*DV4eMeXgtssDp2HSrl>K z?_M}<{Hh|Mrp5Jszh;q4R(|ra92X~6o1S4; znkD?fEI^{Or$7k{20uN{9KO2FbBF6&gw;^93hwGqL$bJ{9+~A-IPvbLid(ye__x~% z@Q-ih2&NqxTFIFaTjx)nm4Ke$f=+n9pxbgyO#x{HRv0kE*3~>-$@_AYbCE{I!&k6< zKu_*Qg!iq%Wtef$Ps*jpBuCB?`lX>9H4hLU-}dX+*~LPjNipnco-3ceFu=zhxH!M_ z#f8Vb-us!*o3)=??bna}csIHfw?<%4U}m2GwodciL-p>`{9gLA$mkAw-`nlD9)&XU zEeBc4;LFE=`*T!PtrSp6QQzOjuoERGgVx_J`m#@GU6VJZsdfhC3#mqYX*6=cGr$sX zCeJRgA<7pmnB=08&aAdkBCp>4d#j`66c4uzFr=5vX+z3vzy91e*$86waQVkh{#BFE z+gjn)LCYzhue@R0$QBBEo0sRCS9MYWwn~LFZxEZOvL?8s8Ri5vyGtonyh{Kwe(zqp?fQ9OY#LhX=6ZzpKE$siAB-()Ahoe!)0zQ?B?5!FZrhv zfC)m9@+(>x;yB+3?MTk@h+h$?1kk1T9mL^8`?Sk22Jw@ZhR_;!0~GKOV~a=E;hcKbv$x}1x^15Uq{yh0_GZDyAipI zoaTkAgC~c-Te9|7tIEYz?aB5N6N8mysemcVJcj#RxT~*01ljjl230C|slxHTiYUF` zYDl~6A$MtETj_o52~c^^X>J>00bR=@4(NMTZ6&9~`x<$TR})~{ef^E$H1>V!8nvaY z@nei=E93G`vmf=*#4Ao}#h=p0QnFTpYZHzBDo^cRJF1Q)%rAZu1C3+ez;)iejQNds zvq^U_ur7vibKF#}o81VC#D=;tzT*qy1F=V0g~yN0hET`F09&1@{3mq#y^Vf`9*4fT zBPro?lYiUSrg{#p>jHN9;UcrICGUQp6W)wlCI7&VDY){Mg&sU+Q|H(d7$x1K1gt6L z#HTG4y$$*OeFgt*02|GkJ?l>l8r@n9C84ge^4PT9_fI22^rxi?GO&#(Y$kW0UTrvs zb~uB0czJ(GfQ(edmUUvn2_w8!d8aw0Ciu<}`k3t_ zo93*_aSS^bqE)vfZ;L@LPp$IdajnyLe_mM01+zmbt3}t6*T3gIU+FQYTrT;^c$m;!yN?&{YD4BD>z8j3r(GspY}xzrio(!06wgFO{)MOR7s- zN=g+X9-|qTlRDfbIBbvtZ%R3Un@Eu@sm~iP|JGal57l%(`Cv|a`stt-(TE};7TR7?X`aX zYdGz89O!9?-rvT5|NZNWo(sURwjDR_8XJhscJ-vG6N8|3PhfLYRrAvZ6)cz@#CKFh zRWtm#E_DZowo)NP>(YEb#fn87ldzmjiEB3G)MjpPZ=aaWUO)cZ+|mC~DpUbJGr(y3 z>HZ<%o6e7qg?Rm2JowePwVh+bMpLn)3}NHjz}XGNTS(bkdWVZ{C{VQHvIh;X{<511F3e!}olYePI-4P~%1dGD*Xb9`9!%dX}cgRU+STF#eZTBZ?iuoUg z&e4CV9AI}^M0dW(%6<#G#iUpTH#zbXnmQIS2kOa>2| z?FF5LO_*quWy*bb2oAW!0JD8J1<;H)y4^#5JHG$_G7k<|faLiB^ zO&t1#VK6p+k+b#!JSi{#)z|;e+u#d5FeF9*$_n3nwI`%-5!(jgf>g?wkrj-mse-vpQj^!a-l9qZh{kUnk?DPaeOQfih(pwV-MBJghm1QbX} zQPO%_+tI5zzU?*5)2p8=8$PX#%>uM$CE%hx%S=~U$v+*Rqvs2G0DdFf4m_z$8Q6a7 zLYqbBh&ozEX93gbQGpfl_3$n`M@#tiqpP zO8?-pq(NIqSUSq0tb{ll(Tb)~#+=agyD0HZ_L{pk67Jpbl_CkdGF)y6H}&CPEVQl#64>SF{EsOHGly4n8b z8(lt=D`@4DFzb^B5=dJ8>a|R;(bxC{`hJR#?(kz-5#*UiAU?x7DXEy_a(d7Hyt~gi z|HW~|qmV&C3z6N1kXj2G2H83a_sdECe^<3VML)R}`+b_sNS$+NeOjm`+CGhIJH$amoe-WidK)MP; z0Y*DL&f>9#xc}lU=SM+83Lmj00)BD=nxKl=20x9|k-(5%WJqYds2=SjHr52QZ& zisrtnzGUTmhv41u*mx!!JiTJPk;ET<-E%k+#Dx19&S}g9u$sgF+2)ML6B&RT+LEr3 zgvq;o8q+GCaKdB+AE-=c_Vi;;UB~Z(Iw}FFdd=I)HO_(wlAq_!m=N@mT-An8s32iYx1=F*JcVOWt``_6==6k3a)= zr3>XnjP5OMt?h53K;Tf0>9-Tgr{s@AG*8}~8yix@(qcGmXy3qxZ~1B~mDqsU9mIdn z4*x@M7CU#auj-1{CPW&!p_IMztGgwq>PJqfaGs75A>>(a9}Pz6rwHz zm0hP!@jn?0jRT1*{0iFD_0?w5u+{{cRaXlehvR8O5N(vx7?lL&)XA3Bwkwj|SMo${ zqMoJxdFNiCIRH^4;cCx5D)#|=#2ss5glF@SehPpvIzXxYKJWWVI+ypjMlqILz+qS3 z%)IQI8DMoAn9&6;qPUfh4|aNC4x1OY&u>ulKg zQyMP#tCea{AYNmBo!gz3|9$0`NHN&SUxlIHpzZuZK&Z}r!#G$Vl-^s7&Z@D})UZ%i zMGS90pfAD_eIE8WSjhj$DvI1(@n@`wPq6ht_X1QQ`FGgY6*)NYzT4tRS|x)_tym37 zJ5IX(ZK9onMIED)G_#@H1h$sC-loNxn`0cKqzRSXP!mIzxnLj|iHb_kX z^|B%;P%Gc%h;lSt9HXolOHWZ*GFysc6hs9IznD1D(2*k#Ykughq=9*i!1us=+qA&i zoHh{ZA~W3D()zR5>l(jd+W&@2$iZ^)*dVh%1)Atx&M*?Yki-a|g6;D0>zlhj>iM4h zDB;a)NDsX2HqhkHhwc$9@Cx;jJ+=VKz3URBinRe}sXQzD@7MkI;l;`U2&+EB01Ljg zf4@j5T-h4_J$5QHmq1feSy$pwccmG@d9ooYlow{P7%%T@(WE+TqDvC2Xj!S{z8o>TkLAf1v&cMSyNK2*qYiN^J_AgtBR# z-sTxvdFrcm^vd^ZKgbI;?0B4I)NkWulGjQ)0KfWcU7Rx`^) zEH%GPq!$T4BQMK&4|3@_5(sEbW=E`%i@t$caiIKGAR+sYU;p0^F#xZW3zw7)o-E02 zP_|JvWXs8f4mkjx_h?Ld=*;&zyE~GVRH1MSP5qh`;xiYSj{K`ZFfb&XQ_+!@9r}v{ zp5N92EH*ex!e86?4C=S3p#K;I0FRk}rA5QG1pd1qs)2RJd)k}}f|wJ(@DFe6PDnI1 z^fAf~0C*tY&ucnO6POdFOc?kYQc*5O7z)!X|btVMVmznlUD^&aH(l6;cv!bWZ%l%=XaVXn@yWTgvb-a%Agx6!DrEL zp3*SDQfcO1KQ~%ak+2~i>j5_A_yL9lgcjqDA3JKC+C-0_)W0Qu;@CcQ zVvg-{*4rbj$`^*i-+TPZJ9@3>gX_LH;FR8y0Wd#uN~+V1fyWxq=o zo8>kd5{WMvw;T693DcMkli=liq&*sx+7%H#a{6p%52v>EKFKUKOMT_$rT^w(zkRS` zzZNfM4WMXAx&@vqTX`vd@~RO0d>w8*zfg!g@}w1;LCss?Vw8!h4NP_(jfFQuJs;m^ zdIO^eqj$2L0-EmJ3u06H8wc>eQ^ohh{sX@iu{&~5%HZ55MO#|MyU;99E*@y;PDs@k zfX@1>zQ^Af_j%(4KG3mZddvreeWe>+G>Fqv(>hGJ4>7f0jijQnNU>*e*MBe0{QIch zxB7Rs0;q1Qb@jNhOz6DnO>U&mIoA9zj|O!zvOf|ur_;hd{2u*wzVW%(nRO2)oVO;R z_Z4al>=teYn8Yycx506+b_~12%3arUfcsnobrt>DeG2?lmkAT{T4=i|(RQky@g3oa zEbdra_xeZR;VwAbQGjiTZ5dzNqRL+H5k1uxT% zJ2(GQesSf1nGO`1Vr;(s;Q0rj34{b%z#j+|pSH;wT)Zl*@B7F)bXg!^nXT_Vs>QZ; zu~RUvCwWGScqc1y4GQ>W>!m9ZEk0q;ty*-0&IH?<;bjYt$?g zRZJ}Li~zCx{SJ_oJ)kAPFL$h{!6-m!`m*p4pFNvi;-BF8mxtH?Et(`Hi*scjV&y{P zRyf7!=*Y?aTgcF5W7+x3Ff&(<+e{t985DY)cSn+Wc<2|r$)4*i& zEj*z5_AqPU`2Q}{e?RwXoIH>gD<%4L6uQ#q#y8VQdgL}kNyu{sK<4yh_Nxa?ifkm* z)O$t=O-x?$3%}Eytc-nLbkv_d6n?pTo)fFxWMt)xkhklO#NQTK_f7qyWoTqW@=n1b zvGtC39DY!!5=mPSq08v|g`ZNN?*`K2GVAW=QG&*AQoP4?N9!Aoyn!F(DxfVEV!FL- zdHK{sYgG+qy{J7&!Mow0dx&VP^p^s$qrcI}|C^UxJSfc#+9Kz3XukWXoMU3j-ji=3 zr$D(q1UIhnYs&$gP#LcLVxekoIt+zF`)i;)7cNv||ANB#U-VK;kA=wHrO%_8W!N~4 zgcN$Z90eBrGXMBOJognZ0Jqk!9v;YP6!jb|Wd9WB6m9>L(=gys z0MIe*=fgi_?}M!-(;kl}ZuM?lU{GLsfuJ;Rdpo^zLP~^5y#rP9+uApbtMpy3_A!G{8WSoznU{EhJWxRgxSX+dFsd?E z)LKt*P5<%A?$T=NSh;EQc=P(N(FVHv?aOQ3>nr%Hu8TZ8*~cp`Q=d@|;md*6eissu zkO-@cc`Nep$u-S~%%W2n)&rtF%MY(q^VkZ!y0&ehX?6DFt*;L?C2XT3A*^l$lyb&? z)35p=o!4vT}O4dbe9C}22Qq=xO~V)yIqD*8hZx4tw@hq;Ix-P zwo%Y#_5DIy8V1E9M~~D0_T!W`m(VmbEMm}>wA3Thp?oUKUmJAO&hD2=Ob%BTekGQ@ zPIkqCnuU*-v~4&N3l<`O>9h5AcCmWmuWiSBqhZ39qy=6XFMGw9kBWBu+m{2sTKONp z#)Ms)nPtNg@U?I_+zmvXOG^v!W46>hN|xUb2E0VkAk4EJ=#7FRDeyG^)7#MQby55JI6)mYpK3j8&m z6dsMwhESGs&~A?-L?dGV_Mjuj26%+pUk!HkNKKH4SSS(Agb_vU;?PK^(qTZdS}r3(-`B#=rsQDIt`mpb@>&OJ|9_KHuvPi6M4)E#T?` zXICG{G}c(BWi-2Nioj6BFq2I+J8jlm&u3<(L+}LsmDbJnNn&uktmDlh5_2H+YS{QNhwx`}XLj#?t)C@PB%Ju5= zPM4Rc=&#(<|`#6hqe z&fZVfWAV2=a9}ARwPVj{wI?1d-0*(pug$dfiI#K$aTCNh9n;HnFA7+;?qsvnt)23- z{o0jlyu*5@hYgJ#)VH3wA@dAaxD`;R*9`R(i(eiy5LXDE(=e@EOW_5U2$L1qCyGNE$`7rT6c_8p z$p;*MiIbf#Uhy1*O&L=@uN60?J}JYA$h-Mkyx{Ap34_)D`kM7pOs`TFy_Rujk~Rdd zn>hY;Y5_QwBVwQ|@(_$j1KqX=hH$6J!pJy_u>S2%2>w%!-cMrX+F9y6iE;CV z4I5y7z@_NIcpuqIraa-!h$!x{J?W{dB?)+uoJeT1FMv0kPx@H-D7z|-?TlKwIxu!F+ZR>XUNIs_amKO2?6eC7owhoSG20TV? zJvM|+t*46MNVNKt8|=7?6T2iQMl5OEz9<*ktlO3}HV5{Ah;FbNP;K1E*Y*;n#tlZ0 z*3Ip-{j4Bz1FO!Cw^3en*gylv zWLU9RlGj+JeVU9Y(h`In88i=I|QEegu8c^o55-YK|Q z_`^>}be*Zh%#dm$>KN4EHH21IjeU2Ne;rwEZOn!r^)r>jF-Af^4E`Y3uu3(%MvO>< zr(jvYVywMF0~@=hUKupGaYkX2@zAQ-8(SrY;3Z{UMpMbSV^BoKF|V6OXR~PXiPUxm zfvdcFolmDz)xs;hXdL;boX$S>{{Hdt#IM!2#MCGieeiH6%2JK?)c`CA*HXIE0^P_l~wpsnZZcV?p86s5Q<{Mcc zPmAulf6GS!f$FZ4mz`be-l)+Z!n6Ish7-Rz-LMq6 zQf&$QF!*gR2QvgA25195r&+{KA9G{pRh)u>!Yoo6aW2Im1tZY@)Z005pn3nx+ZoXf zIaH1ltDRP$aXyNs#$nntzjd(loc+10ht>_J1?)DwjBC?-i-76I8{Icdb8+tq-G@Y| zan9Js9Egnrr{m`1PZGxPr$7w&?er)kkJ$oN+sfmG$r;=%!=%)Gmo^|=$=gq-m40pg z{11UeTa?x3~Z`1n82y|Wi~+gp9n_j@CIIA+%~ii9$1gY_Z6dnusmAc8FKj8picqE1}V#*wT1N` zUuP>yg5v$P>}VmFH%6KRYvC2maeH|pxC(2&>4nV`!%qi#_hbd(B_)bOeI+#|F671R z3u&7UEaM?~zL8>75zL$Rqxm29m&C#TBDWQzYCpZu}RbLuVuQZ4Ql|)A4N3XVB6+i5x zvtH#LgMHrH8)3qN3sF705I=pw9X=DKM{IFX@;k8PX%+G3SC9nxo+MHMuFRTm!PL!5 z05LO&W0TE^#t*GjDO-U@p0;CCo0Zzw4zH9m?E%1)!<}PAl{KxCJc|^}RFD!xRr)(K?L=h1W8YBkNHHC{mDu~%}}JMdmmW)a%W zi>Q0F;pt%$bm9)y$AajSmYUV_BPBq5%EF!u86xa}@sG;%1&s6IRdZ~ZwX=xvRr6g@2=J+#tVzXL6hbH%%9PiDLk}BR;1(Cn6dur zm7C$wpzw@hL;M{byFh9nfXCtE_P)c`{Bs@aXbLJi$M!$g?}v~Fose2hI9+FFd{voC zl-8)*q~v9B1*4rI60IB#=gL^|_Hd+scCdA00<&|B7V!LJPW|63+GNG@o7}o4OMUh$wbjOVtpOxquQ6g8a#_kEImjiMWy1U z?j3R`SosjZ+yIo1HKiNV=?N@mLenEaU@c_8?dE&8s&W7=bDy6d!~K*Dij)l;;nT=D zQ6@KXY<$iv*fffXxIiFN)A9bERA~7!0Wi3sc1d?I=KhPk`<6+wrttCTB%LZ z&%B5bFabgwFLj~v`Z`_n_9?&O>!;sWV2Zr>!MB)z2vb%d(o8;U2f;J=x7a$->hBL5 zMUaHOa-n6i2kAF6YsXcI!;UNEz;XF}@_*X2*%Gx^x=$TL8IOz!|J~_-pHo9=Ypt*#6$s z2N^g3_1%YT2TciAEAk2X6-mSnf{LlIcl`^cvQ*;S%!8oPF@Qi$^)lDRz8-O+-TV6FE=lU23gwJ z*?HA>9|`!=sVO`-HEfafIj%{%EsX*y2)R^+7!c74!fQq%0yjHOqMKql#V)#Kw~`-dNFXG$^PMz$Uo zfQ1llcg#aTZb26J6{vHfkW5Syly6VbO4Gb3CauK5VN+8AncuiX*o{f8rrv+CZ7h}5 z$cm)!i=1j+^cPxr!_ao~@Pc*H0t+S%o;IyWJ^#FM-cPe#pAAbKk|r#M;3p{wr`I|g zQi^`mZ7EJ7Ylkesm5^%tgex#6#)+|B+tym?&1HpvJ90QzxE2^fvG?Zj_;UC?ybb_( z{r0z~hOGT^TtUkqGr6*K^4)u*e!j|U9_sA6Kt zr1%S5Gozp7wAL_;d!xD}sc9jO4OqIP)GxRI{8i7{cJA;S71IKUf|T?0CT&-@oDjL5 z{}K~6wN{E6_Za+@AOE9HQgN#jKerXUQ}JmRLeWOmu|*9nehPzSxOPDI&5Ts}jZ!9) z?3Z?9^a49d$*<7RqQA12;&b+~EQcI4fF}VQKEf|l-J3qri4teApD&CqgI6Wm81!AY z*xYCwV7Zf14607;-^wP_P&rkb?tG@J+`tgdRzlu>ey|eg-9?r>P8k})%u7=(-Z*qN zIfQcmoxV(v@=zo-3~uT_}RdEG9>5WG@4m~W_3 zM_f7XS*M8F3uG5>z<84-uoWKCQU-0KqVdeE#6LNKw1X705#8f3y*@Kr)?%Y%7uW@W zEvO2Iql3zekwFp~a2@xFyQ&yO_oazlcOYqOz$^D9 z2I*CvUU$~`7QV6*woA|wD@#>06qs%E>h44+W8R!6akv;Yf<7A3;)hqa#3yN z0f&yz!&e7MGJbq=%Oc?Y1+C$Gh3RE|gPkZQenNUrC9W|?uzo8T<(jGbo*qluY~bV& z*Hk-gHpz?P;3NyOF*UuCFV6RtYso{xmg(;rlP0<@cyx_XMhQ$@oh z!!kp7t^<-C6LSn!)Up~a3(bQJ1r84_qBIj9Gw;|0u8>a*8(kancNoxhE*&okUJ1do zFm{XNQYfBhWH-+rvdh5}NWDtbxKgvKRFQn-P(1={N1cbhkq=9pMe>jnvg*0Y=Gs*Q z^BbcD4NqC-%|OF$oz6!sSpcad3wV8DG??O!907_~hFDCTLCj%1qaA+WnX65@&H?4{ zg_}-~Kg^y5cGLR0Ni|_+meY-x6Sv>V*a}QBH4v)X=v&eJU^i~HIg&v|$1B7Bh{!S3VA&E%@p!UZ| zcBa7Z1%f>d6S~;&vOA@Prw}^%{%X|u{==lgS@bbjf=NCdT9Z7}&{A(sOokC#pWps_ z3GV1|oa(_gzV0v$vm%M>IX-#?Hx^y<%Y>U(t`A|vr+EYV)PrV-jpL5tDcg{tRPnTR zP9dfUz%Vj3&Dm?s?;zDPK=ECX;7YUYtE{nTWyMxjra){dm zWT-`7PhTs7IAXw#SDok`awkIUEMMYHT5?>fO=-1DjFT=EKbMEQAwCR>@6usS^b>@| z*Hx|@ISiC89ss4=K*=>1D({B+495VgRg8LXV=#?M&0e8W@P4qYaE8fs&3GG<+FaIW zrcbfZ48a4+DGvq#tdaVz$8{&HECMR8*I;67o^ml@^THqYl;goe2;h+hoqSXos^9xm z7U4(IrQ~8WaIF0de_;=$HF&0?v8bZyPE3!uaMoEl8Hf_zzbX5Cb9TP}eHV|86Ug|W z^`^-ePIQH6JrE2)up7QJUk)7+tEhuQHDLCwsOtnLbf{*&`$WAm#I+&FR3sQUJ@2>TG>>75 z@!lggrVdUg(%g>=n@IspXgxXHng;X1>uh6ZRu8`pNr^|V-8LY`)$h(`r8+>e`hN|x@FeA_P~*-!ZS4@Y_>Hs8%9XRN(n@NY<^hyy zK$PTFiJeeAyoqoB3&egHER)Z7?Gq}uDYrSjemXl4ZafO5&U(Bur4Zm}0sqpTmT{dV zTHQQk_z-M(A6)%X;baJ2<8&I+QcPB3Pbq*4MyN}ROWj=$y$A3}oZ?@NiuH9PbCX(| z*Tq0KZST=NbLA|r5aX0O!LQH zjO_oM96Mb)S$1MRVL}Zw$#_P_o8jlMZy3roPcVJ?7OEu)`40fX!4fOK^mF5 zHE0RBux5^^%rL)9V?2P4p|!W0 z9IGK}(}BnvUL!zO>@#+Q_{K-aW~MCW;G99kT4mAU{4xGOOy%MF^Ay~W0%`Hxm# z0`nOoi5^<;5y`7NizvJoVkY?m9s@x%%*U};Ic-f^Wr|co;_&mA{T6u-Ipog9gA689 z7yx@dpd|F1R=b{oJ;t5)cs_~zSZ%9uF{N%Rk+^|5Q`u{YeBK5(5dA@BEFMEvGgb8q z1U_*7H85NArWi#E)Q!WZu=gK1+}*1>`4?t61}h65V-uIqgV$d&#uvKIfWNLg<5RDV zKQ#dNQA{!s| z4m(V*5KU^FYs-)*F3AP^!SF^hS~&j|Ix)MkbHz#S$@@m%nLxs7WlV|Au3nbWK^Yp}QCm?Vy)cWOI#fIa4vg}_f%yTbvNzeZuT_;j zgma=0OlSg{hzteNUz*^(#Kuzm4g@JZ{kl-M%&kP%v?>1t5e-om-7u>TxM8Q)v`{uO zWJ~&R1X!_u2$DkO#uNZgisJh73LX`HBGT#(5xmGL1VXxAKB{H?+tc+5F2q^t0>+vO zplUg`RC5e2rzMKn0&>^HyTi*>i;}?2gowf9MO>#3NsGO>a-0+Ss?{K~L? z7Cy)RD-hFM#AVsf48j1irxvDuXhBB{BLy@vr^JlzgKM*yma4Z^-BJ+P=NvW5I$VHc&x`4e8Q*iHg9XmxPW4MMS!Q)R5$0K}7*YnzRT=Afbegv|s}S zq)7=qBGL%~LI_Dn@@~%k-!b0j!FwOR@PmY7y1isU<31Dea4rl$$=(+1=RM4+-_OB}5rBco&>R z9Ux}ii^2S+Ku1U^WQ5lc2a4b#-gGV7D@31Lw^A0ia8eW#^4#+iX`k_at;E5lo2c;q z5{=SKg(^UPc^U8dr>DB{FYI%v_3<22625FJlUzJ(Uutl`G)Y@NIDBGxqyKk9{^i*{ z0fL=52{zto<#JLZcME-OC5Fq~41vJD+gH+86lu`Xp9qwhKQuM+qyL30Y?Ia+C$Swd zMl{)u<1|(Ok?TP&(~-3MjzAx~J{?{-ZrcJiVZU#fu;`UaT1`sSu(7+ieoYffr49l2 zC0}D%!0ruKv62+>Dhmga1iGYmWX^N{d_1`wbY9K?2MBbtcx!^Q4koa(ln8|dbteOZ z`%ueYkoDK-NMng<;dO!9n6M}pOF2r|DG+u2EgSH zZ?#_8(c1jATMMnAa%5W?zXk`Sjp!IzfkQl<-|XxtSjRcFJfm&d`nd^J*4@=;0-mP;O%y8gyXx4X}p>|FDN1957XMTi|O?6W+drqc=%<7a036xN4K{+OlrVO&<OUd8n~R~jQGj?>a223iSWit<(0UA+cdm0RO?H0F>CfNl*f zwyhXFLLj=V{>Dhr_GKsHod=5|c})Su6Sp6uyY_~JhWALCE16V$PqF06`Yrw6`Mv(yLB_jk?%me-{E*8)Yco@>Z}KK8yn=eY%oU)j0d$OWG}Z^Pf%29m zWJ%j!w%goG6Zl`z)?0T8x1iO=d6>&{V(@XDi7g;JA6#_v(%dHs--&3pt2E#v0?OL( zJ|mc<#TUyiJDUt_wlyK5*sHg_`{rwSH57N8;0yr$?M!Lkw@FLXNSe-dU|i6lSA&_! zjR1w>Jp1OQ&pCOKZAuPcto4A5UniZ??`C|^Dn>#e_j>AUysfW8O^fqn1)?l7*ixcHUPbd=Pz<8TveDFE=rthmfqm)9wZto@;(IVV5$ zuMAUYbLb4j?#k%>RA9$ws{{1!O$SI)j3UMswXqiYZpM0IUE5~Qy6Gou_H~Q0@&Z*S z-%+n(tOB#AJxPPr*)&}4y-}EGu__IabCEZKHg^Vq%J%Q*Bq&rBnMxj#&DAb|T3bWS zu1QiWrdfMHw7^^``So>y!`OBun z6>4z?`aHs1;N<(YpHRb3*sMmD2^L^t{+R}jwFkP{yOE}UdJ3`ar-)U;xFCib_?S)$ zqBfOYd45UO4hT%lU;z;jk6(0kyYb{2Hzy=PNor6@SbpEZVF>Rnha7Zc5q@-Wq>1a? zQKEByPhKQMac;(YOcI|;sP?L;sJhA#Z z){AwLNXOG+KyFq z*W)Gk?UWVH$@A@g^DR{f5O&9tIu_g~?C#_8bs;=X86@{u1E8C=;lUtRmb80|;Cc|l zbuT^Gf>K^3?i$Lq(Qj09K~^At&x?wF&X?KSKuc_S9=#iYvSwdCxPf-QyQt^u+d;PN zAj5yCyk#_2=B(4zk(8r|2^n?HEpY%!OC5QCcPFAM40ah18l(Q*{UaTx`a2>!)|Bm}vER}<#k>d8 zrDnZxt^NF&>7fH-kp;TewE{)9{`OYD6mvD9?3OPNCg*wyKB1AOB)(L)=f7QK7`NYL zDLc0%bsIK^1E^WY4IMlp?j!$qk-faPghW;4hYmqtc_K(rebgMGto-&@BMUwYH>Pci zx+L?wKK;5>CYwa%>(?0fn1j!v{YF%Xg^9rPD1qPY`ac|(+mH7jmzT#htI9*Cg*gr= zteUo03~XhIz7A2?p2aOT&=y)gD=N&gmgUKgUJ$D)ZLpY!z8HjD>M+^V_Qn;m{JGz) z>X~(Wu4Mw4Mrm^hvg5U-`fg(yZJ;D~kL7=aj+R5Cu-4-^Tz|S3>Mb>CLB`Ls3hQbZZk949n?h?aXjiqb7lV)Zi^2>YpytiY?BTnA`0{q3g>hTBBT4$?v;?rkotoqmgA{ShvgKfbp(=6Ao!Y74 zZrZq+quu>f_1OuPZ0i#b^h>PS8B&%ie;=2|ZQv(-q||MyV4Oz0j~du6UQ!W*@i|al zzjOZ=ZueztFM%$lJ00CLk5ek@^L4^kV29oeU$3|w6vS()0<_EDEVL!*XBfXORdLQ8 zagTV78DHezm+UT@(O#rc<2vot$sxCLCtU8cIroqJE65Cd`W~=TF#|+XMR{8CYzAnAUqMw_ zG=n$aq+=5)|NI8bEB})zY8%=111?EtLVrA=wESmfbKzO%kd#F3to>oX%yzb!}wvliZD=CVqD)UVidWxjc0^% z_y;_2j>V(GV0P)<=}}NS+jd?-#cV1bq5pqVn^9*3x8;m&4}dUU6Vhhkl1H?oQnQce z7!Ud=``mKLi!20(x@R2;Qqk(ZE(x=X!e%2k4&&mM;V0JboOZz4m)EcvX}|#yN6n`e z7TOP^&HvzzJen%{Z!&;TsWsXxQ^0!RgeO{A8qZrAN8<|J`+t1SF$QEkT){~x|LX%* zEs1h-W<8Cw0PD8E$E-t-%F7Ma>k_TD86nfWNM$fOYqB+K2R8c%n4^IR7@W=WeGZg# zd3Oh&=Id5xAZCE$LXxx}7HH&R_jcl(S)#2Axz0ZvwNWJuG6&zpTz^sosfHX3}$XhNYwz4+A zu|%?iU1#_H_QV({MGZO#UCN8(bqx0<;ZY&p^@(z7fX$$H&dqK|E8vRx*GZU_L;)@m zEK}2_Dt8FL7Nq3|?3S>OaXy{__y|)VQoB;N3L6}~3$*dBWZRCB%s9pO(W=mDXxg;Y zEW`n(S{j(=>Cag|Rv*$7VXDt-3Md?Xd(s~5pwfT}x=jyVtXLbrjYl#4%vw^O_+XuZ za)ZWBHzQQR`5*hUPi3VLq3w2dzA%6wio0M(_Onx>Oap?4mq?yt)u?v_vUg$~`vuTQ zYTqcR=sb$o*%@rZ{{~w~XFEOF1AQwX!LcTIYz?4NP7bgA@Ej}xI^5z@IxZ(@`nEP2 zu)H6Z^DcK~-Ob#2t!<RaeH!FO*D?4!;Pd}pLoHl{_voVJPNN<%!?j91HtnBg6@){rM6dC0w-8uy^j>M zChoQcl#Z2qGd(+F0{0)KLoY3fQrxYf2e@uM7WieJ*Bc{aiXEIPn|WxdOgSQ@qv94u z)cTMr{-tDh!h+{DKnorx+iTA`WLsL^Z(r&}g$faE_+$df$&U+%eJYEW0@H9Y=CLG{;@8OA4QDQO@e zOeWa*(*c@?^CI+k&@;3Bk+=!Vt5Q~b3%who_G8wLzGPNe=-eTSs$T`94nFOWozovj zQvs#pa%X!=I6oEH9h3IZUw+Qs=ESnB+;a8YAV^!BuGwUt2hS3+k+Cbb^~c3Rl_Ppx zUG*9Z3Zv)L*sDNW$P`{TEt#1u%&^&6OaF?J1muD3yyOQ*8#A(Kr;}E&j&e4jAa|2# z2cPM{n{8H9!SPi*C zFRTfYr$d%5>?FBdReL}7174hKzBx=UVHH!RAeIQN8YxX93_-Q4#J;{)=w#}Y(wuh!+O%nC>I==x8b=qN{l3I0M(?+ho#kZh; zt>fhwMINj%j#>!ywv|be;Twi#StSh>E;9g1e82Yg*m*qjeCv@NW#F&f7q^SewsziW zm+9w#@tff_6?>G`Y}5@P9G-k&I%|(y-8qZ?f23@xp*iI`O`Zw5v{Wf+bsIp_+9SRB zD6Nb#T?hlH&Hsis&QFAQF2_p2DWG(EB`Q=|Ov7W;!j~kMCEb8=ju)zGHLkt>jVr8v zBV!Fq$B!%{J{y9X`p%o$$unAE_!bHZpLb_iYCtlPcAZ@S8T+}>%GJviD3@7gRh5-@^xVzZ?S@?Q zDD0l&-M;Qm{x{z7zm&mg2M-B(6@aDh{~=T6(^D4BG$Ff8c=u8o*ClKH+Fu!8zbdu* zcC-J$cn9<3n;&*};B<-dyp4G<>yzBbzEDq-d(l1R-C8kZYE0^@ov7| z=CUyH^hT3czEo zN-B9BF`wSpNw?vGpGS zhCeuAd5$$i)I#Y^1e?h=E^Vfc4urcD&mt$lNu*SHx`^?IQ&qnnjBYioyvJ(!Jm zNp1DSSQE0nwoX?4s6;g19yU(GNxl-$#Q6IZFHXO1oT`w80|^?s6?zJ=pK7IQ+}{z} zslXjXJlpnDayQrxLVjE2n10^POWm{>w-<|3#6jEXd!M|&u=rqfa4}d$D)D5mmwg%3 zHhvDAr!jAKcAbI? zCMM*>WH-oZuItTC3-Dw&JjRno%dgk^4LAZ|T3^2`y1F``-`d?OX?;_RQx0BG$h)nZ zhVK4fRtK1v)RiWQ)QDDwO1Mc`qo}uV2kFXM=>6FKr7`2W6C&F8qXV-q@MK$eemx}( z!QB=^2*fz&EzY3>%3@)WD z>TEOHOGn(}{xDQx_TPT9RcyULDlo;&c91!_E&w=AkI-|u(>SjzY&G6C-R>YMgKuDU zOgKA#;r{ZmqR%0~ZQF9lPI1b%J#X;D8DJo5^ynSb&Oo;P&wR|bHLw1*#$HUI*!A%8 zH=m7dC6iC4T0ffy>)xzbpI>D#ZVqOUii;%0>?9=wTAvGL$17qRG?G?@CT^Q&X-)vQ&CFl6YN9G9u7*Eu8#NNhnJi#1>e08tYdoq;dn%vgA#wp5 zg)YC941`VUVH)9jpniDUmi_^vFFn=q=G$_}$K^j%mkP;k#gR9 zO#vNH)lkuJrv(fmE?@hxUp55jiWJS-PD!mdv?g|cPg$?IQ&3Le(uVnLmL;Fy?5m8c zN}ehs(Bbj{e$t?H1nhRJ`8Vr z%-Tn2o^vJt7&3i)J)=U_+S&6R&>gJmzgEl(w3*A(=}vWoW=Pe1a(%Z{5Tzp2p;}XV zr`fvgmvXhOw^?kDQ#&TDg0xu}r^96s?J;ke%e5>~{hD&D*0Ck|9Yx`sy!URcGpSO7 zFE$>FYk!jBy^2@~)phkpZn)_s1N}$8u9xeV_x@jeUIxdt#{V zBh;wP{FL+kC>xmy600Y3qs0R)!c6gqQOa{DdI$9ZWN%*J{ezvYx|H%P_y))gV9TeH z`c)xhjW5Z`g1~^1WI~?#yjQeKA(WhnT6=YKqd(sXw}gdre@?t|R|)obDDnsQ-Ca{x z@jZ|v<7VJewMc2K2V-0sR6*2T^l8piG`TK`2JntV9tL7-$xofbycke4J_F%AO29O5 z6J;sG?)4$$>Kn(3N?)bfVvi-UThQ9~Qe2Qv@~Yff>mcNaW@gvROoJn*cF5&Nf#HJ8 z!=?j^!CI6C>UYh>jaD>s51i2_TKK^lFcS6e!+obxrf+|WVa7~6h?-sq_nQv<^y^MR zf^J1~UV^MF#pbgO#=u5E*zt}-+9;eelbQ*PPbbT1w{X@ixc#cCsu+rC>CS0`|HL$K z0OLfL=Aw*A9LXQX*n$mrJBQr;_G*nY!$#V*S@W7=$M7y#hjmjd@P-mSrHc+-8=A(?=Mt{#T!`3HOsjH^lP1GN?nu5C38Yhxo*7t4l4|$0zD!&4eimMDuw$3weii(Ns&&+*(*|iChmXV z?`0f}YJVq%>#`6-a-6Sqc0p)wnTsa`oC=q#r(40pg!MeR5jLF!MtD5b`5#v~KQkna zJkdBRy153kuYmVoA=w?7hU+@PN_1ym@3vTw$lI`znuZV5CbwdDTk#rW_x2d`{w>BF zegqLsl(Or@P2Zi%;&c{|aeONLPC0LwvPOu6yY%r;baLOrKg=ZoV^&qWwFFXQ`t!#+ zHfLsLmV!`W@j5~NcRczlVphhFfSN-7Re z;1Nl?tySEuY|?G5#$lLKA`@PttR|~c4=`5<{&Vun#sD5UP&dAuE0`&w_kS~2K+wsL z0@LGay4zREnjt#LZXo76_EsL;2b&{k^(ag9#mP{dz16(+`Cg+u#CiEDjOdKJ%2k*% zAe%T_yGp6hvdbfK?{&63G~O}>2$P7U1+E{fo==OLL#f%Xh1CJBAPo8a?RAes=9`y0 zm8Wwnb0>!YG~;1H9;xcsAdh;iuI^vzK(SA4_!CeT2W~VsCiDHWf3uV{pld7^!E62` zfnb*fnie;gcw!tcD--V84h&a$C5jre1O-DJa&0RkiZMT-!<==F87pM4)CY;Ka+GDw zs5N1u=ND4D_;&8Ht3RzIOHV{$6Qq{Aw5g`v%0e6bC|YYs2-Z6V?ZW@odi5PX3<3j; z$nMZ)?Pmgj5+i*w)e+VqYZo)nV9dY`d>bK;SvRLOkote!9v7Sy2Ijg(&OIkb6-Tj` ziCQ6?Cn@%7oqBuLPl%fXXG#>D4Ou$5GqJA7!2q!Wlb4qV3?qKK&HBC2N^VYBs_I)@ zFe{mj@p_OYJ*50>e~em^@#j@^(oo~tGYWSAfvSK_x&?w13?t8h! zQ-&*i4h8XzdihGI57cyLNl3dbC@-qf9~WW$5sOZO(jqVZfX4p$m}~J9rs;+&I^GCe zemdR$gM=(`)yu2a@>9$JaHo8-l4@l}{QK)oJjVFVj}(7SED9uPc8 z56KhtKEmnVA?sn%2R3TbbI=6*`;YxOw5gKz4dzB>$Q`tXV`;0-{QIMzy*{_ul%ti2O2ozhE41eJl zvBgU&@l^QSx^@P_Y=>g)3J0q$=wqQA`T(sOQEXHCM5(JRBwS%{enXLeP|%xlg5mZ_ z0y|9~(L9{mJrEay8t~Vi_(LXge1DT4KawmR(z~3dr$7qG@X-_2 ztLLi!j<-1p!zC9AB7W*ybcIs1Iz=PruCYec2)Dl!_~ZrZO-EpL?xQ-Qd9O-dG!a%z zTAF9wwsC-{2&{YV0|#4j(=YngH@zA8b;d(lz3Svc$haRd?yN@6gW|`-%)4PdL329< zmzBAro3j9$y#yCan%hoGUR933WD-vvr>o0JX7r5(y22Te7jd(*GJnnr>kJ%6p)HK7 zf%*hA62UD|Z*MXzeY52gd)zz;6*BT%?;12~oR&Q~G>mcv=}Es4UvyO~2QjXFC)%xbT_jopco0wzjpos{wdXm!bM3-$+p z!%-a;D|U=!F#YteLdT_Pg#4mJ3i%Ny_Dt3 zpN4_DFRYLbnTGew_sj9ChubEi!l%|^9M!`u+beR-ucWM#SBTtn#I!f5)TG~Hp)FsH zy#A!FnO9Zp5kbJD*>WL8>a>l`_irH3;RxH8G3T$^JTnGd=5wpiigf^nb3k?HNS3aW zeO;H{&VnV?^AZ|a%UV8SG<7h2EXYRfL#t}_AbF^a@|a+?V3ilx^mjZOTUne_j^!P+ z{zA1^V$#-w$8gnmgIV<_5L(nqosgNg9z*y2;xD+x6okjwY?AmV9$8Hk8}rXA=p0up zjogLmryJA<2Quy(f?4IdPVeNV@s=CJIgHk8yp!bZtmDZ~LF-War#gko$>68~;mWxVJ{bB5EpNn7kk zO{i761&2chC5R5JJ_YUzm%DU0{NXE-c8@Xv_~b@<<@8{?3$Ju1R6Ql9lQyFf)K6bR zhR+<@c&rl?()BPcJ-^-chpf$KtM}2CJT&xL)^BoGvSQBqGf`m7F9!3|L`mhkT)~*d zE@_=($CGoo)U?*$&DOG8Hp(`xxKsHd>vPAn0%gi>!lk#-jZtIX@zEjY8b5#ONV`($ z#JyK!ZG1d$#pm1$<|%6E$NQ!ipO};j>U<)mRl@wlQXAReOX7+MpY);pXvnPgmb@_{ zg*zrA!Nl}SlPlA((o!i>Zqgae3UOS%mBi7DQ7868uePHOW*yGotl(6L_KWbF`f@AT zVPW@K0XkFuX=IPj;vI&Z>Un99ZxT8FY&G{Q>g3;-Afg``xQa zlvMv+6CmH-F`Z-jhA3&7D85JdvQ!1c#<_`jumc?F(UX;WV#+X=z$x;iU8$r!SdmPv1=QkQmz>YzZP^%p7hFMsdFQs1h5BO0W4 z!y2=hB|iunz8~%g3oi~@gK#pm{^Ig-oc4gprz;{uGgsM|etUM9T+In~Htj)E`plr! zRcY#69VKx?^4R0nWP_TccX@}cI2GWf*s4g(RZu;r0yd(g^OMwCvoh8e{PN*F&R7^@ zH85XS73sHC4k3mvtZ_cHHpCE)AsF3yPsd!o(TC{0_zHr4ygZW==g)i8kMgwXdS}ym z2EK!6wKg}o@j2pN+qYaD)x2o*m_zn2hRWwvK{CsP|yzTB?C zl@UT5Oqe=t5}`X#PVj>Hoy7)Qu<@=7-};ENtXY2M>W8;-Q^KoeJly*aa%r23kxo;z z=oBWXE>@cM%8c3iO_<0Ojo~&q#DV#ueowV-e%k;ItD)pyf{Xi#*+XM%AYa(%26ed=?@!XXYv4OkPFU$O|V#;2g`bm{jmqB1GD@x!Z{!R$UxtjkeR>TESk8#x~4 zjy#K0We1>^UekYo%Mh}2g`)V@8jwparG)v7K^I_3A$;PpsN|Q8EiC4@O^_^DNQYSEUvHq#Pd&)h&fz@ z1Lek7+hL3%^EsiQ^UL{D>iHw-COsGDKk zo79L{?%6Gian6P}&3Dwd(tiqV*h+Ex8jn&=ZX&`gG8=03)sHl;ye7xHpaNNhSA*)+ ze4Gdw89b;(b=3b&@9Ls}8wy1zP_vq8LItx>Yjp1?{v9=%5#UHXcTNMGqU#sQ&KKow zEc?N<3>Vi>MnNV`v2g~W>yEHN)JFbRm;s5sX@THA(P!s5-n}zLXII@y${kqn81Lo2 z#{XUOhT`t)5$Q{BWd~1gK4_(|eoQTPhx)=S;)s*d8^o<#@*)o*9A+5Ced;DeMy(JD zn|0i_)tW}|6q%Vy>pn~h-g0cInN%aeNb$YM_zC>vDg;g4|3DbVMX(6wU_p`z9q1n(&2<8VV~S^7Seq_7rzwkrKwrRq@69vw{iZy|k}*2R9U$^ZJGV z7yl^_gHiaMEmqJJopf=OKE+w4q80-EmWUr#bdM**7q6;x1ORV_Go_*%`0`>ld6gnP z@L8PA_88}2r|2|h_*y!NUd7T_Bi8q}(KfpYum~i4^}fg%2ZlH33@VpR%QK)zavA+( zRvBY)OK?J*sp}X~$zElzuCi(mED|>mAhxRG-7O?_YJ37|PuU2ua0rYv<*d&QZJk92 z_ARmlNVe*i$3ciAGw{KKZ)+9Y`YaeG8j@oHMb=#USm`2M(;QF9N7$?AZ&SQ z6n}!{r-O2vx=3R)A+jH&XiRa2T{2-7l7&~s*Ke1y5&w0-6F1i;Q0D0 z7r8}}YVgfpG=n|1G$Pl(&25_NaHkM7*~jE~RRPXA+MPLi#4mCN9h(NK`cp>x=gM=kR4Yk;}nQpXdo!KmCeqGwL8(0ijL)D$_zh!FTKu0~N1yulYA*$``(%xr3!T|7XM2G5ZBUdFjU zIMO;w&;P7GJaP3jDnjO^4Y#EAOGKmwA~TYIk#OLL{M=(YBQ-0WzCa*P zpnJ)$RbG-D2p)v*bCK~OAL(RJCaTzVT~rv2?_Fg`Z*>rt76T?;H?<^+vP!y}Mmy%6 z!eaeBw(9OT@_|{RvDFkjZI-e;>o8bceY!r~sx<*D0f{&tZ(~BZj3Bmq zGrgcO)ngK)%LdI|j@HuoxVw{m2!1I>M5AG?hZUpRAg�J)hN@B9#<);O``XcWbR% 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 X$FlH?XzZc-00000NkvXXu0mjf1{7?P literal 0 HcmV?d00001 diff --git a/measurements/Throughput/client.graphml b/measurements/Throughput/client.graphml new file mode 100644 index 0000000..d0b1d53 --- /dev/null +++ b/measurements/Throughput/client.graphml @@ -0,0 +1,185 @@ + + + + + + + + + + + + B:funbody_throughput_test.py + + + + + + + + + + + OUT: + + + + + + + + + + 0x2308_U1 + + + + + + + + 1751825758771 + + DEL_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + + ADD_NODE + WyJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMzMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NDg3LCJ5IjozMTN9LHt9LCI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + e425a002ed1453f66a4fb1dad3ad2923 + + + 1751825761336 + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDg3LCJ5IjozMTN9XQ== + + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6NDg3LCJ5IjozMTN9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + d7861c7337345a2010806e89311d85bf + + + 1751825767651 + + DEL_NODE + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + + ADD_NODE + WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTA3LCJ5IjoxMDJ9LHt9LCIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + 19b85e105d5758f18c55915fbce84663 + + + 1751825770936 + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTA3LCJ5IjoxMDJ9XQ== + + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTA3LCJ5IjoxMDJ9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 03b8818572c5800d88c583073a1ef559 + + + 1751825773370 + + DEL_EDGE + WyI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLCJ0YXJnZXRJRCI6IjIxOTZjMTQ2LTE4MGMtNGQxNC1iYmFhLTM0MGY3NmUxNDgwOSIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQifV0= + + 1dd8b4edaeed282d75d1daeb3195b728 + + + 1751826367735 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + ca298c11df338ea36bce176af0fe3b69 + + + 1751826515156 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + c6ee9fdcb90f48bc1de9bdc44b7da91f + + + 1751826596605 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + b79566da6d5ea6c2cf2cbb618da677d2 + + + 1751826901740 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + ba871dc0f4bc75adee32e34c87854508 + + + 1751827730897 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 8bb2b4d5cd9d445722b307d6bdb3d9fd + + + 1751828973865 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 3609737de0e0d000c3d43a620f592090 + + + 1751879990560 + + UPDATE_EDGE + WyIwY2QxNGIzOS1hYjBiLTQxODktOTcxMi0wMGYzMGQ3Y2VmZTgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyIwY2QxNGIzOS1hYjBiLTQxODktOTcxMi0wMGYzMGQ3Y2VmZTgiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwOF9VMSIsdHJ1ZV0= + + 0fb79b2f266bed8408c82460441b7871 + + + \ No newline at end of file diff --git a/measurements/Throughput/funbody_throughput_test.py b/measurements/Throughput/funbody_throughput_test.py new file mode 100644 index 0000000..d517488 --- /dev/null +++ b/measurements/Throughput/funbody_throughput_test.py @@ -0,0 +1,40 @@ +# funbody_throughput.py +import time +import concore + +print("Starting ZMQ throughput server (funbody)") + +# --- ZMQ Configuration --- +# Ensure these environment variables are set before running +# Example: PORT_NAME_F2_OUT="F1_out" PORT_F2_OUT="5555" python funbody_throughput.py + +# Initialize the ZMQ server port +concore.init_zmq_port( + port_name=PORT_NAME_B_OUT, + port_type="bind", + address="tcp://0.0.0.0:" + PORT_B_OUT, # Bind to all interfaces on the specified port + socket_type_str="REP" +) + +# --- Server Loop --- +print(f"Funbody server listening on port {PORT_B_OUT}. Press Ctrl+C to stop.") + +try: + while True: + # Wait to receive any message from a client + received_message = concore.read(PORT_NAME_B_OUT, "throughput_test", "{}") + + if received_message: + # As soon as a message is received, send a reply back + reply_message = {"status": "ok"} + concore.write(PORT_NAME_B_OUT, "throughput_reply", reply_message) + else: + # The read timed out; just continue waiting for the next message + continue + +except KeyboardInterrupt: + print("\nServer shutting down.") + +finally: + # Clean up the ZMQ connection + concore.terminate_zmq() \ No newline at end of file diff --git a/measurements/Throughput/funcall_throughput_test.py b/measurements/Throughput/funcall_throughput_test.py new file mode 100644 index 0000000..6c58aac --- /dev/null +++ b/measurements/Throughput/funcall_throughput_test.py @@ -0,0 +1,57 @@ +# funcall_throughput.py +import time +import concore + +print("Starting ZMQ throughput test (funcall)") + +# --- ZMQ Configuration --- +# Ensure these environment variables are set before running +# Example: PORT_NAME_IN_F1="F1_out" PORT_IN_F1="5555" python funcall_throughput.py + +# Initialize the ZMQ connection to the funbody server +concore.init_zmq_port( + port_name=PORT_NAME_IN_A, + port_type="connect", + address="tcp://192.168.0.109:" + PORT_IN_A, # Use 127.0.0.1 for local testing + socket_type_str="REQ" +) + +# --- Test Parameters --- +TEST_DURATION_SECONDS = 10 +message_to_send = {"ping": "hello"} +message_count = 0 + +print(f"Running test for {TEST_DURATION_SECONDS} seconds...") + +start_time = time.perf_counter() +end_time = start_time + TEST_DURATION_SECONDS + +# --- Main Test Loop --- +while time.perf_counter() < end_time: + # Send a message to the funbody server + concore.write(PORT_NAME_IN_A, "throughput_test", message_to_send) + + # Wait for the reply + reply = concore.read(PORT_NAME_IN_A, "throughput_reply", "{}") + + # If we get a valid reply, increment our counter + if reply: + message_count += 1 + else: + print("Warning: Missed a reply from the server.") + # In a real-world scenario, you might want to break or handle this + break + +# --- Calculate and Print Results --- +actual_duration = time.perf_counter() - start_time +throughput = message_count / actual_duration + +print("\n--- Throughput Test Complete ---") +print(f"Total messages exchanged: {message_count}") +print(f"Total time: {actual_duration:.2f} seconds") +print(f"Throughput: {throughput:.2f} messages/sec") +print("---------------------------------") + + +# Clean up the ZMQ connection +concore.terminate_zmq() \ No newline at end of file diff --git a/measurements/Throughput/plot_fig4.py b/measurements/Throughput/plot_fig4.py new file mode 100644 index 0000000..2076d57 --- /dev/null +++ b/measurements/Throughput/plot_fig4.py @@ -0,0 +1,34 @@ +import matplotlib.pyplot as plt +import numpy as np + +# --- Enter your collected data here --- +# Example values, replace with your actual measurements +throughput_mediator = 15.7 # messages/sec +throughput_zmq = 25432.1 # messages/sec +# ----------------------------------------- + +protocols = ['Mediator', 'ZeroMQ'] +values = [throughput_mediator, throughput_zmq] +colors = ['#F44336', '#4CAF50'] + +plt.figure(figsize=(8, 6)) +bars = plt.bar(protocols, values, color=colors) + +# Add plot details +plt.ylabel('Throughput (Messages/Second)', fontsize=12) +plt.title('Figure 4: Maximum Throughput Comparison', fontsize=16, pad=20) +plt.xticks(fontsize=12) +# Use a logarithmic scale if the difference is very large +plt.yscale('log') +plt.grid(axis='y', linestyle='--', alpha=0.7) + +# Add text labels on top of the bars +for bar in bars: + yval = bar.get_height() + plt.text(bar.get_x() + bar.get_width()/2.0, yval, f'{yval:,.0f}', va='bottom', ha='center', fontsize=11) + +# Save the figure for your paper +plt.savefig('figure4_throughput_comparison.png', dpi=300) +print("Plot saved as 'figure4_throughput_comparison.png'") + +plt.show() \ No newline at end of file diff --git a/measurements/Throughput/server.graphml b/measurements/Throughput/server.graphml new file mode 100644 index 0000000..81b5102 --- /dev/null +++ b/measurements/Throughput/server.graphml @@ -0,0 +1,221 @@ + + + + + + + + + + + + A:funcall_throughput_test.py + + + + + + + + + + + IN: + + + + + + + + + + 0x2306_U1 + + + + + + + + 1751825545123 + + DEL_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + + ADD_NODE + WyJBOmZ1bmNhbGxfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMjMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHt9LCIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + 0f6a06a5f49f1d83657221f267bbf65e + + + 1751825547451 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjEwMCwieSI6MTAwfV0= + + c07fdf0b5fbc290aea42a3bd74c45a6b + + + 1751825549601 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjUzMC4wMDIxOTE0MDExMDk5LCJ5IjoyOTIuMDAwOTc4NDg2MDc3fV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + 55cb72ce7faf50386f9f71afe1e576fb + + + 1751825564072 + + DEL_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + + ADD_NODE + WyJJbjoiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjoxOTUuMDAwNDg0MTQ2NzU2OCwieSI6OTAuOTk5OTU0MTMzNDY1MTR9LHt9LCJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + d13798fff2bf40cbacc6bc0f73cc3e5a + + + 1751825566634 + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJbjoiLHRydWVd + + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJTjoiLHRydWVd + + 1292dab0cd809e0bc822a88cbe296a4f + + + 1751825570934 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fV0= + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjEwMCwieSI6MTAwfV0= + + 71a0470230ca5a52edc2cb9ff06f3d28 + + + 1751825572700 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjE5NS4wMDA0ODQxNDY3NTY4LCJ5Ijo5MC45OTk5NTQxMzM0NjUxNH1d + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTk1LjAwMDQ4NDE0Njc1NjgsInkiOjkwLjk5OTk1NDEzMzQ2NTE0fSx7IngiOjE5Mi4wMDA0Njg4NTc5MTE5LCJ5Ijo5NC45OTk5NzQ1MTg1OTE3N31d + + 86c56976fc63f27dc9485ecc73f2de2d + + + 1751825576935 + + DEL_EDGE + WyI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLCJ0YXJnZXRJRCI6IjI0YmUwYzEzLTVkOGMtNGY5MC1iMGJiLTFlMDcyN2IwNDJkNyIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUifV0= + + e3d7f90d81fe934dfa3c417169de8824 + + + 1751826381936 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + 39ad7e349fa9310a7b969d4ebab5282e + + + 1751826525320 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 8efbfe0ae1b0204fce1d374693fa71a4 + + + 1751826583001 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 28d360705ea6c4b2c2fe71ddd4ac747b + + + 1751826587218 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + 4688004b0c03d91e2da0b196f1c26a63 + + + 1751826894632 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + 8cbf36e069285329a3e6c103fadd2d15 + + + 1751827827801 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 474cb438a743ffd7c3e75d28317657f3 + + + 1751828982344 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 4ec6d444cdddc40c1917aba4da2ee7d0 + + + \ No newline at end of file diff --git a/measurements/readme.md b/measurements/readme.md new file mode 100644 index 0000000..6ef9f52 --- /dev/null +++ b/measurements/readme.md @@ -0,0 +1,59 @@ +Performance Measurement Guide: File-Based vs. ZeroMQThis guide provides a step-by-step methodology for quantifying and comparing the performance of a multi-node system using two different inter-process communication (IPC) methods:File-Based: Nodes communicate by writing and reading files in shared directories.ZeroMQ-Based: Nodes communicate over high-performance, in-memory messaging sockets.By following these steps, you can generate concrete data on latency, throughput, and resource utilization to demonstrate the impact of migrating from a file-based to a ZMQ-based architecture.PrerequisitesTwo Project Versions: You must have two separate versions of your concore project generator: one that uses the original file-based communication, and one that uses the new ZMQ-based system we developed.Python Libraries: Ensure you have the necessary Python libraries installed. psutil is required for programmatically measuring CPU usage.pip install pyzmq psutil +macOS Command Line Tools: You should be comfortable with basic Terminal commands. The iostat and top commands are used for monitoring.Step 1: Test Environment SetupFirst, create a clean directory structure for your tests.# 1. Create a main directory for the performance tests +mkdir concore_performance_tests +cd concore_performance_tests + +# 2. Create a directory to hold the source scripts for the nodes +mkdir source_scripts + +# 3. Create a directory for the file-based system output +mkdir file_based_project + +# 4. Create a directory for the ZMQ-based system output +mkdir zmq_project +Next, create the following two files inside the concore_performance_tests directory.a) graph.graphmlThis simple 4-node pipeline graph will be used for all tests. + + + + + + A:producer.py + + + B:processor.py + + + C:processor.py + + + D:consumer.py + + + A_to_B + + + B_to_C + + + C_to_D + + + +b) test_data.dat (Large data file for throughput testing)Run this command in your terminal to create a 100MB file.mkfile 100m test_data.dat +Finally, place the sample node scripts (provided in the other documents) into the source_scripts directory.Step 2: Running the Baseline (File-Based) TestsFirst, generate the file-based project using your original mkconcore.py.# Navigate to the project directory +cd file_based_project + +# Run mkconcore.py to generate the project +python3 /path/to/your/original/mkconcore.py ../graph.graphml ../source_scripts . posix +Now, run the following tests from within the file_based_project directory.Test 1: Latency / End-to-End TimeThis test measures the time to process 1,000 small messages through the pipeline.Set the test mode in source_scripts/producer.py to 'latency'.Run the test using the time command:./build +time ./run +Record the real time from the output. This is your End-to-End Time.Example: real 0m48.521sCalculate Average Latency: End-to-End Time / 1000 messages.Test 2: ThroughputThis test measures the speed of transferring the 100MB file.Set the test mode in source_scripts/producer.py to 'throughput'.Run the test:./build +time ./run +Record the real time.Calculate Throughput: 100 MB / (time in seconds).Test 3: CPU & Disk I/OThis test monitors system resources during the throughput test. You will need two terminal windows.In Terminal 2, start the disk monitor:iostat -d 1 +In Terminal 1, run the throughput test (time ./run).In Terminal 2, watch the MB/s column for your disk (e.g., disk0). Note the peak value.Stop iostat (Ctrl+C). Now start the CPU monitor:top -o cpu +In Terminal 1, run the throughput test again.In Terminal 2, watch the %CPU column for your python processes and note the approximate average value.Step 3: Running the ZeroMQ TestsNow, generate the ZMQ-based project using your new, modified mkconcore.py.# Navigate to the project directory +cd ../zmq_project # Go back up and into the zmq directory + +# Run the new mkconcore.py +python3 /path/to/your/new/mkconcore.py ../graph.graphml ../source_scripts . posix +Repeat the exact same three tests as in Step 2 from within the zmq_project directory. Use the ZMQ versions of the sample scripts.Step 4: Analyze the ResultsFill in a table like the one below with your collected data. This will give you a clear, quantitative comparison of the two systems.MetricFile-Based SystemZeroMQ SystemImprovement FactorAvg. LatencyYour value (ms)Your value (ms)CalculateData ThroughputYour value (MB/s)Your value (MB/s)CalculateEnd-to-End TimeYour value (s)Your value (s)CalculateAvg. CPU UsageYour value (%)Your value (%)CalculateDisk WritesYour value (MB)Your value (MB)CalculateThis structured approach will provide undeniable evidence of the performance gains from your architectural improvements. \ No newline at end of file diff --git "a/measurements/throughput_test/Screenshot 2025-07-07 at 12.43.32\342\200\257AM.png" "b/measurements/throughput_test/Screenshot 2025-07-07 at 12.43.32\342\200\257AM.png" new file mode 100644 index 0000000000000000000000000000000000000000..f156b6b2f9326e7dc986ed3386b783c975b75ca2 GIT binary patch literal 235625 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

XY}1S>b-jOij}uH>$;|f{zpHp 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νcisp>_=&=1ZQN1RU+?|A(%( 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

jDR4&>onZMjlP@sw2eyY_+ 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�J)hN@B9#<);O``XcWbR% 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 X$FlH?XzZc-00000NkvXXu0mjf1{7?P literal 0 HcmV?d00001 diff --git a/measurements/throughput_test/client.graphml b/measurements/throughput_test/client.graphml new file mode 100644 index 0000000..e731ea1 --- /dev/null +++ b/measurements/throughput_test/client.graphml @@ -0,0 +1,173 @@ + + + + + + + + + + + + B:funbody_throughput_test.py + + + + + + + + + + + OUT: + + + + + + + + + + 0x2306_U1 + + + + + + + + 1751825758771 + + DEL_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + + ADD_NODE + WyJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMzMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NDg3LCJ5IjozMTN9LHt9LCI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + e425a002ed1453f66a4fb1dad3ad2923 + + + 1751825761336 + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDg3LCJ5IjozMTN9XQ== + + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6NDg3LCJ5IjozMTN9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + d7861c7337345a2010806e89311d85bf + + + 1751825767651 + + DEL_NODE + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + + ADD_NODE + WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTA3LCJ5IjoxMDJ9LHt9LCIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + 19b85e105d5758f18c55915fbce84663 + + + 1751825770936 + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTA3LCJ5IjoxMDJ9XQ== + + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTA3LCJ5IjoxMDJ9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 03b8818572c5800d88c583073a1ef559 + + + 1751825773370 + + DEL_EDGE + WyI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLCJ0YXJnZXRJRCI6IjIxOTZjMTQ2LTE4MGMtNGQxNC1iYmFhLTM0MGY3NmUxNDgwOSIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQifV0= + + 1dd8b4edaeed282d75d1daeb3195b728 + + + 1751826367735 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + ca298c11df338ea36bce176af0fe3b69 + + + 1751826515156 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + c6ee9fdcb90f48bc1de9bdc44b7da91f + + + 1751826596605 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + b79566da6d5ea6c2cf2cbb618da677d2 + + + 1751826901740 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + ba871dc0f4bc75adee32e34c87854508 + + + 1751827730897 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 8bb2b4d5cd9d445722b307d6bdb3d9fd + + + 1751828973865 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 3609737de0e0d000c3d43a620f592090 + + + \ No newline at end of file diff --git a/measurements/throughput_test/client_cpu.graphml b/measurements/throughput_test/client_cpu.graphml new file mode 100644 index 0000000..495721d --- /dev/null +++ b/measurements/throughput_test/client_cpu.graphml @@ -0,0 +1,185 @@ + + + + + + + + + + + + B:funbody_cpu.py + + + + + + + + + + + OUT: + + + + + + + + + + 0x2306_U1 + + + + + + + + 1751825758771 + + DEL_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + + ADD_NODE + WyJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMzMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NDg3LCJ5IjozMTN9LHt9LCI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ== + + e425a002ed1453f66a4fb1dad3ad2923 + + + 1751825761336 + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDg3LCJ5IjozMTN9XQ== + + + SET_POS + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6NDg3LCJ5IjozMTN9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + d7861c7337345a2010806e89311d85bf + + + 1751825767651 + + DEL_NODE + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + + ADD_NODE + WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTA3LCJ5IjoxMDJ9LHt9LCIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ== + + 19b85e105d5758f18c55915fbce84663 + + + 1751825770936 + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTA3LCJ5IjoxMDJ9XQ== + + + SET_POS + WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTA3LCJ5IjoxMDJ9LHsieCI6MTAwLCJ5IjoxMDB9XQ== + + 03b8818572c5800d88c583073a1ef559 + + + 1751825773370 + + DEL_EDGE + WyI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLCJ0YXJnZXRJRCI6IjIxOTZjMTQ2LTE4MGMtNGQxNC1iYmFhLTM0MGY3NmUxNDgwOSIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQifV0= + + 1dd8b4edaeed282d75d1daeb3195b728 + + + 1751826367735 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + ca298c11df338ea36bce176af0fe3b69 + + + 1751826515156 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + c6ee9fdcb90f48bc1de9bdc44b7da91f + + + 1751826596605 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + b79566da6d5ea6c2cf2cbb618da677d2 + + + 1751826901740 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + ba871dc0f4bc75adee32e34c87854508 + + + 1751827730897 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 8bb2b4d5cd9d445722b307d6bdb3d9fd + + + 1751828973865 + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 3609737de0e0d000c3d43a620f592090 + + + 1751872486908 + + UPDATE_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsid2lkdGgiOjIzMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsid2lkdGgiOjIzMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJCOmZ1bmJvZHlfY3B1LnB5Iix0cnVlXQ== + + a0691587adb56f1c913b278379ea8cd5 + + + \ No newline at end of file diff --git a/measurements/throughput_test/concore.py b/measurements/throughput_test/concore.py new file mode 100644 index 0000000..ce3ab0a --- /dev/null +++ b/measurements/throughput_test/concore.py @@ -0,0 +1,289 @@ +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 + + self.socket.setsockopt(zmq.RCVTIMEO, 2000) + self.socket.setsockopt(zmq.SNDTIMEO, 2000) + self.socket.setsockopt(zmq.LINGER, 0) + + 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}") + + def send_json_with_retry(self, message): + for attempt in range(5): + try: + self.socket.send_json(message) + return + except zmq.Again: + print(f"Send timeout (attempt {attempt + 1}/5)") + time.sleep(0.5) + print("Failed to send after retries.") + return + + def recv_json_with_retry(self): + for attempt in range(5): + try: + return self.socket.recv_json() + except zmq.Again: + print(f"Receive timeout (attempt {attempt + 1}/5)") + time.sleep(0.5) + print("Failed to receive after retries.") + return None + +# 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.recv_json_with_retry() + 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.send_json_with_retry(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}") + + 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/throughput_test/funbody_cpu.py b/measurements/throughput_test/funbody_cpu.py new file mode 100644 index 0000000..28f1c16 --- /dev/null +++ b/measurements/throughput_test/funbody_cpu.py @@ -0,0 +1,71 @@ +# funbody_throughput_test.py (MODIFIED FOR RESOURCE MONITORING) +import time +import concore +import os +import json +import threading +import psutil +import csv + +# --- MONITORING FUNCTION (to be run in a separate thread) --- +def monitor_resources(stop_event, output_list): + """Monitors this script's CPU and memory usage.""" + process = psutil.Process(os.getpid()) + while not stop_event.is_set(): + cpu_percent = process.cpu_percent(interval=0.5) + memory_mb = process.memory_info().rss / (1024 * 1024) + output_list.append({'cpu_percent': cpu_percent, 'memory_mb': memory_mb}) + +print("funbody (Receiver) using ZMQ PULL socket for Throughput & Resource Test.") + + +TEST_DURATION = 10 +message_count = 0 +test_started = False +resource_records = [] + +# --- Start Monitoring --- +stop_monitoring = threading.Event() +monitor_thread = threading.Thread(target=monitor_resources, args=(stop_monitoring, resource_records)) +monitor_thread.start() + +# --- Main Throughput Test Logic (Unchanged) --- +concore.init_zmq_port( + port_name=PORT_NAME_B_OUT, + port_type="bind", + address="tcp://0.0.0.0:" + PORT_B_OUT, # Bind to all interfaces on the specified port + socket_type_str="REP" +) + +print(f"Receiver waiting for messages on port {PORT_B_OUT}...") +while True: + message_str = concore.read(PORT_NAME_B_OUT, "stream", "{}") + if message_str is None: break + try: + message_dict = json.loads(message_str) + except (json.JSONDecodeError, TypeError): + continue + if isinstance(message_dict, dict) and 'type' in message_dict: + if message_dict['type'] == 'control': + if message_dict['value'] == 'START' and not test_started: + test_started = True + elif message_dict['value'] == 'STOP' and test_started: + break + elif message_dict['type'] == 'data' and test_started: + message_count += 1 + +# --- Stop Monitoring and Save Results --- +stop_monitoring.set() +monitor_thread.join() +concore.terminate_zmq() + +if message_count > 0: + throughput = message_count / TEST_DURATION + print(f"THROUGHPUT RESULT: {throughput:.2f} messages/second") + +if resource_records: + with open('receiver_usage.csv', 'w', newline='') as f: + writer = csv.DictWriter(f, fieldnames=['cpu_percent', 'memory_mb']) + writer.writeheader() + writer.writerows(resource_records) + print("Receiver resource usage saved to receiver_usage.csv") \ No newline at end of file diff --git a/measurements/throughput_test/funbody_throughput_test.py b/measurements/throughput_test/funbody_throughput_test.py new file mode 100644 index 0000000..d517488 --- /dev/null +++ b/measurements/throughput_test/funbody_throughput_test.py @@ -0,0 +1,40 @@ +# funbody_throughput.py +import time +import concore + +print("Starting ZMQ throughput server (funbody)") + +# --- ZMQ Configuration --- +# Ensure these environment variables are set before running +# Example: PORT_NAME_F2_OUT="F1_out" PORT_F2_OUT="5555" python funbody_throughput.py + +# Initialize the ZMQ server port +concore.init_zmq_port( + port_name=PORT_NAME_B_OUT, + port_type="bind", + address="tcp://0.0.0.0:" + PORT_B_OUT, # Bind to all interfaces on the specified port + socket_type_str="REP" +) + +# --- Server Loop --- +print(f"Funbody server listening on port {PORT_B_OUT}. Press Ctrl+C to stop.") + +try: + while True: + # Wait to receive any message from a client + received_message = concore.read(PORT_NAME_B_OUT, "throughput_test", "{}") + + if received_message: + # As soon as a message is received, send a reply back + reply_message = {"status": "ok"} + concore.write(PORT_NAME_B_OUT, "throughput_reply", reply_message) + else: + # The read timed out; just continue waiting for the next message + continue + +except KeyboardInterrupt: + print("\nServer shutting down.") + +finally: + # Clean up the ZMQ connection + concore.terminate_zmq() \ No newline at end of file diff --git a/measurements/throughput_test/funcall_cpu.py b/measurements/throughput_test/funcall_cpu.py new file mode 100644 index 0000000..b03f815 --- /dev/null +++ b/measurements/throughput_test/funcall_cpu.py @@ -0,0 +1,63 @@ +# funcall_throughput_test.py (MODIFIED FOR RESOURCE MONITORING) +import time +import concore +import os +import json +import threading +import psutil +import csv + +# --- MONITORING FUNCTION (to be run in a separate thread) --- +def monitor_resources(stop_event, output_list): + """Monitors this script's CPU and memory usage.""" + process = psutil.Process(os.getpid()) + while not stop_event.is_set(): + # Get CPU (as a percentage) and Memory (RSS in MB) + cpu_percent = process.cpu_percent(interval=0.5) + memory_mb = process.memory_info().rss / (1024 * 1024) + output_list.append({'cpu_percent': cpu_percent, 'memory_mb': memory_mb}) + +print("funcall (Sender) using ZMQ PUSH socket for Throughput & Resource Test.") + + +TEST_DURATION = 10 +message_count = 0 +resource_records = [] + +# --- Start Monitoring --- +stop_monitoring = threading.Event() +monitor_thread = threading.Thread(target=monitor_resources, args=(stop_monitoring, resource_records)) +monitor_thread.start() + +# --- Main Throughput Test Logic (Unchanged) --- +concore.init_zmq_port( + port_name=PORT_NAME_IN_A, + port_type="connect", + address="tcp://192.168.0.109:" + PORT_IN_A, # Use 127.0.0.1 for local testing + socket_type_str="REQ" +) +print(f"Sender starting. Will send data for 10 seconds.") +start_signal = json.dumps({"type": "control", "value": "START"}) +concore.write(PORT_NAME_IN_A, "stream", start_signal) +time.sleep(1) +start_time = time.perf_counter() +while (time.perf_counter() - start_time) < TEST_DURATION: + data_message = json.dumps({"type": "data", "value": message_count}) + concore.write(PORT_NAME_IN_A, "stream", data_message) + message_count += 1 +time.sleep(1) +stop_signal = json.dumps({"type": "control", "value": "STOP"}) +concore.write(PORT_NAME_IN_A, "stream", stop_signal) +print(f"Sender finished. Sent approximately {message_count} messages.") + +# --- Stop Monitoring and Save Results --- +stop_monitoring.set() +monitor_thread.join() +concore.terminate_zmq() + +if resource_records: + with open('sender_usage.csv', 'w', newline='') as f: + writer = csv.DictWriter(f, fieldnames=['cpu_percent', 'memory_mb']) + writer.writeheader() + writer.writerows(resource_records) + print("Sender resource usage saved to sender_usage.csv") \ No newline at end of file diff --git a/measurements/throughput_test/funcall_throughput_test.py b/measurements/throughput_test/funcall_throughput_test.py new file mode 100644 index 0000000..6c58aac --- /dev/null +++ b/measurements/throughput_test/funcall_throughput_test.py @@ -0,0 +1,57 @@ +# funcall_throughput.py +import time +import concore + +print("Starting ZMQ throughput test (funcall)") + +# --- ZMQ Configuration --- +# Ensure these environment variables are set before running +# Example: PORT_NAME_IN_F1="F1_out" PORT_IN_F1="5555" python funcall_throughput.py + +# Initialize the ZMQ connection to the funbody server +concore.init_zmq_port( + port_name=PORT_NAME_IN_A, + port_type="connect", + address="tcp://192.168.0.109:" + PORT_IN_A, # Use 127.0.0.1 for local testing + socket_type_str="REQ" +) + +# --- Test Parameters --- +TEST_DURATION_SECONDS = 10 +message_to_send = {"ping": "hello"} +message_count = 0 + +print(f"Running test for {TEST_DURATION_SECONDS} seconds...") + +start_time = time.perf_counter() +end_time = start_time + TEST_DURATION_SECONDS + +# --- Main Test Loop --- +while time.perf_counter() < end_time: + # Send a message to the funbody server + concore.write(PORT_NAME_IN_A, "throughput_test", message_to_send) + + # Wait for the reply + reply = concore.read(PORT_NAME_IN_A, "throughput_reply", "{}") + + # If we get a valid reply, increment our counter + if reply: + message_count += 1 + else: + print("Warning: Missed a reply from the server.") + # In a real-world scenario, you might want to break or handle this + break + +# --- Calculate and Print Results --- +actual_duration = time.perf_counter() - start_time +throughput = message_count / actual_duration + +print("\n--- Throughput Test Complete ---") +print(f"Total messages exchanged: {message_count}") +print(f"Total time: {actual_duration:.2f} seconds") +print(f"Throughput: {throughput:.2f} messages/sec") +print("---------------------------------") + + +# Clean up the ZMQ connection +concore.terminate_zmq() \ No newline at end of file diff --git a/measurements/throughput_test/plot.py b/measurements/throughput_test/plot.py new file mode 100644 index 0000000..604c3e4 --- /dev/null +++ b/measurements/throughput_test/plot.py @@ -0,0 +1,34 @@ +import matplotlib.pyplot as plt +import numpy as np + +# --- Enter your collected data here --- +# Example values, replace with your actual measurements +throughput_mediator = 15.7 # messages/sec +throughput_zmq = 4497.8 # messages/sec +# ----------------------------------------- + +protocols = ['Mediator', 'ZeroMQ'] +values = [throughput_mediator, throughput_zmq] +colors = ['#F44336', '#4CAF50'] + +plt.figure(figsize=(8, 6)) +bars = plt.bar(protocols, values, color=colors) + +# Add plot details +plt.ylabel('Throughput (Messages/Second)', fontsize=12) +plt.title('Figure 4: Maximum Throughput Comparison', fontsize=16, pad=20) +plt.xticks(fontsize=12) +# Use a logarithmic scale if the difference is very large +plt.yscale('log') +plt.grid(axis='y', linestyle='--', alpha=0.7) + +# Add text labels on top of the bars +for bar in bars: + yval = bar.get_height() + plt.text(bar.get_x() + bar.get_width()/2.0, yval, f'{yval:,.0f}', va='bottom', ha='center', fontsize=11) + +# Save the figure for your paper +plt.savefig('figure4_throughput_comparison.png', dpi=300) +print("Plot saved as 'figure4_throughput_comparison.png'") + +plt.show() \ No newline at end of file diff --git a/measurements/throughput_test/plot_fig5.py b/measurements/throughput_test/plot_fig5.py new file mode 100644 index 0000000..77391fe --- /dev/null +++ b/measurements/throughput_test/plot_fig5.py @@ -0,0 +1,42 @@ +import pandas as pd +import seaborn as sns +import matplotlib.pyplot as plt + +# Load all data and calculate averages +try: + avg_cpu_sender_zmq = pd.read_csv('sender_zmq_usage.csv')['cpu_percent'].mean() + avg_mem_sender_zmq = pd.read_csv('sender_zmq_usage.csv')['memory_mb'].mean() + + # In a real test, you would also measure the receiver. For simplicity, we plot sender. + # avg_cpu_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['cpu_percent'].mean() + # avg_mem_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['memory_mb'].mean() + + # Create placeholder data for Mediator until you run the test + avg_cpu_sender_mediator = 25.5 # Example value + avg_mem_sender_mediator = 60.2 # Example value + +except FileNotFoundError: + print("One or more CSV files not found. Using placeholder data.") + # Placeholder data for plotting if you haven't run the experiment yet + avg_cpu_sender_zmq, avg_mem_sender_zmq = 15.0, 45.0 + avg_cpu_sender_mediator, avg_mem_sender_mediator = 25.5, 60.2 + +# Prepare data for plotting +data = { + 'Protocol': ['Mediator', 'ZeroMQ', 'Mediator', 'ZeroMQ'], + 'Metric': ['CPU Usage (%)', 'CPU Usage (%)', 'Memory Usage (MB)', 'Memory Usage (MB)'], + 'Value': [avg_cpu_sender_mediator, avg_cpu_sender_zmq, avg_mem_sender_mediator, avg_mem_sender_zmq] +} +df_plot = pd.DataFrame(data) + +# Create the grouped bar chart +plt.figure(figsize=(10, 7)) +sns.barplot(x='Metric', y='Value', hue='Protocol', data=df_plot, palette={'Mediator': '#F44336', 'ZeroMQ': '#4CAF50'}) + +plt.title('Figure 5: Resource Utilization During Throughput Test (Sender)', fontsize=16) +plt.xlabel('Performance Metric', fontsize=12) +plt.ylabel('Average Usage', fontsize=12) +plt.legend(title='Protocol') +plt.grid(axis='y', linestyle='--', alpha=0.7) + +plt.show() \ No newline at end of file diff --git a/measurements/throughput_test/server.graphml b/measurements/throughput_test/server.graphml new file mode 100644 index 0000000..81b5102 --- /dev/null +++ b/measurements/throughput_test/server.graphml @@ -0,0 +1,221 @@ + + + + + + + + + + + + A:funcall_throughput_test.py + + + + + + + + + + + IN: + + + + + + + + + + 0x2306_U1 + + + + + + + + 1751825545123 + + DEL_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + + ADD_NODE + WyJBOmZ1bmNhbGxfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMjMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHt9LCIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + 0f6a06a5f49f1d83657221f267bbf65e + + + 1751825547451 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjEwMCwieSI6MTAwfV0= + + c07fdf0b5fbc290aea42a3bd74c45a6b + + + 1751825549601 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjUzMC4wMDIxOTE0MDExMDk5LCJ5IjoyOTIuMDAwOTc4NDg2MDc3fV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + 55cb72ce7faf50386f9f71afe1e576fb + + + 1751825564072 + + DEL_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + + ADD_NODE + WyJJbjoiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjoxOTUuMDAwNDg0MTQ2NzU2OCwieSI6OTAuOTk5OTU0MTMzNDY1MTR9LHt9LCJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + d13798fff2bf40cbacc6bc0f73cc3e5a + + + 1751825566634 + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJbjoiLHRydWVd + + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJTjoiLHRydWVd + + 1292dab0cd809e0bc822a88cbe296a4f + + + 1751825570934 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fV0= + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjEwMCwieSI6MTAwfV0= + + 71a0470230ca5a52edc2cb9ff06f3d28 + + + 1751825572700 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjE5NS4wMDA0ODQxNDY3NTY4LCJ5Ijo5MC45OTk5NTQxMzM0NjUxNH1d + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTk1LjAwMDQ4NDE0Njc1NjgsInkiOjkwLjk5OTk1NDEzMzQ2NTE0fSx7IngiOjE5Mi4wMDA0Njg4NTc5MTE5LCJ5Ijo5NC45OTk5NzQ1MTg1OTE3N31d + + 86c56976fc63f27dc9485ecc73f2de2d + + + 1751825576935 + + DEL_EDGE + WyI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLCJ0YXJnZXRJRCI6IjI0YmUwYzEzLTVkOGMtNGY5MC1iMGJiLTFlMDcyN2IwNDJkNyIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUifV0= + + e3d7f90d81fe934dfa3c417169de8824 + + + 1751826381936 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + 39ad7e349fa9310a7b969d4ebab5282e + + + 1751826525320 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 8efbfe0ae1b0204fce1d374693fa71a4 + + + 1751826583001 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 28d360705ea6c4b2c2fe71ddd4ac747b + + + 1751826587218 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + 4688004b0c03d91e2da0b196f1c26a63 + + + 1751826894632 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + 8cbf36e069285329a3e6c103fadd2d15 + + + 1751827827801 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 474cb438a743ffd7c3e75d28317657f3 + + + 1751828982344 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 4ec6d444cdddc40c1917aba4da2ee7d0 + + + \ No newline at end of file diff --git a/measurements/throughput_test/server_cpu.graphml b/measurements/throughput_test/server_cpu.graphml new file mode 100644 index 0000000..9bf33ce --- /dev/null +++ b/measurements/throughput_test/server_cpu.graphml @@ -0,0 +1,245 @@ + + + + + + + + + + + + A:funcall_cpu.py + + + + + + + + + + + IN: + + + + + + + + + + 0x2307_U1 + + + + + + + + 1751825545123 + + DEL_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + + ADD_NODE + WyJBOmZ1bmNhbGxfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMjMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHt9LCIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciXQ== + + 0f6a06a5f49f1d83657221f267bbf65e + + + 1751825547451 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjEwMCwieSI6MTAwfV0= + + c07fdf0b5fbc290aea42a3bd74c45a6b + + + 1751825549601 + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfSx7IngiOjUzMC4wMDIxOTE0MDExMDk5LCJ5IjoyOTIuMDAwOTc4NDg2MDc3fV0= + + + SET_POS + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjI5Mi4wMDA5Nzg0ODYwNzd9LHsieCI6NTMwLjAwMjE5MTQwMTEwOTksInkiOjQyMC4wMDE2MzA4MTAxMjgzfV0= + + 55cb72ce7faf50386f9f71afe1e576fb + + + 1751825564072 + + DEL_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + + ADD_NODE + WyJJbjoiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJvcmRpbiIseyJ4IjoxOTUuMDAwNDg0MTQ2NzU2OCwieSI6OTAuOTk5OTU0MTMzNDY1MTR9LHt9LCJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiXQ== + + d13798fff2bf40cbacc6bc0f73cc3e5a + + + 1751825566634 + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJbjoiLHRydWVd + + + UPDATE_NODE + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsid2lkdGgiOjEwMCwiaGVpZ2h0Ijo1MCwic2hhcGUiOiJyZWN0YW5nbGUiLCJvcGFjaXR5IjoxLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJJTjoiLHRydWVd + + 1292dab0cd809e0bc822a88cbe296a4f + + + 1751825570934 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fV0= + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjEwMCwieSI6MTAwfV0= + + 71a0470230ca5a52edc2cb9ff06f3d28 + + + 1751825572700 + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTkyLjAwMDQ2ODg1NzkxMTksInkiOjk0Ljk5OTk3NDUxODU5MTc3fSx7IngiOjE5NS4wMDA0ODQxNDY3NTY4LCJ5Ijo5MC45OTk5NTQxMzM0NjUxNH1d + + + SET_POS + WyJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLHsieCI6MTk1LjAwMDQ4NDE0Njc1NjgsInkiOjkwLjk5OTk1NDEzMzQ2NTE0fSx7IngiOjE5Mi4wMDA0Njg4NTc5MTE5LCJ5Ijo5NC45OTk5NzQ1MTg1OTE3N31d + + 86c56976fc63f27dc9485ecc73f2de2d + + + 1751825576935 + + DEL_EDGE + WyI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUiXQ== + + + ADD_EDGE + W3sic291cmNlSUQiOiJkYmMzYWYzYS0xZmY0LTQwNDUtOWYxYy05ZDU4ZjMzNjkyYmMiLCJ0YXJnZXRJRCI6IjI0YmUwYzEzLTVkOGMtNGY5MC1iMGJiLTFlMDcyN2IwNDJkNyIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI2ODQxM2ZhOC1lNWJjLTQzYTgtODllZS00MTM5Zjk5NTdmMjUifV0= + + e3d7f90d81fe934dfa3c417169de8824 + + + 1751826381936 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + 39ad7e349fa9310a7b969d4ebab5282e + + + 1751826525320 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 8efbfe0ae1b0204fce1d374693fa71a4 + + + 1751826583001 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + 28d360705ea6c4b2c2fe71ddd4ac747b + + + 1751826587218 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + 4688004b0c03d91e2da0b196f1c26a63 + + + 1751826894632 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + 8cbf36e069285329a3e6c103fadd2d15 + + + 1751827827801 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + 474cb438a743ffd7c3e75d28317657f3 + + + 1751828982344 + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJjZjQzOGJhYS02N2Q0LTQ1Y2UtOTk4Yi1mYjU0ODU3MGZjZGMiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + 4ec6d444cdddc40c1917aba4da2ee7d0 + + + 1751872426393 + + UPDATE_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsid2lkdGgiOjIyMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJBOmZ1bmNhbGxfdGhyb3VnaHB1dF90ZXN0LnB5Iix0cnVlXQ== + + + UPDATE_NODE + WyIyNGJlMGMxMy01ZDhjLTRmOTAtYjBiYi0xZTA3MjdiMDQyZDciLHsid2lkdGgiOjIyMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJBOmZ1bmNhbGxfY3B1LnB5Iix0cnVlXQ== + + 72b043d710aeb2d0db300c844fe93875 + + + 1751873408899 + + UPDATE_EDGE + WyJkMDNiMGFjMS05OTA1LTRhMjUtOTgwMS0wMDNmNGZlYWJjODQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0= + + + UPDATE_EDGE + WyJkMDNiMGFjMS05OTA1LTRhMjUtOTgwMS0wMDNmNGZlYWJjODQiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwN19VMSIsdHJ1ZV0= + + 30848cb7ede5f6155725091f45680e40 + + + \ No newline at end of file From 8974f7a4a069810e0effd94cc864ec5beec37936 Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Sun, 17 Aug 2025 15:14:14 +0530 Subject: [PATCH 15/17] Corrected Figure Names And Corrected readme.md --- ...igure5.png => ResourceUsageComparison.png} | Bin ...g => latencyComparisonUsingViolinPlot.png} | Bin ...{Figure_4.png => ThroughputComparison.png} | Bin measurements/readme.md | 94 +++++++----------- 4 files changed, 35 insertions(+), 59 deletions(-) rename measurements/CPU/{Figure5.png => ResourceUsageComparison.png} (100%) rename measurements/Latency/{figure3_latency_comparison.png => latencyComparisonUsingViolinPlot.png} (100%) rename measurements/Throughput/{Figure_4.png => ThroughputComparison.png} (100%) diff --git a/measurements/CPU/Figure5.png b/measurements/CPU/ResourceUsageComparison.png similarity index 100% rename from measurements/CPU/Figure5.png rename to measurements/CPU/ResourceUsageComparison.png diff --git a/measurements/Latency/figure3_latency_comparison.png b/measurements/Latency/latencyComparisonUsingViolinPlot.png similarity index 100% rename from measurements/Latency/figure3_latency_comparison.png rename to measurements/Latency/latencyComparisonUsingViolinPlot.png diff --git a/measurements/Throughput/Figure_4.png b/measurements/Throughput/ThroughputComparison.png similarity index 100% rename from measurements/Throughput/Figure_4.png rename to measurements/Throughput/ThroughputComparison.png diff --git a/measurements/readme.md b/measurements/readme.md index 6ef9f52..f22f9f4 100644 --- a/measurements/readme.md +++ b/measurements/readme.md @@ -1,59 +1,35 @@ -Performance Measurement Guide: File-Based vs. ZeroMQThis guide provides a step-by-step methodology for quantifying and comparing the performance of a multi-node system using two different inter-process communication (IPC) methods:File-Based: Nodes communicate by writing and reading files in shared directories.ZeroMQ-Based: Nodes communicate over high-performance, in-memory messaging sockets.By following these steps, you can generate concrete data on latency, throughput, and resource utilization to demonstrate the impact of migrating from a file-based to a ZMQ-based architecture.PrerequisitesTwo Project Versions: You must have two separate versions of your concore project generator: one that uses the original file-based communication, and one that uses the new ZMQ-based system we developed.Python Libraries: Ensure you have the necessary Python libraries installed. psutil is required for programmatically measuring CPU usage.pip install pyzmq psutil -macOS Command Line Tools: You should be comfortable with basic Terminal commands. The iostat and top commands are used for monitoring.Step 1: Test Environment SetupFirst, create a clean directory structure for your tests.# 1. Create a main directory for the performance tests -mkdir concore_performance_tests -cd concore_performance_tests - -# 2. Create a directory to hold the source scripts for the nodes -mkdir source_scripts - -# 3. Create a directory for the file-based system output -mkdir file_based_project - -# 4. Create a directory for the ZMQ-based system output -mkdir zmq_project -Next, create the following two files inside the concore_performance_tests directory.a) graph.graphmlThis simple 4-node pipeline graph will be used for all tests. - - - - - - A:producer.py - - - B:processor.py - - - C:processor.py - - - D:consumer.py - - - A_to_B - - - B_to_C - - - C_to_D - - - -b) test_data.dat (Large data file for throughput testing)Run this command in your terminal to create a 100MB file.mkfile 100m test_data.dat -Finally, place the sample node scripts (provided in the other documents) into the source_scripts directory.Step 2: Running the Baseline (File-Based) TestsFirst, generate the file-based project using your original mkconcore.py.# Navigate to the project directory -cd file_based_project - -# Run mkconcore.py to generate the project -python3 /path/to/your/original/mkconcore.py ../graph.graphml ../source_scripts . posix -Now, run the following tests from within the file_based_project directory.Test 1: Latency / End-to-End TimeThis test measures the time to process 1,000 small messages through the pipeline.Set the test mode in source_scripts/producer.py to 'latency'.Run the test using the time command:./build -time ./run -Record the real time from the output. This is your End-to-End Time.Example: real 0m48.521sCalculate Average Latency: End-to-End Time / 1000 messages.Test 2: ThroughputThis test measures the speed of transferring the 100MB file.Set the test mode in source_scripts/producer.py to 'throughput'.Run the test:./build -time ./run -Record the real time.Calculate Throughput: 100 MB / (time in seconds).Test 3: CPU & Disk I/OThis test monitors system resources during the throughput test. You will need two terminal windows.In Terminal 2, start the disk monitor:iostat -d 1 -In Terminal 1, run the throughput test (time ./run).In Terminal 2, watch the MB/s column for your disk (e.g., disk0). Note the peak value.Stop iostat (Ctrl+C). Now start the CPU monitor:top -o cpu -In Terminal 1, run the throughput test again.In Terminal 2, watch the %CPU column for your python processes and note the approximate average value.Step 3: Running the ZeroMQ TestsNow, generate the ZMQ-based project using your new, modified mkconcore.py.# Navigate to the project directory -cd ../zmq_project # Go back up and into the zmq directory - -# Run the new mkconcore.py -python3 /path/to/your/new/mkconcore.py ../graph.graphml ../source_scripts . posix -Repeat the exact same three tests as in Step 2 from within the zmq_project directory. Use the ZMQ versions of the sample scripts.Step 4: Analyze the ResultsFill in a table like the one below with your collected data. This will give you a clear, quantitative comparison of the two systems.MetricFile-Based SystemZeroMQ SystemImprovement FactorAvg. LatencyYour value (ms)Your value (ms)CalculateData ThroughputYour value (MB/s)Your value (MB/s)CalculateEnd-to-End TimeYour value (s)Your value (s)CalculateAvg. CPU UsageYour value (%)Your value (%)CalculateDisk WritesYour value (MB)Your value (MB)CalculateThis structured approach will provide undeniable evidence of the performance gains from your architectural improvements. \ No newline at end of file +# Project Measurements +This repository contains the source code and studies for various system performance measurements. All studies are organized into dedicated folders for easy navigation and execution. + +# Running the Measurement Studies +To run any of the studies, navigate to the respective folder and execute the provided source code using concore. + +For example, to run a CPU measurement study: + +1. Navigate to the CPU directory. + +2. Execute the relevant script(s) within that folder using concore. + +The output will provide the measured results specific to each study. + +# Study Folders and Their Focus +* CPU +This folder contains studies and source code for measuring CPU resource usage. Running these will help you understand how much processing power is consumed by the application under test. + +* Latency +This folder houses studies and source code dedicated to measuring communication latency. These studies are designed to quantify the delay in data transfer between systems. + +* Throughput +Within this folder, you'll find studies and source code for measuring data throughput. These will help assess the rate at which data can be processed or transferred over a given period. + +# Communication Measurement Studies (Single System) +The following studies are designed for measurements within a single system, allowing for direct comparison of their round-trip times: + +* fileOnlyCommunication +This folder contains studies and source code specifically for measuring communication times that involve only file-based interactions on a single machine. + +* ZeroMQOnlyCommunication +Here you will find studies and source code focused on measuring communication times using ZeroMQ within a single system setup. + +# Network Communication Measurements (Two Systems Required) +For the Latency, Throughput, and CPU Usage measurements, two different systems are required. These systems should be connected over the same network to ensure efficient and accurate communication measurements between them. This setup is crucial for evaluating network-dependent performance metrics effectively. \ No newline at end of file From 498834870221852f18a6b78ecfc26c6cecb3a25e Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Sat, 23 Aug 2025 00:35:24 +0530 Subject: [PATCH 16/17] replaced the png format with pdf, now all plots will be saved as pdf --- ...=> plotResourceUsageDuringThrouputTest.py} | 23 ++++---- measurements/CPU/resource_utilization.pdf | Bin 0 -> 14691 bytes .../Latency/latencyDistributionComparison.py | 47 ++++++++++++++++ ...fig3(2).py => latencyDistributionOfZMQ.py} | 28 +++++---- measurements/Latency/latency_comparison.pdf | Bin 0 -> 16631 bytes measurements/Latency/plot_fig3(1).py | 53 ------------------ measurements/Latency/zmq_latency.pdf | Bin 0 -> 14181 bytes .../Throughput/maximumThroughputComaprison.py | 41 ++++++++++++++ measurements/Throughput/plot_fig4.py | 34 ----------- .../Throughput/throughput_comparison.pdf | Bin 0 -> 14603 bytes 10 files changed, 116 insertions(+), 110 deletions(-) rename measurements/CPU/{plot_fig5.py => plotResourceUsageDuringThrouputTest.py} (60%) create mode 100644 measurements/CPU/resource_utilization.pdf create mode 100644 measurements/Latency/latencyDistributionComparison.py rename measurements/Latency/{plot_fig3(2).py => latencyDistributionOfZMQ.py} (55%) create mode 100644 measurements/Latency/latency_comparison.pdf delete mode 100644 measurements/Latency/plot_fig3(1).py create mode 100644 measurements/Latency/zmq_latency.pdf create mode 100644 measurements/Throughput/maximumThroughputComaprison.py delete mode 100644 measurements/Throughput/plot_fig4.py create mode 100644 measurements/Throughput/throughput_comparison.pdf diff --git a/measurements/CPU/plot_fig5.py b/measurements/CPU/plotResourceUsageDuringThrouputTest.py similarity index 60% rename from measurements/CPU/plot_fig5.py rename to measurements/CPU/plotResourceUsageDuringThrouputTest.py index 2990a9d..32c719d 100644 --- a/measurements/CPU/plot_fig5.py +++ b/measurements/CPU/plotResourceUsageDuringThrouputTest.py @@ -7,17 +7,11 @@ avg_cpu_sender_zmq = pd.read_csv('sender_usage.csv')['cpu_percent'].mean() avg_mem_sender_zmq = pd.read_csv('sender_usage.csv')['memory_mb'].mean() - # In a real test, you would also measure the receiver. For simplicity, we plot sender. - # avg_cpu_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['cpu_percent'].mean() - # avg_mem_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['memory_mb'].mean() - - # Create placeholder data for Mediator until you run the test avg_cpu_sender_mediator = 25.5 # Example value - avg_mem_sender_mediator = 60.2 # Example value + avg_mem_sender_mediator = 60.2 # Example value except FileNotFoundError: print("One or more CSV files not found. Using placeholder data.") - # Placeholder data for plotting if you haven't run the experiment yet avg_cpu_sender_zmq, avg_mem_sender_zmq = 15.0, 45.0 avg_cpu_sender_mediator, avg_mem_sender_mediator = 25.5, 60.2 @@ -30,13 +24,16 @@ df_plot = pd.DataFrame(data) # Create the grouped bar chart -plt.figure(figsize=(10, 7)) +plt.figure(figsize=(8.27, 11.69)) # A4 size in inches (210mm x 297mm) sns.barplot(x='Metric', y='Value', hue='Protocol', data=df_plot, palette={'Mediator': '#F44336', 'ZeroMQ': '#4CAF50'}) -plt.title('Figure 5: Resource Utilization During Throughput Test (Sender)', fontsize=16) -plt.xlabel('Performance Metric', fontsize=12) -plt.ylabel('Average Usage', fontsize=12) -plt.legend(title='Protocol') +plt.xlabel('Performance Metric', fontsize=14) +plt.ylabel('Average Usage', fontsize=14) +plt.legend(title='Protocol', fontsize=12, title_fontsize=12) plt.grid(axis='y', linestyle='--', alpha=0.7) -plt.show() +plt.tight_layout() + +# Save to PDF +plt.savefig("resource_utilization.pdf", format="pdf") +plt.show() \ No newline at end of file diff --git a/measurements/CPU/resource_utilization.pdf b/measurements/CPU/resource_utilization.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ccf1b4e3aab1de604eba5c8e7ce745f9fc43157f GIT binary patch literal 14691 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 SW&(ynp9gd`#(BiXYQ4MLO| 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 F{{ZI4hVuXb literal 0 HcmV?d00001 From e76c3c794f7bd79c2812ff6d3aefc5a53cbc4b8d Mon Sep 17 00:00:00 2001 From: Saksham Gera Date: Wed, 27 Aug 2025 02:52:02 +0530 Subject: [PATCH 17/17] Added The Comments in Both concore.py and mkconcore.py --- concore.py | 71 ++++++++++++++--- .../Throughput/maximumThroughputComaprison.py | 1 - .../Throughput/throughput_comparison.pdf | Bin 14603 -> 13263 bytes mkconcore.py | 74 ++++++++++++++++-- 4 files changed, 129 insertions(+), 17 deletions(-) diff --git a/concore.py b/concore.py index ce3ab0a..6d71f0f 100644 --- a/concore.py +++ b/concore.py @@ -5,26 +5,35 @@ import re import zmq # Added for ZeroMQ -#if windows, create script to kill this process +# 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 +# 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 --- +# =================================================================== +# ZeroMQ Communication Wrapper +# =================================================================== class ZeroMQPort: def __init__(self, port_type, address, zmq_socket_type): + """ + port_type: "bind" or "connect" + address: ZeroMQ address (e.g., "tcp://*:5555") + zmq_socket_type: zmq.REQ, zmq.REP, zmq.PUB, zmq.SUB etc. + """ self.context = zmq.Context() self.socket = self.context.socket(zmq_socket_type) self.port_type = port_type # "bind" or "connect" self.address = address - self.socket.setsockopt(zmq.RCVTIMEO, 2000) - self.socket.setsockopt(zmq.SNDTIMEO, 2000) - self.socket.setsockopt(zmq.LINGER, 0) + # Configure timeouts & immediate close on failure + self.socket.setsockopt(zmq.RCVTIMEO, 2000) # 2 sec receive timeout + self.socket.setsockopt(zmq.SNDTIMEO, 2000) # 2 sec send timeout + self.socket.setsockopt(zmq.LINGER, 0) # Drop pending messages on close + # Bind or connect if self.port_type == "bind": self.socket.bind(address) print(f"ZMQ Port bound to {address}") @@ -33,6 +42,7 @@ def __init__(self, port_type, address, zmq_socket_type): print(f"ZMQ Port connected to {address}") def send_json_with_retry(self, message): + """Send JSON message with retries if timeout occurs.""" for attempt in range(5): try: self.socket.send_json(message) @@ -44,6 +54,7 @@ def send_json_with_retry(self, message): return def recv_json_with_retry(self): + """Receive JSON message with retries if timeout occurs.""" for attempt in range(5): try: return self.socket.recv_json() @@ -89,6 +100,9 @@ def terminate_zmq(): print(f"Error while terminating ZMQ port {port.address}: {e}") # --- ZeroMQ Integration End --- +# =================================================================== +# File & Parameter Handling +# =================================================================== def safe_literal_eval(filename, defaultValue): try: with open(filename, "r") as file: @@ -97,10 +111,13 @@ def safe_literal_eval(filename, defaultValue): # Keep print for debugging, but can be made quieter # print(f"Info: Error reading {filename} or file not found, using default: {e}") return defaultValue - + + +# Load input/output ports if present iport = safe_literal_eval("concore.iport", {}) oport = safe_literal_eval("concore.oport", {}) +# Global variables s = '' olds = '' delay = 1 @@ -110,14 +127,20 @@ def safe_literal_eval(filename, defaultValue): simtime = 0 #9/21/22 +# =================================================================== +# Parameter Parsing +# =================================================================== 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 + # Windows sometimes keeps quotes if sparams[0] == '"' and sparams[-1] == '"': #windows keeps "" need to remove sparams = sparams[1:-1] + + # Convert key=value;key2=value2 to Python dict format 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)))+"}" @@ -137,11 +160,16 @@ def safe_literal_eval(filename, defaultValue): #9/30/22 def tryparam(n, i): + """Return parameter `n` from params dict, else default `i`.""" return params.get(n, i) #9/12/21 +# =================================================================== +# Simulation Time Handling +# =================================================================== def default_maxtime(default): + """Read maximum simulation time from file or use default.""" global maxtime maxtime_path = os.path.join(inpath + "1", "concore.maxtime") maxtime = safe_literal_eval(maxtime_path, default) @@ -149,6 +177,7 @@ def default_maxtime(default): default_maxtime(100) def unchanged(): + """Check if global string `s` is unchanged since last call.""" global olds, s if olds == s: s = '' @@ -156,16 +185,21 @@ def unchanged(): olds = s return False +# =================================================================== +# I/O Handling (File + ZMQ) +# =================================================================== def read(port_identifier, name, initstr_val): global s, simtime, retrycount + # Default return default_return_val = initstr_val if isinstance(initstr_val, str): try: default_return_val = literal_eval(initstr_val) except (SyntaxError, ValueError): pass - + + # Case 1: ZMQ port if isinstance(port_identifier, str) and port_identifier in zmq_ports: zmq_p = zmq_ports[port_identifier] try: @@ -178,6 +212,7 @@ def read(port_identifier, name, initstr_val): print(f"Unexpected error during ZMQ read on port {port_identifier} (name: {name}): {e}. Returning default.") return default_return_val + # Case 2: File-based port try: file_port_num = int(port_identifier) except ValueError: @@ -197,6 +232,7 @@ def read(port_identifier, name, initstr_val): print(f"Error reading {file_path}: {e}. Using default value.") return default_return_val + # Retry logic if file is empty attempts = 0 max_retries = 5 while len(ins) == 0 and attempts < max_retries: @@ -214,6 +250,8 @@ def read(port_identifier, name, initstr_val): return default_return_val s += ins + + # Try parsing try: inval = literal_eval(ins) if isinstance(inval, list) and len(inval) > 0: @@ -230,8 +268,13 @@ def read(port_identifier, name, initstr_val): def write(port_identifier, name, val, delta=0): + """ + Write data either to ZMQ port or file. + `val` must be list (with simtime prefix) or string. + """ global simtime + # Case 1: ZMQ port if isinstance(port_identifier, str) and port_identifier in zmq_ports: zmq_p = zmq_ports[port_identifier] try: @@ -240,7 +283,8 @@ def write(port_identifier, name, val, delta=0): 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}") - + + # Case 2: File-based port try: if isinstance(port_identifier, str) and port_identifier in zmq_ports: file_path = os.path.join("../"+port_identifier, name) @@ -251,8 +295,9 @@ def write(port_identifier, name, val, delta=0): print(f"Error: Invalid port identifier '{port_identifier}' for file operation. Must be integer or ZMQ name.") return + # File writing rules if isinstance(val, str): - time.sleep(2 * delay) + time.sleep(2 * delay) # string writes wait longer elif not isinstance(val, list): print(f"File write to {file_path} must have list or str value, got {type(val)}") return @@ -269,6 +314,10 @@ def write(port_identifier, name, val, delta=0): print(f"Error writing to {file_path}: {e}") def initval(simtime_val_str): + """ + Initialize simtime from string containing a list. + Example: "[10, 'foo', 'bar']" → simtime=10, returns ['foo','bar'] + """ global simtime try: val = literal_eval(simtime_val_str) diff --git a/measurements/Throughput/maximumThroughputComaprison.py b/measurements/Throughput/maximumThroughputComaprison.py index 1dd0342..607d259 100644 --- a/measurements/Throughput/maximumThroughputComaprison.py +++ b/measurements/Throughput/maximumThroughputComaprison.py @@ -15,7 +15,6 @@ # Add plot details plt.ylabel('Throughput (Messages/Second)', fontsize=14) -plt.title('Figure 6: Maximum Throughput Comparison', fontsize=18, pad=25) plt.xticks(fontsize=12) plt.yscale('log') # log scale for large differences plt.grid(axis='y', linestyle='--', alpha=0.7) diff --git a/measurements/Throughput/throughput_comparison.pdf b/measurements/Throughput/throughput_comparison.pdf index 7793b139f42b8e6f99a2c3de5ee55e21457903ff..5854b05a0b0dfb015fa5f41eb267ef11eeff92fd 100644 GIT binary patch delta 2741 zcmZWqX;f3!7JdO_hzx-Q5eRrNfKt)i`Q{d|iUNXF6mhDEh7bl30!c&)`l6KjVDVa% zv#M6bMWIelt4OLi02NqbL@#zt)`8NXpkNqdi#Mafz3K#D_*!k%6@(AB` zd5YYvYf^L+l{FY1H{IJ^kr@7p3|DN)pS5(c&uo`GrnpR#iiL=4p1$%S0vRhnN=Ja>{{6MfdRj;JU25A9|KwEgANbP5Rl1IGR?n z@WuL$WL?3HGw{^0k&$f<51)2Tub+A_w^u~p{HXNd{QR%GCs?*!^lw{#eCi^%c&FFA zT*oM_<1}QLnQS-sU0q*$OI;s1U=zCFf%TDJ@A|gB{K%r=-SoNz-sd{D+(xX*>uSl# zB^Q{@2p9w$y zhU0=$tCn4tonUjleAG5!8L~3FK!FZZ_;yzhh0^JonH}!KM{l;&FKCI`-&Lsq^daYe!zSg}rk7uD_vS|BHTkM(u@jIlAGIid4tT zwg0QWd${ZA#u-B|eRD?of{*pbZm5ck-LO3F*8P*P6Z_$4!QnS){a%qb(tkhmBs|(< z@!Epf?Nsd2_Wu0^M>e-Tt07YE!?S)vQJcSNI_wt~S9<5!in}XC5wC69PrA_W%=|C7 zMevnr@fxjKDNp5)DsBTG#Q*{f0HJX>$r6F~)?dN|E0Mm!n&80^D-rAx`RG0P2|QS0 zErh!#Ziau@2qCcj41P9Is6T6)%!78eLOo{h$%Ey#LipU_Q#i%mS)VI#=fNcoLVbnf zEFSE35WxyZAH9pvh6gtaM34{_!vl^YeV3?^2X8qEVb-KB=p_18{yBRE<;Q@eD4j2YV6+jvfq)LDyIFKgtrAa`V3{Vt--80FW51B_GCvCAX^%pk|v!;Nyu05{5|0o*930=PjANL6V{fE&fq0d5fE zOVj0QW!gq%f)?OLQ3In+PE2AcqqG{}#ws-cXF!~x5KVFxAPmZUsb-^GlLQE(x+Yz& zPy)i}Knn53xXynm_~@r z2nPO}km^uI#;(CVAPw*h07Yqn?ZOWmf}?CLV=_?$MaH{B7>XO1v2iF)jpq=QL6{i9?bg$8Rt~8r${08Iqw*%upzISjL*62yRHnag?zT-FwwhGUol( z7*c4|bnj@AJDXz{q#4sV8Dd(94CT()-?=L}D8mVpF34!gq+JYRGOP%Lb63XS3$h5s z5CUG1iAnZANuyLMEnp+Kn=3pmfjyd|7s2e=e2rGF)@G@d3G9~zLvX&2Pe^1a|Nldq BlivUU delta 3824 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 diff --git a/mkconcore.py b/mkconcore.py index c05e8aa..b243c23 100644 --- a/mkconcore.py +++ b/mkconcore.py @@ -1,3 +1,67 @@ +# The script handles different environments: Docker, POSIX (macOS/Ubuntu), and Windows. +# It reads the graph nodes (representing computational tasks) and edges (representing data flow). +# Based on this information, it generates a directory structure and a set of helper scripts +# (build, run, stop, clear, maxtime, params, unlock) to manage the workflow. +# It also includes logic to handle "script specialization" for ZMQ-based communication, +# where it modifies source files to include specific port and port-name information. + +# The script does the following: +# 1. Initial Setup and Argument Parsing: +# - Defines global constants for tool names (g++, iverilog, python3, matlab, etc.) and paths. +# - Parses command-line arguments for the GraphML file, source directory, output directory, and execution type (posix, windows, docker). +# - Checks for the existence of input/output directories and creates the output structure. +# - Logs the configuration details. + +# 2. Graph Parsing and Adjacency Matrix Creation: +# - Uses BeautifulSoup to parse the input GraphML file. +# - Identifies nodes and edges, storing them in dictionaries. +# - Creates a simple adjacency matrix (m) and a reachability matrix (ms) from the graph, +# detecting any unreachable nodes and logging a warning. + +# 3. Script Specialization (Aggregation and Execution): +# - This is a key part of the logic that handles ZMQ connections. +# - It iterates through the edges, specifically looking for ones with labels in the format "0x_". +# - It aggregates these port parameters for each node. +# - It then uses an external script `copy_with_port_portname.py` to "specialize" the original source files. This means it creates +# new versions of the scripts, injecting the ZMQ port information directly into the code. +# - The `nodes_dict` is then updated to point to these newly created, specialized scripts. + +# 4. Port Mapping and File Generation: +# - Generates `.iport` (input port) and `.oport` (output port) mapping files for each node. +# - These files are simple dictionaries that map volume names (for file-based communication) or port names (for ZMQ) +# to their corresponding port numbers or indices. This allows the individual scripts to know how to connect to their +# peers in the graph. + +# 5. File Copying and Script Generation: +# - Copies all necessary source files (`.py`, `.cpp`, `.m`, etc.) from the source directory to the `outdir/src` directory. +# - Handles cases where specialized scripts were created, ensuring the new files are copied instead of the originals. +# - Copies a set of standard `concore` files (`.py`, `.hpp`, `.v`, `.m`, `mkcompile`) into the `src` directory. + +# 6. Environment-Specific Scripting (Main Logic Branches): +# - This is the largest and most complex part, where the script's behavior diverges based on the `concoretype`. + +# a. Docker: +# - Generates `Dockerfile`s for each node's container. If a custom Dockerfile exists in the source directory, it's used. +# Otherwise, it generates a default one based on the file extension (`.py`, `.cpp`, etc.). +# - Creates `build.bat` (Windows) or `build` (POSIX) scripts to build the Docker images for each node. +# - Creates `run.bat`/`run` scripts to launch the containers, setting up the necessary shared volumes (`-v`) for data transfer. +# - Creates `stop.bat`/`stop` and `clear.bat`/`clear` scripts to manage the containers and clean up the volumes. +# - Creates helper scripts like `maxtime.bat`/`maxtime`, `params.bat`/`params`, and `unlock.bat`/`unlock` to +# pass runtime parameters or API keys to the containers. + +# b. POSIX (Linux/macOS) and Windows: +# - These branches handle direct execution on the host machine without containers. +# - Creates a separate directory for each node inside the output directory. +# - Uses the `build` script to copy source files and create symbolic links (`ln -s` on POSIX, `mklink` on Windows) +# between the node directories and the shared data directories (representing graph edges). +# - Generates `run` and `debug` scripts to execute the programs. It uses platform-specific commands +# like `start /B` for Windows and `xterm -e` or `osascript` for macOS to run the processes. +# - The `stop` and `clear` scripts use `kill` or `del` commands to manage the running processes and files. +# - Generates `maxtime`, `params`, and `unlock` scripts that directly write files to the shared directories. + +# 7. Permissions: +# - Sets the executable permission (`stat.S_IRWXU`) for the generated scripts on POSIX systems. + from bs4 import BeautifulSoup import logging import re @@ -17,13 +81,13 @@ CPPEXE = "g++" #Ubuntu/macOS C++ 6/22/21 VWIN = "iverilog" #Windows verilog 6/25/21 VEXE = "iverilog" #Ubuntu/macOS verilog 6/25/21 -PYTHONEXE = "python3" #Ubuntu/macOS python 3 -PYTHONWIN = "python" #Windows python 3 +PYTHONEXE = "python3" #Ubuntu/macOS python3 +PYTHONWIN = "python" #Windows python3 MATLABEXE = "matlab" #Ubuntu/macOS matlab MATLABWIN = "matlab" #Windows matlab -OCTAVEEXE = "octave" #Ubuntu/macOS octave -OCTAVEWIN = "octave" #Windows octave -M_IS_OCTAVE = False #treat .m as octave +OCTAVEEXE = "octave" #Ubuntu/macOS octave +OCTAVEWIN = "octave" #Windows octave +M_IS_OCTAVE = False #treat .m as octave MCRPATH = "~/MATLAB/R2021a" #path to local Ubunta Matlab Compiler Runtime DOCKEREXE = "sudo docker"#assume simple docker install DOCKEREPO = "markgarnold"#where pulls come from 3/28/21