# -*- generated by 1.0.1 -*-
import da
PatternExpr_214 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern217_'), da.pat.FreePattern(None)])
PatternExpr_221 = da.pat.FreePattern('a')
PatternExpr_249 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern252_'), da.pat.TuplePattern([da.pat.FreePattern('n2'), da.pat.FreePattern('v')])])
PatternExpr_280 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern283_'), da.pat.TuplePattern([da.pat.FreePattern('n2'), da.pat.FreePattern(None)])])
PatternExpr_316 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern319_'), da.pat.FreePattern(None)])
PatternExpr_323 = da.pat.FreePattern('a')
PatternExpr_363 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_368 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.FreePattern(None)]), da.pat.TuplePattern([da.pat.ConstantPattern('done')])])
PatternExpr_408 = da.pat.TuplePattern([da.pat.ConstantPattern('prepare'), da.pat.FreePattern('n')])
PatternExpr_415 = da.pat.FreePattern('p')
PatternExpr_421 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.FreePattern('n2'), da.pat.FreePattern(None)])
PatternExpr_450 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_476 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.FreePattern('n'), da.pat.FreePattern(None)])
PatternExpr_510 = da.pat.TuplePattern([da.pat.ConstantPattern('accept'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_523 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.FreePattern('n2'), da.pat.FreePattern(None)])
PatternExpr_558 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_563 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.FreePattern(None)]), da.pat.TuplePattern([da.pat.ConstantPattern('done')])])
PatternExpr_606 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_632 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.BoundPattern('_BoundPattern635_'), da.pat.BoundPattern('_BoundPattern636_')])
PatternExpr_639 = da.pat.FreePattern('a')
PatternExpr_783 = da.pat.TuplePattern([da.pat.ConstantPattern('learned')])
PatternExpr_788 = da.pat.BoundPattern('_BoundPattern789_')
PatternExpr_790 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern796_')]), da.pat.TuplePattern([da.pat.ConstantPattern('learned')])])
_config_object = {}
import sys
from random import randint
TIMEOUT = 1

