{"version":3,"file":"index.cjs","sources":["../src/providers/mapbox.ts","../src/api.ts","../src/utils.ts","../src/features/hotelFeature.ts","../src/features/weatherFeature.ts","../src/index.ts"],"sourcesContent":["import mapboxgl, { type ControlPosition, type IControl } from \"mapbox-gl\";\nimport type { FeatureCollection, Point } from \"geojson\";\nimport type {\n  MapProvider,\n  MapProviderConfig,\n  MarkerData,\n  HeatmapData,\n  HeatmapVisibility,\n} from \"./types\";\nimport type { Viewport } from \"../types\";\n\nexport class MapboxProvider implements MapProvider {\n  private map: mapboxgl.Map | null = null;\n  private markers: mapboxgl.Marker[] = [];\n\n  private viewportChangeCallback: ((viewport: Viewport) => void) | null = null;\n  private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n  async initialize(config: MapProviderConfig): Promise<void> {\n    if (!config.accessToken) {\n      throw new Error(\"Access token is required\");\n    }\n\n    // Handle selector - remove leading '#' if present since Mapbox expects just the ID\n    const containerId = config.selector.startsWith(\"#\")\n      ? config.selector.slice(1)\n      : config.selector;\n\n    this.map = new mapboxgl.Map({\n      accessToken: config.accessToken,\n      container: containerId,\n      style: config.style || \"mapbox://styles/mapbox/streets-v12\",\n      center: config.center || [0, 0],\n      zoom: config.zoom || 8,\n    });\n\n    this.map.addControl(new mapboxgl.NavigationControl(), \"top-right\");\n    this.map.addControl(new mapboxgl.GeolocateControl(), \"top-right\");\n\n    // Wait for the map to fully load before resolving\n    return new Promise((resolve) => {\n      this.map!.on(\"load\", () => {\n        resolve();\n      });\n    });\n  }\n  addControl(control: IControl, position?: ControlPosition) {\n    this.map?.addControl(control, position);\n  }\n  setCenter(lng: number, lat: number): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    this.map.setCenter({ lng, lat });\n  }\n\n  setZoom(zoom: number): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    this.map.setZoom(zoom);\n  }\n\n  resize(): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    // Force the map to resize to fit its container\n    this.map.resize();\n  }\n\n  getViewport(): Viewport {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    const bounds = this.map.getBounds();\n    if (!bounds) {\n      throw new Error(\"Map bounds not available\");\n    }\n\n    return {\n      south: bounds.getSouth(),\n      west: bounds.getWest(),\n      north: bounds.getNorth(),\n      east: bounds.getEast(),\n      low: {\n        latitude: bounds.getSouth(),\n        longitude: bounds.getWest(),\n      },\n      high: {\n        latitude: bounds.getNorth(),\n        longitude: bounds.getEast(),\n      },\n    };\n  }\n\n  setViewport(viewport: Viewport): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    // Use BOTH low (southwest) and high (northeast) to create bounding box\n    // This ensures ALL hotels are visible on the map\n    const southwest: [number, number] = [\n      viewport.low.longitude,\n      viewport.low.latitude,\n    ];\n    const northeast: [number, number] = [\n      viewport.high.longitude,\n      viewport.high.latitude,\n    ];\n    this.map.fitBounds([southwest, northeast], {\n      padding: { top: 0, bottom: 0, left: 0, right: 0 },\n      maxZoom: 15, // Don't zoom in too much for single hotels\n      duration: 500, // Smooth animation (0.5 seconds)\n    });\n  }\n\n  onViewportChange(callback: (viewport: Viewport) => void): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    this.viewportChangeCallback = callback;\n\n    // Listen to map movement events (drag, zoom, etc.)\n    this.map.on(\"moveend\", () => {\n      // Debounce to avoid excessive calls\n      if (this.debounceTimer) {\n        clearTimeout(this.debounceTimer);\n      }\n\n      this.debounceTimer = setTimeout(() => {\n        if (this.viewportChangeCallback) {\n          const viewport = this.getViewport();\n          this.viewportChangeCallback(viewport);\n        }\n      }, 1000); // Wait 1 second after user stops moving the map\n    });\n  }\n\n  renderMarkers(markersData: MarkerData[], clearFirst: boolean = false): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n    if (clearFirst) {\n      this.clearMarkers();\n    }\n\n    const markers = markersData.map(({ element, lnglat }) => {\n      const marker = new mapboxgl.Marker({ element })\n        .setLngLat(lnglat)\n        .addTo(this.map!);\n      return marker;\n    });\n\n    this.markers = [...this.markers, ...markers];\n  }\n\n  clearMarkers(): void {\n    this.markers.forEach((marker) => marker.remove());\n    this.markers = [];\n  }\n\n  setMarkersVisibility(visible: boolean): void {\n    const display = visible ? \"\" : \"none\";\n    this.markers.forEach((marker) => {\n      const element = marker.getElement();\n      if (element) {\n        element.style.display = display;\n      }\n    });\n  }\n\n  renderHeatmap({ points, sourceId, layerId, paint }: HeatmapData): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    const geojson: FeatureCollection<Point> = {\n      type: \"FeatureCollection\",\n      features: points.map((point) => ({\n        type: \"Feature\",\n        geometry: {\n          type: \"Point\",\n          coordinates: point.lnglat,\n        },\n        properties: {\n          weight: point.weight ?? 1,\n        },\n      })),\n    };\n\n    const existingSource = this.map.getSource(sourceId) as\n      | mapboxgl.GeoJSONSource\n      | undefined;\n\n    if (existingSource) {\n      existingSource.setData(geojson);\n    } else {\n      // Default paint style if not provided\n      const defaultPaint = {\n        \"heatmap-weight\": [\n          \"interpolate\",\n          [\"linear\"],\n          [\"get\", \"weight\"],\n          0,\n          0,\n          1,\n          1,\n        ],\n        \"heatmap-intensity\": [\"interpolate\", [\"linear\"], [\"zoom\"], 0, 1, 15, 3],\n        \"heatmap-color\": [\n          \"interpolate\",\n          [\"linear\"],\n          [\"heatmap-density\"],\n          0,\n          \"rgba(0,0,255,0)\",\n          0.5,\n          \"rgb(0,255,0)\",\n          1,\n          \"rgb(255,0,0)\",\n        ],\n        \"heatmap-radius\": [\"interpolate\", [\"linear\"], [\"zoom\"], 0, 2, 9, 20],\n        \"heatmap-opacity\": [\"interpolate\", [\"linear\"], [\"zoom\"], 7, 1, 9, 0.6],\n      };\n\n      this.map.addSource(sourceId, {\n        type: \"geojson\",\n        data: geojson,\n      });\n\n      this.map.addLayer({\n        id: layerId,\n        type: \"heatmap\",\n        source: sourceId,\n        layout: {\n          visibility: \"none\",\n        },\n        paint: paint || defaultPaint,\n      });\n    }\n  }\n\n  setHeatmapVisibility({ visible, layerId }: HeatmapVisibility): void {\n    if (!this.map) {\n      throw new Error(\"Map not initialized\");\n    }\n\n    if (this.map.getLayer(layerId)) {\n      this.map.setLayoutProperty(\n        layerId,\n        \"visibility\",\n        visible ? \"visible\" : \"none\"\n      );\n    }\n  }\n\n  destroy(): void {\n    this.clearMarkers();\n\n    // Clear debounce timer\n    if (this.debounceTimer) {\n      clearTimeout(this.debounceTimer);\n      this.debounceTimer = null;\n    }\n\n    this.viewportChangeCallback = null;\n\n    if (this.map) {\n      this.map.remove();\n      this.map = null;\n    }\n  }\n}\n","/**\n * API client for fetching hotel data and weather data from the BFF\n */\n\nimport type {\n  FetchHotelsParams,\n  PlaceHotelsResponse,\n  FetchWeatherParams,\n  WeatherData,\n} from \"./types\";\n\nconst normalizeBaseURL = (url: string): string => {\n  return url.endsWith(\"/\") ? url : `${url}/`;\n};\n\n/**\n * Fetch hotels for a given place with availability and pricing\n */\nexport const fetchPlaceHotels = async (\n  params: FetchHotelsParams\n): Promise<PlaceHotelsResponse> => {\n  const { placeId, proxyBaseURL, ...requestData } = params;\n\n  // Validate required parameters\n  if (!proxyBaseURL) {\n    throw new Error(\"proxyBaseURL is required\");\n  }\n\n  if (!placeId) {\n    throw new Error(\"placeId is required\");\n  }\n \n  const baseURL = normalizeBaseURL(proxyBaseURL);\n  const url = `${baseURL}api/map/places/${placeId}/hotels`;\n\n  try {\n    const response = await fetch(url, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify(requestData),\n    });\n\n    if (!response.ok) {\n      const errorText = await response.text();\n      throw new Error(\n        `Failed to fetch hotels: ${response.status} ${response.statusText}${\n          errorText ? ` - ${errorText}` : \"\"\n        }`\n      );\n    }\n\n    const data: PlaceHotelsResponse = await response.json();\n    return data;\n  } catch (error) {\n    if (error instanceof Error) {\n      throw error;\n    }\n    throw new Error(\"Unknown error occurred while fetching hotels\");\n  }\n};\n\n/**\n * Fetch weather data for a specific location\n */\nexport const fetchWeather = async (\n  params: FetchWeatherParams\n): Promise<WeatherData> => {\n  const { latitude, longitude, proxyBaseURL } = params;\n\n  // Validate required parameters\n  if (!proxyBaseURL) {\n    throw new Error(\"proxyBaseURL is required\");\n  }\n\n  if (latitude === undefined || longitude === undefined) {\n    throw new Error(\"latitude and longitude are required\");\n  }\n\n  const baseURL = normalizeBaseURL(proxyBaseURL);\n  const url = `${baseURL}api/weather?lat=${latitude}&lon=${longitude}`;\n\n  try {\n    const response = await fetch(url, {\n      method: \"GET\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n      },\n    });\n\n    if (!response.ok) {\n      const errorText = await response.text();\n      throw new Error(\n        `Failed to fetch weather: ${response.status} ${response.statusText}${\n          errorText ? ` - ${errorText}` : \"\"\n        }`\n      );\n    }\n\n    const data: WeatherData = await response.json();\n    return data;\n  } catch (error) {\n    if (error instanceof Error) {\n      throw error;\n    }\n    throw new Error(\"Unknown error occurred while fetching weather\");\n  }\n};\n","export const getCurrencySymbol = (currency: string): string => {\n  const symbols: Record<string, string> = {\n    EUR: \"€\",\n    USD: \"$\",\n    GBP: \"£\",\n    JPY: \"¥\",\n    AUD: \"A$\",\n    CAD: \"C$\",\n    CHF: \"CHF\"\n  };\n  return symbols[currency] || currency;\n};\n","import { fetchPlaceHotels } from \"../api\";\n\nimport type { FetchHotelsParams, State, Hotel } from \"../types\";\nimport type { MapProvider, MarkerData, HeatmapPoint } from \"../providers/types\";\nimport { getCurrencySymbol } from \"../utils\";\n\nexport interface HotelFeature {\n  /**\n   * Load hotels for a place and display them on the map\n   */\n  loadHotels(params: FetchHotelsParams): Promise<void>;\n\n  /**\n   * Get currently displayed hotels\n   */\n  getHotels(): Hotel[];\n\n  /**\n   * Toggle the visibility of the heatmap layer. When `visible` is omitted,\n   * the visibility will be toggled.\n   */\n  toggleHeatmap(visible?: boolean): void;\n\n  /**\n   * Returns whether the heatmap layer is currently visible.\n   */\n  isHeatmapVisible(): boolean;\n}\n\nconst HOTEL_HEATMAP_SOURCE_ID = \"hotel-heatmap-source\";\nconst HOTEL_HEATMAP_LAYER_ID = \"hotel-heatmap-layer\";\n\n// Hotel heatmap styling - blue (low prices) to red (high prices)\nconst HOTEL_HEATMAP_PAINT = {\n  \"heatmap-weight\": [\"interpolate\", [\"linear\"], [\"get\", \"weight\"], 0, 0, 1, 1],\n  \"heatmap-intensity\": [\"interpolate\", [\"linear\"], [\"zoom\"], 0, 1, 15, 3],\n  \"heatmap-color\": [\n    \"interpolate\",\n    [\"linear\"],\n    [\"heatmap-density\"],\n    0,\n    \"rgba(33,102,172,0)\",\n    0.2,\n    \"rgb(103,169,207)\",\n    0.4,\n    \"rgb(209,229,240)\",\n    0.6,\n    \"rgb(253,219,199)\",\n    0.8,\n    \"rgb(239,138,98)\",\n    1,\n    \"rgb(178,24,43)\",\n  ],\n  \"heatmap-radius\": [\"interpolate\", [\"linear\"], [\"zoom\"], 0, 2, 9, 20],\n  \"heatmap-opacity\": [\"interpolate\", [\"linear\"], [\"zoom\"], 7, 1, 9, 0.6],\n};\n\nexport const hotelFeature = (\n  provider: MapProvider,\n  state: State\n): HotelFeature => {\n  let latestHeatmapPoints: HeatmapPoint[] = [];\n  let heatmapVisible = false;\n\n  const updateHeatmap = (points: HeatmapPoint[]) => {\n    latestHeatmapPoints = points;\n\n    provider.renderHeatmap({\n      points: latestHeatmapPoints,\n      sourceId: HOTEL_HEATMAP_SOURCE_ID,\n      layerId: HOTEL_HEATMAP_LAYER_ID,\n      paint: HOTEL_HEATMAP_PAINT,\n    });\n    syncLayers();\n  };\n\n  const syncLayers = () => {\n    const hasData = latestHeatmapPoints.length > 0;\n\n    if (!hasData) {\n      heatmapVisible = false;\n    }\n\n    const showHeatmap = heatmapVisible && hasData;\n\n    provider.setHeatmapVisibility({\n      visible: showHeatmap,\n      layerId: HOTEL_HEATMAP_LAYER_ID,\n    });\n    provider.setMarkersVisibility(!showHeatmap);\n  };\n\n  return {\n    async loadHotels(params: FetchHotelsParams) {\n      // Fetch hotels\n      const hotelData = await fetchPlaceHotels(params);\n\n      // Auto-display: set viewport and show markers\n      provider.setViewport(hotelData.viewport);\n      state.currentHotels = hotelData.hotels;\n\n      const hotelMarkers = hotelData.hotels.map((hotel) => {\n        const el = document.createElement(\"a\");\n        el.className = \"custom-marker\";\n        el.innerHTML = `${hotel.price} ${getCurrencySymbol(hotel.currency)}`;\n        el.href = hotel.deepLink;\n        el.target = \"_blank\";\n        el.title = hotel.name;\n\n        return {\n          element: el,\n          lnglat: [hotel.longitude, hotel.latitude],\n          type: \"Hotel\",\n        } as MarkerData;\n      });\n\n      provider.renderMarkers(hotelMarkers);\n      updateHeatmap(\n        hotelData.hotels.map((hotel) => ({\n          lnglat: [hotel.longitude, hotel.latitude],\n          weight: hotel.price,\n        }))\n      );\n    },\n\n    getHotels() {\n      return [...state.currentHotels];\n    },\n\n    toggleHeatmap(visible?: boolean) {\n      if (typeof visible === \"boolean\") {\n        heatmapVisible = visible;\n      } else {\n        heatmapVisible = !heatmapVisible;\n      }\n\n      syncLayers();\n    },\n\n    isHeatmapVisible() {\n      return heatmapVisible && latestHeatmapPoints.length > 0;\n    },\n  };\n};\n","import { fetchWeather } from \"../api\";\nimport type { WeatherData } from \"../types\";\nimport type { MapProvider } from \"../providers/types\";\n\nexport interface WeatherFeature {\n  loadWeather(proxyBaseURL: string): Promise<void>;\n  toggleWeatherLayer(visible: boolean): void;\n  isWeatherLayerVisible(): boolean;\n}\n\nexport class WeatherControl {\n  private container: HTMLDivElement | null = null;\n  private weatherData: WeatherData | null = null;\n\n  onAdd(): HTMLElement {\n    this.container = document.createElement(\"div\");\n    this.container.className =\n      \"mapboxgl-ctrl mapboxgl-ctrl-group weather-control\";\n    this.container.style.display = \"none\"; // Hidden by default\n    this.updateDisplay();\n    return this.container;\n  }\n\n  onRemove(): void {\n    if (this.container && this.container.parentNode) {\n      this.container.parentNode.removeChild(this.container);\n    }\n    this.container = null;\n  }\n\n  setWeather(weather: WeatherData | null): void {\n    this.weatherData = weather;\n    this.updateDisplay();\n  }\n\n  show(): void {\n    if (this.container) {\n      this.container.style.display = \"block\";\n    }\n  }\n\n  hide(): void {\n    if (this.container) {\n      this.container.style.display = \"none\";\n    }\n  }\n\n  private updateDisplay(): void {\n    if (!this.container) return;\n\n    if (this.weatherData) {\n      this.container.innerHTML = `\n        <div class=\"weather-widget\">\n          <img src=\"https://openweathermap.org/img/wn/${\n            this.weatherData.icon\n          }@2x.png\"\n               alt=\"${this.weatherData.description}\"\n               class=\"weather-icon\" />\n          <div class=\"weather-info\">\n            <div class=\"weather-temp\">${Math.round(\n              this.weatherData.temperature\n            )}°C</div>\n            <div class=\"weather-desc\">${this.weatherData.description}</div>\n            ${\n              this.weatherData.city\n                ? `<div class=\"weather-city\">${this.weatherData.city}</div>`\n                : \"\"\n            }\n          </div>\n        </div>\n      `;\n    } else {\n      this.container.innerHTML = '<div class=\"weather-widget\">Loading...</div>';\n    }\n  }\n}\n\nexport const weatherFeature = (provider: MapProvider): WeatherFeature => {\n  let currentWeather: WeatherData | null = null;\n  let weatherLayerVisible = false;\n  let proxyBaseURL: string | null = null;\n  let isAutoRefreshEnabled = false;\n  const weatherControl = new WeatherControl();\n  provider.addControl(weatherControl as any, \"top-right\");\n\n  return {\n    async loadWeather(proxyURL: string) {\n      proxyBaseURL = proxyURL;\n\n      const viewport = provider.getViewport();\n\n      const centerLat = (viewport.low.latitude + viewport.high.latitude) / 2;\n      const centerLon = (viewport.low.longitude + viewport.high.longitude) / 2;\n\n      try {\n        const weather = await fetchWeather({\n          latitude: centerLat,\n          longitude: centerLon,\n          proxyBaseURL: proxyURL,\n        });\n\n        currentWeather = weather;\n\n        // Re-render markers with weather data if layer is visible\n        if (weatherLayerVisible) {\n          this.toggleWeatherLayer(true);\n        }\n\n        // Set up auto-refresh on viewport change (only once)\n        if (!isAutoRefreshEnabled && proxyBaseURL) {\n          isAutoRefreshEnabled = true;\n          provider.onViewportChange(async () => {\n            if (weatherLayerVisible && proxyBaseURL) {\n              try {\n                await this.loadWeather(proxyBaseURL);\n              } catch (error) {\n                console.error(\n                  \"Failed to refresh weather on viewport change:\",\n                  error\n                );\n              }\n            }\n          });\n        }\n      } catch (error) {\n        console.error(\"Failed to fetch weather:\", error);\n        throw error;\n      }\n    },\n\n    toggleWeatherLayer(visible: boolean) {\n      weatherLayerVisible = visible;\n\n      const weather = visible && currentWeather ? currentWeather : undefined;\n\n      if (weather) {\n        weatherControl.setWeather(weather);\n        weatherControl.show();\n      } else {\n        weatherControl.hide();\n      }\n    },\n\n    isWeatherLayerVisible() {\n      return weatherLayerVisible;\n    },\n  };\n};\n","/**\n * LiteAPI Hotel Map SDK\n *\n * A simple SDK for displaying hotel prices on interactive maps.\n * Completely abstracts the underlying map provider.\n */\n\nimport \"mapbox-gl/dist/mapbox-gl.css\";\n  import { version } from \"../package.json\";\nimport { MapboxProvider } from \"./providers/mapbox\";\nimport type { MapInitOptions, CommonMapControls, State } from \"./types\";\nimport {\n  hotelFeature,\n  type HotelFeature,\n  weatherFeature,\n  type WeatherFeature,\n} from \"./features\";\n\n/**\n * Internal implementation of map initialization\n */\nconst mapInit = async (\n  options: MapInitOptions\n): Promise<HotelFeature & WeatherFeature & CommonMapControls> => {\n  if (!options.selector) {\n    throw new Error(\"selector is required\");\n  }\n\n  const provider = new MapboxProvider();\n\n  await provider.initialize({\n    selector: options.selector,\n    accessToken:\n      \"pk.eyJ1IjoiZmFyaGFkbmlheiIsImEiOiJjbWhkemp4emgwODBhMmlzYjcxcGd1dHN0In0.zNj_g870pLjrTpl-TjwX4w\",\n    style: options.style,\n    center: options.center,\n    zoom: options.zoom,\n  });\n\n  const state: State = { currentHotels: [] };\n\n  const hotelFeature_ = hotelFeature(provider, state);\n  const weatherFeature_ = weatherFeature(provider);\n  const commonControls: CommonMapControls = {\n    setCenter(lng: number, lat: number) {\n      provider.setCenter(lng, lat);\n    },\n\n    setZoom(zoom: number) {\n      provider.setZoom(zoom);\n    },\n\n    resize() {\n      provider.resize();\n    },\n\n    getViewport() {\n      return provider.getViewport();\n    },\n\n    destroy() {\n      provider.destroy();\n      state.currentHotels = [];\n    },\n  };\n  const controls = {\n    ...hotelFeature_,\n    ...weatherFeature_,\n    ...commonControls,\n  };\n\n  // Auto-load hotels if hotelsQuery is provided\n  if (options.hotelsQuery) {\n    await controls.loadHotels(options.hotelsQuery);\n  }\n\n  // Execute onLoad callback if provided\n  if (options.onLoad) {\n    await options.onLoad(controls);\n  }\n\n  return controls;\n};\n\nconst LiteAPI = {\n  /**\n   * Map namespace\n   */\n  Map: {\n    version,\n    init: mapInit,\n  },\n};\nexport default LiteAPI;\n\nexport { mapInit };\n\nexport type {\n  MapInitOptions,\n  CommonMapControls,\n  Hotel,\n  Occupancy,\n  Viewport,\n  FetchHotelsParams,\n  WeatherData,\n  FetchWeatherParams,\n} from \"./types\";\n\nexport { type HotelFeature, type WeatherFeature } from \"./features\";\n\nexport type { HeatmapPoint, HeatmapPaintStyle } from \"./providers/types\";\n"],"names":["MapboxProvider","config","containerId","mapboxgl","resolve","control","position","lng","lat","zoom","bounds","viewport","southwest","northeast","callback","markersData","clearFirst","markers","element","lnglat","marker","visible","display","points","sourceId","layerId","paint","geojson","point","existingSource","defaultPaint","normalizeBaseURL","url","fetchPlaceHotels","params","placeId","proxyBaseURL","requestData","response","errorText","error","fetchWeather","latitude","longitude","getCurrencySymbol","currency","HOTEL_HEATMAP_SOURCE_ID","HOTEL_HEATMAP_LAYER_ID","HOTEL_HEATMAP_PAINT","hotelFeature","provider","state","latestHeatmapPoints","heatmapVisible","updateHeatmap","syncLayers","hasData","showHeatmap","hotelData","hotelMarkers","hotel","el","WeatherControl","weather","weatherFeature","currentWeather","weatherLayerVisible","isAutoRefreshEnabled","weatherControl","proxyURL","centerLat","centerLon","mapInit","options","hotelFeature_","weatherFeature_","controls","LiteAPI","version"],"mappings":"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"}