# -*- generated by 1.0.12 -*-
import da
PatternExpr_216 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern219_'), da.pat.FreePattern(None)])
PatternExpr_223 = da.pat.FreePattern('a')
PatternExpr_251 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern254_'), da.pat.TuplePattern([da.pat.FreePattern('n2'), da.pat.FreePattern('v')])])
PatternExpr_282 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern285_'), da.pat.TuplePattern([da.pat.FreePattern('n2'), da.pat.FreePattern(None)])])
PatternExpr_318 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.BoundPattern('_BoundPattern321_'), da.pat.FreePattern(None)])
PatternExpr_325 = da.pat.FreePattern('a')
PatternExpr_366 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_371 = 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_411 = da.pat.TuplePattern([da.pat.ConstantPattern('prepare'), da.pat.FreePattern('n')])
PatternExpr_418 = da.pat.FreePattern('p')
PatternExpr_424 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.FreePattern('n2'), da.pat.FreePattern(None)])
PatternExpr_453 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_479 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.FreePattern('n'), da.pat.FreePattern(None)])
PatternExpr_514 = da.pat.TuplePattern([da.pat.ConstantPattern('accept'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_527 = da.pat.TuplePattern([da.pat.ConstantPattern('respond'), da.pat.FreePattern('n2'), da.pat.FreePattern(None)])
PatternExpr_563 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_568 = 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_611 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.FreePattern('n'), da.pat.FreePattern('v')])
PatternExpr_637 = da.pat.TuplePattern([da.pat.ConstantPattern('accepted'), da.pat.BoundPattern('_BoundPattern640_'), da.pat.BoundPattern('_BoundPattern641_')])
PatternExpr_644 = da.pat.FreePattern('a')
PatternExpr_789 = da.pat.TuplePattern([da.pat.ConstantPattern('learned')])
PatternExpr_794 = da.pat.BoundPattern('_BoundPattern795_')
PatternExpr_796 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern802_')]), 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_216, sources=[PatternExpr_223], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_1', PatternExpr_251, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_2', PatternExpr_282, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_3', PatternExpr_318, sources=[PatternExpr_325], destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_ProposerReceivedEvent_4', PatternExpr_366, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])

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

    def run(self):
        while (not PatternExpr_371.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), to=self._state.majority)
        super()._label('_st_label_211', block=False)
        _st_label_211 = 0
        self._timer_start()
        while (_st_label_211 == 0):
            _st_label_211 += 1
            if (len({a for (_, (_, _, a), (_ConstantPattern234_, _BoundPattern236_, _)) in self._ProposerReceivedEvent_0 if (_ConstantPattern234_ == 'respond') if (_BoundPattern236_ == self._state.n)}) > (len(self._state.acceptors) / 2)):
                v = self.anyof(({v for (_, _, (_ConstantPattern270_, _BoundPattern272_, (n2, v))) in self._ProposerReceivedEvent_1 if (_ConstantPattern270_ == 'respond') if (_BoundPattern272_ == self._state.n) if (n2 == max({n2 for (_, _, (_ConstantPattern299_, _BoundPattern301_, (n2, _))) in self._ProposerReceivedEvent_2 if (_ConstantPattern299_ == 'respond') if (_BoundPattern301_ == self._state.n)}))} or {randint(1, 100)}))
                responded = {a for (_, (_, _, a), (_ConstantPattern336_, _BoundPattern338_, _)) in self._ProposerReceivedEvent_3 if (_ConstantPattern336_ == 'respond') if (_BoundPattern338_ == self._state.n)}
                self.send(('accept', self._state.n, v), to=responded)
                self.debug('### chose', self._state.n, v)
                _st_label_211 += 1
            elif self._timer_expired:
                self.output('failed proposal number', self._state.n)
                _st_label_211 += 1
            else:
                super()._label('_st_label_211', block=True, timeout=TIMEOUT)
                _st_label_211 -= 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_411, sources=[PatternExpr_418], destinations=None, timestamps=None, record_history=None, handlers=[self._Acceptor_handler_410]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_1', PatternExpr_424, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_2', PatternExpr_453, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_3', PatternExpr_479, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_AcceptorReceivedEvent_4', PatternExpr_514, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._Acceptor_handler_513]), da.pat.EventPattern(da.pat.SentEvent, '_AcceptorSentEvent_5', PatternExpr_527, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_AcceptorReceivedEvent_6', PatternExpr_563, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])

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

    def run(self):
        super()._label('_st_label_560', block=False)
        _st_label_560 = 0
        while (_st_label_560 == 0):
            _st_label_560 += 1
            if PatternExpr_568.match_iter(self._AcceptorReceivedEvent_6, SELF_ID=self._id):
                _st_label_560 += 1
            else:
                super()._label('_st_label_560', block=True)
                _st_label_560 -= 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_410(self, n, p):
        n2 = None

        def UniversalOpExpr_422():
            nonlocal n2
            for (_, _, (_ConstantPattern440_, n2, _)) in self._AcceptorSentEvent_1:
                if (_ConstantPattern440_ == 'respond'):
                    if (not (n > n2)):
                        return False
            return True
        if UniversalOpExpr_422():
            maxprop = self.anyof({(n, v) for (_, _, (_ConstantPattern469_, n, v)) in self._AcceptorSentEvent_2 if (_ConstantPattern469_ == 'accepted') if (n == max({n for (_, _, (_ConstantPattern494_, n, _)) in self._AcceptorSentEvent_3 if (_ConstantPattern494_ == 'accepted')}))})
            self.send(('respond', n, maxprop), to=p)
    _Acceptor_handler_410._labels = None
    _Acceptor_handler_410._notlabels = None

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

        def ExistentialOpExpr_525():
            nonlocal n2
            for (_, _, (_ConstantPattern543_, n2, _)) in self._AcceptorSentEvent_5:
                if (_ConstantPattern543_ == 'respond'):
                    if (n2 > n):
                        return True
            return False
        if (not ExistentialOpExpr_525()):
            self.send(('accepted', n, v), to=self._state.learners)
    _Acceptor_handler_513._labels = None
    _Acceptor_handler_513._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_611, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_LearnerReceivedEvent_1', PatternExpr_637, sources=[PatternExpr_644], destinations=None, timestamps=None, record_history=True, handlers=[])])

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

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

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

        def ExistentialOpExpr_609():
            nonlocal v, n, a
            for (_, _, (_ConstantPattern628_, n, v)) in self._LearnerReceivedEvent_0:
                if (_ConstantPattern628_ == 'accepted'):
                    if (len({a for (_, (_, _, a), (_ConstantPattern655_, _BoundPattern657_, _BoundPattern658_)) in self._LearnerReceivedEvent_1 if (_ConstantPattern655_ == 'accepted') if (_BoundPattern657_ == n) if (_BoundPattern658_ == v)}) > (len(self._state.acceptors) / 2)):
                        return True
            return False
        _st_label_608 = 0
        self._timer_start()
        while (_st_label_608 == 0):
            _st_label_608 += 1
            if ExistentialOpExpr_609():
                self.output('learned', n, v)
                _st_label_608 += 1
            elif self._timer_expired:
                self.output('failed learning anything')
                _st_label_608 += 1
            else:
                super()._label('_st_label_608', block=True, timeout=(TIMEOUT * 10))
                _st_label_608 -= 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_789, sources=[PatternExpr_794], 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_780', block=False)
        l = None

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