Exemple #1
0
 def change_print(self, prev_player_info, prefix="", incremental=True):
     """ Print change in player information
     :prev_player: previous player information
     :prefix: optional prefix string for  printout
         if present space is added
     :incremental: changes only else all fields
     """
     if prefix != "":
         prefix += " "
     min_id = min(self.get_min_id(), prev_player_info.get_min_id())
     max_id = max(self.get_max_id(), prev_player_info.get_max_id())
     for pl_id in range(min_id, max_id+1):
         if self.has_player(pl_id) and prev_player_info.has_player(pl_id):
             self.player_diff_print(prev_player_info.get_player(pl_id),
                                     self.get_player(pl_id), prefix,
                                     incremental=incremental)
         elif self.has_player(pl_id):
             player = self.get_player(pl_id)
             SlTrace.lg(f"{prefix} added: {player}")
         elif prev_player_info.has_player(pl_id):
             player = prev_player_info.get_player(pl_id)
             SlTrace.lg(f"{prefix} dropped {player}")
Exemple #2
0
    def setCell(self, row=None, col=None, val=None):
        """ Set cell value
        :returns: updated cell
        """
        ret = self.vals.setCell(row=row, col=col, val=val)
        if not self.isValid():
            SlTrace.lg(f"setCell: row={row}, col={col}, val={val} not valid")
            self.display("Invalid arrangement")
            SlTrace.lg("by rows")
            for ri in range(self.nRow):
                nr = ri + 1
                SlTrace.lg(
                    f"row:{nr} vals:{self.getRowVals(nr, include_nones=True)}")
            SlTrace.lg("by columns")
            for ci in range(self.nCol):
                nc = ci + 1
                SlTrace.lg(
                    f"col:{nc} vals:{self.getColVals(nc, include_nones=True)}")
            self.display("After listing")
            raise SelectError("Invalid arrangement")

        return ret
 def mouse_down(self, event):
     if SlTrace.trace("part_info"):
         cnv = event.widget
         x, y = cnv.canvasx(event.x), cnv.canvasy(event.y)
         parts = self.get_parts_at(x, y)
         if parts:
             SlTrace.lg("x=%d y=%d" % (x, y))
             for part in parts:
                 SlTrace.lg("    %s\n%s" % (part, part.str_edges()))
     self.is_down = True
     if self.inside:
         SlTrace.lg("Click in canvas event:%s" % event, "motion")
         cnv = event.widget
         x, y = cnv.canvasx(event.x), cnv.canvasy(event.y)
         SlTrace.lg("x=%d y=%d" % (x, y), "down")
    def cmd_position_adjust(self, keysym):
        """ Positioning commands
         c - center within screen
         m - move to some place ???
         Left - move to left
         Right - move to right
         Up - move up
         Down - move down
        Movement depends on previous command.
        1. If previous heading unchanged
            then move one side in current direction
        2. Else if previous marker is a line,shape or image
            then set heading and location that the
            next such object will be flush
            with the previous objec but have
            the new heading
         
        :keysym: key event keysym
        """
        if (keysym == "Up" or keysym == "Down" or keysym == "Left"
                or keysym == "Right"):
            prev_heading = self.get_heading()
            marker = DmMoveKey(self, keysym=keysym)
            new_heading = marker.get_heading()
            if new_heading != prev_heading:
                marker = DmHeading(self, heading=new_heading)
            cmd = DrawingCommand(f"cmd_{keysym}")
            cmd.add_marker(marker)
            SlTrace.lg(f"cmd={cmd}", "cmd_trace")
            return cmd.do_cmd()

        if keysym == 'c':
            marker = DmPosition(self, x_cor=0, y_cor=0)
            cmd = DrawingCommand(f"cmd_{keysym}")
            cmd.add_marker(marker)
            return cmd.do_cmd()
        else:
            raise SelectError(f"Don't understand keysym:{keysym}")
