Ejemplo n.º 1
0
    def semantic_analysis(self, messenger: messages.MessageGenerator) -> bool:
        """
        On a declaration, a new identifier is introduced into the scope. This has to be an unique identifier
        on this scope lvl. But it can overshadow higher scoped (global...) declared variables with the same identifier.
        :return: Amount of errors encountered in node and children.
        """
        ret = True
        self._generate_secondary_types(messenger)
        # We have all the info for the corresponding attribute object
        attr = self._make_attribute()
        attr.is_const = self.is_const

        # Special action's required if we initialize array's
        if self._type_stack[-1] == type_specifier.TypeSpecifier.ARRAY:
            self._array_size = self.type_modifier_node.get_static_size()
            attr.array_size = self._array_size

        # Check of the expression is semantically correct
        elif self._expression_node:
            if not self._expression_node.semantic_analysis(messenger):
                return False
            self.analyze_initializer(messenger)

        if self.id and not self._parent_node.add_to_scope_symbol_table(
                self.id, attr):
            messenger.error_redeclaration(self.id, self._line, self._column)
            ret = False

        return ret
Ejemplo n.º 2
0
 def __init__(self, addr, x, y, depth, energy, clock, verbose=False):
     assert clock.__class__.__name__ is 'Clock', 'Need a clock object'
     self.verbose = verbose
     self.inbox = []
     self.outbox = []  # pair [msg, number of transmissions]
     self.waitingACK = False
     self.isSink = addr in self.sinkNodesAddr
     self.clock = clock
     # for TDMA
     self.round = 0
     #
     self.addr = addr
     self.position = [x, y, depth]
     # Energy related
     self.energy = energy
     self.maxEnergy = energy
     self.criticalEnergy = False
     self.energyThresholds = [0.05, 0.2, 0.5]
     self.energyThreshold = energy * self.energyThresholds.pop()
     # for UOAR
     self.state = UOARState.INITIAL
     self.status = UOARStatus.IDLE
     self.oneighbors = {}
     self.numReachableNodes = 0
     self.highestScore = [0, INFINITY]  # pair [score, addr]
     self.nextHop = None
     self.nextHopDist = INFINITY
     self.hopsToSink = INFINITY
     self.stopWaiting = False
     self.updateStatus = 0  # 0: not updating
     # 1: update in progress
     # 2: update done
     self.cheadList = {}  # to route phase [addr, is in route]
     self.cmemberList = []
     # self.score  = 0
     self.greaterDistance = 0
     self.avgDistance = 0
     # for possible connection head-member
     self.minHopsToSink = INFINITY
     self.memberAlternative = None
     # for retransmissions
     self.numRetries = 0
     # for recovery (next hop is dead)
     self.msgsLostCount = 0
     self.msgsLostLimit = 2
     self.deadNode = None
     # for statistics
     self.recvdMsgsCounter = 0
     self.sentMsgsCounter = 0
     self.avgNumHops = 0
     self.maxNumHops = 0
     self.avgTimeSpent = 0
     self.maxTimeSpent = 0
     # best for memory
     self.acouticAck = MG.create_acoustic_ack(addr, 0)
     time, _ = Tools.estimate_transmission(self.acouticAck)
     self.acousticAckTime = 2 * time
     self.opticalAck = MG.create_optical_ack(addr, 0)
     time, _ = Tools.estimate_transmission(self.opticalAck)
     self.opticalAckTime = 2 * time
