From e394441c8d64a89f5679d6185178622e5d5156a3 Mon Sep 17 00:00:00 2001 From: Filip Rutkowski Date: Wed, 21 Feb 2024 20:51:40 +0000 Subject: [PATCH 1/5] Align viewbox center with vacuum map center This removes the need to adjust all the coordinates by the bounding box. It is enough to divide by 50. --- deebot_client/map.py | 129 +++++++++++++------------------------------ tests/test_map.py | 79 ++++++++++---------------- 2 files changed, 65 insertions(+), 143 deletions(-) diff --git a/deebot_client/map.py b/deebot_client/map.py index c2864b80..21be6361 100644 --- a/deebot_client/map.py +++ b/deebot_client/map.py @@ -155,32 +155,6 @@ class TracePoint(Point): connected: bool -@dataclasses.dataclass -class AxisManipulation: - """Map manipulation.""" - - map_shift: float - svg_max: float - _transform: Callable[[float, float], float] | None = None - - def __post_init__(self) -> None: - self._svg_center = self.svg_max / 2 - - def transform(self, value: float) -> float: - """Transform value.""" - if self._transform is None: - return value - return self._transform(self._svg_center, value) - - -@dataclasses.dataclass -class MapManipulation: - """Map manipulation.""" - - x: AxisManipulation - y: AxisManipulation - - @dataclasses.dataclass class BackgroundImage: """Background image.""" @@ -237,33 +211,27 @@ class BackgroundImage: ) -def _calc_value(value: float, axis_manipulation: AxisManipulation) -> float: - try: - if value is not None: - # SVG allows sub-pixel precision, so we use floating point coordinates for better placement. - new_value = ( - (float(value) / _PIXEL_WIDTH) + _OFFSET - axis_manipulation.map_shift - ) - new_value = axis_manipulation.transform(new_value) - # return value inside min and max - return round( - min(axis_manipulation.svg_max, max(0, new_value)), _ROUND_TO_DIGITS - ) - - except (ZeroDivisionError, ValueError): - pass - - return 0 - - def _calc_point( x: float, y: float, - map_manipulation: MapManipulation, ) -> Point: return Point( - _calc_value(x, map_manipulation.x), - _calc_value(y, map_manipulation.y), + 0 if x is None else round(x / _PIXEL_WIDTH, _ROUND_TO_DIGITS), + 0 if y is None else round(-y / _PIXEL_WIDTH, _ROUND_TO_DIGITS), + ) + + +def _calc_point_in_viewbox(x: float, y: float, viewbox: svg.ViewBoxSpec) -> Point: + point = _calc_point(x, y) + return Point( + min( + max(point.x, float(viewbox.min_x)), + float(viewbox.min_x) + float(viewbox.width), + ), + min( + max(point.y, float(viewbox.min_y)), + float(viewbox.min_y) + float(viewbox.height), + ), ) @@ -295,14 +263,17 @@ def _points_to_svg_path( def _get_svg_positions( - positions: list[Position], - map_manipulation: MapManipulation, + positions: list[Position], viewbox: svg.ViewBoxSpec ) -> list[svg.Element]: svg_positions: list[svg.Element] = [] for position in sorted(positions, key=lambda x: _POSITIONS_SVG[x.type].order): - pos = _calc_point(position.x, position.y, map_manipulation) + pos = _calc_point_in_viewbox(position.x, position.y, viewbox) svg_positions.append( - svg.Use(href=f"#{_POSITIONS_SVG[position.type].svg_id}", x=pos.x, y=pos.y) + svg.Use( + href=f"#{_POSITIONS_SVG[position.type].svg_id}", + x=pos.x, + y=pos.y, + ) ) return svg_positions @@ -310,7 +281,6 @@ def _get_svg_positions( def _get_svg_subset( subset: MapSubsetEvent, - map_manipulation: MapManipulation, ) -> Path | svg.Polygon: _LOGGER.debug("Creating svg subset for %s", subset) @@ -319,7 +289,6 @@ def _get_svg_subset( _calc_point( subset_coordinates[i], subset_coordinates[i + 1], - map_manipulation, ) for i in range(0, len(subset_coordinates), 2) ] @@ -448,10 +417,7 @@ def _draw_map_pieces(self, image: Image.Image) -> None: if current_piece.in_use: image.paste(current_piece.image, (image_x, image_y)) - def _get_svg_traces_path( - self, - map_manipulation: MapManipulation, - ) -> Path | None: + def _get_svg_traces_path(self) -> Path | None: if len(self._map_data.trace_values) > 0: _LOGGER.debug("[get_svg_map] Draw Trace") return Path( @@ -461,11 +427,7 @@ def _get_svg_traces_path( stroke_linejoin="round", vector_effect="non-scaling-stroke", transform=[ - svg.Translate( - _OFFSET - map_manipulation.x.map_shift, - _OFFSET - map_manipulation.y.map_shift, - ), - svg.Scale(0.2, 0.2), + svg.Scale(0.2, -0.2), ], d=_points_to_svg_path(self._map_data.trace_values), ) @@ -569,29 +531,22 @@ def get_svg_map(self) -> str | None: # Build the SVG elements svg_map = svg.SVG() svg_map.elements = [_SVG_DEFS] - manipulation = MapManipulation( - AxisManipulation( - map_shift=background.bounding_box[0], - svg_max=background.bounding_box[2] - background.bounding_box[0], - ), - AxisManipulation( - map_shift=background.bounding_box[1], - svg_max=background.bounding_box[3] - background.bounding_box[1], - _transform=lambda c, v: 2 * c - v, - ), - ) # Set map viewBox based on background map bounding box. svg_map.viewBox = svg.ViewBoxSpec( - 0, - 0, - manipulation.x.svg_max, - manipulation.y.svg_max, + background.bounding_box[0] - _OFFSET, + _OFFSET - background.bounding_box[3], + (background.bounding_box[2] - background.bounding_box[0]), + (background.bounding_box[3] - background.bounding_box[1]), ) # Map background. svg_map.elements.append( svg.Image( + x=svg_map.viewBox.min_x, + y=svg_map.viewBox.min_y, + width=svg_map.viewBox.width, + height=svg_map.viewBox.height, style="image-rendering: pixelated", href=f"data:image/png;base64,{base64.b64encode(background.image).decode('ascii')}", ) @@ -599,26 +554,16 @@ def get_svg_map(self) -> str | None: # Additional subsets (VirtualWalls and NoMopZones) svg_map.elements.extend( - [ - _get_svg_subset(subset, manipulation) - for subset in self._map_data.map_subsets.values() - ] + [_get_svg_subset(subset) for subset in self._map_data.map_subsets.values()] ) # Traces (if any) - if svg_traces_path := self._get_svg_traces_path(manipulation): - svg_map.elements.append( - # Elements to vertically flip - svg.G( - transform_origin=r"50% 50%", - transform=[svg.Scale(1, -1)], - elements=[svg_traces_path], - ) - ) + if svg_traces_path := self._get_svg_traces_path(): + svg_map.elements.append(svg_traces_path) # Bot and Charge stations svg_map.elements.extend( - _get_svg_positions(self._map_data.positions, manipulation) + _get_svg_positions(self._map_data.positions, svg_map.viewBox) ) self._last_image = str(svg_map) diff --git a/tests/test_map.py b/tests/test_map.py index 61ec349d..8ddc7df3 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -17,6 +17,7 @@ Polygon, SmoothCubicBezierRel, VerticalLineToRel, + ViewBoxSpec, ) from deebot_client.events.map import ( @@ -32,14 +33,13 @@ PositionType, ) from deebot_client.map import ( - AxisManipulation, Map, MapData, - MapManipulation, Path, Point, TracePoint, _calc_point, + _calc_point_in_viewbox, _get_svg_subset, _points_to_svg_path, ) @@ -53,54 +53,41 @@ from deebot_client.event_bus import EventBus _test_calc_point_data = [ - (10, 100, (100, 0, 200, 50), Point(100.0, 0.0)), - (10, 100, (0, 0, 1000, 1000), Point(400.2, 598.0)), - (None, 100, (0, 0, 1000, 1000), Point(0, 598.0)), + (5000, 0, Point(100.0, 0.0)), + (20010, -29900, Point(400.2, 598.0)), + (None, 29900, Point(0, -598.0)), ] -@pytest.mark.parametrize(("x", "y", "image_box", "expected"), _test_calc_point_data) +@pytest.mark.parametrize(("x", "y", "expected"), _test_calc_point_data) def test_calc_point( x: int, y: int, - image_box: tuple[int, int, int, int], expected: Point, ) -> None: - manipulation = MapManipulation( - AxisManipulation( - map_shift=image_box[0], - svg_max=image_box[2] - image_box[0], - ), - AxisManipulation( - map_shift=image_box[1], - svg_max=image_box[3] - image_box[1], - _transform=lambda c, v: 2 * c - v, - ), - ) - result = _calc_point(x, y, manipulation) + result = _calc_point(x, y) assert result == expected -@pytest.mark.parametrize(("error"), [ValueError(), ZeroDivisionError()]) -def test_calc_point_exceptions( - error: Exception, +_test_calc_point_in_viewbox_data = [ + (100, 100, ViewBoxSpec(-100, -100, 200, 150), Point(2.0, -2.0)), + (-64000, -64000, ViewBoxSpec(0, 0, 1000, 1000), Point(0.0, 1000.0)), + (64000, 64000, ViewBoxSpec(0, 0, 1000, 1000), Point(1000.0, 0.0)), + (None, 1000, ViewBoxSpec(-500, -500, 1000, 1000), Point(0.0, -20.0)), +] + + +@pytest.mark.parametrize( + ("x", "y", "viewbox", "expected"), _test_calc_point_in_viewbox_data +) +def test_calc_point_in_viewbox( + x: int, + y: int, + viewbox: ViewBoxSpec, + expected: Point, ) -> None: - def transform(_: float, __: float) -> float: - raise error - - manipulation = MapManipulation( - AxisManipulation( - map_shift=50, - svg_max=100, - _transform=transform, - ), - AxisManipulation( - map_shift=50, - svg_max=100, - ), - ) - result = _calc_point(100, 100, manipulation) - assert result == Point(0, 100) + result = _calc_point_in_viewbox(x, y, viewbox) + assert result == expected async def test_MapData(event_bus: EventBus) -> None: @@ -236,7 +223,7 @@ def test_points_to_svg_path( stroke_width=1.5, stroke_dasharray=[4], vector_effect="non-scaling-stroke", - d=[MoveTo(x=322.0, y=413.36), HorizontalLineToRel(dx=35.34)], + d=[MoveTo(x=-78.0, y=-13.36), HorizontalLineToRel(dx=35.34)], ), ), ( @@ -251,20 +238,10 @@ def test_points_to_svg_path( stroke_width=1.5, stroke_dasharray=[4], vector_effect="non-scaling-stroke", - points=[391.16, 458.2, 391.16, 419.64, 424.28, 419.64, 424.28, 458.2], + points=[-8.84, -58.2, -8.84, -19.64, 24.28, -19.64, 24.28, -58.2], ), ), ], ) def test_get_svg_subset(subset: MapSubsetEvent, expected: Path | Polygon) -> None: - manipulation = MapManipulation( - AxisManipulation( - map_shift=0, - svg_max=1000, - ), - AxisManipulation( - map_shift=0, - svg_max=1000, - ), - ) - assert _get_svg_subset(subset, manipulation) == expected + assert _get_svg_subset(subset) == expected From 73a7121dc2c09a237d5b4979782be911364db963 Mon Sep 17 00:00:00 2001 From: Filip Rutkowski Date: Sat, 24 Feb 2024 17:15:41 +0000 Subject: [PATCH 2/5] Add test for Map._get_svg_positions --- tests/test_map.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/test_map.py b/tests/test_map.py index 8ddc7df3..af820c83 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -16,6 +16,7 @@ PathData, Polygon, SmoothCubicBezierRel, + Use, VerticalLineToRel, ViewBoxSpec, ) @@ -40,6 +41,7 @@ TracePoint, _calc_point, _calc_point_in_viewbox, + _get_svg_positions, _get_svg_subset, _points_to_svg_path, ) @@ -245,3 +247,51 @@ def test_points_to_svg_path( ) def test_get_svg_subset(subset: MapSubsetEvent, expected: Path | Polygon) -> None: assert _get_svg_subset(subset) == expected + + +_test_get_svg_positions_data = [ + ( + [Position(PositionType.CHARGER, 5000, -55000)], + ViewBoxSpec(-500, -500, 1000, 1000), + [Use(href="#c", x=100, y=500)], + ), + ( + [Position(PositionType.DEEBOT, 15000, 15000)], + ViewBoxSpec(-500, -500, 1000, 1000), + [Use(href="#d", x=300, y=-300)], + ), + ( + [ + Position(PositionType.CHARGER, 25000, 55000), + Position(PositionType.DEEBOT, -5000, -50000), + ], + ViewBoxSpec(-500, -500, 1000, 1000), + [Use(href="#d", x=-100, y=500), Use(href="#c", x=500, y=-500)], + ), + ( + [ + Position(PositionType.DEEBOT, -10000, 10000), + Position(PositionType.CHARGER, 50000, 5000), + ], + ViewBoxSpec(-500, -500, 1000, 1000), + [Use(href="#d", x=-200, y=-200), Use(href="#c", x=500, y=-100)], + ), +] + + +@pytest.mark.parametrize( + ("positions", "viewbox", "expected"), _test_get_svg_positions_data +) +def test_get_svg_positions( + positions: list[Position], + viewbox: ViewBoxSpec, + expected: list[Use], +) -> None: + result = _get_svg_positions(positions, viewbox) + assert len(result) == len(expected) + for result_item, expected_item in zip(result, expected, strict=True): + assert type(result_item) == Use + assert result_item.href == expected_item.href + assert result_item.x == expected_item.x + assert result_item.y == expected_item.y + assert result_item == expected_item From 4ce9449ddb2b3e563d901fe3dcba48915f35c1df Mon Sep 17 00:00:00 2001 From: Filip Rutkowski Date: Mon, 6 May 2024 19:40:56 +0000 Subject: [PATCH 3/5] Add test for deebot_client.Map._get_svg_traces_path --- deebot_client/map.py | 6 +++--- tests/test_map.py | 31 ++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/deebot_client/map.py b/deebot_client/map.py index 21be6361..41fa1734 100644 --- a/deebot_client/map.py +++ b/deebot_client/map.py @@ -17,6 +17,7 @@ from PIL import Image, ImageColor, ImageOps, ImagePalette import svg +from deebot_client import util from deebot_client.events.map import CachedMapInfoEvent, MapChangedEvent from .commands.json import GetMinorMap @@ -38,7 +39,6 @@ from .util import ( OnChangedDict, OnChangedList, - decompress_7z_base64_data, ) if TYPE_CHECKING: @@ -385,7 +385,7 @@ async def on_map_subset(event: MapSubsetEvent) -> None: def _update_trace_points(self, data: str) -> None: _LOGGER.debug("[_update_trace_points] Begin") - trace_points = decompress_7z_base64_data(data) + trace_points = util.decompress_7z_base64_data(data) for i in range(0, len(trace_points), 5): position_x, position_y = struct.unpack(" Image.Image: def update_points(self, base64_data: str) -> None: """Add map piece points.""" - decoded = decompress_7z_base64_data(base64_data) + decoded = util.decompress_7z_base64_data(base64_data) old_crc32 = self._crc32 self._crc32 = zlib.crc32(decoded) diff --git a/tests/test_map.py b/tests/test_map.py index af820c83..087dbbb8 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -2,7 +2,7 @@ import asyncio from typing import TYPE_CHECKING -from unittest.mock import ANY, AsyncMock, Mock, call +from unittest.mock import ANY, AsyncMock, Mock, call, patch import pytest from svg import ( @@ -15,6 +15,7 @@ MoveToRel, PathData, Polygon, + Scale, SmoothCubicBezierRel, Use, VerticalLineToRel, @@ -155,6 +156,34 @@ async def on_change() -> None: assert not map._unsubscribers +@patch( + "deebot_client.util.decompress_7z_base64_data", + Mock(return_value=b"\x10\x00\x00\x01\x00"), +) +async def test_Map_svg_traces_path( + execute_mock: AsyncMock, event_bus_mock: Mock +) -> None: + map = Map(execute_mock, event_bus_mock) + + path = map._get_svg_traces_path() + assert path is None + + map._update_trace_points("") + path = map._get_svg_traces_path() + + assert path == Path( + fill="none", + stroke="#fff", + stroke_width=1.5, + stroke_linejoin="round", + vector_effect="non-scaling-stroke", + transform=[ + Scale(0.2, -0.2), + ], + d=[MoveTo(x=16, y=256)], + ) + + def test_compact_path() -> None: """Test that the path is compacted correctly.""" path = Path( From d6463b57e4f63f97a38843f8eb45bebbe15bec53 Mon Sep 17 00:00:00 2001 From: Robert Resch Date: Thu, 30 May 2024 09:09:19 +0200 Subject: [PATCH 4/5] Apply suggestions from code review --- deebot_client/map.py | 10 +++------- tests/test_map.py | 20 +++++++------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/deebot_client/map.py b/deebot_client/map.py index 41fa1734..dc938b7e 100644 --- a/deebot_client/map.py +++ b/deebot_client/map.py @@ -269,11 +269,7 @@ def _get_svg_positions( for position in sorted(positions, key=lambda x: _POSITIONS_SVG[x.type].order): pos = _calc_point_in_viewbox(position.x, position.y, viewbox) svg_positions.append( - svg.Use( - href=f"#{_POSITIONS_SVG[position.type].svg_id}", - x=pos.x, - y=pos.y, - ) + svg.Use(href=f"#{_POSITIONS_SVG[position.type].svg_id}", x=pos.x, y=pos.y) ) return svg_positions @@ -385,7 +381,7 @@ async def on_map_subset(event: MapSubsetEvent) -> None: def _update_trace_points(self, data: str) -> None: _LOGGER.debug("[_update_trace_points] Begin") - trace_points = util.decompress_7z_base64_data(data) + trace_points = decompress_7z_base64_data(data) for i in range(0, len(trace_points), 5): position_x, position_y = struct.unpack(" Image.Image: def update_points(self, base64_data: str) -> None: """Add map piece points.""" - decoded = util.decompress_7z_base64_data(base64_data) + decoded = decompress_7z_base64_data(base64_data) old_crc32 = self._crc32 self._crc32 = zlib.crc32(decoded) diff --git a/tests/test_map.py b/tests/test_map.py index 4231f2a0..16126079 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -280,27 +280,27 @@ def test_get_svg_subset(subset: MapSubsetEvent, expected: Path | Polygon) -> Non _test_get_svg_positions_data = [ ( - [Position(PositionType.CHARGER, 5000, -55000)], + [Position(PositionType.CHARGER, 5000, -55000, 0)], ViewBoxSpec(-500, -500, 1000, 1000), [Use(href="#c", x=100, y=500)], ), ( - [Position(PositionType.DEEBOT, 15000, 15000)], + [Position(PositionType.DEEBOT, 15000, 15000, 0)], ViewBoxSpec(-500, -500, 1000, 1000), [Use(href="#d", x=300, y=-300)], ), ( [ - Position(PositionType.CHARGER, 25000, 55000), - Position(PositionType.DEEBOT, -5000, -50000), + Position(PositionType.CHARGER, 25000, 55000, 0), + Position(PositionType.DEEBOT, -5000, -50000, 0), ], ViewBoxSpec(-500, -500, 1000, 1000), [Use(href="#d", x=-100, y=500), Use(href="#c", x=500, y=-500)], ), ( [ - Position(PositionType.DEEBOT, -10000, 10000), - Position(PositionType.CHARGER, 50000, 5000), + Position(PositionType.DEEBOT, -10000, 10000, 0), + Position(PositionType.CHARGER, 50000, 5000, 0), ], ViewBoxSpec(-500, -500, 1000, 1000), [Use(href="#d", x=-200, y=-200), Use(href="#c", x=500, y=-100)], @@ -317,10 +317,4 @@ def test_get_svg_positions( expected: list[Use], ) -> None: result = _get_svg_positions(positions, viewbox) - assert len(result) == len(expected) - for result_item, expected_item in zip(result, expected, strict=True): - assert type(result_item) == Use - assert result_item.href == expected_item.href - assert result_item.x == expected_item.x - assert result_item.y == expected_item.y - assert result_item == expected_item + assert result == expected From 6cca195f3063f13a417ca5f45c8351bf53f4be4d Mon Sep 17 00:00:00 2001 From: Robert Resch Date: Thu, 30 May 2024 07:36:40 +0000 Subject: [PATCH 5/5] Some optimations --- deebot_client/map.py | 30 +++++++++++++++++++++--------- tests/test_map.py | 15 ++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/deebot_client/map.py b/deebot_client/map.py index dc938b7e..57226edf 100644 --- a/deebot_client/map.py +++ b/deebot_client/map.py @@ -17,7 +17,6 @@ from PIL import Image, ImageColor, ImageOps, ImagePalette import svg -from deebot_client import util from deebot_client.events.map import CachedMapInfoEvent, MapChangedEvent from .commands.json import GetMinorMap @@ -39,6 +38,7 @@ from .util import ( OnChangedDict, OnChangedList, + decompress_7z_base64_data, ) if TYPE_CHECKING: @@ -163,6 +163,18 @@ class BackgroundImage: image: bytes +class ViewBoxFloat: + """ViewBox where all values are converted to float.""" + + def __init__(self, view_box: svg.ViewBoxSpec) -> None: + self.min_x = float(view_box.min_x) + self.min_y = float(view_box.min_y) + self.width = float(view_box.width) + self.height = float(view_box.height) + self.max_x = self.min_x + self.width + self.max_y = self.min_y + self.height + + # SVG definitions referred by map elements _SVG_DEFS = svg.Defs( elements=[ @@ -221,16 +233,16 @@ def _calc_point( ) -def _calc_point_in_viewbox(x: float, y: float, viewbox: svg.ViewBoxSpec) -> Point: +def _calc_point_in_viewbox(x: float, y: float, view_box: ViewBoxFloat) -> Point: point = _calc_point(x, y) return Point( min( - max(point.x, float(viewbox.min_x)), - float(viewbox.min_x) + float(viewbox.width), + max(point.x, view_box.min_x), + view_box.max_x, ), min( - max(point.y, float(viewbox.min_y)), - float(viewbox.min_y) + float(viewbox.height), + max(point.y, view_box.min_y), + view_box.max_y, ), ) @@ -263,11 +275,11 @@ def _points_to_svg_path( def _get_svg_positions( - positions: list[Position], viewbox: svg.ViewBoxSpec + positions: list[Position], view_box: ViewBoxFloat ) -> list[svg.Element]: svg_positions: list[svg.Element] = [] for position in sorted(positions, key=lambda x: _POSITIONS_SVG[x.type].order): - pos = _calc_point_in_viewbox(position.x, position.y, viewbox) + pos = _calc_point_in_viewbox(position.x, position.y, view_box) svg_positions.append( svg.Use(href=f"#{_POSITIONS_SVG[position.type].svg_id}", x=pos.x, y=pos.y) ) @@ -559,7 +571,7 @@ def get_svg_map(self) -> str | None: # Bot and Charge stations svg_map.elements.extend( - _get_svg_positions(self._map_data.positions, svg_map.viewBox) + _get_svg_positions(self._map_data.positions, ViewBoxFloat(svg_map.viewBox)) ) self._last_image = str(svg_map) diff --git a/tests/test_map.py b/tests/test_map.py index 16126079..8376aba2 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -40,6 +40,7 @@ Path, Point, TracePoint, + ViewBoxFloat, _calc_point, _calc_point_in_viewbox, _get_svg_positions, @@ -81,15 +82,15 @@ def test_calc_point( @pytest.mark.parametrize( - ("x", "y", "viewbox", "expected"), _test_calc_point_in_viewbox_data + ("x", "y", "view_box", "expected"), _test_calc_point_in_viewbox_data ) def test_calc_point_in_viewbox( x: int, y: int, - viewbox: ViewBoxSpec, + view_box: ViewBoxSpec, expected: Point, ) -> None: - result = _calc_point_in_viewbox(x, y, viewbox) + result = _calc_point_in_viewbox(x, y, ViewBoxFloat(view_box)) assert result == expected @@ -157,7 +158,7 @@ async def on_change() -> None: @patch( - "deebot_client.util.decompress_7z_base64_data", + "deebot_client.map.decompress_7z_base64_data", Mock(return_value=b"\x10\x00\x00\x01\x00"), ) async def test_Map_svg_traces_path( @@ -309,12 +310,12 @@ def test_get_svg_subset(subset: MapSubsetEvent, expected: Path | Polygon) -> Non @pytest.mark.parametrize( - ("positions", "viewbox", "expected"), _test_get_svg_positions_data + ("positions", "view_box", "expected"), _test_get_svg_positions_data ) def test_get_svg_positions( positions: list[Position], - viewbox: ViewBoxSpec, + view_box: ViewBoxSpec, expected: list[Use], ) -> None: - result = _get_svg_positions(positions, viewbox) + result = _get_svg_positions(positions, ViewBoxFloat(view_box)) assert result == expected