valetudo-map-parser 0.1.9b52__py3-none-any.whl → 0.1.9b53__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -492,10 +492,20 @@ class ColorsManagement:
492
492
  background = tuple(map(int, array[y, x]))
493
493
 
494
494
  # Update cache (with simple LRU-like behavior)
495
- if len(cache) >= ColorsManagement._cache_size:
496
- # Remove a random entry if cache is full
497
- cache.pop(next(iter(cache)))
498
- cache[cache_key] = background
495
+ try:
496
+ if len(cache) >= ColorsManagement._cache_size:
497
+ # Remove a random entry if cache is full
498
+ if cache: # Make sure cache is not empty
499
+ cache.pop(next(iter(cache)))
500
+ else:
501
+ # If cache is somehow empty but len reported >= _cache_size
502
+ # This is an edge case that shouldn't happen but we handle it
503
+ pass
504
+ cache[cache_key] = background
505
+ except KeyError:
506
+ # If we encounter a KeyError, reset the cache
507
+ # This is a rare edge case that might happen in concurrent access
508
+ ColorsManagement._bg_color_cache = {cache_key: background}
499
509
 
500
510
  except (IndexError, ValueError):
501
511
  return foreground
@@ -57,9 +57,6 @@ class Drawable:
57
57
  # Extract alpha from color
58
58
  alpha = color[3] if len(color) == 4 else 255
59
59
 
60
- # For debugging
61
- _LOGGER.debug("Drawing with color %s and alpha %s", color, alpha)
62
-
63
60
  # Create the full color with alpha
64
61
  full_color = color if len(color) == 4 else (*color, 255)
65
62
 