Ejemplo n.º 3
0
    def semantic_analysis(self, messenger: messages.MessageGenerator):

        if not self._generate_secondary_types(messenger):
            return False

        defined = False

        if self._expression_node:
            # Expression semantics still need to be right
            if not self._expression_node.semantic_analysis(messenger):
                return False

            # Need a constant
            if not self._expression_node.is_constant():
                messenger.error_init_is_not_constant(self._line, self._column)
                return False

            self.analyze_initializer(messenger)

            defined = True

        attribute = Attributes.AttributesGlobal(self._type_stack, self._line,
                                                self._column, defined, self)

        # Function types have something extra, their function signature need to be recorded
        if self._type_stack and self._type_stack[
                -1] == type_specifier.TypeSpecifier.FUNCTION:
            function_signature = self._type_modifier_node.get_function_signature(
            )

            attribute.function_signature = function_signature
        attribute.llvm_name = self.id

        self._add_to_table(attribute, messenger)
        return True
Ejemplo n.º 4
0
    def semantic_analysis(self, messenger: messages.MessageGenerator):
        node = self._parent_node.find_while_sw_node()

        if not node:
            messenger.error_break_not_while(self.line, self.column)
            return False

        return True
Ejemplo n.º 5
0
    def semantic_analysis(self, messenger: messages.MessageGenerator) -> bool:

        # First check if the id was declared
        if not self.is_in_table(self.id):
            messenger.error_undeclared_var(self.id, self._line, self._column)
            return False

        self._is_global = True if self.is_in_global_table(self.id) else False
        self._type_stack = self.get_attribute(self.id).operator_stack
        if not self._generate_secondary_types(messenger):  # the modifiers applied in the expression
            return False
        return True
Ejemplo n.º 6
0
 def application_generate_msg(self):
     # Generates an application message and puts it into the end of the
     # outbox.
     # assert self.nextHop is not None, 'No next hop found'
     # Simulating the application message as one optical data message.
     msg = MG.create_optical_datamsg(self.addr, 1, self.basicPayload,
                                     self.clock.read())
     if self.state is UOARState.CLUSTER_MEMBER:
         end_msg = MG.create_optical_datamsg(self.addr, self.nextHop, msg,
                                             self.clock.read())
     else:
         end_msg = MG.create_acoustic_datamsg(self.addr, self.nextHop, msg,
                                              self.clock.read())
     self.outbox.append([end_msg, 0])