Exemple #5
0
    def get_component_next_val(self,
                               name,
                               nrange=50,
                               inc_dir=1,
                               default_value=None):
        """ Next value for this component
        :name: control name
        :nrange: - number of samples for incremental
        :default_value: default value
        """
        cur_value = self.get_current_val(name, 1)
        next_direction = self.get_component_val(name, "next", "same")
        if SlTrace.trace("get_next_val"):
            SlTrace.lg("get_next_val %s cur_val=%s next=%s" %
                       (name, cur_value, next_direction))
        if isinstance(cur_value, str):
            next_value = self.ctl_list_value(name)
            SlTrace.lg(
                "get_value %s str next=%s val=%s" %
                (name, next_direction, next_value), "get_next_val")

            return next_value

        else:
            min_value = float(self.get_component_val(name, "min", cur_value))
            max_value = float(self.get_component_val(name, "max", cur_value))
            inc_value = (max_value - min_value) / nrange
            if next_direction == "ascend":
                new_value = cur_value + inc_dir * inc_value
            elif next == "descend":
                new_value = cur_value - inc_dir * inc_value
            elif next_direction == "random":
                new_value = random.randint(min_value, max_value)
            else:
                new_value = cur_value + inc_value
            if new_value < min_value or new_value > max_value:
                new_value = self.step_end(name, new_value)
            self.set_current_val(name, new_value)
Exemple #6
0
 def move_edge(self, edge, xinc, yinc, adjusts=None):
     """ Move selected edge, adjusting connected parts
     Direction of movement is constrained to perpendicular to edge
     Connected parts are:
         the corners at each edge end
         the end-points of the edges, not including this edge,
             connected to the end-corners
     :edge:  selected edge
     :xinc:  x destination delta
     :yinc:  y destination delta
     :adjusts: adjusted connections
                 Default: all connections
     :highlight: True - highlight after move
     """
     self.display_clear(edge)  # Clear display before moveing
     delta_x = xinc
     delta_y = yinc
     edge_dx, edge_dy = edge.edge_dxy()
     if edge_dx == 0:
         delta_y = 0  # No movement parallel to edge
     if edge_dy == 0:
         delta_x = 0  # No movement parallel to edge
     coord = edge.loc.coord
     p1, p2 = coord[0], coord[1]
     SlTrace.lg(
         "move_edge: %s by delta_x=%d,delta_y=%d" %
         (edge, delta_x, delta_y), "move_part")
     """ Collect moves group:
         Collect all parts which need to be moved in whole or part.
         Each part is present once.  If an edge end is moved only the other edge's
         ends need to be adjusted
              
     """
     mover = SelectMover(self, delta_x=delta_x, delta_y=delta_y)
     mover.add_moves(parts=edge)
     ###mover.add_moves(parts=edge.connecteds)
     ###mover.add_adjusts(edge.connecteds)      # Adjust those connected to corners and so on
     mover.move_list(delta_x, delta_y)
Exemple #7
0
def select_copy(obj, levels=4, use_select_copy=True):
    """ Copy object to allow most manipulations of the copy
    without affecting the original
        Checks for member function "select_copy"  and if present
        and if more_copy is True uses it
            for the copy if present.
        Iterates at most levels with
            1. if member function "select_copy"
                return
            2. if hasattr __dict__
                iterate over __dict__.keys()
            3. direct copy attribute
    :levels: maximum number of levels of recursion
    :use_select_copy: Use select_copy member, if present
            default: True
    """
    if levels < 1:
        return obj  # Above max level, return self

    ###if use_select_copy and hasattr(obj, "select_copy"):
    ###    return obj.select_copy(levels=levels-1)
    global select_copy_depth
    select_copy_depth += 1

    SlTrace.lg(
        "select_copy depth=%d obj:type(%s) %s" %
        (select_copy_depth, type(obj), str(obj)), "select_copy")
    if hasattr(obj, "copy"):
        if hasattr(obj, "part_check"):
            obj.part_check(prefix="select_copy")
        res = obj.copy()
    else:
        res = copy.deepcopy(obj)
    #res = copy.copy(obj)
    SlTrace.lg("select_copy depth=%d return" % select_copy_depth,
               "select_copy")
    select_copy_depth -= 1
    return res
