# -*- generated by 1.0.12 -*-
import da
PatternExpr_268 = da.pat.TuplePattern([da.pat.ConstantPattern('totalHops'), da.pat.FreePattern('src'), da.pat.FreePattern('dst'), da.pat.FreePattern('numHops'), da.pat.FreePattern('tDist')])
PatternExpr_379 = da.pat.TuplePattern([da.pat.ConstantPattern('randomNodeList'), da.pat.FreePattern('objList')])
PatternExpr_386 = da.pat.FreePattern('X')
PatternExpr_437 = da.pat.TuplePattern([da.pat.ConstantPattern('LookupCompleted'), da.pat.FreePattern(None)])
PatternExpr_459 = da.pat.TuplePattern([da.pat.ConstantPattern('LookupCompleted'), da.pat.FreePattern('t')])
PatternExpr_934 = da.pat.ConstantPattern('JoinCompleted')
PatternExpr_938 = da.pat.FreePattern('p')
PatternExpr_1052 = da.pat.TuplePattern([da.pat.ConstantPattern('randomNodeList'), da.pat.FreePattern('objs')])
PatternExpr_1059 = da.pat.FreePattern('X')
PatternExpr_1122 = da.pat.TuplePattern([da.pat.ConstantPattern('LookupCompleted'), da.pat.FreePattern(None)])
PatternExpr_1144 = da.pat.TuplePattern([da.pat.ConstantPattern('LookupCompleted'), da.pat.FreePattern('t')])
_config_object = {}
import os
import sys
import pastry
import time
import random
import numpy as np
from math import sqrt
import controller

class ClientLookup(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._ClientLookupReceivedEvent_2 = []
        self._ClientLookupReceivedEvent_3 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_ClientLookupReceivedEvent_0', PatternExpr_268, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._ClientLookup_handler_267]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ClientLookupReceivedEvent_1', PatternExpr_379, sources=[PatternExpr_386], destinations=None, timestamps=None, record_history=None, handlers=[self._ClientLookup_handler_378]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ClientLookupReceivedEvent_2', PatternExpr_437, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ClientLookupReceivedEvent_3', PatternExpr_459, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, boot, N, b, L, M, keySize, lTrials, tl, tps, **rest_1206):
        super().setup(boot=boot, N=N, b=b, L=L, M=M, keySize=keySize, lTrials=lTrials, tl=tl, tps=tps, **rest_1206)
        self._state.boot = boot
        self._state.N = N
        self._state.b = b
        self._state.L = L
        self._state.M = M
        self._state.keySize = keySize
        self._state.lTrials = lTrials
        self._state.tl = tl
        self._state.tps = tps
        self._state.successRuns = 0
        self._state.totalHops = 0
        self._state.countList = [0 for o in range(0, 14)]
        self._state.distInfo = []
        pass

    def run(self):
        print('######################## Starting lookup for nodes ########################')
        start_time = time.time()
        for i in range(self._state.lTrials):
            self.send(('getRandomNodes', 2), to=self._state.boot)
        super()._label('_st_label_434', block=False)
        t = None

        def ExistentialOpExpr_435():
            nonlocal t
            for (_, _, (_ConstantPattern451_, _)) in self._ClientLookupReceivedEvent_2:
                if (_ConstantPattern451_ == 'LookupCompleted'):
                    if (len({t for (_, _, (_ConstantPattern474_, t)) in self._ClientLookupReceivedEvent_3 if (_ConstantPattern474_ == 'LookupCompleted')}) == self._state.lTrials):
                        return True
            return False
        _st_label_434 = 0
        self._timer_start()
        while (_st_label_434 == 0):
            _st_label_434 += 1
            if ExistentialOpExpr_435():
                end_time = time.time()
                print('Total time taken in lookup is', (end_time - start_time))
                print('Average time taken in lookup is ', ((end_time - start_time) / self._state.lTrials))
                pass
                _st_label_434 += 1
            elif self._timer_expired:
                print("Couldn't determine time taken for lookup")
                pass
                _st_label_434 += 1
            else:
                super()._label('_st_label_434', block=True, timeout=self._state.tps)
                _st_label_434 -= 1
        if (not (self._state.successRuns == 0)):
            print('N = {} , lookup trails {} , successRuns {} '.format(self._state.N, self._state.lTrials, self._state.successRuns))
            print(self._state.countList)
            print('Average hops: ', float((self._state.totalHops / self._state.successRuns)))
            x = [(d2 / d1) for (d1, d2) in self._state.distInfo]
            print('Relative Distance Info ', np.mean(x))
            f = open('results.txt', 'a')
            f.write('N = {} , b = {} , keySize = {} , |L| = {} , |M| = {} , lookup trails {} , successRuns {} '.format(self._state.N, self._state.b, self._state.keySize, self._state.L, self._state.M, self._state.lTrials, self._state.successRuns))
            f.write(('\n' + str(self._state.countList)))
            f.write(('\nAverage hops: ' + str(float((self._state.totalHops / self._state.successRuns)))))
            f.write(('\nRelative Distance: ' + str(np.mean(x))))
            f.write('\n\n')
        else:
            print('All runs failed lookup')
        print('Terminating ClientLookup')

    def getRelativeDistance(self, coord1, coord2):
        yDiff = (coord1[1] - coord2[1])
        xDiff = (coord1[0] - coord2[0])
        dist = sqrt(((yDiff ** 2) + (xDiff ** 2)))
        return dist

    def _ClientLookup_handler_267(self, src, dst, numHops, tDist):
        print('Minimum number of hops to route from ', src.nodeid, ' to ', dst.nodeid, ' is ', numHops)
        print('Length of route distance from ', src.nodeid, ' to ', dst.nodeid, ' is ', tDist)
        print('Length of ficticious distance from ', src.nodeid, ' to ', dst.nodeid, ' is ', self.getRelativeDistance(src.coordinates, dst.coordinates))
        t = self.logical_clock()
        self.send(('LookupCompleted', t), to=self._id)
        self.send(('LookupCompleted', t), to=self.parent())
        if (numHops > 0):
            self._state.successRuns += 1
            self._state.totalHops += numHops
            self._state.countList[numHops] = (self._state.countList[numHops] + 1)
            self._state.distInfo.append((self.getRelativeDistance(src.coordinates, dst.coordinates), tDist))
        pass
    _ClientLookup_handler_267._labels = None
    _ClientLookup_handler_267._notlabels = None

    def _ClientLookup_handler_378(self, objList, X):
        srcObj = objList[0]
        dstObj = objList[1]
        self.send(('getHopCount', srcObj, dstObj), to=dstObj.nodeObj)
    _ClientLookup_handler_378._labels = None
    _ClientLookup_handler_378._notlabels = None