@@ -38,48 +38,130 @@ class HypferRoomsHandler:
38
38
  """
39
39
  self.vacuum_id = vacuum_id
40
40
  self.drawing_config = drawing_config
41
+ self.current_json_data = None # Will store the current JSON data being processed
41
42
 
42
43
  @staticmethod
43
44
  def sublist(data: list, chunk_size: int) -> list:
44
45
  return [data[i : i + chunk_size] for i in range(0, len(data), chunk_size)]
45
46
 
47
+ # Cache for RDP results
48
+ _rdp_cache = {}
49
+
46
50
  @staticmethod
47
51
  def perpendicular_distance(
48
52
  point: tuple[int, int], line_start: tuple[int, int], line_end: tuple[int, int]
49
53
  ) -> float:
50
- """Calculate the perpendicular distance from a point to a line."""
54
+ """Calculate the perpendicular distance from a point to a line.
55
+ Optimized for performance.
56
+ """
57
+ # Fast path for point-to-point distance
51
58
  if line_start == line_end:
52
- return sqrt(
53
- (point[0] - line_start[0]) ** 2 + (point[1] - line_start[1]) ** 2
54
- )
59
+ dx = point[0] - line_start[0]
60
+ dy = point[1] - line_start[1]
61
+ return sqrt(dx*dx + dy*dy)
55
62
 
56
63
  x, y = point
57
64
  x1, y1 = line_start
58
65
  x2, y2 = line_end
59
66
 
60
- # Calculate the line length
61
- line_length = sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
62
- if line_length == 0:
67
+ # Precompute differences for efficiency
68
+ dx = x2 - x1
69
+ dy = y2 - y1
70
+
71
+ # Calculate the line length squared (avoid sqrt until needed)
72
+ line_length_sq = dx*dx + dy*dy
73
+ if line_length_sq == 0:
63
74
  return 0
64
75
 
65
76
  # Calculate the distance from the point to the line
66
- return abs((y2 - y1) * x - (x2 - x1) * y + x2 * y1 - y2 * x1) / line_length
77
+ # Using the formula: |cross_product| / |line_vector|
78
+ # This is more efficient than the original formula
79
+ cross_product = abs(dy * x - dx * y + x2 * y1 - y2 * x1)
80
+ return cross_product / sqrt(line_length_sq)
67
81
 
68
82
  async def rdp(
69
83
  self, points: List[Tuple[int, int]], epsilon: float
70
84
  ) -> List[Tuple[int, int]]:
71
- """Ramer-Douglas-Peucker algorithm for simplifying a curve."""
85
+ """Ramer-Douglas-Peucker algorithm for simplifying a curve.
86
+ Optimized with caching and better performance.
87
+ """
88
+ # Create a hashable key for caching
89
+ # Convert points to a tuple for hashing
90
+ points_tuple = tuple(points)
91
+ cache_key = (points_tuple, epsilon)
92
+
93
+ # Check cache first
94
+ if cache_key in self._rdp_cache:
95
+ return self._rdp_cache[cache_key]
96
+
97
+ # Base case
72
98
  if len(points) <= 2:
73
99
  return points
74
100
 
75
- # Find the point with the maximum distance
76
- dmax = 0
77
- index = 0
78
- for i in range(1, len(points) - 1):
79
- d = self.perpendicular_distance(points[i], points[0], points[-1])
80
- if d > dmax:
81
- index = i
82
- dmax = d
101
+ # For very small point sets, process directly without recursion
102
+ if len(points) <= 5:
103
+ # Find the point with the maximum distance
104
+ dmax = 0
105
+ index = 0
106
+ for i in range(1, len(points) - 1):
107
+ d = self.perpendicular_distance(points[i], points[0], points[-1])
108
+ if d > dmax:
109
+ index = i
110
+ dmax = d
111
+
112
+ # If max distance is greater than epsilon, keep the point
113
+ if dmax > epsilon:
114
+ result = [points[0]] + [points[index]] + [points[-1]]
115
+ else:
116
+ result = [points[0], points[-1]]
117
+
118
+ # Cache and return
119
+ self._rdp_cache[cache_key] = result
120
+ return result
121
+
122
+ # For larger point sets, use numpy for faster distance calculation
123
+ if len(points) > 20:
124
+ # Convert to numpy arrays for vectorized operations
125
+ points_array = np.array(points)
126
+ start = points_array[0]
127
+ end = points_array[-1]
128
+
129
+ # Calculate perpendicular distances in one vectorized operation
130
+ line_vector = end - start
131
+ line_length = np.linalg.norm(line_vector)
132
+
133
+ if line_length == 0:
134
+ # If start and end are the same, use direct distance
135
+ distances = np.linalg.norm(points_array[1:-1] - start, axis=1)
136
+ else:
137
+ # Normalize line vector
138
+ line_vector = line_vector / line_length
139
+ # Calculate perpendicular distances using vector operations
140
+ vectors_to_points = points_array[1:-1] - start
141
+ # Project vectors onto line vector
142
+ projections = np.dot(vectors_to_points, line_vector)
143
+ # Calculate projected points on line
144
+ projected_points = start + np.outer(projections, line_vector)
145
+ # Calculate distances from points to their projections
146
+ distances = np.linalg.norm(points_array[1:-1] - projected_points, axis=1)
147
+
148
+ # Find the point with maximum distance
149
+ if len(distances) > 0:
150
+ max_idx = np.argmax(distances)
151
+ dmax = distances[max_idx]
152
+ index = max_idx + 1 # +1 because we skipped the first point
153
+ else:
154
+ dmax = 0
155
+ index = 0
156
+ else:
157
+ # For medium-sized point sets, use the original algorithm
158
+ dmax = 0
159
+ index = 0
160
+ for i in range(1, len(points) - 1):
161
+ d = self.perpendicular_distance(points[i], points[0], points[-1])
162
+ if d > dmax:
163
+ index = i
164
+ dmax = d
83
165
 
84
166
  # If max distance is greater than epsilon, recursively simplify
85
167
  if dmax > epsilon:
@@ -88,9 +170,23 @@ class HypferRoomsHandler:
88
170
  second_segment = await self.rdp(points[index:], epsilon)
89
171
 
90
172
  # Build the result list (avoiding duplicating the common point)
91
- return first_segment[:-1] + second_segment
173
+ result = first_segment[:-1] + second_segment
92
174
  else:
93
- return [points[0], points[-1]]
175
+ result = [points[0], points[-1]]
176
+
177
+ # Limit cache size
178
+ if len(self._rdp_cache) > 100: # Keep only 100 most recent items
179
+ try:
180
+ self._rdp_cache.pop(next(iter(self._rdp_cache)))
181
+ except (StopIteration, KeyError):
182
+ pass
183
+
184
+ # Cache the result
185
+ self._rdp_cache[cache_key] = result
186
+ return result
187
+
188
+ # Cache for corner results
189
+ _corners_cache = {}
94
190
 
95
191
  async def async_get_corners(
96
192
  self, mask: np.ndarray, epsilon_factor: float = 0.05
@@ -98,6 +194,7 @@ class HypferRoomsHandler:
98
194
  """
99
195
  Get the corners of a room shape as a list of (x, y) tuples.
100
196
  Uses contour detection and Douglas-Peucker algorithm to simplify the contour.