Exemple #8
0
    def properties_sect_print(self,
                              base_prefix,
                              snapshot=None,
                              sect_name="undo",
                              max_len=None,
                              incremental=True,
                              title=None):
        """ Print properties sect
        :base_prefix: section prefix, with or without trailing "." e.g. "player_control"
        :snapshot: properties snapshot
                default: current properties
        :sect_name: section name e.g. "undo"
        :max_len: print at most this many entries
        :incremental: just changes from previous entry
        :title: printed before listing
                default: sect_name
        """

        if title is None:
            title = sect_name
        SlTrace.lg(title)
        if not base_prefix.endswith("."):
            base_prefix += "."

        player_info = self.player_info(base_prefix, snapshot)
        player_infos = self.player_infos(base_prefix,
                                         snapshot,
                                         sect_name=sect_name)
        nprint = 0
        for i in range(len(player_infos)):
            prev_player_info = player_infos[i]
            if max_len is None or nprint < max_len:
                player_info.change_print(prev_player_info,
                                         prefix=f"{i:2}",
                                         incremental=incremental)
                SlTrace.lg("")
                nprint += 1
            player_info = prev_player_info
    def delete_window(self):
        """ Process Trace Control window close
        """
        self.mw.eval('::ttk::CancelRepeat')
        self.playing = False  # Accept no more activity
        self.running = False
        self.run = False
        SlTrace.lg("delete_window - wait for call backs to die out")
        self.mw.after(2000)
        SlTrace.lg("Closing windows")

        if self.score_win is not None:
            self.score_win.destroy()
            self.score_win = None

        if self.mw is not None:
            self.mw.destroy()
            self.mw = None

        if self.on_exit is not None:
            self.on_exit()

        sys.exit()  # Else quit
Exemple #10
0
 def setup_scores_frame(self):
     """ Set/Reset players' scores frame
     """
     if self.player_control is None:
         SlTrace.lg("player control not yet set")
         return
     
     if self.scores_frame is not None:
         self.scores_frame.pack_forget()
         self.scores_frame.destroy()
         self.scores_frame = None
     self.players = {}               # Clear, to add currently playing
     self.scores_frame = Frame(self.scores_container_frame)
     self.scores_frame.pack()    
     players = self.player_control.get_players()
     
     headings_frame = Frame(self.scores_frame)
     headings_frame.pack()
     self.set_field_headings(headings_frame)
     self.players_frame = Frame(self.scores_frame)
     self.players_frame.pack()
     for player in players:
         self.add_player(player)
Exemple #11
0
 def set_play_level(self, play_level=None):
     """ Set players' level via
     comma separated string
     :play_level: comma separated string of playing player's Labels
     """
     players = self.get_players(all=True)
     play_levels = [x.strip() for x in play_level.split(',')]
     def_level = "2"
     if len(play_levels) == 0:
         SlTrace.lg("Setting to default level: {}".format(def_level)) 
         play_levels = def_level  # Default
     player_idx = -1
     for player in players:
         player_idx += 1
         if player_idx < len(play_levels):
             player_level = play_levels[player_idx]
         else:
             player_level = play_levels[-1]  # Use last level
         plevel = int(player_level)
         playing_var = player.ctls_vars["level"]
         player.level = plevel
         playing_var.set(plevel)
         SlTrace.lg("Setting {} play level to {:d}".format(player, plevel))
Exemple #12
0
    def display(self, msg=None):
        display_str = ""
        if msg is None:
            msg = "Data Display"
        display_str += f"{msg}\n"
        if self.vals is None:
            raise SelectError("data gone")

        horiz_grp_divider = " " + "-" * (2*self.nCol+self.nSubCol-1) + "\n"             
        for nr in range(1, self.nRow+1):
            if nr % self.nSubRow == 1:
                display_str += horiz_grp_divider
            for nc in range(1, self.nCol+1):
                if nc == 1:
                    display_str +="|"
                val = self.getCellVal(row=nr, col=nc)
                disp = "  " if self.isEmpty(val) else f"{val} "
                display_str += disp
                if nc % self.nSubCol == 0:
                    display_str += "|"
            display_str += "\n"
        display_str += horiz_grp_divider
        SlTrace.lg(display_str)
    def down_click(self, part, event=None):
        """ Process down click over highlighted part
        All highlighted parts elicit a call
        :part: highlighted part
        :event: event if available
        :Returns: True if processing is complete
        """
        if self.down_click_call is not None:
            return self.down_click_call(part, event=event)
        """ Self processing
        """
        if part.is_edge() and not part.is_turned_on():
            SlTrace.lg("turning on %s" % part, "turning_on")
            self.drawn_lines.append(part)
            part.turn_on(player=self.get_player())
            regions = part.get_adjacents()  # Look if we completed any squares
            for square in regions:
                if square.is_complete():
                    self.complete_square(part, square)

            return True  # Indicate processing is done

        return False
 def annotate_squares(self, squares, player=None):
     """ Annotate squares in board with players info
     Updates select_cmd: prev_parts, new_parts as appropriate
     :squares: list of squares to annotate
     :player: player whos info is used
             Default: use current player
     """
     if player is None:
         player = self.get_player()
     if not isinstance(squares, list):
         squares = [squares]
     for square in squares:
         square.part_check(prefix="annotate_squares")
     for square in squares:
         sc = select_copy(square)
         self.add_prev_parts(square)
         sc.set_centered_text(player.label,
                              color=player.color,
                              color_bg=player.color_bg)
         if SlTrace.trace("annotate_square"):
             SlTrace.lg("annotate_square: %s\n%s" % (sc, sc.str_edges()))
         self.add_new_parts(sc)
     return