class Proposer(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._ProposerReceivedEvent_0 = []
        self._ProposerReceivedEvent_1 = []
        self._ProposerReceivedEvent_2 = []
        self._ProposerReceivedEvent_3 = []
        self._ProposerReceivedEvent_4 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_0', PatternExpr_214, sources=[PatternExpr_221], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_1', PatternExpr_249, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_2', PatternExpr_280, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_3', PatternExpr_316, sources=[PatternExpr_323], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_4', PatternExpr_363, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, acceptors):
        self._state.acceptors = acceptors
        self._state.n = None
        self._state.majority = self._state.acceptors

    def run(self):
        while (not PatternExpr_368.match_iter(self._ProposerReceivedEvent_4, SELF_ID=self._id)):
            self.to_consent()
        self.output('terminating')

    def to_consent(self):
        self._state.n = ((0, self._id) if (self._state.n == None) else ((self._state.n[0] + 1), self._id))
        self.send(('prepare', self._state.n), self._state.majority)
        super()._label('_st_label_209', block=False)
        _st_label_209 = 0
        self._timer_start()
        while (_st_label_209 == 0):
            _st_label_209 += 1
            if (len({a for (_, (_, _, a), (_ConstantPattern232_, _BoundPattern234_, _)) in self._ProposerReceivedEvent_0 if (_ConstantPattern232_ == 'respond') if (_BoundPattern234_ == self._state.n)}) > (len(self._state.acceptors) / 2)):
                v = self.anyof(({v for (_, _, (_ConstantPattern268_, _BoundPattern270_, (n2, v))) in self._ProposerReceivedEvent_1 if (_ConstantPattern268_ == 'respond') if (_BoundPattern270_ == self._state.n) if (n2 == max({n2 for (_, _, (_ConstantPattern297_, _BoundPattern299_, (n2, _))) in self._ProposerReceivedEvent_2 if (_ConstantPattern297_ == 'respond') if (_BoundPattern299_ == self._state.n)}))} or {randint(1, 100)}))
                responded = {a for (_, (_, _, a), (_ConstantPattern334_, _BoundPattern336_, _)) in self._ProposerReceivedEvent_3 if (_ConstantPattern334_ == 'respond') if (_BoundPattern336_ == self._state.n)}
                self.send(('accept', self._state.n, v), responded)
                self.debug('### chose', self._state.n, v)
                _st_label_209 += 1
            elif self._timer_expired:
                self.output('failed proposal number', self._state.n)
                _st_label_209 += 1
            else:
                super()._label('_st_label_209', block=True, timeout=TIMEOUT)
                _st_label_209 -= 1

    def anyof(self, s):
        return (next(iter(s)) if s else None)

class Acceptor(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._AcceptorSentEvent_1 = []
        self._AcceptorSentEvent_2 = []
        self._AcceptorSentEvent_3 = []
        self._AcceptorSentEvent_5 = []
        self._AcceptorReceivedEvent_6 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_AcceptorReceivedEvent_0', PatternExpr_408, sources=[PatternExpr_415], destinations=None, timestamps=None, record_history=None, handlers=[self._Acceptor_handler_407]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_1', PatternExpr_421, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_2', PatternExpr_450, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_3', PatternExpr_476, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_AcceptorReceivedEvent_4', PatternExpr_510, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._Acceptor_handler_509]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_5', PatternExpr_523, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_AcceptorReceivedEvent_6', PatternExpr_558, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, learners):
        self._state.learners = learners
        pass

    def run(self):
        super()._label('_st_label_555', block=False)
        _st_label_555 = 0
        while (_st_label_555 == 0):
            _st_label_555 += 1
            if PatternExpr_563.match_iter(self._AcceptorReceivedEvent_6, SELF_ID=self._id):
                _st_label_555 += 1
            else:
                super()._label('_st_label_555', block=True)
                _st_label_555 -= 1
        self.output('terminating')

    def anyof(self, s):
        "return any element of set s if s is not empty or 'None' otherwise"
        return (next(iter(s)) if s else None)

    def _Acceptor_handler_407(self, n, p):
        n2 = None

        def UniversalOpExpr_419():
            nonlocal n2
            for (_, _, (_ConstantPattern437_, n2, _)) in self._AcceptorSentEvent_1:
                if (_ConstantPattern437_ == 'respond'):
                    if (not (n > n2)):
                        return False
            return True
        if UniversalOpExpr_419():
            maxprop = self.anyof({(n, v) for (_, _, (_ConstantPattern466_, n, v)) in self._AcceptorSentEvent_2 if (_ConstantPattern466_ == 'accepted') if (n == max({n for (_, _, (_ConstantPattern491_, n, _)) in self._AcceptorSentEvent_3 if (_ConstantPattern491_ == 'accepted')}))})
            self.send(('respond', n, maxprop), p)
    _Acceptor_handler_407._labels = None
    _Acceptor_handler_407._notlabels = None

    def _Acceptor_handler_509(self, n, v):
        n2 = None

        def ExistentialOpExpr_521():
            nonlocal n2
            for (_, _, (_ConstantPattern539_, n2, _)) in self._AcceptorSentEvent_5:
                if (_ConstantPattern539_ == 'respond'):
                    if (n2 > n):
                        return True
            return False
        if (not ExistentialOpExpr_521()):
            self.send(('accepted', n, v), self._state.learners)
    _Acceptor_handler_509._labels = None
    _Acceptor_handler_509._notlabels = None

class Learner(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._LearnerReceivedEvent_0 = []
        self._LearnerReceivedEvent_1 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_LearnerReceivedEvent_0', PatternExpr_606, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_LearnerReceivedEvent_1', PatternExpr_632, sources=[PatternExpr_639], destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, acceptors):
        self._state.acceptors = acceptors
        pass

    def run(self):
        self.learn()
        self.output('terminating')
        self.send(('learned',), self.nodeof(self._id))

    def learn(self):
        super()._label('_st_label_603', block=False)
        n = v = a = None

        def ExistentialOpExpr_604():
            nonlocal n, v, a
            for (_, _, (_ConstantPattern623_, n, v)) in self._LearnerReceivedEvent_0:
                if (_ConstantPattern623_ == 'accepted'):
                    if (len({a for (_, (_, _, a), (_ConstantPattern650_, _BoundPattern652_, _BoundPattern653_)) in self._LearnerReceivedEvent_1 if (_ConstantPattern650_ == 'accepted') if (_BoundPattern652_ == n) if (_BoundPattern653_ == v)}) > (len(self._state.acceptors) / 2)):
                        return True
            return False
        _st_label_603 = 0
        self._timer_start()
        while (_st_label_603 == 0):
            _st_label_603 += 1
            if ExistentialOpExpr_604():
                self.output('learned', n, v)
                _st_label_603 += 1
            elif self._timer_expired:
                self.output('failed learning anything')
                _st_label_603 += 1
            else:
                super()._label('_st_label_603', block=True, timeout=(TIMEOUT * 10))
                _st_label_603 -= 1

class Node_(da.NodeProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._Node_ReceivedEvent_0 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_0', PatternExpr_783, sources=[PatternExpr_788], 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 5)
        nlearners = (int(sys.argv[3]) if (len(sys.argv) > 3) else 3)
        acceptors = self.new(Acceptor, num=nacceptors)
        proposers = self.new(Proposer, (acceptors,), num=nproposers)
        learners = self.new(Learner, (acceptors,), num=nlearners)
        for p in acceptors:
            self._setup(p, (learners,))
        self._start(((acceptors | proposers) | learners))
        super()._label('_st_label_774', block=False)
        l = None

        def UniversalOpExpr_775():
            nonlocal l
            for l in learners:
                if (not PatternExpr_790.match_iter(self._Node_ReceivedEvent_0, _BoundPattern796_=l)):
                    return False
            return True
        _st_label_774 = 0
        while (_st_label_774 == 0):
            _st_label_774 += 1
            if UniversalOpExpr_775():
                _st_label_774 += 1
            else:
                super()._label('_st_label_774', block=True)
                _st_label_774 -= 1
        self.output('done')
        self.send(('done',), (acceptors | proposers))
