<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def create_marker(self, category, start, finish, marker=None, **kwargs):
 """ Create a new marker in the TimeLine with the specified options :param category: Category identifier, key as given in categories dictionary upon initialization :type category: Any :param start: Start time for the marker :type start: float :param finish: Finish time for the marker :type finish: float :param marker: marker dictionary (replaces kwargs) :type marker: dict[str, Any] **Marker Options** Options can be given either in the marker dictionary argument, or as keyword arguments. Given keyword arguments take precedence over tag options, which take precedence over default options. :param text: Text to show in the marker. Text may not be displayed fully if the zoom level does not allow the marker to be wide enough. Updates when resizing the marker. :type text: str :param background: Background color for the marker :type background: str :param foreground: Foreground (text) color for the marker :type foreground: str :param outline: Outline color for the marker :type outline: str :param border: The width of the border (for which outline is the color) :type border: int :param font: Font tuple to set for the marker :type font: tuple :param iid: Unique marker identifier to use. A marker is generated if not given, and its value is returned. Use this option if keeping track of markers in a different manner than with auto-generated iid's is necessary. :type iid: str :param tags: Set of tags to apply to this marker, allowing callbacks to be set and other options to be configured. The option precedence is from the first to the last item, so the options of the last item overwrite those of the one before, and those of the one before that, and so on. :type tags: tuple[str] :param move: Whether the marker is allowed to be moved :type move: bool Additionally, all the options with the ``marker_`` prefix from :meth:`__init__`, but without the prefix, are supported. Active state options are also available, with the ``active_`` prefix for ``background``, ``foreground``, ``outline``, ``border``. These options are also available for the hover state with the ``hover_`` prefix. :return: identifier of the created marker :rtype: str :raise ValueError: One of the specified arguments is invalid """

        kwargs = kwargs if marker is None else marker
        if category not in self._categories:
            raise ValueError("category argument not a valid category: {}".format(category))
        if start < self._start or finish > self._finish:
            raise ValueError("time out of bounds")
        self.check_marker_kwargs(kwargs)
        # Update the options based on the tags. The last tag always takes precedence over the ones before it, and the
        # marker specific options take precedence over tag options
        tags = kwargs.get("tags", ())
        options = kwargs.copy()
        # Check the tags
        for tag in tags:
            # Update the options
            kwargs.update(self._tags[tag])
        # Update with the specific marker options
        kwargs.update(options)
        # Process the other options
        iid = kwargs.pop("iid", str(self._iid))
        background = kwargs.get("background", "default")
        foreground = kwargs.get("foreground", "default")
        outline = kwargs.get("outline", "default")
        font = kwargs.get("font", "default")
        border = kwargs.get("border", "default")
        move = kwargs.get("move", "default")
        change_category = kwargs.get("change_category", "default")
        allow_overlap = kwargs.get("allow_overlap", "default")
        snap_to_ticks = kwargs.get("snap_to_ticks", "default")
        # Calculate pixel positions
        x1 = start / self._resolution * self._zoom_factor
        x2 = finish / self._resolution * self._zoom_factor
        y1, y2 = self._rows[category]
        # Create the rectangle
        rectangle_id = self._timeline.create_rectangle(
            (x1, y1, x2, y2),
            fill=background if background != "default" else self._marker_background,
            outline=outline if outline != "default" else self._marker_outline,
            tags=("marker",),
            width=border if border != "default" else self._marker_border
        )
        # Create the text
        text = kwargs.get("text", None)
        text_id = self._draw_text((x1, y1, x2, y2), text, foreground, font) if text is not None else None
        # Save the marker
        locals_ = locals()
        self._markers[iid] = {
            key: (
                locals_[key.replace("hover_", "").replace("active_", "")] if key in (
                    prefix + color for prefix in ["", "hover_", "active_"]
                    for color in ["background", "foreground", "outline", "border"]
                ) and key not in kwargs else (locals_[key] if key in locals_ else kwargs[key])
            ) for key in self.marker_options
        }
        # Save the marker's Canvas IDs
        self._canvas_markers[rectangle_id] = iid
        self._canvas_markers[text_id] = iid
        self._timeline.tag_lower("marker")
        # Attempt to prevent duplicate iids
        while str(self._iid) in self.markers:
            self._iid += 1
        return iid