# -*- generated by 1.0.12 -*-
import da
PatternExpr_287 = da.pat.TuplePattern([da.pat.ConstantPattern('token'), da.pat.FreePattern('Q1'), da.pat.FreePattern('LN1')])
PatternExpr_304 = da.pat.TuplePattern([da.pat.ConstantPattern('request'), da.pat.FreePattern('p'), da.pat.FreePattern('n')])
PatternExpr_352 = da.pat.TuplePattern([da.pat.ConstantPattern('token'), da.pat.FreePattern(None), da.pat.FreePattern(None)])
PatternExpr_375 = da.pat.TuplePattern([da.pat.ConstantPattern('token'), da.pat.FreePattern(None), da.pat.FreePattern('LN1')])
PatternExpr_399 = da.pat.TuplePattern([da.pat.ConstantPattern('token'), da.pat.FreePattern(None), da.pat.FreePattern('LN2')])
PatternExpr_464 = da.pat.TuplePattern([da.pat.ConstantPattern('Done')])
PatternExpr_469 = da.pat.BoundPattern('_BoundPattern470_')
PatternExpr_471 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern477_')]), 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._PSentEvent_2 = []
        self._PReceivedEvent_3 = []
        self._PSentEvent_4 = []
        self._PReceivedEvent_5 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_0', PatternExpr_287, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_286]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_1', PatternExpr_304, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_303]), da.pat.EventPattern(da.pat.SentEvent, '_PSentEvent_2', PatternExpr_352, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_3', PatternExpr_375, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.SentEvent, '_PSentEvent_4', PatternExpr_399, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_5', PatternExpr_464, sources=[PatternExpr_469], destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, ps, orig_token, nrounds, **rest_559):
        super().setup(ps=ps, orig_token=orig_token, nrounds=nrounds, **rest_559)
        self._state.ps = ps
        self._state.orig_token = orig_token
        self._state.nrounds = nrounds
        self._state.RN = dict(((p, 0) for p in self._state.ps))
        self._state.Q = []
        self._state.LN = dict(((p, 0) for p in self._state.ps))

    def run(self):

        def anounce():
            self.output('In cs!')
        if self.haveToken():
            self.output("I'm lucky!")
        for i in range(self._state.nrounds):
            self.cs(anounce)
        self.send(('Done',), to=self._state.ps)
        super()._label('_st_label_455', block=False)
        p = None

        def UniversalOpExpr_456():
            nonlocal p
            for p in self._state.ps:
                if (not PatternExpr_471.match_iter(self._PReceivedEvent_5, _BoundPattern477_=p, SELF_ID=self._id)):
                    return False
            return True
        _st_label_455 = 0
        while (_st_label_455 == 0):
            _st_label_455 += 1
            if UniversalOpExpr_456():
                _st_label_455 += 1
            else:
                super()._label('_st_label_455', block=True)
                _st_label_455 -= 1
        self.output('Done!')

    def cs(self, task):
        super()._label('request', block=False)
        if (not self.haveToken()):
            self._state.RN[self._id] += 1
            self.send(('request', self._id, self._state.RN[self._id]), to=self._state.ps)
            super()._label('_st_label_229', block=False)
            _st_label_229 = 0
            while (_st_label_229 == 0):
                _st_label_229 += 1
                if self.haveToken():
                    _st_label_229 += 1
                else:
                    super()._label('_st_label_229', block=True)
                    _st_label_229 -= 1
        task()
        self._state.LN[self._id] = self._state.RN[self._id]
        self._state.Q.extend([p for p in self._state.ps if (not (p in self._state.Q)) if (self._state.RN[p] == (self._state.LN[p] + 1))])
        if (len(self._state.Q) > 0):
            p = self._state.Q.pop()
            self.send(('token', self._state.Q, self._state.LN), to=p)

    def haveToken(self):

        def ExistentialOpExpr_350():
            for (_, _, (_ConstantPattern367_, _, _)) in self._PSentEvent_2:
                if (_ConstantPattern367_ == 'token'):
                    if True:
                        return True
            return False
        LN1 = LN2 = None

        def ExistentialOpExpr_373():
            nonlocal LN1, LN2
            for (_, _, (_ConstantPattern391_, _, LN1)) in self._PReceivedEvent_3:
                if (_ConstantPattern391_ == 'token'):

                    def ExistentialOpExpr_397(LN1):
                        nonlocal LN2
                        for (_, _, (_ConstantPattern415_, _, LN2)) in self._PSentEvent_4:
                            if (_ConstantPattern415_ == 'token'):
                                if (LN2[self._id] > LN1[self._id]):
                                    return True
                        return False
                    if (not ExistentialOpExpr_397(LN1=LN1)):
                        return True
            return False
        return ((self._state.orig_token and (not ExistentialOpExpr_350())) or ExistentialOpExpr_373())

    def _P_handler_286(self, Q1, LN1):
        self._state.Q = Q1
        self._state.LN = LN1
    _P_handler_286._labels = None
    _P_handler_286._notlabels = None

    def _P_handler_303(self, p, n):
        self._state.RN[p] = max((self._state.RN[p], n))
        if (self.haveToken() and (self._state.RN[p] == (self._state.LN[p] + 1))):
            self.send(('token', self._state.Q, self._state.LN), to=p)
    _P_handler_303._labels = None
    _P_handler_303._notlabels = None

class Node_(da.NodeProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._events.extend([])

    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)
        lucky = ps.pop()
        self._setup(ps, ((ps | {lucky}), False, nrounds))
        self._setup({lucky}, ((ps | {lucky}), True, nrounds))
        self._start((ps | {lucky}))