if (__name__ == '__main__'):
    main()

class Node_(da.NodeProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._Node_ReceivedEvent_0 = []
        self._Node_ReceivedEvent_1 = []
        self._Node_ReceivedEvent_2 = []
        self._Node_ReceivedEvent_3 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_0', PatternExpr_934, sources=[PatternExpr_938], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_1', PatternExpr_1052, sources=[PatternExpr_1059], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_2', PatternExpr_1122, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_3', PatternExpr_1144, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])
    _config_object = {'channel': 'fifo', 'clock': 'lamport'}

    def run(self):
        N = (int(sys.argv[1]) if (len(sys.argv) > 1) else 10)
        dNodes = (int(sys.argv[2]) if (len(sys.argv) > 2) else 0)
        lTrials = (int(sys.argv[3]) if (len(sys.argv) > 3) else 50)
        b = (int(sys.argv[4]) if (len(sys.argv) > 4) else 2)
        keySize = (int(sys.argv[5]) if (len(sys.argv) > 5) else 16)
        tl = (int(sys.argv[6]) if (len(sys.argv) > 6) else 15)
        td = (int(sys.argv[7]) if (len(sys.argv) > 7) else 1)
        ti = (int(sys.argv[8]) if (len(sys.argv) > 8) else 1)
        tack = (float(sys.argv[9]) if (len(sys.argv) > 9) else 1.0)
        tn = (int(sys.argv[10]) if (len(sys.argv) > 10) else 5)
        tps = (int(sys.argv[11]) if (len(sys.argv) > 11) else 100)
        L = (2 ** b)
        M = (2 ** (b + 1))
        leafSetLen = int((L / 2))
        boot = self.new(pastry.BootStrapNode)
        self._setup(boot, (b, keySize, L, M, leafSetLen, tack))
        self._start(boot)
        startTimeNodeInit = time.time()
        ps = self.new(pastry.PastryNode, num=N)
        totalTimeJoin = 0.0
        ctl = None
        count = 0
        for p in ps:
            endTimeNodeJoin = time.time()
            startTimeNodeJoin = time.time()
            self._setup(p, (ctl, boot, b, keySize, L, M, leafSetLen, ti, tack, tn, tps))
            self._start(p)
            super()._label('_st_label_931', block=False)
            p = None

            def ExistentialOpExpr_932():
                nonlocal p
                for (_, (_, _, p), _ConstantPattern947_) in self._Node_ReceivedEvent_0:
                    if (_ConstantPattern947_ == 'JoinCompleted'):
                        if True:
                            return True
                return False
            _st_label_931 = 0
            self._timer_start()
            while (_st_label_931 == 0):
                _st_label_931 += 1
                if ExistentialOpExpr_932():
                    count += 1
                    endTimeNodeJoin = time.time()
                    pass
                    _st_label_931 += 1
                elif self._timer_expired:
                    endTimeNodeJoin = time.time()
                    pass
                    _st_label_931 += 1
                else:
                    super()._label('_st_label_931', block=True, timeout=5)
                    _st_label_931 -= 1
            else:
                if (_st_label_931 != 2):
                    continue
            if (_st_label_931 != 2):
                break
            time.sleep(0.1)
            totalTimeJoin += (endTimeNodeJoin - startTimeNodeJoin)
        N = count
        endTimeNodeInit = time.time()
        print('All Pastry Nodes initialized')
        f = open('NodeStatistics.txt', 'a')
        f.write('N = {}'.format(N))
        f.write(('\nTotal time taken in node joining ' + str(totalTimeJoin)))
        f.write(('\nAverage time taken in node joining ' + str((totalTimeJoin / len(ps)))))
        f.write(('\nTime taken in nodes initialization is ' + str((endTimeNodeInit - startTimeNodeInit))))
        f.write('\n\n')
        self.send(('getRandomNodes', dNodes), to=boot)
        super()._label('_st_label_1049', block=False)
        objs = X = None

        def ExistentialOpExpr_1050():
            nonlocal objs, X
            for (_, (_, _, X), (_ConstantPattern1070_, objs)) in self._Node_ReceivedEvent_1:
                if (_ConstantPattern1070_ == 'randomNodeList'):
                    if True:
                        return True
            return False
        _st_label_1049 = 0
        self._timer_start()
        while (_st_label_1049 == 0):
            _st_label_1049 += 1
            if ExistentialOpExpr_1050():
                kList = [o.nodeObj for o in objs]
                self.end(kList)
                _st_label_1049 += 1
            elif self._timer_expired:
                pass
                _st_label_1049 += 1
            else:
                super()._label('_st_label_1049', block=True, timeout=td)
                _st_label_1049 -= 1
        super()._label('_st_label_1091', block=False)
        _st_label_1091 = 0
        self._timer_start()
        while (_st_label_1091 == 0):
            _st_label_1091 += 1
            if False:
                pass
                _st_label_1091 += 1
            elif self._timer_expired:
                pass
                _st_label_1091 += 1
            else:
                super()._label('_st_label_1091', block=True, timeout=td)
                _st_label_1091 -= 1
        cl = self.new(ClientLookup, num=1)
        self._setup(cl, (boot, N, b, L, M, keySize, lTrials, tl, tps))
        self._start(cl)
        super()._label('_st_label_1119', block=False)
        t = None

        def ExistentialOpExpr_1120():
            nonlocal t
            for (_, _, (_ConstantPattern1136_, _)) in self._Node_ReceivedEvent_2:
                if (_ConstantPattern1136_ == 'LookupCompleted'):
                    if (len({t for (_, _, (_ConstantPattern1159_, t)) in self._Node_ReceivedEvent_3 if (_ConstantPattern1159_ == 'LookupCompleted')}) == lTrials):
                        return True
            return False
        _st_label_1119 = 0
        self._timer_start()
        while (_st_label_1119 == 0):
            _st_label_1119 += 1
            if ExistentialOpExpr_1120():
                print('All processes completed. Killing everyone.')
                for p in ps:
                    self.send('ExitProcess', to=p)
                self.send('ExitProcess', to=boot)
                _st_label_1119 += 1
            elif self._timer_expired:
                for p in ps:
                    self.send('ExitProcess', to=p)
                self.send('ExitProcess', to=boot)
                _st_label_1119 += 1
            else:
                super()._label('_st_label_1119', block=True, timeout=tps)
                _st_label_1119 -= 1
        print('Terminating Main')
        pass
