# -*- generated by 1.0.12 -*-
import da
PatternExpr_234 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_239 = da.pat.BoundPattern('_BoundPattern241_')
PatternExpr_267 = da.pat.TuplePattern([da.pat.ConstantPattern('learned'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_276 = da.pat.FreePattern('p')
PatternExpr_290 = da.pat.TuplePattern([da.pat.ConstantPattern('ProposedValue'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_299 = da.pat.FreePattern('p')
PatternExpr_313 = da.pat.TuplePattern([da.pat.ConstantPattern('AcceptedValue'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_322 = da.pat.FreePattern('p')
PatternExpr_242 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern248_')]), da.pat.TuplePattern([da.pat.ConstantPattern('done')])])
PatternExpr_766 = da.pat.TuplePattern([da.pat.ConstantPattern('learned')])
PatternExpr_771 = da.pat.BoundPattern('_BoundPattern772_')
PatternExpr_1144 = da.pat.TuplePattern([da.pat.ConstantPattern('learned')])
PatternExpr_1149 = da.pat.BoundPattern('_BoundPattern1150_')
PatternExpr_1508 = da.pat.TuplePattern([da.pat.ConstantPattern('learned')])
PatternExpr_1513 = da.pat.BoundPattern('_BoundPattern1514_')
PatternExpr_773 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern779_')]), da.pat.TuplePattern([da.pat.ConstantPattern('learned')])])
PatternExpr_1151 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern1157_')]), da.pat.TuplePattern([da.pat.ConstantPattern('learned')])])
PatternExpr_1515 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern1521_')]), da.pat.TuplePattern([da.pat.ConstantPattern('learned')])])
_config_object = {}
import sys
import os
import random
import time
import matplotlib.pyplot as plot1
import matplotlib.pyplot as plot2
import numpy as np
from statistics import stdev
from subprocess import call
BasicPaxos = da.import_da('basic_paxos')
PreemptPaxos = da.import_da('preempt_paxos')

class Monitor(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._MonitorReceivedEvent_0 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_MonitorReceivedEvent_0', PatternExpr_234, sources=[PatternExpr_239], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_MonitorReceivedEvent_1', PatternExpr_267, sources=[PatternExpr_276], destinations=None, timestamps=None, record_history=None, handlers=[self._Monitor_handler_266]), da.pat.EventPattern(da.pat.ReceivedEvent, '_MonitorReceivedEvent_2', PatternExpr_290, sources=[PatternExpr_299], destinations=None, timestamps=None, record_history=None, handlers=[self._Monitor_handler_289]), da.pat.EventPattern(da.pat.ReceivedEvent, '_MonitorReceivedEvent_3', PatternExpr_313, sources=[PatternExpr_322], destinations=None, timestamps=None, record_history=None, handlers=[self._Monitor_handler_312])])

    def setup(self, learners, acceptors, proposers, **rest_1728):
        super().setup(learners=learners, acceptors=acceptors, proposers=proposers, **rest_1728)
        self._state.learners = learners
        self._state.acceptors = acceptors
        self._state.proposers = proposers
        self._state.proposerVal = set()
        self._state.acceptedVal = set()
        self._state.learnerVal = set()

    def run(self):
        super()._label('yieldpt', block=False)
        _st_label_231 = 0
        while (_st_label_231 == 0):
            _st_label_231 += 1
            if PatternExpr_242.match_iter(self._MonitorReceivedEvent_0, _BoundPattern248_=self.parent(), SELF_ID=self._id):
                _st_label_231 += 1
            else:
                super()._label('yieldpt', block=True)
                _st_label_231 -= 1
        self.agreementCheck()
        self.validityCheck()
        self.terminationCheck()
        self.output('terminating')

    def agreementCheck(self):
        if (len(self._state.learnerVal) == 1):
            print('Agreement is existing')
        else:
            print('Agreement is violated')

    def validityCheck(self):
        if (self._state.proposerVal >= self._state.learnerVal):
            print('Validity is existing')
        else:
            print('Validity is violated')

    def terminationCheck(self):
        if (not (len(self._state.learnerVal) == 0)):
            print('Temination is existing')
        else:
            print('Termination failed')

    def _Monitor_handler_266(self, n, v, p):
        if (p in self._state.learners):
            self._state.learnerVal.add(v)
    _Monitor_handler_266._labels = None
    _Monitor_handler_266._notlabels = None

    def _Monitor_handler_289(self, n, v, p):
        if (p in self._state.proposers):
            self._state.proposerVal.add(v)
    _Monitor_handler_289._labels = None
    _Monitor_handler_289._notlabels = None

    def _Monitor_handler_312(self, n, v, p):
        if (p in self._state.acceptors):
            self._state.acceptedVal.add(v)
    _Monitor_handler_312._labels = None
    _Monitor_handler_312._notlabels = None

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._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_0', PatternExpr_766, sources=[PatternExpr_771], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_1', PatternExpr_1144, sources=[PatternExpr_1149], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_2', PatternExpr_1508, sources=[PatternExpr_1513], destinations=None, timestamps=None, record_history=True, handlers=[])])

    def run(self):
        nacceptors = (int(sys.argv[1]) if (len(sys.argv) > 1) else 3)
        nproposers = (int(sys.argv[2]) if (len(sys.argv) > 2) else 2)
        nlearners = (int(sys.argv[3]) if (len(sys.argv) > 3) else 2)
        nruns = (int(sys.argv[4]) if (len(sys.argv) > 4) else 2)
        nmessagelossrate = (float(sys.argv[5]) if (len(sys.argv) > 5) else 0.5)
        nmessageDelay = (int(sys.argv[6]) if (len(sys.argv) > 6) else 5)
        nwaitaroundtime = (int(sys.argv[7]) if (len(sys.argv) > 7) else 5)
        ntimeoutproposers = (int(sys.argv[8]) if (len(sys.argv) > 8) else 1)
        ntimeoutlearners = (int(sys.argv[9]) if (len(sys.argv) > 9) else 10)
        (cpuStartTime, cpuEndTime, elapsedStartTime, elapsedEndTime) = (0, 0, 0, 0)
        nmessagelossrateWhole = int((nmessagelossrate * 100))
        nmessagelossrateValue = int((nmessagelossrateWhole / 5))
        CPULossRate = {}
        ElapsedLossRate = {}
        nmessageDelayValue = int((nmessageDelay / 5))
        nwaitValue = int((nwaitaroundtime / 5))
        CPULossRate = {}
        ElapsedLossRate = {}
        if (not os.path.exists('message_loss_results')):
            os.mkdir('message_loss_results')
        plot1.figure(1)
        plot2.figure(2)
        AlgoList = [BasicPaxos, PreemptPaxos]
        for algo in AlgoList:
            CPULossRate = {}
            ElapsedLossRate = {}
            CPU_Times_StandardDeviation = []
            Elapsed_times_StandardDeviation = []
            sde_time_cpu = {}
            sde_elapsed_time = {}
            for nLossValue in range(nmessagelossrateValue, (nmessagelossrateWhole + 1), nmessagelossrateValue):
                (cpuTime, elapsedTime) = (0, 0)
                for i in range(nruns):
                    monitor = self.new(Monitor, num=1)
                    acceptors = self.new(algo.Acceptor, num=nacceptors)
                    proposers = self.new(algo.Proposer, (acceptors, monitor, ntimeoutproposers, (nLossValue / 100), nmessageDelayValue, nwaitValue), num=nproposers)
                    learners = self.new(algo.Learner, num=nlearners)
                    self._setup(monitor, (learners, acceptors, proposers))
                    self._start(monitor)
                    for p in acceptors:
                        self._setup(p, (learners, monitor, nmessageDelayValue))
                    for p in learners:
                        self._setup(p, (acceptors, monitor, ntimeoutlearners))
                    cpuStartTime = time.process_time()
                    elapsedStartTime = time.time()
                    self._start(((acceptors | proposers) | learners))
                    super()._label('_st_label_757', block=False)
                    l = None

                    def UniversalOpExpr_758():
                        nonlocal l
                        for l in learners:
                            if (not PatternExpr_773.match_iter(self._Node_ReceivedEvent_0, _BoundPattern779_=l)):
                                return False
                        return True
                    _st_label_757 = 0
                    while (_st_label_757 == 0):
                        _st_label_757 += 1
                        if UniversalOpExpr_758():
                            _st_label_757 += 1
                        else:
                            super()._label('_st_label_757', block=True)
                            _st_label_757 -= 1
                    else:
                        if (_st_label_757 != 2):
                            continue
                    if (_st_label_757 != 2):
                        break
                    self.send(('done',), to=(acceptors | proposers))
                    cpuEndTime = time.process_time()
                    elapsedEndTime = time.time()
                    cpuTime += (cpuEndTime - cpuStartTime)
                    elapsedTime += (elapsedEndTime - elapsedStartTime)
                    CPU_Times_StandardDeviation.append(cpuTime)
                    Elapsed_times_StandardDeviation.append(elapsedTime)
                    self.send(('done',), to=monitor)
                cpuTime = float((cpuTime / nruns))
                elapsedTime = float((elapsedTime / nruns))
                CPULossRate[(nLossValue / 100)] = cpuTime
                ElapsedLossRate[(nLossValue / 100)] = elapsedTime
                sde_time_cpu[(nLossValue / 100)] = stdev(CPU_Times_StandardDeviation)
                sde_elapsed_time[(nLossValue / 100)] = stdev(Elapsed_times_StandardDeviation)
            if (algo == BasicPaxos):
                print('BASIC PAXOS:')
            else:
                print('BASIC PAXOS WITH PREEMPTION:')
            print('CPU LOSS TIME FOR MESSAGE LOSS', CPULossRate)
            print('ELAPSED LOSS TIME FOR MESSAGE LOSS', ElapsedLossRate)
            print('STANDARD DEVIATION OF CPU TIME FOR MESSAGE LOSS', sde_time_cpu)
            print('STANDARD DEVIATION OF ELAPSED TIME FOR MESSAGE LOSS', sde_elapsed_time)
            list1 = sorted(CPULossRate.items())
            (x, y) = zip(*list1)
            plot1.xlabel('Message Loss Rate', fontsize=18)
            plot1.ylabel('Time', fontsize=16)
            plot1.plot(x, y, label='MessageLossRateAvgCPUTime')
            lists2 = sorted(ElapsedLossRate.items())
            (a, b) = zip(*lists2)
            plot1.xlabel('Message Loss Rate', fontsize=18)
            plot1.ylabel('Time', fontsize=16)
            plot2.plot(a, b, label='MessageLossRateAvgElapsedime')
        plot1.legend(['BasicPaxosCPUTime', 'BasicPaxosELAPSEDTime', 'PremeptionCPUTime', 'PreemptionELAPSEDTime'], loc='upper left', prop={'size': 5})
        savedFileName = ('message_loss_results/' + 'messageLossRate.png')
        plot1.savefig(savedFileName)
        if (not os.path.exists('message_delay_results')):
            os.mkdir('message_delay_results')
        plot1.figure()
        plot2.figure()
        for algo in AlgoList:
            CPULossRate = {}
            ElapsedLossRate = {}
            for nmessageDelayValue in range(nmessageDelayValue, (nmessageDelay + 1), nmessageDelayValue):
                (cpuTime, elapsedTime) = (0, 0)
                for i in range(nruns):
                    monitor = self.new(Monitor, num=1)
                    acceptors = self.new(algo.Acceptor, num=nacceptors)
                    proposers = self.new(algo.Proposer, (acceptors, monitor, ntimeoutproposers, (nmessagelossrateValue / 100), nmessageDelayValue, nwaitValue), num=nproposers)
                    learners = self.new(algo.Learner, num=nlearners)
                    self._setup(monitor, (learners, acceptors, proposers))
                    self._start(monitor)
                    for p in acceptors:
                        self._setup(p, (learners, monitor, nmessageDelayValue))
                    for p in learners:
                        self._setup(p, (acceptors, monitor, ntimeoutlearners))
                    cpuStartTime = time.process_time()
                    elapsedStartTime = time.time()
                    self._start(((acceptors | proposers) | learners))
                    super()._label('_st_label_1136', block=False)
                    l = None

                    def UniversalOpExpr_1137():
                        nonlocal l
                        for l in learners:
                            if (not PatternExpr_1151.match_iter(self._Node_ReceivedEvent_1, _BoundPattern1157_=l)):
                                return False
                        return True
                    _st_label_1136 = 0
                    while (_st_label_1136 == 0):
                        _st_label_1136 += 1
                        if UniversalOpExpr_1137():
                            _st_label_1136 += 1
                        else:
                            super()._label('_st_label_1136', block=True)
                            _st_label_1136 -= 1
                    else:
                        if (_st_label_1136 != 2):
                            continue
                    if (_st_label_1136 != 2):
                        break
                    self.send(('done',), to=(acceptors | proposers))
                    cpuEndTime = time.process_time()
                    elapsedEndTime = time.time()
                    cpuTime += (cpuEndTime - cpuStartTime)
                    elapsedTime += (elapsedEndTime - elapsedStartTime)
                    CPU_Times_StandardDeviation.append(cpuTime)
                    Elapsed_times_StandardDeviation.append(elapsedTime)
                    self.send(('done',), to=monitor)
                cpuTime = float((cpuTime / nruns))
                elapsedTime = float((elapsedTime / nruns))
                CPULossRate[nmessageDelayValue] = cpuTime
                ElapsedLossRate[nmessageDelayValue] = elapsedTime
                sde_time_cpu[nmessageDelayValue] = stdev(CPU_Times_StandardDeviation)
                sde_elapsed_time[nmessageDelayValue] = stdev(Elapsed_times_StandardDeviation)
            if (algo == BasicPaxos):
                print('BASIC PAXOS:')
            else:
                print('BASIC PAXOS WITH PREEMPTION:')
            print('CPU LOSS TIME FOR MESSAGE LOSS', CPULossRate)
            print('ELAPSED LOSS TIME FOR MESSAGE LOSS', ElapsedLossRate)
            print('STANDARD DEVIATION OF CPU TIME FOR MESSAGE DELAY', sde_time_cpu)
            print('STANDARD DEVIATION OF ELAPSED TIME FOR MESSAGE DELAY', sde_elapsed_time)
            list1 = sorted(CPULossRate.items())
            (x, y) = zip(*list1)
            plot1.xlabel('Message Delay Rate', fontsize=18)
            plot1.ylabel('Time', fontsize=16)
            plot1.plot(x, y, label='MessageDelayAvgCPUTime')
            lists2 = sorted(ElapsedLossRate.items())
            (a, b) = zip(*lists2)
            plot1.xlabel('Message Delay Rate', fontsize=18)
            plot1.ylabel('Time', fontsize=16)
            plot2.plot(a, b, label='MessageDelayAvgElapsedTime')
        plot1.legend(['BasicPaxosCPUTime', 'BasicPaxosELAPSEDTime', 'PremeptionCPUTime', 'PreemptionELAPSEDTime'], loc='upper left', prop={'size': 5})
        savedFileName = ('message_delay_results/' + 'MessageDelay.png')
        plot1.savefig(savedFileName)
        if (not os.path.exists('message_wait_results')):
            os.mkdir('message_wait_results')
        plot1.figure()
        plot2.figure()
        for algo in AlgoList:
            CPULossRate = {}
            ElapsedLossRate = {}
            for nWaitValue in range(nwaitValue, (nwaitaroundtime + 1), nwaitValue):
                (cpuTime, elapsedTime) = (0, 0)
                for i in range(nruns):
                    monitor = self.new(Monitor, num=1)
                    acceptors = self.new(algo.Acceptor, num=nacceptors)
                    proposers = self.new(algo.Proposer, (acceptors, monitor, ntimeoutproposers, (nmessagelossrateValue / 100), nmessageDelayValue, nWaitValue), num=nproposers)
                    learners = self.new(algo.Learner, num=nlearners)
                    self._setup(monitor, (learners, acceptors, proposers))
                    self._start(monitor)
                    for p in acceptors:
                        self._setup(p, (learners, monitor, nmessageDelayValue))
                    for p in learners:
                        self._setup(p, (acceptors, monitor, ntimeoutlearners))
                    cpuStartTime = time.process_time()
                    elapsedStartTime = time.time()
                    self._start(((acceptors | proposers) | learners))
                    super()._label('_st_label_1500', block=False)
                    l = None

                    def UniversalOpExpr_1501():
                        nonlocal l
                        for l in learners:
                            if (not PatternExpr_1515.match_iter(self._Node_ReceivedEvent_2, _BoundPattern1521_=l)):
                                return False
                        return True
                    _st_label_1500 = 0
                    while (_st_label_1500 == 0):
                        _st_label_1500 += 1
                        if UniversalOpExpr_1501():
                            _st_label_1500 += 1
                        else:
                            super()._label('_st_label_1500', block=True)
                            _st_label_1500 -= 1
                    else:
                        if (_st_label_1500 != 2):
                            continue
                    if (_st_label_1500 != 2):
                        break
                    self.send(('done',), to=(acceptors | proposers))
                    cpuEndTime = time.process_time()
                    elapsedEndTime = time.time()
                    cpuTime += (cpuEndTime - cpuStartTime)
                    elapsedTime += (elapsedEndTime - elapsedStartTime)
                    CPU_Times_StandardDeviation.append(cpuTime)
                    Elapsed_times_StandardDeviation.append(elapsedTime)
                    self.send(('done',), to=monitor)
                cpuTime = float((cpuTime / nruns))
                elapsedTime = float((elapsedTime / nruns))
                CPULossRate[nWaitValue] = cpuTime
                ElapsedLossRate[nWaitValue] = elapsedTime
                sde_time_cpu[nWaitValue] = stdev(CPU_Times_StandardDeviation)
                sde_elapsed_time[nWaitValue] = stdev(Elapsed_times_StandardDeviation)
            if (algo == BasicPaxos):
                print('BASIC PAXOS:')
            else:
                print('BASIC PAXOS WITH PREEMPTION:')
            print('CPU LOSS TIME FOR MESSAGE LOSS', CPULossRate)
            print('ELAPSED LOSS TIME FOR MESSAGE LOSS', ElapsedLossRate)
            print('STANDARD DEVIATION OF CPU TIME FOR WAIT TIME', sde_time_cpu)
            print('STANDARD DEVIATION OF ELAPSED TIME FOR WAIT TIME', sde_elapsed_time)
            list1 = sorted(CPULossRate.items())
            (x, y) = zip(*list1)
            plot1.xlabel('Wait Around Rate', fontsize=18)
            plot1.ylabel('Time', fontsize=16)
            plot1.plot(x, y, label='WaitDelayAvgCPUTime')
            lists2 = sorted(ElapsedLossRate.items())
            (a, b) = zip(*lists2)
            plot1.xlabel('Wait Around Rate', fontsize=18)
            plot1.ylabel('Time', fontsize=16)
            plot2.plot(a, b, label='WaitDelayAvgELAPSEDTime')
        plot1.legend(['BasicPaxosCPUTime', 'BasicPaxosELAPSEDTime', 'PremeptionCPUTime', 'PreemptionELAPSEDTime'], loc='upper left', prop={'size': 5})
        savedFileName = ('message_wait_results/' + 'WaitDelay1.png')
        plot1.savefig(savedFileName)