197
+ Optimized with caching and faster calculations.
101
198
 
102
199
  Args:
103
200
  mask: Binary mask of the room (1 for room, 0 for background)
@@ -106,7 +203,18 @@ class HypferRoomsHandler:
106
203
  Returns:
107
204
  List of (x, y) tuples representing the corners of the room
108
205
  """
109
- # Find contours in the mask
206
+ # Create a hash of the mask and epsilon factor for caching
207
+ mask_hash = hash((mask.tobytes(), epsilon_factor))
208
+
209
+ # Check if we have a cached result
210
+ if mask_hash in self._corners_cache:
211
+ return self._corners_cache[mask_hash]
212
+
213
+ # Fast path for empty masks
214
+ if not np.any(mask):
215
+ return []
216
+
217
+ # Find contours in the mask - this uses our optimized method with caching
110
218
  contour = await self.async_moore_neighbor_trace(mask)
111
219
 
112
220
  if not contour:
@@ -118,7 +226,7 @@ class HypferRoomsHandler:
118
226
  x_min, x_max = np.min(x_indices), np.max(x_indices)
119
227
  y_min, y_max = np.min(y_indices), np.max(y_indices)
120
228
 
121
- return [
229
+ result = [
122
230
  (x_min, y_min), # Top-left
123
231
  (x_max, y_min), # Top-right
124
232
  (x_max, y_max), # Bottom-right
@@ -126,12 +234,28 @@ class HypferRoomsHandler:
126
234
  (x_min, y_min), # Back to top-left to close the polygon
127
235
  ]
128
236
 
129
- # Calculate the perimeter of the contour
130
- perimeter = 0
131
- for i in range(len(contour) - 1):
132
- x1, y1 = contour[i]
133
- x2, y2 = contour[i + 1]
134
- perimeter += np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
237
+ # Cache the result
238
+ self._corners_cache[mask_hash] = result
239
+ return result
240
+
241
+ # For small contours (less than 10 points), skip simplification
242
+ if len(contour) <= 10:
243
+ # Ensure the contour is closed
244
+ if contour[0] != contour[-1]:
245
+ contour.append(contour[0])
246
+
247
+ # Cache and return
248
+ self._corners_cache[mask_hash] = contour
249
+ return contour
250
+
251
+ # For larger contours, calculate perimeter more efficiently using numpy
252
+ points = np.array(contour)
253
+ # Calculate differences between consecutive points
254
+ diffs = np.diff(points, axis=0)
255
+ # Calculate squared distances
256
+ squared_dists = np.sum(diffs**2, axis=1)
257
+ # Calculate perimeter as sum of distances
258
+ perimeter = np.sum(np.sqrt(squared_dists))
135
259
 
136
260
  # Apply Douglas-Peucker algorithm to simplify the contour
137
261
  epsilon = epsilon_factor * perimeter
@@ -147,7 +271,7 @@ class HypferRoomsHandler:
147
271
  LOGGER.debug(
148
272
  f"{self.vacuum_id}: Too few points in contour, using bounding box"
149
273
  )
150
- return [
274
+ result = [
151
275
  (x_min, y_min), # Top-left
152
276
  (x_max, y_min), # Top-right
153
277
  (x_max, y_max), # Bottom-right
@@ -155,16 +279,34 @@ class HypferRoomsHandler:
155
279
  (x_min, y_min), # Back to top-left to close the polygon
156
280
  ]
157
281
 
282
+ # Cache the result
283
+ self._corners_cache[mask_hash] = result
284
+ return result
285
+
158
286
  # Ensure the contour is closed
159
287
  if simplified_contour[0] != simplified_contour[-1]:
160
288
  simplified_contour.append(simplified_contour[0])
161
289
 
290
+ # Limit cache size
291
+ if len(self._corners_cache) > 50: # Keep only 50 most recent items
292
+ try:
293
+ self._corners_cache.pop(next(iter(self._corners_cache)))
294
+ except (StopIteration, KeyError):
295
+ pass
296
+
297
+ # Cache the result
298
+ self._corners_cache[mask_hash] = simplified_contour
162
299
  return simplified_contour
163
300
 
301
+ # Cache for labeled arrays to avoid redundant calculations
302
+ _label_cache = {}
303
+ _hull_cache = {}
304
+
164
305
  @staticmethod
165
306
  async def async_moore_neighbor_trace(mask: np.ndarray) -> List[Tuple[int, int]]:
166
307
  """