Exemple #15
0
    def is_square_complete(self, part, squares=None, ifadd=False):
        """ Determine if this edge completes one or more square(s) region(s)
        :part: - possibly completing edge
        :squares: - any squares completed are appended to this list
                default: no regions are appended
        :ifadd: If part is added
                default: part must already be added
        """
        if part.is_edge():
            SlTrace.lg("complete square testing %s" % part,
                       "square_completion")
            regions = part.get_adjacents()  # Look if we completed any square
            ncomp = 0
            for square in regions:
                if (ifadd and square.is_complete(added=part)
                        or square.is_complete()):
                    ncomp += 1
                    if squares is not None:
                        squares.append(square)
            if ncomp > 0:
                return True

        return False
Exemple #16
0
    def get_component_val(self, name, comp_name=None, default=None):
        """ Get component value of named control
        If widget is present, get from widget
        else if control is present, get from control
        else if properties is present, get from properties
        :name: - control name
        :comp_name: if present, append with "_" comp_name
        :default: - use if value not found - MANDATORY
                    data type is used if control entry data type is unknown
        """
        if default is None:
            raise SelectError(
                "get_component_val: %s_%s mandatory default parameter missing"
                % (name, comp_name))

        name_comp = name
        if comp_name is not None:
            name_comp += "_" + comp_name
        comp_entry = self.get_ctl_entry(name_comp)
        if comp_entry is None:
            raise SelectError(
                "get_component_value(%s, %s - component NOT FOUD" %
                (name, comp_name))

        if comp_entry is not None:
            if comp_entry.value_type is None:
                comp_entry.value_type = type(default)
            ctl_widget = comp_entry.ctl_widget
            if ctl_widget is not None:
                widget_val = comp_entry.get_input()
                if widget_val is not None:
                    vt = comp_entry.value_type
                    if vt == int:
                        if widget_val == "":
                            widget_val = "0"  # Treat undefined as 0
                        value = int(widget_val)
                    elif vt == float:
                        if widget_val == "":
                            widget_val = "0"  # Treat undefined as 0
                        value = float(widget_val)
                    elif vt == str:
                        value = widget_val
                    else:
                        value = widget_val  # No change - should we check?
                        SlTrace.lg(
                            "get_component_val: %s ??? value_type(%s) widget_val=%s type(%s)"
                            % (name_comp, vt, widget_val, type(widget_val)))
                        SlTrace.lg("  type(int)=%s comp_entry.value_type=%s" %
                                   (type(int), comp_entry.value_type))
                    return value
                else:
                    SlTrace.lg(
                        "get_component_val: %s None return from comp_entry.get_input"
                        % comp_name)
            return comp_entry.value

        return default  # No component entry - return default
 def test_is_covering_but_once():
     SlTrace.lg("\ntest_covering_but_once")
     good1 = ['g7', 'g8', 'h8', 'h7']
     dgood1 = DisplayedPath(path=good1, disp_board=dboard)
     ctv = ChessTourValidation(locs=good1)
     if ctv.is_covering_but_once(dgood1):
         SlTrace.lg(f"expected: pass of {good1}")
     else:
         SlTrace.lg(f"UNEXPECTED FAIL of {good1}")
Exemple #18
0
    def get_selected(cls, block=None):
        """ Get selected info, block if selected, else None
        :block:  block to check.
        """
        if block is None:
            raise SelectError("get_selected: with block is None")

        selected = None
        for sid in cls.selects:
            selected = cls.selects[sid]
            if selected.block.id == sid:
                break

        if selected.block is None:
            raise SelectError("selected with None for block")

        if selected.x_coord is None:
            SlTrace.lg("selected with None for x_coord")
            cv_width = cls.get_cv_width()
            cv_height = cls.get_cv_height()
            selected = SelectInfo(block=None,
                                  x_coord=cv_width / 2,
                                  y_coord=cv_height / 2)  # HACK
        return selected