Ejemplo n.º 7
0
    def analyze_initializer(self, messenger: messages.MessageGenerator):
        """
        Here we will check if the type of the initializer is conform with te type of the declaration
        :return:
        """
        expression_stack = self._expression_node.type_stack
        prev_ele = expression_stack[-1]
        for element in reversed(self._type_stack):

            if expression_stack and element == expression_stack[-1]:
                prev_ele = expression_stack.pop()
            else:
                messenger.warning_init_makes_a_from_b(
                    prev_ele.value, self._type_stack[-1].value, self._line,
                    self._column)
                break

        return True
    def generate_secondary_type(self, node: "ExpressionNode.ExpressionNode",
                                messenger: messages.MessageGenerator):
        """
        Function requires an expressionNode and adjust this node's type trough it's type stack.
        This node modifies the ExpressionNode state in type_stack and l_value(bool that tell's if l or r val)

        :param ExpressionNode node: ExpressionNode that we are modifying.
        :param MessageGenerator messenger: A messageGenerator that we use to generate error messages
        :return: bool: True if the modification's are legal, False if they are not.
        """
        if not self._type_modifier_node:
            if len(self._children) < 1:
                self._param_list_node = None
        else:
            if len(self._children) < 2:
                self._param_list_node = None

        # Check the type_modifier subtree. Children of this type modifier node get to modify the type stack first.
        if self._type_modifier_node:
            if not self._type_modifier_node.generate_secondary_type(
                    node, messenger):
                return False

        # else this node should be applied first == base

        # Meaning the Dereference operator
        if self._modifier_type == type_specifier.TypeSpecifier.POINTER:
            # We can only dereference pointer types.
            if node.type_stack_ref(
            )[-1].value == type_specifier.TypeSpecifier.POINTER:
                # If we dereference the type loses it's 'ptr' type
                node.type_stack_ref().pop()
                # Dereference operator returns a lvalue
                node.l_value = True

            else:
                messenger.error_unary_not_ptr(self._line, self._column)
                return False

        # Ref operator value becomes an address
        elif self._modifier_type == type_specifier.TypeSpecifier.ADDRESS:
            if node.l_value:
                # At the right side POINTER means address of. Used for type matching but maybe i should create
                # an alias to make this line more clear.
                node.type_stack_ref().append(
                    type_specifier.TypeSpecifier(
                        type_specifier.TypeSpecifier.POINTER))
                node.l_value = False

            else:
                messenger.error_lvalue_required_addr(node.line, node.column)
                return False

        # Function call,
        elif self._modifier_type == type_specifier.TypeSpecifier.FUNCTION:
            # We require a function. In C you can call pointers to functions so this must be extended.
            if node.type_stack_ref(
            )[-1] == type_specifier.TypeSpecifier.FUNCTION:
                # The parameter's calls their expression's need to be checked for correctness.
                self._param_list_node.semantic_analysis(messenger)
                # for simplicity we == is overloaded. We can go in more detail about the function signatures as
                # extension

                if self.get_function_signature() == node.type_stack_ref(
                )[-1].function_signature:
                    node.type_stack_ref().pop()

                else:
                    if not self._check_any_consistent(
                            node.type_stack_ref()[-1].function_signature):
                        messenger.error_signature_does_not_match(
                            self._line, self._column)
                        return False

            else:
                messenger.error_object_not_function(self._line, self._column)
                return False

        # Array's
        elif self._modifier_type == type_specifier.TypeSpecifier.ARRAY:
            # First check if we can subscript.
            if not node.type_stack_ref(
            )[-1] == type_specifier.TypeSpecifier.ARRAY:
                messenger.error_subscript_not_array(self.line, self.column)
                return False

            if not self._param_list_node:
                messenger.error_expected_expression(self.line, self.column)
                return False
            self._param_list_node.semantic_analysis(messenger)
            if not self._param_list_node.type_stack[
                    -1] == type_specifier.TypeSpecifier.INT:
                messenger.error_subscript_not_integer(self.line, self.column)
                return False
            node.type_stack_ref().pop()

        return True