167
- Trace the contour of a binary mask using an optimized Moore-Neighbor tracing.
308
+ Trace the contour of a binary mask using an optimized approach.
309
+ Uses caching and simplified algorithms for better performance.
168
310
 
169
311
  Args:
170
312
  mask: Binary mask of the room (1 for room, 0 for background)
@@ -172,81 +314,129 @@ class HypferRoomsHandler:
172
314
  Returns:
173
315
  List of (x, y) tuples representing the contour
174
316
  """
175
- # Convert to uint8 and pad
176
- padded = np.pad(mask.astype(np.uint8), 1, mode="constant")
177
- height, width = padded.shape
178
-
179
- # Find the first non-zero point efficiently (scan row by row)
180
- # This is much faster than np.argwhere() for large arrays
181
- start = None
182
- for y in range(height):
183
- # Use NumPy's any() to quickly check if there are any 1s in this row
184
- if np.any(padded[y]):
185
- # Find the first 1 in this row
186
- x = np.where(padded[y] == 1)[0][0]
187
- start = (int(x), int(y))
188
- break
189
-
190
- if start is None:
317
+ # Create a hash of the mask for caching
318
+ mask_hash = hash(mask.tobytes())
319
+
320
+ # Check if we have a cached result
321
+ if mask_hash in HypferRoomsHandler._hull_cache:
322
+ return HypferRoomsHandler._hull_cache[mask_hash]
323
+
324
+ # Fast path for empty masks
325
+ if not np.any(mask):
191
326
  return []
192
327
 
193
- # Pre-compute directions
194
- directions = [
195
- (-1, -1),
196
- (-1, 0),
197
- (-1, 1),
198
- (0, 1),
199
- (1, 1),
200
- (1, 0),
201
- (1, -1),
202
- (0, -1),
203
- ]
204
-
205
- # Use a 2D array for visited tracking (faster than set)
206
- visited = np.zeros((height, width), dtype=bool)
207
-
208
- # Initialize contour
209
- contour = []
210
- contour.append((int(start[0] - 1), int(start[1] - 1))) # Adjust for padding
211
-
212
- current = start
213
- prev_dir = 7
214
- visited[current[1], current[0]] = True
215
-
216
- # Main tracing loop
217
- while True:
218
- found = False
219
-
220
- # Check all 8 directions
221
- for i in range(8):
222
- dir_idx = (prev_dir + i) % 8
223
- dx, dy = directions[dir_idx]
224
- nx, ny = current[0] + dx, current[1] + dy
225
-
226
- # Bounds check and value check
227
- if (
228
- 0 <= ny < height
229
- and 0 <= nx < width
230
- and padded[ny, nx] == 1
231
- and not visited[ny, nx]
232
- ):
233
- current = (nx, ny)
234
- visited[ny, nx] = True
235
- contour.append(
236
- (int(nx - 1), int(ny - 1))
237
- ) # Adjust for padding and convert to int
238
- prev_dir = (dir_idx + 5) % 8
239
- found = True
240
- break
241
-
242
- # Check termination conditions
243
- if not found or (
244
- len(contour) > 3
245
- and (int(current[0] - 1), int(current[1] - 1)) == contour[0]
246
- ):
247
- break
248
-
249
- return contour
328
+ # Find bounding box of non-zero elements (much faster than full labeling for simple cases)
329
+ y_indices, x_indices = np.where(mask > 0)
330
+ if len(x_indices) == 0 or len(y_indices) == 0:
331
+ return []
332
+
333
+ # For very small rooms (less than 100 pixels), just use bounding box
334
+ if len(x_indices) < 100:
335
+ x_min, x_max = np.min(x_indices), np.max(x_indices)
336
+ y_min, y_max = np.min(y_indices), np.max(y_indices)
337
+
338
+ # Create a simple rectangle
339
+ hull_vertices = [
340
+ (int(x_min), int(y_min)), # Top-left
341
+ (int(x_max), int(y_min)), # Top-right
342
+ (int(x_max), int(y_max)), # Bottom-right
343
+ (int(x_min), int(y_max)), # Bottom-left
344
+ (int(x_min), int(y_min)), # Back to top-left to close the polygon
345
+ ]
346
+
347
+ # Cache and return the result
348
+ HypferRoomsHandler._hull_cache[mask_hash] = hull_vertices
349
+ return hull_vertices
350
+
351
+ # For larger rooms, use convex hull but with optimizations
352
+ try:
353
+ # Import here to avoid overhead for small rooms
354
+ from scipy import ndimage
355
+ from scipy.spatial import ConvexHull
356
+
357
+ # Use cached labeled array if available
358
+ if mask_hash in HypferRoomsHandler._label_cache:
359
+ labeled_array = HypferRoomsHandler._label_cache[mask_hash]
360
+ else:
361
+ # Find connected components - this is expensive
362
+ labeled_array, _ = ndimage.label(mask)
363
+ # Cache the result for future use
364
+ HypferRoomsHandler._label_cache[mask_hash] = labeled_array
365
+
366
+ # Limit cache size to prevent memory issues
367
+ if len(HypferRoomsHandler._label_cache) > 50: # Keep only 50 most recent items
368
+ # Remove oldest item (first key)
369
+ try:
370
+ HypferRoomsHandler._label_cache.pop(next(iter(HypferRoomsHandler._label_cache)))
371
+ except (StopIteration, KeyError):
372
+ # Handle edge case of empty cache
373
+ pass
374
+
375
+ # Create a mask with all components
376
+ all_components_mask = (labeled_array > 0)
377
+
378
+ # Sample points instead of using all points for large masks
379
+ # This significantly reduces computation time for ConvexHull
380
+ if len(x_indices) > 1000:
381
+ # Sample every 10th point for very large rooms
382
+ step = 10
383
+ elif len(x_indices) > 500:
384
+ # Sample every 5th point for medium-sized rooms
385
+ step = 5
386
+ else:
387
+ # Use all points for smaller rooms
388
+ step = 1
389
+
390
+ # Sample points using the step size
391
+ sampled_y = y_indices[::step]
392
+ sampled_x = x_indices[::step]
393
+
394
+ # Create a list of points
395
+ points = np.column_stack((sampled_x, sampled_y))
396
+
397
+ # Compute the convex hull
398
+ hull = ConvexHull(points)
399
+
400
+ # Extract the vertices of the convex hull
401
+ hull_vertices = [(int(points[v, 0]), int(points[v, 1])) for v in hull.vertices]
402
+
403
+ # Ensure the hull is closed
404
+ if hull_vertices[0] != hull_vertices[-1]:
405
+ hull_vertices.append(hull_vertices[0])
406
+
407
+ # Cache and return the result
408
+ HypferRoomsHandler._hull_cache[mask_hash] = hull_vertices
409
+
410
+ # Limit hull cache size
411
+ if len(HypferRoomsHandler._hull_cache) > 50:
412
+ try:
413
+ HypferRoomsHandler._hull_cache.pop(next(iter(HypferRoomsHandler._hull_cache)))
414
+ except (StopIteration, KeyError):
415
+ pass
416
+
417
+ return hull_vertices
418
+
419
+ except Exception as e:
420
+ LOGGER.warning(f"Failed to compute convex hull: {e}. Falling back to bounding box.")
421
+
422
+ # Fallback to bounding box if convex hull fails
423
+ x_min, x_max = np.min(x_indices), np.max(x_indices)
424
+ y_min, y_max = np.min(y_indices), np.max(y_indices)
425
+
426
+ # Create a simple rectangle
427
+ hull_vertices = [
428
+ (int(x_min), int(y_min)), # Top-left
429
+ (int(x_max), int(y_min)), # Top-right
430
+ (int(x_max), int(y_max)), # Bottom-right
431
+ (int(x_min), int(y_max)), # Bottom-left
432
+ (int(x_min), int(y_min)), # Back to top-left to close the polygon
433
+ ]
434
+
435
+ # Cache and return the result
436
+ HypferRoomsHandler._hull_cache[mask_hash] = hull_vertices
437
+ return hull_vertices
438
+
439
+
250
440
 
251
441
  async def async_extract_room_properties(
252
442
  self, json_data: Dict[str, Any]
@@ -267,6 +457,9 @@ class HypferRoomsHandler:
267
457
  vacuum_id = self.vacuum_id
268
458
  room_id_counter = 0
269
459
 
460
+ # Store the JSON data for reference in other methods
461
+ self.current_json_data = json_data
462
+
270
463
  for layer in json_data.get("layers", []):
271
464
  if layer.get("__class") == "MapLayer" and layer.get("type") == "segment":
272
465
  meta_data = layer.get("metaData", {})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: valetudo-map-parser
3
- Version: 0.1.9b52
3
+ Version: 0.1.9b53
4
4
  Summary: A Python library to parse Valetudo map data returning a PIL Image object.
5
5
  License: Apache-2.0
6
6
  Author: Sandro Cantarella
@@ -2,8 +2,8 @@ valetudo_map_parser/__init__.py,sha256=cewtLadNSOg3X2Ts2SuG8mTJqo0ncsFRg_sQ4VkM4
2
2
  valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
3
3
  valetudo_map_parser/config/auto_crop.py,sha256=6OvRsWzXMXBaSEvgwpaaisNdozDKiDyTmPjknFxoUMc,12624
4
4
  valetudo_map_parser/config/color_utils.py,sha256=D4NXRhuPdQ7UDKM3vLNYR0HnACl9AB75EnfCp5tGliI,4502
5
- valetudo_map_parser/config/colors.py,sha256=5nk8QbNomv_WeE2rOLIswroGsxV4RZMd0slXrPlt-MY,29297
6
- valetudo_map_parser/config/drawable.py,sha256=VhaNK62EBCxcQdNg7-dyUNepsYX6IFzej3raOt7_rVU,34268
5
+ valetudo_map_parser/config/colors.py,sha256=LE7sl4Qy0TkxbkjgB3dotYIfXqhc-fllkFQxexVvUvg,29909
6
+ valetudo_map_parser/config/drawable.py,sha256=qenuxD1-Vvyus9o8alJFYRqL54aO3pakMqPSYNGvpe8,34169
7
7
  valetudo_map_parser/config/drawable_elements.py,sha256=bkEwdbx1upt9vaPaqE_VR1rtwRsaiH-IVKc3mHNa8IY,12065
8
8
  valetudo_map_parser/config/enhanced_drawable.py,sha256=6yGoOq_dLf2VCghO_URSyGfLAshFyzS3iEPeHw1PeDo,12586
9
9
  valetudo_map_parser/config/optimized_element_map.py,sha256=52BCnkvVv9bre52LeVIfT8nhnEIpc0TuWTv1xcNu0Rk,15744
@@ -14,13 +14,13 @@ valetudo_map_parser/config/types.py,sha256=e-eZSwbPm3m5JfCDaKhnUFspmcRFSv74huxeg
14
14
  valetudo_map_parser/config/utils.py,sha256=RsMjpjVqNbkI502yhLiRaB0GjCADqmRRcz-TkC6zklQ,31073
15
15
  valetudo_map_parser/hypfer_draw.py,sha256=P8CrKysLaBb63ZArfqxN2Og6JCU6sPHPFHOte5noCGg,26654
16
16
  valetudo_map_parser/hypfer_handler.py,sha256=WYFrp-q5wBsy0cTcVQUCXXVGTtW30z2W2dYvjKz2el8,23292
17
- valetudo_map_parser/hypfer_rooms_handler.py,sha256=3QL8QZc6aMXxYn_L6gv1iL204I0rAzutWPVzc_4MfJ4,14505
17
+ valetudo_map_parser/hypfer_rooms_handler.py,sha256=NkpOA6Gdq-2D3lLAxvtNuuWMvPXHxeMY2TO5RZLSHlU,22652
18
18
  valetudo_map_parser/map_data.py,sha256=zQKE8EzWxR0r0qyfD1QQq51T1wFrpcIeXtnpm92-LXQ,17743
19
19
  valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  valetudo_map_parser/rand25_handler.py,sha256=eLFX_gmGLaWQwvp8hVj8CgcNOfLsYNIdE1OLRcQy_yM,19988
21
21
  valetudo_map_parser/reimg_draw.py,sha256=1q8LkNTPHEA9Tsapc_JnVw51kpPYNhaBU-KmHkefCQY,12507
22
- valetudo_map_parser-0.1.9b52.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
23
- valetudo_map_parser-0.1.9b52.dist-info/METADATA,sha256=jd0uF9vdxA_LxkXlWoLtOCyWvXJD3knHXVTQYDNn3E4,3321
24
- valetudo_map_parser-0.1.9b52.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
25
- valetudo_map_parser-0.1.9b52.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
26
- valetudo_map_parser-0.1.9b52.dist-info/RECORD,,
22
+ valetudo_map_parser-0.1.9b53.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
23
+ valetudo_map_parser-0.1.9b53.dist-info/METADATA,sha256=i8nDujD2s2Qs62WwEv-3AIO23XJTvxvSZXY5QcswEtc,3321
24
+ valetudo_map_parser-0.1.9b53.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
25
+ valetudo_map_parser-0.1.9b53.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
26
+ valetudo_map_parser-0.1.9b53.dist-info/RECORD,,