Exemple #19
0
 def __init__(self,
              road_width=.05,
              road_length=.05 * 2,
              surface=SurfaceType.DEFAULT,
              **kwargs):
     """ Setup object
     :road_width: road width as a fraction of track's width dimensions'
             e.g. 1,1 with container==None ==> block is whole canvas
     :road_length: road width as a fraction of track's width dimensions'
             e.g. 1,1 with container==None ==> block is whole canvas
     :surface: road surface type - determines look and operation/handeling                                                    collisions)
     """
     SlTrace.lg("RoadTrack: %s" % (self))
     super().__init__(**kwargs)
     if self.container is None:
         canvas = self.get_canvas()
         if canvas is None:
             self.canvas = Canvas(width=self.cv_width,
                                  height=self.cv_height)
     self.roads = []  # List of components    # Parts of track
     self.road_width = road_width
     self.road_length = road_length
     self.surface = surface
     self.background = "lightgreen"
    def set_check_box(self,
                      frame=None,
                      field=None,
                      label=None,
                      value=False,
                      command=None):
        """ Set up check box for field
        :field: local field name
        :label: button label - default final section of field name
        :value: value to set "string"
        :command: function to call with new value when box changes
                    default: no call
        """
        if frame is None:
            frame = self.base_frame
        if label is None:
            label = field

        if label is not None:
            wlabel = Label(frame, text=label)
            wlabel.pack(side="left")
        content = BooleanVar()
        full_field = self.field_name(field)
        value = self.get_prop_val(full_field, value)
        content.set(value)
        cmd = None
        if command is not None:  # HACK - only works for ONE checkbox
            self.check_box_change_content = content
            self.check_box_change_callback = command
            cmd = self.check_box_change
        widget = Checkbutton(frame, variable=content, command=cmd)
        widget.pack(side="left", fill="none", expand=True)
        self.ctls[full_field] = widget
        self.ctls_vars[full_field] = content
        SlTrace.lg(f"set_check_box adding field:{full_field}")
        self.set_prop_val(full_field, value)
Exemple #21
0
 def get_image_files(self, file_dir=None, name=None):
     """ Get list of image files given name
     :file_dir: file directory
             default: self.image_path
     :name: selection name
         default: all images
     :returns: list of absolute paths to image files
     """
     if file_dir is None:
         file_dir = self.image_path
     if name is not None:
         file_dir = os.path.join(file_dir, name)
     names = os.listdir(file_dir)
     image_files = []
     for name in sorted(names):
         path = os.path.join(file_dir, name)
         if (os.path.exists(path) and not os.path.isdir(path)):
             try:
                 im = Image.open(path)
                 image_files.append(path)
                 im.close()
             except IOError:
                 SlTrace.lg(f"Not an image file: {path}")
     return image_files
    def __init__(self, car_bin):
        """ Setup car bin
        :car_bin: car bin instance
        """
        self.car_bin = car_bin

        SlTrace.lg("CarBinSetup: car_bin pts: %s" %
                   self.car_bin.get_absolute_points())

        car_rot = 0  # HACK
        nentries = 4  # Number of entries (space)
        entry_space = .08  # between entries
        entry_width = 5 * (1. - nentries * entry_space) / nentries
        entry_height = .25 * (1. - 2 * entry_space)  # height of entry
        pos_inc = Pt(0., 1.2 * entry_height)  # to next entry
        pos = Pt(entry_space,
                 entry_space)  # HACK - Add extra  to move to right

        entry = CarSimple(self.car_bin,
                          rotation=car_rot,
                          position=pos,
                          width=entry_width,
                          height=entry_height,
                          base_color="red")
        SlTrace.lg("entry pts: %s" % entry.get_absolute_points())
        self.add_entry(entry)

        pos += pos_inc
        entry = CarSimple(self.car_bin,
                          rotation=car_rot,
                          position=pos,
                          width=entry_width,
                          height=entry_height,
                          base_color="blue")
        SlTrace.lg("entry pts: %s" % entry.get_absolute_points())
        self.add_entry(entry)

        pos += pos_inc
        entry = CarSimple(self.car_bin,
                          rotation=car_rot,
                          position=pos,
                          width=entry_width,
                          height=entry_height,
                          base_color="green")
        SlTrace.lg("entry pts: %s" % entry.get_absolute_points())
        self.add_entry(entry)
