def task2(actions): ship_coords = (0, 0) wayp_coords = (10, 1) for action_str in actions: log(action_str, ship_coords, wayp_coords) action = action_str[0] value = int(action_str[1:]) if action in ("N", "S", "E", "W"): if action == "N": move_dir = Direction.NORTH() elif action == "S": move_dir = Direction.SOUTH() elif action == "E": move_dir = Direction.EAST() elif action == "W": move_dir = Direction.WEST() for _ in range(value): wayp_coords = move_dir.move_grid_coordinates(wayp_coords) elif action == "F": ship_coords = (ship_coords[0] + value * wayp_coords[0], ship_coords[1] + value * wayp_coords[1]) elif action == "L": wayp_coords = rotate_counterclockwise(wayp_coords, value, origin=(0,0)) elif action == "R": wayp_coords = rotate_clockwise(wayp_coords, value, origin=(0,0)) log(f"New coordinates {ship_coords} {wayp_coords}\n") return abs(int(ship_coords[0])) + abs(int(ship_coords[1]))
def task1(actions): coords = (0, 0) cur_dir = Direction.EAST() for action_str in actions: log(action_str, coords) action = action_str[0] value = int(action_str[1:]) if action in ("N", "S", "E", "W", "F"): if action == "N": move_dir = Direction.NORTH() elif action == "S": move_dir = Direction.SOUTH() elif action == "E": move_dir = Direction.EAST() elif action == "W": move_dir = Direction.WEST() elif action == "F": move_dir = cur_dir for _ in range(value): coords = move_dir.move_grid_coordinates(coords) elif action == "L": cur_dir.rotate_counterclockwise(value) elif action == "R": cur_dir.rotate_clockwise(value) log(f"New coordinates {coords}\n") return abs(coords[0]) + abs(coords[1])
def repair_level(node, neighbourhood, ring_level, neighbours): """Repair a ring at a certain level by inserting new neighbours. The new inserted nodes could be propagated to higher levels. """ LOGGER.debug("[DBG] Repair level: " + str(ring_level) + " with " + str(len(neighbours)) + " neighbours (" + str(neighbours) + ")") ring = neighbourhood.get_ring(ring_level) # wrap_left = neighbourhood.can_wrap(Direction.LEFT) # wrap_right= neighbourhood.can_wrap(Direction.RIGHT) left = ring.get_side(Direction.LEFT) right = ring.get_side(Direction.RIGHT) added_left, added_right = False, False for new_node in neighbours: added_left |= left.add_neighbour(new_node) added_right |= right.add_neighbour(new_node) neighbourhood.update(new_node) sides = ((Direction.LEFT, added_left, left), (Direction.RIGHT, added_right, right)) for direction, added, half_ring in sides: LOGGER.log( logging.INFO, "[DBG] Added " + Direction.get_name(direction) + " : " + str(added)) if (added): # Tell nodes that local node is one of their new neighbour. NeighbourhoodNet.ping_half_ring(node, half_ring, ring_level) # Fix the ring higher. route_msg = SNFixupHigher(node, ring_level, direction) node.route_internal(route_msg)
def compute_cpe_and_data(self, message, side_join): """Compute the CPE of the joining node.""" ln = self.__local_node side_local = Direction.get_opposite(side_join) # Create the CPE. data_store = ln.data_store [cut_dimension, cut_value, data_left, data_right] = data_store.get_partition_value(ln.cpe) # Create the CPE for the joining node. join_node = InternalNode(side_join, cut_dimension, cut_value) join_cpe = copy.deepcopy(ln.cpe) join_cpe.add_node(join_node) # Create the CPE for the local node. local_node = InternalNode(side_local, cut_dimension, cut_value) local_cpe = copy.deepcopy(ln.cpe) local_cpe.add_node(local_node) print("NEW CPE:: ", local_cpe) # Split the data. if (side_join == Direction.LEFT): join_value = data_left local_value = data_right else: assert side_join == Direction.RIGHT join_value = data_right local_value = data_left return join_cpe, join_value, local_cpe, local_value
def repair_level(node, neighbourhood, ring_level, neighbours): """Repair a ring at a certain level by inserting new neighbours. The new inserted nodes could be propagated to higher levels. """ LOGGER.debug( "[DBG] Repair level: " + str(ring_level) + " with " + str(len(neighbours)) + " neighbours (" + str(neighbours) + ")") ring = neighbourhood.get_ring(ring_level) # wrap_left = neighbourhood.can_wrap(Direction.LEFT) # wrap_right= neighbourhood.can_wrap(Direction.RIGHT) left = ring.get_side(Direction.LEFT) right = ring.get_side(Direction.RIGHT) added_left, added_right = False, False for new_node in neighbours: added_left |= left.add_neighbour(new_node) added_right |= right.add_neighbour(new_node) neighbourhood.update(new_node) sides = ((Direction.LEFT, added_left, left), (Direction.RIGHT, added_right, right)) for direction, added, half_ring in sides: LOGGER.log(logging.INFO, "[DBG] Added " + Direction.get_name(direction) + " : " + str(added)) if(added): # Tell nodes that local node is one of their new neighbour. NeighbourhoodNet.ping_half_ring(node, half_ring, ring_level) # Fix the ring higher. route_msg = SNFixupHigher(node, ring_level, direction) node.route_internal(route_msg)
def compute_cpe_and_data(self, message, side_join): """Compute the CPE of the joining node.""" ln=self.__local_node side_local = Direction.get_opposite(side_join) # Create the CPE. data_store = ln.data_store [cut_dimension, cut_value, data_left, data_right] = data_store.get_partition_value(ln.cpe) # Create the CPE for the joining node. join_node = InternalNode(side_join, cut_dimension, cut_value) join_cpe = copy.deepcopy(ln.cpe) join_cpe.add_node(join_node) # Create the CPE for the local node. local_node = InternalNode(side_local, cut_dimension, cut_value) local_cpe = copy.deepcopy(ln.cpe) local_cpe.add_node(local_node) print("NEW CPE:: ", local_cpe) # Split the data. if(side_join == Direction.LEFT): join_value = data_left local_value = data_right else: assert side_join == Direction.RIGHT join_value = data_right local_value = data_left return join_cpe, join_value, local_cpe, local_value
def which_side_space(self, space_part, forking=False): """ Indicates to which side of the node belongs the 'space_part'. 'Left' means one of the internal nodes would have to be followed to the left instead so that the desired part is reached. """ nb_here = 0 here, left, right = False, False, False for inode in self.__internal_nodes: if(not space_part.exists(inode.dimension)): if (not forking): raise CPEMissingDimension( "Mandatory dimension %s isn't defined in %s"% (repr(inode.dimension),repr(space_part)), inode.dimension) else: # no clue, a split is required. # - here? is still undefined: further inodes could invalidate it. # - left? or right? will be set depending on our own direction # on the offending inode. (l,r) = Direction.get_directions(Direction.get_opposite(inode.direction)) left |=l ; right |=r nb_here+=1 else: try: m_range = space_part.get_component(inode.dimension) if(inode.is_here(m_range)): nb_here += 1 left |= inode.is_more_on_the_left(m_range) right |= inode.is_more_on_the_right(m_range) else: # The range is managed by the opposite side. @test1171706 # 0_0 opposite_side = Direction.get_opposite(inode.dimension.direction) opposite_side = Direction.get_opposite(inode.direction) left |= (opposite_side == Direction.LEFT) right |= (opposite_side == Direction.RIGHT) break # you need all the dimensions to say 'it's here' so that it's actually here. except: raise ValueError("Component %s of %s is of unknown type: %s"%( repr(inode.dimension),repr(space_part),repr(m_range))) here |= (nb_here == len(self.__internal_nodes)) assert True == left | here | right, "The request coudn't be oriented." return [left, here, right]
def reset(self, being): super(BeingWidget, self).reset(being) for direc, widget in self.items.items(): widget.reset(being) widget.setOpacity(0) direc = Direction.toViewed(self['direction']) self.setDirection(direc)
def test_bare_bones(self): left, right = Direction.get_directions(Direction.LEFT) assert left, "Direction.get_directions(Direction.LEFT)" assert not right, "Direction.get_directions(Direction.LEFT)" left, right = Direction.get_directions(Direction.RIGHT) assert not left, "Direction.get_directions(R)" assert right, "Direction.get_directions(R)" assert Direction.get_opposite(Direction.LEFT) == Direction.RIGHT assert Direction.get_opposite(Direction.RIGHT) == Direction.LEFT assert RouterReflect.check_position_partition_tree( Direction.LEFT,None,.2,.7), "isn't it on the left ?" assert RouterReflect.check_position_partition_tree( Direction.RIGHT,None,.7,.2), "isn't it on the right ?" print("#0 : directions tests passed") return True
def test_bare_bones(self): left, right = Direction.get_directions(Direction.LEFT) assert left, "Direction.get_directions(Direction.LEFT)" assert not right, "Direction.get_directions(Direction.LEFT)" left, right = Direction.get_directions(Direction.RIGHT) assert not left, "Direction.get_directions(R)" assert right, "Direction.get_directions(R)" assert Direction.get_opposite(Direction.LEFT) == Direction.RIGHT assert Direction.get_opposite(Direction.RIGHT) == Direction.LEFT assert RouterReflect.check_position_partition_tree( Direction.LEFT, None, .2, .7), "isn't it on the left ?" assert RouterReflect.check_position_partition_tree( Direction.RIGHT, None, .7, .2), "isn't it on the right ?" print("#0 : directions tests passed") return True
def from_dict(cls, robot_description): """ Return robot from JSON data received from server." """ direction = Direction(robot_description["direction"]) coordinates = tuple(robot_description["coordinates"]) name = robot_description["name"] robot = cls(direction, coordinates, name) robot.lives = robot_description["lives"] robot.flags = robot_description["flags"] robot.damages = robot_description["damages"] robot.power_down = robot_description["power down"] robot.start_coordinates = robot_description["start coordinates"] return robot
def __init__(self, parent, tile_width, use_svg, is_player): super(BeingWidget, self).__init__(parent, tile_width) ResetItem.__init__(self, tile_width) if use_svg and is_player: klass = ChibiDirectionWidget elif use_svg: klass = SvgSpeciesItem else: klass = CharItem self._current = None self.items = {} for direction in Direction.viewable(use_svg): self.items[direction] = klass(self, tile_width, direction) #FIXME figure out some other place to do this if not use_svg: self.items[direction].setBold() self.animation = BeingAnimation(self)
def __repr__(self): return "<SNFixupHigher ((%i, %s from %s) #%i - RouteByPayload>"%( self.__ring_level, Direction.get_name(self.__direction), self.__src_node, self.__nb_hops)
def test_ring(self): j=0 nd=[] for n,i in (("g3",45),("jt",71),("na",53),("se",42),("sw",59),("xk",19)): nd+=[self.createNode(n,"127.0.0.1%i"%j)] nd[j].numeric_id=i j=j+1 import copy from equation import InternalNode from util import Direction import pdb; pdb.set_trace() cut_dim=("a","b","a","x","c") cut_val=("girl","soft","cute","c","face") from localevent import Router for i in (1, 0, 4, 2): nb = nd[3].neighbourhood side=Router.by_name_get_direction(nd[3].name_id,nd[i].name_id) nextn = nb.get_neighbour(side,0) othern= nb.get_neighbour(not side,0) wrapf = nb.can_wrap(side) wrapb = nb.can_wrap(not side) assert( NodeID.lies_between_direction(side,nd[3].name_id,nd[i].name_id,nextn.name_id,wrapf) or NodeID.lies_between_direction(not side,nd[3].name_id,nd[i].name_id,othern.name_id,wrapb) ) if (not NodeID.lies_between_direction(side,nd[3].name_id,nd[i].name_id,nextn.name_id, wrapf)): print("need to reverse side %s-%s-%s!"%(nd[3].name_id,nd[i].name_id,nextn.name_id)) side=not side nextn=othern print("next on %s is %s"%("LEFT" if side else "RIGHT",repr(nextn))) nb.add_neighbour(0,nd[i]) if (nd[i].numeric_id>=32): nb.add_neighbour(1,nd[i]) if (nd[i].numeric_id<48): nb.add_neighbour(2,nd[i]) if (nd[i].numeric_id>40): nb.add_neighbour(3,nd[i]) if (nd[i].numeric_id<44): nb.add_neighbour(4,nd[i]) if (nd[i].numeric_id>=42): nb.add_neighbour(5,nd[i]) new_side_join = side new_side_local= Direction.get_opposite(new_side_join) njnode=InternalNode(new_side_join,cut_dim[i],cut_val[i]) njcpe =copy.deepcopy(nd[3].cpe) njcpe.add_node(njnode) print("%s gets CPE %s"%(nd[i].pname,njcpe)) nlnode=InternalNode(new_side_local,cut_dim[i],cut_val[i]) nlcpe =copy.deepcopy(nd[3].cpe) nlcpe.add_node(nlnode) print("%s gets CPE %s"%(nd[3].pname,nlcpe)) nd[i].cpe=njcpe nd[3].cpe=nlcpe
def test_ring(self): j = 0 nd = [] for n, i in (("g3", 45), ("jt", 71), ("na", 53), ("se", 42), ("sw", 59), ("xk", 19)): nd += [self.createNode(n, "127.0.0.1%i" % j)] nd[j].numeric_id = i j = j + 1 import copy from equation import InternalNode from util import Direction import pdb pdb.set_trace() cut_dim = ("a", "b", "a", "x", "c") cut_val = ("girl", "soft", "cute", "c", "face") from localevent import Router for i in (1, 0, 4, 2): nb = nd[3].neighbourhood side = Router.by_name_get_direction(nd[3].name_id, nd[i].name_id) nextn = nb.get_neighbour(side, 0) othern = nb.get_neighbour(not side, 0) wrapf = nb.can_wrap(side) wrapb = nb.can_wrap(not side) assert (NodeID.lies_between_direction( side, nd[3].name_id, nd[i].name_id, nextn.name_id, wrapf) or NodeID.lies_between_direction( not side, nd[3].name_id, nd[i].name_id, othern.name_id, wrapb)) if (not NodeID.lies_between_direction( side, nd[3].name_id, nd[i].name_id, nextn.name_id, wrapf)): print("need to reverse side %s-%s-%s!" % (nd[3].name_id, nd[i].name_id, nextn.name_id)) side = not side nextn = othern print("next on %s is %s" % ("LEFT" if side else "RIGHT", repr(nextn))) nb.add_neighbour(0, nd[i]) if (nd[i].numeric_id >= 32): nb.add_neighbour(1, nd[i]) if (nd[i].numeric_id < 48): nb.add_neighbour(2, nd[i]) if (nd[i].numeric_id > 40): nb.add_neighbour(3, nd[i]) if (nd[i].numeric_id < 44): nb.add_neighbour(4, nd[i]) if (nd[i].numeric_id >= 42): nb.add_neighbour(5, nd[i]) new_side_join = side new_side_local = Direction.get_opposite(new_side_join) njnode = InternalNode(new_side_join, cut_dim[i], cut_val[i]) njcpe = copy.deepcopy(nd[3].cpe) njcpe.add_node(njnode) print("%s gets CPE %s" % (nd[i].pname, njcpe)) nlnode = InternalNode(new_side_local, cut_dim[i], cut_val[i]) nlcpe = copy.deepcopy(nd[3].cpe) nlcpe.add_node(nlnode) print("%s gets CPE %s" % (nd[3].pname, nlcpe)) nd[i].cpe = njcpe nd[3].cpe = nlcpe
def walk(self, old_tile, new_tile, level, direction): direc = Direction.toViewed(direction) self.setDirection(direc) self.animation.walk(old_tile, new_tile, level)
def melee(self, tile, direc): direc = Direction.toViewed(direc) self.setDirection(direc) self.animation.melee(tile)
def __repr__(self): return "<SNFixupHigher ((%i, %s from %s) #%i - RouteByPayload>" % ( self.__ring_level, Direction.get_name( self.__direction), self.__src_node, self.__nb_hops)
def _info(self): return "SNFixupHigher (%i, %s from %s) #%i - " % ( self.__ring_level, Direction.get_name( self.__direction), self.__src_node, self.__nb_hops)
def _info(self): return "SNFixupHigher (%i, %s from %s) #%i - "%( self.__ring_level, Direction.get_name(self.__direction), self.__src_node, self.__nb_hops)
def by_cpe_get_next_hop_forking(self, lnode, message): self.__lastcall = ['bycpe+f'] dest = [] left, here, right = lnode.cpe.which_side_space(message.space_part, True) if (here): # NOTE: it cannot be 'naked' message, but must be a clone with # search range that has been 'constraint' to stick here. newmsg = copy.copy(message) newmsg.trace = copy.copy(message.trace) newmsg.limit = PidRange(lnode.partition_id, lnode.partition_id) dest.append((lnode, newmsg)) # create 'directions', that identifies sub-rings to be scanned # and the sub-range of PartitionID that should be taken into account. message.sign( "routing %s%s with %s" % ('L' if left else '', 'R' if right else '', repr(message.limit))) directions = list() if (left): r = message.limit.restrict(Direction.RIGHT, lnode.partition_id) directions.append((Direction.LEFT, r, 'L')) if (right): r = message.limit.restrict(Direction.LEFT, lnode.partition_id) directions.append((Direction.RIGHT, r, 'R')) self.__lastcall.append("scanning rings @%s: %s" % (lnode.partition_id, repr(directions))) part = message.space_part neighbourhood = lnode.neighbourhood lastpid, lastngh = None, None # (point) routing guideline: # for a message that must be sent in direction D, we look for # the farthest neighbour that would not reverse the travelling # direction. # (range) routing guideline: # you send a copy to N[i] if region between N[i] and N[i+1] inter- # sects the region you're searching for. for dirx, prange, pd in directions: for height in range(neighbourhood.nb_ring - 1, -1, -1): if height > 0 and neighbourhood.size(dirx, height) < 2: continue # this ring is empty or has a single node. ngh = neighbourhood.get_neighbour(dirx, height) pid = ngh.partition_id if lastngh != None and ngh.name_id == lastngh.name_id: continue # we just checked this neighbour lastngh = ngh self.__lastcall.append("%s (%i, %s)" % (ngh.pname, height, repr(dirx))) if (ngh.cpe.k == 0): ngh.queue(message) reply = RouteDirect(SNPingRequest(lnode, height), ngh) self.__lastcall.append( "requesting routing table complement at %s" % ngh) return [(ngh, reply)] # todo: rate-limit to avoid redundant PING requests. epid = prange.includes_pid( pid) # effective pid = pid+{-1,0,+1} if (epid != None): left, here, right = ngh.cpe.which_side_space(part, True) if (here or RouterReflect.__goes_forward( dirx, left, right)): self.__lastcall.append( "%s is %s compared to %s" % (part, 'here' if here else 'forw', repr(ngh.cpe))) newmsg = copy.copy(message) newmsg.sign("routed to %s at h=%i" % (ngh.pname, height)) newmsg.limit = prange.restrict( Direction.get_opposite(dirx), epid) dest.append((ngh, newmsg)) else: self.__lastcall.append( "ignored w/ %s, %s, %s - %s" % (repr(left), repr(here), repr(right), 'L' if dirx == Direction.LEFT else 'R')) lastpid = pid prange = prange.restrict(dirx, epid) # ^ messages that will be generated after this one will not be allowed # to forward beyond the 'current position'. if (not RouterReflect.__goes_backward(dirx, left, right)): break else: self.__lastcall.append("%f out of partition range %s" % (pid, repr(prange))) # print("0_0 %s : %i"%(repr(message),len(dest))) # ^it's a bad idea to do a per-message report to the MCP. Use your # 'personal log' for that. Otherwise, you're forcing the MCP to do # a poll with period approaching msg_rate x buffer_size or your # own node will stall, waiting for room to appear in STDOUT buffer. return dest