Ejemplo n.º 9
0
    def handle_message(self, msg):
        # Handles the received messages acording to their types.
        msgType = msg.flags & 0x0f  # first half is the type

        if msgType is UOARTypes.COMMON_DATA:
            if self.verbose:
                print('Handling data message from node ' + str(msg.src))

            innerMsg = msg.payload
            innerMsg.ttl -= 1
            if innerMsg.dst is not self.addr:
                if innerMsg.ttl is not 0:
                    if self.state is UOARState.CLUSTER_MEMBER:
                        msg = MG.create_optical_datamsg(
                            self.addr, self.nextHop, innerMsg,
                            self.clock.read())
                    else:
                        msg = MG.create_acoustic_datamsg(
                            self.addr, self.nextHop, innerMsg,
                            self.clock.read())
                    self.outbox.append([msg, 0])
                else:
                    if self.verbose:
                        print('Message droped (TTL reached 0)')
            self.recvdMsgsCounter += 1
            if self.isSink is True:
                # Hops statistics
                corrCoeff = (self.recvdMsgsCounter - 1) / self.recvdMsgsCounter
                numHops = BASIC_TTL - innerMsg.ttl
                if numHops > self.maxNumHops:
                    self.maxNumHops = numHops
                self.avgNumHops *= corrCoeff
                self.avgNumHops += (numHops / self.recvdMsgsCounter)
                # Time statistics
                time = self.clock.read() - innerMsg.ctime
                if self.verbose:
                    print('Received (time: ' + str(time) + ')')
                if time > self.maxTimeSpent:
                    self.maxTimeSpent = time
                self.avgTimeSpent *= corrCoeff
                self.avgTimeSpent += (time / self.recvdMsgsCounter)

        elif msgType is UOARTypes.INFO_ANNOUN:
            if self.verbose:
                print('Handling info message from node ' + str(msg.src))

            self.numReachableNodes += 1
            nodePosition = msg.payload[0]
            nodeState = msg.payload[1]
            nodeHops = msg.payload[2]
            distFromNode = Tools.distance(self.position, nodePosition)
            # Adding in lists
            if nodeState is UOARState.CLUSTER_HEAD:
                self.cheadList[msg.src] = nodeHops is not INFINITY
            if distFromNode <= OM.maxrange:
                self.oneighbors[msg.src] = nodePosition
                if nodeState is UOARState.CLUSTER_MEMBER and \
                   msg.src not in self.cmemberList:
                    self.cmemberList.append(msg.src)
            updtFactor = (self.numReachableNodes - 1) / self.numReachableNodes
            self.avgDistance = self.avgDistance * updtFactor
            self.avgDistance += (distFromNode / self.numReachableNodes)
            if distFromNode > self.greaterDistance:
                self.greaterDistance = distFromNode

            if self.state is UOARState.INITIAL and not self.isSink:
                # If it is not in a cluster and some neighbor is already
                # member or a head, join it. It's preferable to join as
                # a member than as a head.
                if distFromNode <= OM.maxrange:
                    if nodeState is not UOARState.INITIAL:
                        currDist = INFINITY
                        if self.nextHop in self.oneighbors:
                            nextPos = self.oneighbors[self.nextHop]
                            currDist = Tools.distance(self.position, nextPos)
                        if distFromNode < currDist:
                            self.nextHop = msg.src
                            self.hopsToSink = INFINITY

                else:
                    if nodeState is UOARState.CLUSTER_HEAD:
                        if self.hopsToSink is INFINITY:
                            if self.nextHop is None:
                                self.nextHop = msg.src
                                self.hopsToSink = nodeHops + 1
                        else:
                            if (nodeHops + 1) < self.hopsToSink:
                                self.nextHop = msg.src
                                self.hopsToSink = nodeHops + 1

            if (self.state is not UOARState.INITIAL and \
               self.status is not UOARStatus.DISCOVERING) and \
               nodeState is UOARState.INITIAL:
                # When a node enters in the network and needs information.
                # Routing control messages have higher priority than data
                # messages.
                msg = MG.create_iamsg(self.addr, self.position, self.state,
                                      self.hopsToSink)
                # Insert the message in que outbox or updates the next ot
                # be sent.
                if len(self.outbox) is not 0:
                    firstMsgType = self.outbox[0][0].flags & 0x0f
                    if firstMsgType is not UOARTypes.INFO_ANNOUN:
                        self.outbox.insert(0, [msg, 0])
                    else:
                        self.outbox[0] = [msg, 0]
                else:
                    self.outbox.insert(0, [msg, 0])

        elif msgType is UOARTypes.SCORE_ANNOUN or \
             msgType is UOARTypes.REP_SCORE:
            if self.verbose:
                print('Handling score message from node ' + str(msg.src))

            nodeScore = msg.payload[0]
            if msg.src in self.oneighbors and \
               (self.status is UOARStatus.ANNOUNCING or \
               self.status is UOARStatus.DISCOVERING or \
               self.status is UOARStatus.UPDATING):
                # Cluster heads are nodes with the highest score amoung its
                # neighbors (in case of a tie, the node with lowest addr wins)
                if (self.highestScore[0] < nodeScore) or \
                   (self.highestScore[0] == nodeScore and \
                    self.highestScore[1] > msg.src):
                    self.highestScore = [nodeScore, msg.src]

        elif msgType is UOARTypes.CLUSTER_ANNOUN:
            if self.verbose:
                print('Handling cluster message from node ' + str(msg.src))

            nodeIsHead = msg.payload[0]
            if nodeIsHead:
                # A cluster head node will send its own address in the cluster
                # announcement payload
                if msg.src not in self.cheadList:
                    if self.status is UOARStatus.ELECTING or \
                       self.status is UOARStatus.ANNOUNCING:
                        self.cheadList[msg.src] = False
                    else:
                        self.cheadList[msg.src] = True

                if msg.src in self.cmemberList:
                    self.cmemberList.remove(msg.src)
            else:
                if msg.src in self.oneighbors and \
                   msg.src not in self.cmemberList:
                    self.cmemberList.append(msg.src)
                    if msg.src in self.cheadList:
                        del self.cheadList[msg.src]

            if msg.src in self.oneighbors and \
               self.status is UOARStatus.DISCOVERING:
                self.nextHop = msg.src

        elif msgType is UOARTypes.ROUTE_ANNOUN:
            if self.verbose:
                print('Handling route message from node ' + str(msg.src))
            nodeIsHead = msg.payload[0]
            nodeNextHop = msg.payload[1]
            nodeHops = msg.payload[2] + 1
            nodePosition = msg.payload[3]
            if self.state is UOARState.CLUSTER_HEAD:
                if nodeIsHead:
                    dist = Tools.distance(self.position, nodePosition)
                    self.cheadList[msg.src] = True
                    if self.hopsToSink > nodeHops or \
                       (self.hopsToSink == nodeHops and \
                       dist < self.nextHopDist):
                        self.hopsToSink = nodeHops
                        self.nextHop = msg.src
                        self.nextHopDist = dist

                elif self.isSink is False:
                    if nodeHops < self.minHopsToSink:
                        self.minHopsToSink = nodeHops
                        self.memberAlternative = msg.src

                    if self.nextHop is not None and \
                       nodeNextHop is not self.addr:
                        if msg.src in self.oneighbors and \
                           nodeHops <= (self.hopsToSink + 1):
                            # better be a member than a head
                            # print('Node ' + str(self.addr) + ' was member 2')
                            # print(nodeIsHead)
                            # print(nodeNextHop)
                            # print(nodeHops)
                            # print(nodePosition)
                            # print(self.hopsToSink + 1)
                            self.state = UOARState.CLUSTER_MEMBER
                            self.nextHop = msg.src
                            self.hopsToSink = nodeHops
                            newMsg = MG.create_camsg(self.addr, False,
                                                     self.position)
                            self.outbox.insert(0, [newMsg, 0])

            if (self.status is UOARStatus.WAITING or \
               self.status is UOARStatus.ELECTING) and \
               self.nextHop is msg.src:
                # For members
                if nodeHops < self.minHopsToSink:
                    self.minHopsToSink = nodeHops
                    newMsg = MG.create_ramsg(self.addr, False, self.nextHop,
                                             nodeHops, self.position)
                    self.outbox.insert(0, [newMsg, 0])
                self.stopWaiting = True

        elif msgType is UOARTypes.REQ_SCORE:
            if self.verbose:
                print('Handling req score msg from ' + str(msg.src))

            if msg.src in self.oneighbors:
                # self.score = self.calculate_score()
                # newMsg = MG.create_rpsmsg(self.addr, msg.src, self.score)
                score = self.calculate_score()
                newMsg = MG.create_rpsmsg(self.addr, msg.src, score)
                if len(self.outbox) is not 0:
                    firstMsgType = self.outbox[0].flags & 0x0f
                    if firstMsgType is not UOARTypes.REP_SCORE:
                        self.outbox.insert(0, [newMsg, 0])
                    else:
                        self.outbox[0] = [newMsg, 0]
                else:
                    self.outbox.append([newMsg, 0])

        elif msgType is UOARTypes.UPDATE_INFO:
            if self.verbose:
                print('Handling update info msg from ' + str(msg.src))

            newHead = msg.payload[0]
            newNextHop = msg.payload[1]
            if newHead is self.addr:
                # Must be a head now
                self.state = UOARState.CLUSTER_HEAD
                self.nextHop = newNextHop
            else:
                if self.nextHop is msg.src or newHead in self.oneighbors:
                    # Must update which node is the next hop
                    ##################################################
                    ## Might be a problem is new head is out of range
                    ##################################################
                    self.nextHop = newHead
                self.cheadList[newHead] = True

            if newHead in self.oneighbors:
                self.cmemberList.remove(msg.payload[0])

            if msg.src in self.oneighbors:
                self.cmemberList.append(msg.src)

            del self.cheadList[msg.src]

            if self.verbose:
                print(self.cheadList)
                print(self.cmemberList)

        elif msgType is UOARTypes.REQ_RINFO:
            if self.verbose:
                print('Handling route info request msg from ' + str(msg.src))

            if msg.src is not self.nextHop and \
               msg.payload[0] is not self.nextHop:
                # Only replies if the requester is not its own next hop and
                # they don't share the same next hop. (-_- can't help)

                if msg.src in self.oneighbors:
                    newMsg = MG.create_optical_rprmsg(self.addr, msg.src,
                                                      self.nextHop,
                                                      self.hopsToSink)
                else:
                    newMsg = MG.create_acoustic_rprmsg(self.addr, msg.src,
                                                       self.nextHop,
                                                       self.hopsToSink)
                self.outbox.insert(0, [newMsg, 0])

        elif msgType is UOARTypes.REP_RINFO:
            if self.verbose:
                print('Handling route info reply from ' + str(msg.src))

            if self.status is UOARStatus.RECOVERING:
                nodeNextHop = msg.payload[0]
                nodeHopsToSink = msg.payload[1]
                replier = msg.src
                if replier in self.oneighbors:
                    self.nextHop = msg.src
                    self.hopsToSink = INFINITY
                    print('Node ' + str(self.addr) + ' was member 3')
                    self.state = UOARState.CLUSTER_MEMBER

                if self.state is UOARState.CLUSTER_HEAD and \
                   self.hopsToSink >= nodeHopsToSink:
                    self.nextHop = msg.src
                    self.hopsToSink = nodeHopsToSink + 1

        elif msgType is UOARTypes.ACK:
            if self.verbose:
                print('Handling ACK from node ' + str(msg.src))

            if self.waitingACK:
                self.outbox.pop(0)
                self.waitingACK = False
                if self.msgsLostCount is not 0:
                    self.msgsLostCount = 0
            else:
                if self.verbose:
                    print('error: unknown ack received')

        else:
            if self.verbose:
                print('unknown message type')