Exemple #23
0
def filelist_proc(filename):
    """ Process file containing list of puzzle files
    :filename: filename of file containing list of puzzle files
            Default directory for files in list is dir(filename)
    """
    with open(filename) as f:
        file_list_files[filename] = 1   # Record as being used
        lines = f.readlines()
        filedir = os.path.dirname(filename)
    for i in range(len(lines)):
        line = lines[i]
        ml = re.match(r'^(\.*)#.*$', line)
        if ml:
            line = ml[1]    # Before comment
        line = line.strip()
        if re.match(r'^\s*$', line):
            continue                # Skip blank lines
        name = line
        if not os.path.isabs(name):
            name = os.path.join(filedir, name)
        if name in file_list_files:
            SlTrace.lg(f"file: {file} already used - avoiding recursive use ")
            continue
        file_proc(filename=name, run_after_load=True)
    def open(self, src_file=None):
        """ Open command file
        Opens output files, if specified
        :src_file: Source file default, if no extension ext="csrc"
            If no extension: look for .py, then .csrc
            in source_directories
            else look for file in source_directories
        :returns: True iff successful open (note that py type
                flles are are opened when first get_tok is called
        """
        self.lineno = 0  # Src line number
        self.eof = True  # Cleared on open, set on EOF
        if src_file is None:
            if self.src_file_name is None:
                raise SelectError(
                    "open: no src_file and no self.src_file_name")

            src_file = self.src_file_name
        self.src_file_name = src_file
        if not self.check_file(self.src_file_name):
            return False

        self.new_file = False
        if self.file_type == "csrc":
            try:
                if self.src_lst or SlTrace.trace("csrc"):
                    SlTrace.lg("Open %s" % self.src_file_path)
                self.in_file = open(self.src_file_path, "r")
            except IOError as e:
                errno, strerror = e.args
                SlTrace.lg("Can't open command source file %s: %d %s" %
                           (self.src_file_path, errno, strerror))
                self.eof = True
                return False
        self.eof = False
        return True
Exemple #25
0
    def trace_item(self, rec_id=None, track_no=None, prefix="", begin=-3, end=-1):
        """ Trace(list) entry
        :rec_id: record id
        :trac_no: tracing number
        :begin: start stack list (-99 99 most recent entries)
        :end: end stack list (-1 most recent entry)
        """
        if rec_id is not None:
            if rec_id in self.by_rec_id:
                track = self.by_rec_id[rec_id]
            else:
                return          # Ignore if not tracked
            
        elif track_no is not None:
            if track_no in self.by_track_no:
                track = self.by_track_no[track]
            else:
                return          # Ignore if not tracked
            
        else:
            raise("trace_item has neither rec_id nor track_no")
        rec_id = track[0]
        tags = self.gettags(rec_id)
        track_no = track[1]
        stack = track[2]
        entries = traceback.format_list(stack)

        # Remove the last two entries for the call to extract_stack() and to
        # the one before that, this function. Each entry consists of single
        # string with consisting of two lines, the script file path then the
        # line of source code making the call to this function.
        ###del entries[-2:]
        part = self.get_part_from_tags(tags)
        SlTrace.lg("%s%s %s %s" % (prefix, rec_id, tags, part))
        for entry in entries[begin:end]:
            SlTrace.lg("%s" % (entry))
