# -*- generated by 1.0.2 -*-
import da
PatternExpr_191 = da.pat.TuplePattern([da.pat.ConstantPattern('ack'), da.pat.FreePattern('c'), da.pat.BoundPattern('_BoundPattern196_')])
PatternExpr_233 = da.pat.TuplePattern([da.pat.ConstantPattern('request'), da.pat.FreePattern('c'), da.pat.BoundPattern('_BoundPattern237_')])
PatternExpr_263 = da.pat.TuplePattern([da.pat.ConstantPattern('request'), da.pat.FreePattern('c'), da.pat.FreePattern('p')])
PatternExpr_277 = da.pat.TuplePattern([da.pat.ConstantPattern('request'), da.pat.FreePattern('c'), da.pat.SelfPattern()])
PatternExpr_307 = da.pat.TuplePattern([da.pat.ConstantPattern('ack'), da.pat.FreePattern('c2'), da.pat.BoundPattern('_BoundPattern312_')])
PatternExpr_381 = da.pat.TuplePattern([da.pat.ConstantPattern('Done')])
PatternExpr_386 = da.pat.BoundPattern('_BoundPattern388_')
PatternExpr_389 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern395_')]), da.pat.TuplePattern([da.pat.ConstantPattern('Done')])])
PatternExpr_471 = da.pat.TuplePattern([da.pat.ConstantPattern('Done')])
PatternExpr_476 = da.pat.BoundPattern('_BoundPattern477_')
PatternExpr_478 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern484_')]), da.pat.TuplePattern([da.pat.ConstantPattern('Done')])])
_config_object = {}
import sys

class P(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._PReceivedEvent_0 = []
        self._PReceivedEvent_1 = []
        self._PSentEvent_3 = []
        self._PReceivedEvent_4 = []
        self._PReceivedEvent_5 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_0', PatternExpr_191, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_1', PatternExpr_233, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_2', PatternExpr_263, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_262]), da.pat.EventPattern(da.pat.SentEvent, '_PSentEvent_3', PatternExpr_277, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_4', PatternExpr_307, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_5', PatternExpr_381, sources=[PatternExpr_386], destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, s, n, **rest_494):
        super().setup(s=s, n=n, **rest_494)
        self._state.s = s
        self._state.n = n
        pass

    def run(self):

        def anounce():
            self.output('In cs!')
        for i in range(self._state.n):
            self.cs(anounce)
        self.send(('Done',), self.parent())
        super()._label('_st_label_378', block=False)
        _st_label_378 = 0
        while (_st_label_378 == 0):
            _st_label_378 += 1
            if PatternExpr_389.match_iter(self._PReceivedEvent_5, _BoundPattern395_=self.parent(), SELF_ID=self._id):
                _st_label_378 += 1
            else:
                super()._label('_st_label_378', block=True)
                _st_label_378 -= 1

    def cs(self, task):
        super()._label('request', block=False)
        ownc = self.logical_clock()
        self.send(('request', ownc, self._id), self._state.s)
        super()._label('cs', block=False)
        p = c = None

        def UniversalOpExpr_183():
            nonlocal p, c
            for p in self._state.s:

                def ExistentialOpExpr_189(p):
                    nonlocal c
                    for (_, _, (_ConstantPattern207_, c, _BoundPattern210_)) in self._PReceivedEvent_0:
                        if (_ConstantPattern207_ == 'ack'):
                            if (_BoundPattern210_ == p):
                                if (c > ownc):
                                    return True
                    return False
                if (not ExistentialOpExpr_189(p=p)):
                    return False
            return True
        _st_label_182 = 0
        while (_st_label_182 == 0):
            _st_label_182 += 1
            if UniversalOpExpr_183():
                _st_label_182 += 1
            else:
                super()._label('cs', block=True)
                _st_label_182 -= 1
        task()
        super()._label('release', block=False)
        self.output('Release!')

        def ExistentialOpExpr_231(p):
            for (_, _, (_ConstantPattern248_, c, _BoundPattern251_)) in self._PReceivedEvent_1:
                if (_ConstantPattern248_ == 'request'):
                    if (_BoundPattern251_ == p):
                        if ((c, p) >= (ownc, self._id)):
                            return True
            return False
        self.send(('ack', self.logical_clock(), self._id), {p for p in self._state.s if ExistentialOpExpr_231(p=p)})

    def _P_handler_262(self, c, p):

        def UniversalOpExpr_300(c):
            for p in self._state.s:

                def ExistentialOpExpr_305(p, c):
                    for (_, _, (_ConstantPattern323_, c2, _BoundPattern326_)) in self._PReceivedEvent_4:
                        if (_ConstantPattern323_ == 'ack'):
                            if (_BoundPattern326_ == p):
                                if (c2 > c):
                                    return True
                    return False
                if (not ExistentialOpExpr_305(p=p, c=c)):
                    return False
            return True
        ownc = max(({c for (_, _, (_ConstantPattern293_, c, _ConstantPattern296_)) in self._PSentEvent_3 if (_ConstantPattern293_ == 'request') if (_ConstantPattern296_ == self._id) if (not UniversalOpExpr_300(c=c))} | {(- 1)}))
        if ((ownc == (- 1)) or ((c, p) < (ownc, self._id))):
            self.send(('ack', self.logical_clock(), self._id), p)
    _P_handler_262._labels = None
    _P_handler_262._notlabels = None

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_471, sources=[PatternExpr_476], destinations=None, timestamps=None, record_history=True, handlers=[])])
    _config_object = {'clock': 'Lamport'}

    def run(self):
        nprocs = (int(sys.argv[1]) if (len(sys.argv) > 1) else 10)
        nrounds = (int(sys.argv[2]) if (len(sys.argv) > 2) else 1)
        ps = self.new(P, num=nprocs)
        for p in ps:
            self._setup({p}, ((ps - {p}), nrounds))
        self._start(ps)
        super()._label('_st_label_463', block=False)
        p = None

        def UniversalOpExpr_464():
            nonlocal p
            for p in ps:
                if (not PatternExpr_478.match_iter(self._Node_ReceivedEvent_0, _BoundPattern484_=p)):
                    return False
            return True
        _st_label_463 = 0
        while (_st_label_463 == 0):
            _st_label_463 += 1
            if UniversalOpExpr_464():
                _st_label_463 += 1
            else:
                super()._label('_st_label_463', block=True)
                _st_label_463 -= 1
        self.output('All processes done.')
        self.send(('Done',), ps)