Ejemplo n.º 10
0
    def execute(self, maxTime, isNewSlot):
        # This method is used to simulate the execution of the node. It will
        # return a message, and the required time to transmit it, when the node
        # wants to communicate.
        msg = None
        time = maxTime
        energy = 0

        if self.energy <= 0:
            if self.state is not UOARState.DEAD:
                self.state = UOARState.DEAD
            return time, msg

        if self.isSink is False and self.energy <= self.energyThreshold and \
           (not self.criticalEnergy):
            self.energyThreshold = self.energyThresholds.pop()
            if len(self.energyThresholds) is 0:
                self.criticalEnergy = True

            if self.state is UOARState.CLUSTER_HEAD and \
               len(self.cmemberList) is not 0:
                self.updateStatus = 1

        if isNewSlot:  # new round
            self.round += 1
            if self.verbose:
                print('Round ' + str(self.round) + ': ' + \
                      str(self.clock.read()))
            # Status machine
            if self.status is UOARStatus.READY:
                if self.msgsLostCount is self.msgsLostLimit:
                    self.status = UOARStatus.RECOVERING

            elif self.status is UOARStatus.IDLE:
                self.status = UOARStatus.DISCOVERING

            elif self.status is UOARStatus.DISCOVERING:
                self.status = UOARStatus.ANNOUNCING

            elif self.status is UOARStatus.ANNOUNCING:
                if self.state is UOARState.INITIAL:
                    self.status = UOARStatus.ELECTING
                else:
                    self.status = UOARStatus.READY

            elif self.status is UOARStatus.ELECTING:
                if self.state is UOARState.CLUSTER_MEMBER:
                    self.status = UOARStatus.WAITING
                else:
                    self.status = UOARStatus.HEAD_WAIT

            elif self.status is UOARStatus.WAITING and self.stopWaiting:
                if self.isSink:
                    self.status = UOARStatus.HEAD_WAIT
                else:
                    self.status = UOARStatus.READY

            elif self.status is UOARStatus.HEAD_WAIT and self.stopWaiting:
                self.status = UOARStatus.READY

            elif self.status is UOARStatus.READY and self.updateStatus is 1:
                self.status = UOARStatus.UPDATING

            elif self.status is UOARStatus.UPDATING and self.updateStatus is 0:
                self.status = UOARStatus.READY

            elif self.status is UOARStatus.RECOVERING and \
                 self.deadNode is None and self.msgsLostCount is 0:
                self.status = UOARStatus.READY

        if self.state is UOARState.INITIAL:
            if self.status is UOARStatus.DISCOVERING:
                # First stage: announces its own position to the other nodes
                # and then collects info the neighbors for a round.
                if self.isSink:
                    self.hopsToSink = 0
                    self.stopWaiting = False
                msg = MG.create_iamsg(self.addr, self.position, self.state,
                                      self.hopsToSink)
                if self.verbose:
                    print('Node ' + str(self.addr) + ' sending info msg')

            elif self.status is UOARStatus.ANNOUNCING:
                # Second stage: now that the node know its neighbors it can
                # calculate its score and, if necessary, announce it. If some
                # of its neighbors is already part of a cluster, then it just
                # join it.

                if self.nextHop is not None:
                    if self.hopsToSink is INFINITY:
                        self.state = UOARState.CLUSTER_MEMBER
                        print('Node ' + str(self.addr) + ' is member 1')
                    else:
                        self.state = UOARState.CLUSTER_HEAD
                        print('Node ' + str(self.addr) + ' is head 1')
                    self.cbrBegin = self.round
                    msg = MG.create_camsg(self.addr, False, self.position)
                    if self.verbose:
                        print('Node ' + str(self.addr) +
                              ' sending cluster msg')
                    self.stopWaiting = False

                else:
                    score = self.calculate_score()
                    if self.highestScore[0] < score:
                        # Maybe received some score before its time to
                        # calculate.
                        self.highestScore[0] = score
                        self.highestScore[1] = self.addr
                    msg = MG.create_samsg(self.addr, score)
                    if self.verbose:
                        print('Node ' + str(self.addr) + ' sending score msg')

            elif self.status is UOARStatus.ELECTING:
                # Third stage: cluster head election. It will become one if its
                # score is the highest.
                if self.highestScore[1] is self.addr or self.isSink:
                    if self.isSink:
                        if self.verbose:
                            print('Node is sink: ' + str(self.addr))
                    self.state = UOARState.CLUSTER_HEAD
                    ishead = True
                else:
                    self.state = UOARState.CLUSTER_MEMBER
                    self.nextHop = self.highestScore[1]
                    ishead = False
                self.stopWaiting = False
                msg = MG.create_camsg(self.addr, ishead, self.position)
                if self.verbose:
                    print('Node ' + str(self.addr) + ' sending cluster msg')

            else:
                raise Exception('Unknown initial status')

            time, energy = Tools.estimate_transmission(msg)
            self.energy -= energy
            time = maxTime

        else:
            if self.status is UOARStatus.READY:
                # In this stage the node is ready for routing data.
                time, msg = self.send_next_msg(maxTime)
                if msg is None and self.verbose:
                    print('No message')

            elif self.status is UOARStatus.WAITING:
                # This stage is necessary for all nodes to walk together.
                pass

            elif self.status is UOARStatus.HEAD_WAIT:
                #
                self.stopWaiting = False
                if self.hopsToSink is not INFINITY:
                    # All head neighbors have received the message of hops
                    if not False in self.cheadList.values():
                        self.stopWaiting = True
                    else:
                        for addr, got in self.cheadList.items():
                            if not got:
                                if self.verbose:
                                    print('Missing node ' + str(addr))

                    msg = MG.create_ramsg(self.addr, True, self.nextHop,
                                          self.hopsToSink, self.position)
                    if self.verbose:
                        print('Node ' + str(self.addr) + ' sending route msg')
                    time, energy = Tools.estimate_transmission(msg)
                    self.energy -= energy
                    time = maxTime
                else:
                    if self.memberAlternative is not None:
                        self.hopsToSink = self.minHopsToSink
                        self.nextHop = self.memberAlternative
                        self.stopWaiting = True
                        msg = MG.create_ramsg(self.addr, True, self.nextHop,
                                              self.hopsToSink, self.position)
                        if self.verbose:
                            print('Node ' + str(self.addr), end=' ')
                            print('sending route msg')
                        time, energy = Tools.estimate_transmission(msg)
                        self.energy -= energy
                        time = maxTime

            elif self.status is UOARStatus.UPDATING:
                # This stage is used to potentially find another node, with
                # better score, to be cluster head.
                if self.updateStatus is 1:
                    # Requests the score of neighbors
                    self.highestScore[0] = self.calculate_score()
                    self.highestScore[1] = self.addr
                    msg = MG.create_rqsmsg(self.addr)
                    self.updateStatus = 2

                elif self.updateStatus is 2:
                    bestCandidate = self.highestScore[1]
                    if bestCandidate is not self.addr:
                        if self.verbose:
                            print('Node ' + str(bestCandidate) +
                                  ' is the new cluster head')
                        msg = MG.create_uimsg(self.addr, bestCandidate,
                                              self.nextHop)
                        self.nextHop = bestCandidate
                        self.state = UOARState.CLUSTER_MEMBER
                        # Updating lists
                        self.cheadList[bestCandidate] = True
                        self.cmemberList.remove(bestCandidate)
                    self.updateStatus = 0

                if msg is not None:
                    time, energy = Tools.estimate_transmission(msg)
                    self.energy -= energy
                    time = maxTime

            elif self.status is UOARStatus.RECOVERING:
                #
                if self.deadNode is None:
                    # First round in recovering
                    self.deadNode = self.nextHop
                    self.hopsToSink = INFINITY
                    self.numReachableNodes -= 1
                else:
                    if self.nextHop is self.deadNode:
                        # Node didn't receive any message from cluster
                        self.state = UOARState.CLUSTER_HEAD

                # Updating lists
                if self.deadNode in self.cheadList:
                    del self.cheadList[self.deadNode]
                if self.deadNode in self.cmemberList:
                    self.cmemberList.remove(self.deadNode)
                if self.deadNode in self.oneighbors:
                    del self.oneighbors[self.deadNode]

                if self.state is UOARState.CLUSTER_MEMBER:
                    if len(self.oneighbors) is 0:
                        # if there are no more neighbors
                        self.state = UOARState.CLUSTER_HEAD

                if self.nextHop is not self.deadNode:
                    # Find some new next hop.
                    ishead = self.state is UOARState.CLUSTER_HEAD
                    if ishead:
                        msg = MG.create_camsg(self.addr, ishead, self.position)
                        time, energy = Tools.estimate_transmission(msg)
                    self.msgsLostCount = 0
                    self.deadNode = None
                else:
                    msg = MG.create_rqrmsg(self.addr, self.deadNode)
                    time, energy = Tools.estimate_transmission(msg)
                time = maxTime
                self.energy -= energy

            else:
                raise Exception('Unknown cluster status')

        return time, msg