Exemple #26
0
    def get_part(self, id=None, type=None, sub_type=None, row=None, col=None):
        """ Get basic part
        :id: unique part id
        :type: part type e.g., edge, region, corner default: "edge"
        :sub_type: must match if present e.g. v for vertical, h for horizontal
        :row:  part row
        :col: part column
        :returns: part, None if not found
        """
        if id is not None:
            if id not in self.parts_by_id:
                SlTrace.lg("part not in parts_by_id")
                return None

            part = self.parts_by_id[id]
            return part

        if type is None:
            type = "edge"
        for part in self.parts:
            if part.part_type == type and (sub_type is None
                                           or part.sub_type() == sub_type):
                if part.row == row and part.col == col:
                    return part
 def next_color(self, colr=None, changing=None):
     """ Get next color based on color_current, color_changing
     :colr: color
             default: use self.color_current
     :changing: is color changing
             default: use self.color_changing
     """
     if colr is None:
         colr = self.color_current
     self.color_current = colr
     if changing is None:
         changing = self.color_changing
     self.color_changing = changing
     if self.color_current == 'w':
         if self.color_changing:
             self.color_index += 1
         if self.color_index >= len(self.colors):
             self.color_index = 0  # wrap around
         new_color = self.colors[self.color_index]
     elif self.color_current == '2':
         if changing:
             self.color_index += 1
         if self.color_index >= len(self.custom_colors):
             self.color_index = 0
         new_color = self.custom_colors[self.color_index]
     else:
         new_color = self.color_current
         if type(new_color) != str:
             SlTrace.report(f"new_color:{new_color} not str")
             return
     SlTrace.lg(
         f"new_color:{new_color}"
         f" color_current:{self.color_current}"
         f" color_index:{self.color_index}"
         f" color_changing:{self.color_changing}", "color")
     return new_color
    def fill_points(self, point_list, point_resolution=None):
        """ Fill surrounding points assuming points are connected
        and enclose an area. - we will, eventualy, do
        "what turtle would do".
        Our initial technique assumes a convex region:
            given every sequential group of points (pn,
            pn+1,pn+2), pn+1 is within the fill region.
        We divide up the fill region into triangles:
            ntriangle = len(point_list)-2
            for i in rage(1,ntriangle):
                fill_triangle(pl[0],pl[i],pl[i+1])
            
        :point_list: list (iterable) of surrounding points
        :point_resolution: distance under which cells containing
                each point will cover region with no gaps
                default: self.point_resolution
        :returns: set of points (ix,iy) whose cells
                cover fill region
        """
        if point_resolution is None:
            point_resolution = self.point_resolution
        SlTrace.lg(f"fill_points: {pl(point_list)} res:{point_resolution}",
                   "xpoint")
        fill_point_set = set()
        if len(point_list) < 3:
            return set()

        plist = iter(point_list)
        p1 = point_list[0]
        for i in range(2, len(point_list)):
            p2 = point_list[i]
            p3 = point_list[i - 1]
            points = self.get_points_triangle(
                p1, p2, p3, point_resolution=point_resolution)
            fill_point_set.update(points)
        return fill_point_set
Exemple #29
0
 def test_attr(name):
     """ Test/exercise attribute
     :name: attribute name
     """
     global nrun
     nrun += 1
     SlTrace.lg(f"\n{nrun:3} Testing Attribute: {name}")
     attr = atc.get_attr(name)
     SlTrace.lg(f"  {attr.get_name()}:"
                f"  changes: {attr.get_changes()}"
                f"  index: {attr.get_index()}")
     atc.add_value(name=name, value=f"{name}_test_value_{nrun}")
     values = attr.get_values()
     SlTrace.lg(f"values: {values}")
     for n in range(len(values) * 3):
         SlTrace.lg(f"  {n}: {atc.get_next(name)}"
                    f"  index: {attr.get_index()}")
    def get_drawn_line_points(self, p1, p2, width=None, point_resolution=None):
        """ Get drawn line fill points
        Find perimeter of surrounding points of a rectangle
        For  simplicity we consider vertical width
        :p1: beginning point
        :p2: end point
        :width: width of line
            default: self.line_width
        :point_resolution: fill point spacing
            default: self.point_resolution
        :returns: set of fill points
        """
        ###pts = self.get_line_points(p1,p2)
        ###return set(pts)

        if width is None:
            width = self.line_width
        if point_resolution is None:
            point_resolution = self.point_resolution
        pr = point_resolution
        SlTrace.lg(
            f"get_drawn_Line_points {p1} {p2}"
            f" width: {width} res: {pr}", "xpoint")
        p1x, p1y = p1
        p2x, p2y = p2
        self.set_line_funs(p1, p2)

        dx = self.lfun_unorm_x * width / 2  # draw width offsets
        dy = self.lfun_unorm_y * width / 2
        pp1 = (p1x + dx, p1y + dy)  # upper left corner
        pp2 = (p2x + dx, p2y + dy)  # upper right corner
        pp3 = (p2x - dx, p2y - dy)  # lower right corner
        pp4 = (p1x - dx, p1y - dy)  # lower left corner
        perim_list = [pp1, pp2, pp3, pp4]
        filled_points = self.fill_points(perim_list)
        return filled_points