Repository: r-renato/ha-card-weather-conditions
Branch: master
Commit: 2a264d2ac301
Files: 63
Total size: 518.5 KB
Directory structure:
gitextract_h_qgsp48/
├── .eslintignore
├── .eslintrc.json
├── .github/
│ └── workflows/
│ └── codeql.yml
├── .gitignore
├── .npmignore
├── .vscode/
│ └── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── dist/
│ ├── ha-card-weather-conditions.js
│ └── transl/
│ ├── cs.json
│ ├── da.json
│ ├── de.json
│ ├── en.json
│ ├── es.json
│ ├── fr.json
│ ├── it.json
│ ├── nl.json
│ ├── no-NO.json
│ ├── pt.json
│ ├── ru.json
│ └── sr-latn.json
├── hacs.json
├── info.md
├── package.json
├── rollup.new.config.mjs
├── src/
│ ├── base/
│ │ └── lovelace-base.ts
│ ├── builder/
│ │ ├── b-airquality.ts
│ │ ├── b-camera.ts
│ │ ├── b-meteoalarm.ts
│ │ ├── b-pollen.ts
│ │ ├── b-present.ts
│ │ ├── b-summary.ts
│ │ ├── b-ultraviolet.ts
│ │ └── b-weather-forecast.ts
│ ├── css/
│ │ ├── css-base-card.ts
│ │ ├── css-camera.ts
│ │ ├── css-meteoalarm.ts
│ │ ├── css-pollen.ts
│ │ ├── css-present.ts
│ │ ├── css-summary.ts
│ │ ├── css-ultraviolet.ts
│ │ └── css-weather-forecast.ts
│ ├── ha-weather-ecard.ts
│ ├── iconmodels/
│ │ ├── im-buienradar.ts
│ │ ├── im-climacell.ts
│ │ ├── im-darksky.ts
│ │ ├── im-hass.ts
│ │ ├── im-openweathermap.ts
│ │ └── im-pirateweather.ts
│ ├── templates/
│ │ ├── t-camera.ts
│ │ ├── t-meteoalarm.ts
│ │ ├── t-pollen.ts
│ │ ├── t-present.ts
│ │ ├── t-summary.ts
│ │ ├── t-ultraviolet.ts
│ │ └── t-weather-forecast.ts
│ └── utils/
│ ├── colors.ts
│ ├── config-schema.ts
│ ├── const.ts
│ ├── helper-render.ts
│ └── helper.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintignore
================================================
backup/
dist/
node_modules/
rollup.config.mjs
rollup.config copy.js
rollup.new.config.mjs
================================================
FILE: .eslintrc.json
================================================
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2022,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"airbnb-base"
],
"rules": {
"operator-linebreak": "warn",
"no-trailing-spaces": "warn",
"one-var": "warn",
"one-var-declaration-per-line": "warn",
"dot-notation": "warn",
"max-len": ["error", { "code": 150 }],
"eol-last": ["error", "always"],
"no-console": "off",
"no-unused-vars": ["warn", { "args": "none", "ignoreRestSiblings": true }],
"nonblock-statement-body-position": "warn",
"@typescript-eslint/no-unused-vars": "warn",
"max-classes-per-file": ["warn", 3],
"import/extensions": ["warn", "ignorePackages", {
"ts": "never",
"js": "never"
}]
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".ts", ".jsx", ".tsx"]
}
}
},
"env": {
"browser": true,
"es2022": true
}
}
================================================
FILE: .github/workflows/codeql.yml
================================================
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: "22 7 * * 0"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ javascript ]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
queries: +security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{ matrix.language }}"
================================================
FILE: .gitignore
================================================
# ####### ####### #######
# Folders
.idea
__pycache__
/node_modules/
/.rpt2_cache/
/trash/
/backup/
# ####### ####### #######
# Files
package-lock.json
================================================
FILE: .npmignore
================================================
# OS X
.DS_Store
backup
================================================
FILE: .vscode/settings.json
================================================
{
"eslint.enable": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"editor.tabSize": 2,
"ha_module_path": "/home/drp/homeassistant/www/community/ha-card-weather-conditions",
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 120,
}
================================================
FILE: CHANGELOG.md
================================================
# HA (Lovelace) Card Weather Conditions
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [2.0.1] 2025-06-08
### Fixed
### Added
- ru locale
### Changed
- nl locale
## [2.0.0] 2025-06-08
### Changed
- Readme and PNG image
- Fully reengineered the card
- Czech locale
### Changed
- Update Spanish locale
## [1.9.12] 2021-01-29
### Fixed
- Minor bug fixing
## [1.9.11] 2021-01-29
### Fixed
- Minor bug fixing
## [1.9.10] 2021-01-24
### Changed
Update ClimaCel icons map
## [1.9.9] 2021-01-11
### Added
- Norwegian locale
## [1.9.8] 2021-01-07
### Added
- Danish locale
## [1.9.7] 2020-12-06
### Fixed
- Fixed the snow icon name for the night time (climacell, darksky, openweathermap)
## [1.9.6] 2020-08-17
### Fixed
- German locale, fix for "Feels Like" word
## [1.9.6] 2020-08-08
### Added
- Icon model for: buienradar, defaulthass
## [1.9.5] 2020-08-08
### Fixed
- Documentation
## [1.9.5] 2020-07-21
### Added
- Errors catch and display while loading translations files
## [1.9.4] 2020-07-19
### Fixed
- Minor bug fixing
## [1.9.3] 2020-07-18
### Changed
- Exposition time change from hours to minutes
## [1.9.2] 2020-07-10
### Fixed
- Minor bug fixing
## [1.9.1] 2020-06-22
### Added
- Added icon override mode for the pollen layer
## [1.9.0] 2020-06-21
### Fixed
- Minor bug fixing
### Added
- Add `sea` Weather Forecast session
## [1.8.1] 2020-06-15
### Fixed
- Minor bug fixing
## [1.8.0] 2020-06-15
### Fixed
- Minor bug fixing
### Changed
- Internationalization model
### Added
- Add `pt` language
- Add Alert Layer
### Changed
## [1.7.1] 2020-05-24
### Fixed
- Minor bug fixing
## [1.7.0] 2020-05-23
### Fixed
- Minor bug fixing
### Added
- Add `sr-latn` language
## [1.6.0] 2020-05-22
### Added
- Add `fr` language
## [1.5.1] 2020-05-21
### Fixed
- Minor bug fixing
## [1.5.0] 2020-05-14
### Fixed
- Minor bug fixing
### Added
- Add `uv` (ultraviolet) session
## [1.4.0] 2020-05-13
### Added
- Add `es` language
## [1.3.1] 2020-05-13
### Fixed
- Minor bug fixing
## [1.3.0] 2020-05-10
### Added
- Add moon phase
## [1.2.0] 2020-05-08
### Added
- Add NL (Dutch) language
## [1.1.0] 2020-05-07
### Added
- Add feels_like sensor
## [1.0.1] 2020-05-07
### Fixed
- Minor bug fixing
## [1.0.0] 2020-05-03
- Initial stable version
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Renato Rossi, https://www.linkedin.com/in/renatorossi/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Weather Conditions Card
ha-card-weather-conditions is a powerful and flexible Lovelace card for Home Assistant. It integrates a variety of weather-related data sources to present a comprehensive summary and forecast.
[](https://github.com/hacs/integration)
[![License][license-shield]](LICENSE)
[](https://lgtm.com/projects/g/r-renato/ha-card-weather-conditions/alerts/)
[](https://lgtm.com/projects/g/r-renato/ha-card-weather-conditions/context:javascript)
[![BuyMeCoffee][buymecoffeebadge]][buymecoffee]
## Features
* Current and forecast weather conditions
* Marine forecast (swell, wave, wind)
* Ultraviolet radiation index and protection advice
* Pollen level display (tree, weed, grass)
* Air quality index with multiple pollutant types
* Weather alerts (fire, storm, hydrogeological, hydraulic)
* Meteogram and camera integration
* Multilingual support
* Display MeteoAlarm (Early Warnings for Europe) and Dipartimento Protezione Civile (Italy only) Alert
## **Card Configuration**
To use the ```ha-card-weather-conditions``` card, add the following configuration to your ```lovelace``` dashboard:
```yaml
resources:
# Required: Load the card if installed via HACS
- url: /hacsfiles/ha-card-weather-conditions/ha-card-weather-conditions.js
type: module
# Optional: Load Card Mod to enable advanced styling/customization
- url: /hacsfiles/lovelace-card-mod/card-mod.js
type: module
# ...
```
## **Card Schema Summary**
| **Parameter** | **Type** | **Required** | **Default** | **Description** |
| ------------- | --------- | ------------ | ----------- | ---------------------------------------------------------------------------------------------------------- |
| `type` | `string` | Yes | — | Must be set to `custom:ha-card-weather-conditions`. |
| `language` | `string` | No | `en` | Language for labels. Supported values: `en`, `it`, `nl`, `es`, `de`, `fr`, `sr-latn`, `pt`, `da`, `no-NO`, `cs`, `ru`. |
| `weather` | `object` | No | — | Configuration for main weather source. See dedicated section. |
| `ultraviolet` | `object` | No | — | Configuration for UV index display. See dedicated section for details. |
| `pollen` | `object` | No | — | Configuration for pollen levels. See dedicated section. |
| `airquality` | `object` | No | — | Configuration for air quality index. See dedicated section. |
| `camera` | `string` | No | — | Entity ID of the camera to display. |
## **1 `weather` Object Schema**
The following parameters configure the weather object to display current conditions, short-term and long-term forecasts, as well as related alerts.
This card has been tested with weather data provided by `pirateweather`, `climacell`, `darksky` and `openweathermap` integrations.
| **Name** | **Type** | **Required** | **Default** | **Description** |
| ------------------------- | --------- | ------------ | --------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | No | — | Name of the location displayed in the summary section. |
| `sun` | `string` | No | — | Entity ID for the sun sensor (used to adjust visuals for daylight, sunrise, and sunset). |
| `moonphase` | `string` | No | — | Entity ID for the moon phase sensor. |
| `icons_model` | `string` | **Yes** | `pirateweather` | Icon set to use. Supported values: `pirateweather`, `climacell`, `darksky`, `openweathermap`, `buienradar`, `defaulthass`. |
| `animation` | `boolean` | No | `false` | Enables visual effects like moving clouds, rain, or waves based on weather conditions. |
| `present` | `object` | No | — | Object containing current weather data (e.g., temperature, humidity, pressure). |
| `daily_forecasts` | `object` | No | — | Object containing multi-day weather forecast data. |
| `hourly_forecasts` | `object` | No | — | Object containing hourly weather forecast data. |
| `marine_daily_forecasts` | `object` | No | — | Object with daily marine forecast data (e.g., wave height, wind, tides). |
| `marine_hourly_forecasts` | `object` | No | — | Object with hourly marine forecast data. |
| `meteoalarm` | `string` | No | — | Entity ID from [Meteoalarm](https://meteoalarm.org/) integration for regional weather warnings. |
| `dpcalarm` | `object` | No | — | Object providing DPC (Protezione Civile) alerts such as thunderstorm or flood risks. |
### **1.1 `present` Object Schema**
The present object defines the entities used to display the current weather conditions in the summary section of the card. Each property corresponds to a specific sensor or attribute providing real-time environmental data.
| **Name** | **Type** | **Required** | **Default** | **Description** |
| --------------------------- | ---------- | ------------ | ----------- | ----------------------------------------------------------------------------- |
| `condition` | `string` | No | — | Entity ID providing the current weather condition (e.g. sunny, cloudy, rain). |
| `temperature` | `string` | No | — | Entity ID providing the current temperature. |
| `temperature_feelslike` | `string` | No | — | Entity ID providing the perceived (feels-like) temperature. |
| `temperature_min` | `string` | No | — | Entity ID providing the minimum temperature of the day. |
| `temperature_max` | `string` | No | — | Entity ID providing the maximum temperature of the day. |
| `humidity` | `string` | No | — | Entity ID providing the current humidity level (%). |
| `pressure` | `string` | No | — | Entity ID providing the current atmospheric pressure. |
| `visibility` | `string` | No | — | Entity ID providing the current visibility level. |
| `wind_bearing` | `string` | No | — | Entity ID providing the wind direction in degrees. |
| `wind_speed` | `string` | No | — | Entity ID providing the wind speed. |
| `precipitation_intensity` | `string` | No | — | Entity ID providing the precipitation rate (e.g. mm/h). |
| `precipitation_probability` | `string` | No | — | Entity ID providing the probability of precipitation (%). |
### **1.2 `daily_forecasts` Object Schema**
This object defines the structure for multi-day forecast data, where each property can include multiple time slots (e.g. `day_1`, `day_2`, `day_3`…).
Each forecast element (such as `temperature`, `condition`, `precipitation probability`, etc.) must be represented as a Home Assistant entity (e.g., sensor) that includes the following attributes:
- `datetime`: the timestamp indicating the forecast reference time, in ISO 8601 format, for example: 2025-06-12T22:00:00+00:00
- `unit_of_measurement`: the unit of measure for the forecasted value (e.g., "`°C`", "`mm`", "`%`"), which must be exposed as an attribute of the sensor.
These attributes are essential to ensure accurate time alignment and proper rendering of the forecast data.
| **Name** | **Type** | **Required** | **Default** | **Description** |
| --------------------------- | ------------ | ------------ | ----------- | -------------------------------------------------------------------------- |
| `condition` | `iTimeSlots` | No | — | Object containing the weather condition icons or states for each day slot. |
| `temperature_high` | `iTimeSlots` | No | — | Object containing the daily high temperature values per slot. |
| `temperature_low` | `iTimeSlots` | No | — | Object containing the daily low temperature values per slot. |
| `precipitation_intensity` | `iTimeSlots` | No | — | Object with the forecasted precipitation amount for each slot. |
| `precipitation_probability` | `iTimeSlots` | No | — | Object with the probability of precipitation (%) per slot. |
### **1.3 `hourly_forecasts` Object Schema**
This object defines the structure for hourly weather forecast data. All fields are optional and do not have default values.
Each forecast element (such as `temperature`, `condition`, `precipitation probability`, etc.) must be represented as a Home Assistant entity (e.g., sensor) that includes the following attributes:
- `datetime`: the timestamp indicating the forecast reference time, in ISO 8601 format, for example: 2025-06-12T22:00:00+00:00
- `unit_of_measurement`: the unit of measure for the forecasted value (e.g., "`°C`", "`mm`", "`%`"), which must be exposed as an attribute of the sensor.
These attributes are essential to ensure accurate time alignment and proper rendering of the forecast data.
| **Name** | **Type** | **Required** | **Default** | **Description** |
| --------------------------- | ------------ | ------------ | ----------- | ----------------------------------------------------------------------------- |
| `condition` | `iTimeSlots` | No | — | Object containing the weather condition icons or states for each hourly slot. |
| `temperature` | `iTimeSlots` | No | — | Object containing the perceived ambient temperature for each hour. |
| `temperature_feelslike` | `iTimeSlots` | No | — | Object containing the "feels like" temperature values for each hour. |
| `precipitation_intensity` | `iTimeSlots` | No | — | Object with forecasted precipitation amount per hour. |
| `precipitation_probability` | `iTimeSlots` | No | — | Object with probability of precipitation (%) per hour. |
| `wind_bearing` | `iTimeSlots` | No | — | Object with wind direction (in degrees or cardinal direction) per hour. |
| `wind_speed` | `iTimeSlots` | No | — | Object with wind speed values per hour. |
### **1.3.1 `iTimeSlots` Object Schema**
This object represents a set of six time slots used to store sequential forecast data (e.g., hourly, daily, etc.).
| **Name** | **Type** | **Required** | **Description** |
| -------- | -------- | ------------ | ------------------------------------------------------------ |
| `slot1` | `string` | No | Value for the first time slot (e.g., current or first hour). |
| `slot2` | `string` | No | Value for the second time slot. |
| `slot3` | `string` | No | Value for the third time slot. |
| `slot4` | `string` | No | Value for the fourth time slot. |
| `slot5` | `string` | No | Value for the fifth time slot. |
| `slot6` | `string` | No | Value for the sixth time slot. |
### **1.4 `dpcalarm` Object Schema**
The `dpcalarm` object is used to configure weather-related alerts provided by the Italian Civil Protection Department (DPC), including thunderstorms, hydraulic, and hydrogeological risks. Each property should reference a specific sensor entity ID.
| **Name** | **Type** | **Required** | **Description** |
| ----------------- | -------- | ------------ | ---------------------------------------------------------------------------- |
| `thunderstorms` | `string` | No | Entity ID providing thunderstorm alert information from DPC. |
| `hydraulic` | `string` | No | Entity ID providing hydraulic (river/stream flooding) alert information. |
| `hydrogeological` | `string` | No | Entity ID providing hydrogeological (landslide/soil instability) alert data. |
## **2 `ultraviolet` Object Schema**
The ultraviolet object allows you to display UV-related data such as the current index, ozone level, protection window, and safe exposure times for different skin types (I–VI).
| **Name** | **Type** | **Required** | **Description** |
| ------------------- | -------- | ------------ | ------------------------------------------------------------------------------- |
| `protection_window` | `string` | No | Entity ID providing the time window during which sun protection is recommended. |
| `ozone_level` | `string` | No | Entity ID providing the current atmospheric ozone level. |
| `uv_index` | `string` | No | Entity ID providing the current UV index value. |
| `uv_level` | `string` | No | Entity ID describing the UV risk level (e.g. low, moderate, high). |
| `max_uv_index` | `string` | No | Entity ID providing the maximum forecasted UV index for the day. |
| `set_skin_type_1` | `string` | No | Entity ID providing sun exposure time recommendation for skin type I. |
| `set_skin_type_2` | `string` | No | Entity ID providing sun exposure time recommendation for skin type II. |
| `set_skin_type_3` | `string` | No | Entity ID providing sun exposure time recommendation for skin type III. |
| `set_skin_type_4` | `string` | No | Entity ID providing sun exposure time recommendation for skin type IV. |
| `set_skin_type_5` | `string` | No | Entity ID providing sun exposure time recommendation for skin type V. |
| `set_skin_type_6` | `string` | No | Entity ID providing sun exposure time recommendation for skin type VI. |
## **3 `pollen` Object Schema**
The pollen object provides information about airborne allergens. It defines the range of measured values (`min` and `max`) and includes a list of `entities` describing each pollen type.
| **Name** | **Type** | **Required** | **Description** |
| ---------- | --------------- | ------------ | ----------------------------------------------------------------------- |
| `entities` | `iPollenItem[]` | Yes | Array of pollen data objects, each representing a specific pollen type. |
| `min` | `number` | Yes | Minimum expected pollen concentration (used for scaling). |
| `max` | `number` | Yes | Maximum expected pollen concentration (used for scaling). |
## **3.1 `iPollenItem` Object Schema**
Each `iPollenItem` defines a specific pollen type to be tracked, including a name for display and the corresponding entity ID in Home Assistant.
| **Name** | **Type** | **Required** | **Description** |
| -------- | -------- | ------------ | ----------------------------------------------------------------- |
| `name` | `string` | Yes | Display name of the pollen type (e.g., “Grass”, “Birch”). |
| `entity` | `string` | Yes | Home Assistant entity ID providing the pollen concentration data. |
## **4 `airquality` Object Schema**
The `airquality` object defines the Home Assistant entity IDs used to monitor various air pollution metrics and EPA health indicators. Each field corresponds to a specific air quality parameter.
| **Name** | **Type** | **Required** | **Description** |
| ----------------------- | -------- | ------------ | ---------------------------------------------------------------------------- |
| `pm25` | `string` | No | Entity ID providing PM2.5 (fine particulate matter) concentration. |
| `pm10` | `string` | No | Entity ID providing PM10 (coarse particulate matter) concentration. |
| `o3` | `string` | No | Entity ID providing Ozone (O₃) concentration. |
| `no2` | `string` | No | Entity ID providing Nitrogen Dioxide (NO₂) concentration. |
| `co` | `string` | No | Entity ID providing Carbon Monoxide (CO) concentration. |
| `so2` | `string` | No | Entity ID providing Sulfur Dioxide (SO₂) concentration. |
| `epa_aqi` | `string` | No | Entity ID providing the EPA-computed Air Quality Index. |
| `epa_primary_pollutant` | `string` | No | Entity ID providing the EPA-designated primary pollutant. |
| `epa_health_concern` | `string` | No | Entity ID describing the EPA-assigned health concern level (e.g., moderate). |
## **Card Layers Sample**
This section showcases a complete example of the different visual layers supported by the `ha-card-weather-conditions` card.
Each layer such as summary, weather conditions, air quality, UV index, and alerts—can be configured independently, allowing full control over how and where data appears.
Use this reference as a guide when designing your Lovelace configuration to build a fully personalized weather dashboard.
### **Summary Layer**
The summary layers present a concise visual overview of current weather conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
name: "Acquafredda"
icons_model: pirateweather
moonphase: sensor.moon_phase
present:
condition: sensor.home_condition
temperature: sensor.home_temperature
temperature_feelslike: sensor.home_apparent_temperature
```
### **Present Layer**
This layer displays the current weather conditions using entity data such as temperature, humidity, wind, and more.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
sun: sun.sun
present:
temperature_min: sensor.home_temperature_min
temperature_max: sensor.home_temperature_max
humidity: sensor.home_relative_humidity
pressure: sensor.home_pressure
wind_bearing: sensor.home_wind_bearing
wind_speed: sensor.home_wind_speed
precipitation_intensity: sensor.home_precipitation
precipitation_probability: sensor.home_precipitation_probability
```
### **Daily Forecast Layer**
This layer provides a multi-day weather overview, including expected temperature highs and lows, precipitation probability, and general conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
daily_forecasts:
condition:
slot1: sensor.home_daily_forecast_condition_d1
slot2: sensor.home_daily_forecast_condition_d2
slot3: sensor.home_daily_forecast_condition_d3
slot4: sensor.home_daily_forecast_condition_d4
temperature_high:
slot1: sensor.home_daily_forecast_temperature_max_d1
slot2: sensor.home_daily_forecast_temperature_max_d2
slot3: sensor.home_daily_forecast_temperature_max_d3
slot4: sensor.home_daily_forecast_temperature_max_d4
temperature_low:
slot1: sensor.home_daily_forecast_temperature_min_d1
slot2: sensor.home_daily_forecast_temperature_min_d2
slot3: sensor.home_daily_forecast_temperature_min_d3
slot4: sensor.home_daily_forecast_temperature_min_d4
precipitation_probability:
slot1: sensor.home_daily_forecast_precipitation_probability_d1
slot2: sensor.home_daily_forecast_precipitation_probability_d2
slot3: sensor.home_daily_forecast_precipitation_probability_d3
slot4: sensor.home_daily_forecast_precipitation_probability_d4
precipitation_intensity:
slot1: sensor.home_daily_forecast_precipitation_d1
slot2: sensor.home_daily_forecast_precipitation_d2
slot3: sensor.home_daily_forecast_precipitation_d3
slot4: sensor.home_daily_forecast_precipitation_d4
```
### **Hourly Forecast Layer**
This layer displays detailed weather data for the next several hours, including temperature, precipitation, and wind conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
hourly_forecasts:
condition:
slot1: sensor.home_hourly_forecast_condition_h1
slot2: sensor.home_hourly_forecast_condition_h2
slot3: sensor.home_hourly_forecast_condition_h3
slot4: sensor.home_hourly_forecast_condition_h4
temperature:
slot1: sensor.home_hourly_forecast_temperature_h1
slot2: sensor.home_hourly_forecast_temperature_h2
slot3: sensor.home_hourly_forecast_temperature_h3
slot4: sensor.home_hourly_forecast_temperature_h4
temperature_feelslike:
slot1: sensor.home_hourly_forecast_apparent_temperature_h1
slot2: sensor.home_hourly_forecast_apparent_temperature_h2
slot3: sensor.home_hourly_forecast_apparent_temperature_h3
slot4: sensor.home_hourly_forecast_apparent_temperature_h4
precipitation_intensity:
slot1: sensor.home_hourly_forecast_precipitation_h1
slot2: sensor.home_hourly_forecast_precipitation_h2
slot3: sensor.home_hourly_forecast_precipitation_h3
slot4: sensor.home_hourly_forecast_precipitation_h4
precipitation_probability:
slot1: sensor.home_hourly_forecast_precipitation_probability_h1
slot2: sensor.home_hourly_forecast_precipitation_probability_h2
slot3: sensor.home_hourly_forecast_precipitation_probability_h3
slot4: sensor.home_hourly_forecast_precipitation_probability_h4
wind_bearing:
slot1: sensor.home_hourly_forecast_wind_bearing_h1
slot2: sensor.home_hourly_forecast_wind_bearing_h2
slot3: sensor.home_hourly_forecast_wind_bearing_h3
slot4: sensor.home_hourly_forecast_wind_bearing_h4
wind_speed:
slot1: sensor.home_hourly_forecast_wind_speed_h1
slot2: sensor.home_hourly_forecast_wind_speed_h2
slot3: sensor.home_hourly_forecast_wind_speed_h3
slot4: sensor.home_hourly_forecast_wind_speed_h4
```
### **Marine Daily Forecast Layer**
This layer provides daily marine weather forecasts, including information such as wave height, wind speed, and sea conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
marine_daily_forecasts:
wave_height_max:
slot1: sensor.marine_wave_height_max_day_0
slot2: sensor.marine_wave_height_max_day_1
slot3: sensor.marine_wave_height_max_day_2
slot4: sensor.marine_wave_height_max_day_3
wave_direction:
slot1: sensor.marine_wave_direction_dominant_day_0
slot2: sensor.marine_wave_direction_dominant_day_1
slot3: sensor.marine_wave_direction_dominant_day_2
slot4: sensor.marine_wave_direction_dominant_day_3
swell_wave_height_max:
slot1: sensor.amarine_swell_wave_height_max_day_0
slot2: sensor.marine_swell_wave_height_max_day_1
slot3: sensor.marine_swell_wave_height_max_day_2
slot4: sensor.marine_swell_wave_height_max_day_3
wind_wave_height_max:
slot1: sensor.marine_wind_wave_height_max_day_0
slot2: sensor.marine_wind_wave_height_max_day_1
slot3: sensor.marine_wind_wave_height_max_day_2
slot4: sensor.marine_wind_wave_height_max_day_3
```
### **Alarms Layer**
This layer displays weather alerts and warnings from official sources such as Meteoalarm and the Italian Civil Protection Department (DPC).
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
meteoalarm: binary_sensor.italy_basilicata_meteo_alarm
dpcalarm:
thunderstorms: binary_sensor.dpc_basilicata_temporali_oggi
hydraulic: binary_sensor.dpc_basilicata_idraulico_oggi
hydrogeological: binary_sensor.dpc_basilicata_idrogeologico_oggi
```
### **Ultraviolet Layer**
This layer presents real-time ultraviolet (UV) radiation data, including UV index levels, ozone concentration, and skin protection recommendations.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
ultraviolet:
protection_window: binary_sensor.openuv_protection_window
ozone_level: sensor.openuv_current_ozone_level
uv_index: sensor.openuv_current_uv_index
uv_level: sensor.openuv_current_uv_level
max_uv_index: sensor.openuv_max_uv_index
set_skin_type_1: sensor.openuv_skin_type_1_safe_exposure_time
set_skin_type_2: sensor.openuv_skin_type_2_safe_exposure_time
set_skin_type_3: sensor.openuv_skin_type_3_safe_exposure_time
set_skin_type_4: sensor.openuv_skin_type_4_safe_exposure_time
set_skin_type_5: sensor.openuv_skin_type_5_safe_exposure_time
set_skin_type_6: sensor.openuv_skin_type_6_safe_exposure_time
```
### **Pollen Layer**
This layer displays information about airborne pollen levels, helping users monitor potential allergen exposure.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
pollen:
min: 1
max: 4
entities:
- name: Alder
entity: sensor.openmeteo_pollen_alder_level
- name: Birch
entity: sensor.openmeteo_pollen_birch_level
- name: Grass
entity: sensor.openmeteo_pollen_grass_level
- name: Mugwort
entity: sensor.openmeteo_pollen_mugwort_level
- name: Olive
entity: sensor.openmeteo_pollen_olive_level
- name: Ragweed
entity: sensor.openmeteo_pollen_ragweed_level
```
### **Air Quality Layer**
This layer presents real-time data on key air quality indicators such as PM2.5, PM10, ozone, and nitrogen dioxide levels.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
airquality:
pm25: sensor.lazio_italy_pm2_5
pm10: sensor.lazio_italy_pm10
o3: sensor.roma_lazio_italy_ozone
co: sensor.roma_lazio_italy_carbon_monoxide
epa_aqi: sensor.lazio_italy_air_quality_index
epa_primary_pollutant: sensor.lazio_italy_dominant_pollutant
```
[license-shield]:https://img.shields.io/github/license/r-renato/ha-card-weather-conditions
[buymecoffee]: https://www.buymeacoffee.com/0D3WbkKrn
[buymecoffeebadge]: https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow?style=for-the-badge
================================================
FILE: dist/ha-card-weather-conditions.js
================================================
function e(e,t,i,n){var a,s=arguments.length,o=s<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,n);else for(var r=e.length-1;r>=0;r--)(a=e[r])&&(o=(s<3?a(o):s>3?a(t,i,o):a(t,i))||o);return s>3&&o&&Object.defineProperty(t,i,o),o}"function"==typeof SuppressedError&&SuppressedError;
/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const t=globalThis,i=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,n=Symbol(),a=new WeakMap;let s=class{constructor(e,t,i){if(this._$cssResult$=!0,i!==n)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const t=this.t;if(i&&void 0===e){const i=void 0!==t&&1===t.length;i&&(e=a.get(t)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),i&&a.set(t,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const i=1===e.length?e[0]:t.reduce(((t,i,n)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[n+1]),e[0]);return new s(i,e,n)},r=i?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new s("string"==typeof e?e:e+"",void 0,n))(t)})(e):e
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/,{is:l,defineProperty:c,getOwnPropertyDescriptor:d,getOwnPropertyNames:h,getOwnPropertySymbols:u,getPrototypeOf:p}=Object,m=globalThis,g=m.trustedTypes,y=g?g.emptyScript:"",f=m.reactiveElementPolyfillSupport,v=(e,t)=>e,_={toAttribute(e,t){switch(t){case Boolean:e=e?y:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},w=(e,t)=>!l(e,t),$={attribute:!0,type:String,converter:_,reflect:!1,useDefault:!1,hasChanged:w};Symbol.metadata??=Symbol("metadata"),m.litPropertyMetadata??=new WeakMap;let x=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=$){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),n=this.getPropertyDescriptor(e,i,t);void 0!==n&&c(this.prototype,e,n)}}static getPropertyDescriptor(e,t,i){const{get:n,set:a}=d(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:n,set(t){const s=n?.call(this);a?.call(this,t),this.requestUpdate(e,s,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??$}static _$Ei(){if(this.hasOwnProperty(v("elementProperties")))return;const e=p(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(v("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(v("properties"))){const e=this.properties,t=[...h(e),...u(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(r(e))}else void 0!==e&&t.push(r(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((e=>this.enableUpdating=e)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((e=>e(this)))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((e,n)=>{if(i)e.adoptedStyleSheets=n.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet));else for(const i of n){const n=document.createElement("style"),a=t.litNonce;void 0!==a&&n.setAttribute("nonce",a),n.textContent=i.cssText,e.appendChild(n)}})(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((e=>e.hostConnected?.()))}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach((e=>e.hostDisconnected?.()))}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),n=this.constructor._$Eu(e,i);if(void 0!==n&&!0===i.reflect){const a=(void 0!==i.converter?.toAttribute?i.converter:_).toAttribute(t,i.type);this._$Em=e,null==a?this.removeAttribute(n):this.setAttribute(n,a),this._$Em=null}}_$AK(e,t){const i=this.constructor,n=i._$Eh.get(e);if(void 0!==n&&this._$Em!==n){const e=i.getPropertyOptions(n),a="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:_;this._$Em=n,this[n]=a.fromAttribute(t,e.type)??this._$Ej?.get(n)??null,this._$Em=null}}requestUpdate(e,t,i){if(void 0!==e){const n=this.constructor,a=this[e];if(i??=n.getPropertyOptions(e),!((i.hasChanged??w)(a,t)||i.useDefault&&i.reflect&&a===this._$Ej?.get(e)&&!this.hasAttribute(n._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:n,wrapped:a},s){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,s??t??this[e]),!0!==a||void 0!==s)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===n&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,n=this[t];!0!==e||this._$AL.has(t)||void 0===n||this.C(t,void 0,i,n)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach((e=>e.hostUpdate?.())),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach((e=>e.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach((e=>this._$ET(e,this[e]))),this._$EM()}updated(e){}firstUpdated(e){}};x.elementStyles=[],x.shadowRootOptions={mode:"open"},x[v("elementProperties")]=new Map,x[v("finalized")]=new Map,f?.({ReactiveElement:x}),(m.reactiveElementVersions??=[]).push("2.1.0");
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const b=globalThis,A=b.trustedTypes,z=A?A.createPolicy("lit-html",{createHTML:e=>e}):void 0,E="$lit$",k=`lit$${Math.random().toFixed(9).slice(2)}$`,S="?"+k,C=`<${S}>`,I=document,N=()=>I.createComment(""),P=e=>null===e||"object"!=typeof e&&"function"!=typeof e,T=Array.isArray,U="[ \t\n\f\r]",D=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,M=/>/g,L=RegExp(`>|${U}(?:([^\\s"'>=/]+)(${U}*=${U}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),j=/'/g,R=/"/g,H=/^(?:script|style|textarea|title)$/i,F=(e=>(t,...i)=>({_$litType$:e,strings:t,values:i}))(1),V=Symbol.for("lit-noChange"),W=Symbol.for("lit-nothing"),B=new WeakMap,q=I.createTreeWalker(I,129);function Z(e,t){if(!T(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==z?z.createHTML(t):t}const J=(e,t)=>{const i=e.length-1,n=[];let a,s=2===t?"":3===t?"":"",o=D;for(let t=0;t"===l[0]?(o=a??D,c=-1):void 0===l[1]?c=-2:(c=o.lastIndex-l[2].length,r=l[1],o=void 0===l[3]?L:'"'===l[3]?R:j):o===R||o===j?o=L:o===O||o===M?o=D:(o=L,a=void 0);const h=o===L&&e[t+1].startsWith("/>")?" ":"";s+=o===D?i+C:c>=0?(n.push(r),i.slice(0,c)+E+i.slice(c)+k+h):i+k+(-2===c?t:h)}return[Z(e,s+(e[i]||">")+(2===t?" ":3===t?"":"")),n]};class Y{constructor({strings:e,_$litType$:t},i){let n;this.parts=[];let a=0,s=0;const o=e.length-1,r=this.parts,[l,c]=J(e,t);if(this.el=Y.createElement(l,i),q.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(n=q.nextNode())&&r.length0){n.textContent=A?A.emptyScript:"";for(let i=0;iT(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==W&&P(this._$AH)?this._$AA.nextSibling.data=e:this.T(I.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,n="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=Y.createElement(Z(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(t);else{const e=new K(n,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=B.get(e.strings);return void 0===t&&B.set(e.strings,t=new Y(e)),t}k(e){T(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,n=0;for(const a of e)n===t.length?t.push(i=new G(this.O(N()),this.O(N()),this,this.options)):i=t[n],i._$AI(a),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=W}_$AI(e,t=this,i,n){const a=this.strings;let s=!1;if(void 0===a)e=Q(this,e,t,0),s=!P(e)||e!==this._$AH&&e!==V,s&&(this._$AH=e);else{const n=e;let o,r;for(e=a[0],o=0;o{const n=i?.renderBefore??t;let a=n._$litPart$;if(void 0===a){const e=i?.renderBefore??null;n._$litPart$=a=new G(t.insertBefore(N(),e),e,void 0,i??{})}return a._$AI(e),a})(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return V}}oe._$litElement$=!0,oe.finalized=!0,se.litElementHydrateSupport?.({LitElement:oe});const re=se.litElementPolyfillSupport;re?.({LitElement:oe}),(se.litElementVersions??=[]).push("4.2.0");
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const le={attribute:!0,type:String,converter:_,reflect:!1,hasChanged:w},ce=(e=le,t,i)=>{const{kind:n,metadata:a}=i;let s=globalThis.litPropertyMetadata.get(a);if(void 0===s&&globalThis.litPropertyMetadata.set(a,s=new Map),"setter"===n&&((e=Object.create(e)).wrapped=!0),s.set(i.name,e),"accessor"===n){const{name:n}=i;return{set(i){const a=t.get.call(this);t.set.call(this,i),this.requestUpdate(n,a,e)},init(t){return void 0!==t&&this.C(n,void 0,e,t),t}}}if("setter"===n){const{name:n}=i;return function(i){const a=this[n];t.call(this,i),this.requestUpdate(n,a,e)}}throw Error("Unsupported decorator location: "+n)};
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/function de(e){return(t,i)=>"object"==typeof i?ce(e,t,i):((e,t,i)=>{const n=t.hasOwnProperty(i);return t.constructor.createProperty(i,e),n?Object.getOwnPropertyDescriptor(t,i):void 0})(e,t,i)}const he=o`
--default-red: 244, 67, 54;
--default-pink: 233, 30, 99;
--default-purple: 146, 107, 199;
--default-deep-purple: 110, 65, 171;
--default-indigo: 63, 81, 181;
--default-blue: 33, 150, 243;
--default-light-blue: 3, 169, 244;
--default-cyan: 0, 188, 212;
--default-teal: 0, 150, 136;
--default-green: 76, 175, 80;
--default-light-green: 139, 195, 74;
--default-lime: 205, 220, 57;
--default-yellow: 255, 235, 59;
--default-amber: 255, 193, 7;
--default-orange: 255, 152, 0;
--default-deep-orange: 255, 111, 34;
--default-brown: 121, 85, 72;
--default-light-grey: 189, 189, 189;
--default-grey: 158, 158, 158;
--default-dark-grey: 96, 96, 96;
--default-blue-grey: 96, 125, 139;
--default-black: 0, 0, 0;
--default-white: 255, 255, 255;
--default-disabled: 189, 189, 189;
`,ue=o`
--default-disabled: 111, 111, 111;
`,pe="%c WEATHER-CONDITION-CARD %c 2.0.0",me="/local/community/ha-card-weather-conditions/icons",ge="/local/ha-card-weather-conditions/icons",ye="color: white; background: green; font-weight: 700;",fe="color: green; background: white; font-weight: 700;",ve="color: black; background: white; font-weight: 700;",_e={en:0,it:1,nl:2,es:3,de:4,fr:5,"sr-latn":6,pt:7,da:8,"no-no":9,cs:10,ru:11},we={snowy:"snowy-3","light-snow":"snowy-2","snowy-rainy":"snowy-1","partlycloudy-light-snow":"snowy-1","partlycloudy-snow":"snowy-1","partlycloudy-light-rain":"rainy-1","light-rain":"rainy-1",rainy:"rainy-2","partlycloudy-rain":"rainy-1","partlycloudy-fog":"fog",cloudy:"cloudy-original",partlycloudy:"cloudy-day-2","partlycloudy-lightning":"cloudy-day-1",lightning:"cloudy-day-1",clear:"day"},$e={...we},xe={freezing_rain_heavy:"rainy-3","heavy freezing rain":"rainy-3",freezing_rain:"rainy-2","freezing rain":"rainy-2",freezing_rain_light:"rainy-1","light freezing rain":"rainy-1",freezing_drizzle:"rain-and-sleet-mix","freezing drizzle":"rain-and-sleet-mix",ice_pellets_heavy:"rain-and-snow-mix","heavy ice pellets":"rain-and-snow-mix",ice_pellets:"rain-and-snow-mix","ice pellets":"rain-and-snow-mix",ice_pellets_light:"rain-and-snow-mix","light ice pellets":"rain-and-snow-mix",snow_heavy:"snowy-3","heavy snow":"snowy-3",snow:"snowy-2",snow_light:"snowy-1","light snow":"snowy-1",flurries:"wind",tstorm:"tropical-storm",rain_heavy:"rainy-3","heavy rain":"rainy-3",rain_light:"rainy-1","light rain":"rainy-1",rain:"rainy-2",drizzle:"rainy-1",fog_light:"haze","light fog":"haze",fog:"fog",cloudy:"cloudy-original",mostly_cloudy:"cloudy-day-3","mostly cloudy":"cloudy-day-3",partly_cloudy:"cloudy-day-2","partly cloudy":"cloudy-day-2",mostly_clear:"cloudy-day-1","mostly clear":"cloudy-day-1",clear:"day"},be={...xe,freezing_rain_heavy:"rainy-6","heavy freezing rain":"rainy-6",freezing_rain:"rainy-5","freezing rain":"rainy-5",freezing_rain_light:"rainy-4","light freezing rain":"rainy-4",snow_heavy:"snowy-6","heavy snow":"snowy-6",snow:"snowy-5",snow_light:"snowy-4","light snow":"snowy-4",rain_heavy:"rainy-6","heavy rain":"rainy-6",rain_light:"rainy-4","light rain":"rainy-4",rain:"rainy-5",drizzle:"rainy-4",mostly_cloudy:"cloudy-night-3","mostly cloudy":"cloudy-night-3",partly_cloudy:"cloudy-night-2","partly cloudy":"cloudy-night-2",mostly_clear:"cloudy-night-1","mostly clear":"cloudy-night-1",clear:"night",sunny:"night"},Ae={clear:"day","clear-day":"day",rain:"rainy-2",snow:"snowy-2",sleet:"rain-and-sleet-mix",wind:"cloudy-day-1",fog:"fog",cloudy:"cloudy-original","partly-cloudy-day":"cloudy-day-2"},ze={...Ae,clear:"night","clear-night":"night",wind:"cloudy-night-1","partly-cloudy-day":"cloudy-night-2","partly-cloudy-night":"cloudy-night-2"},Ee={cloudy:"cloudy-day-3",exceptional:"severe-thunderstorm",fog:"fog",hail:"snow-and-sleet-mix",lightning:"severe-thunderstorm","lightning-rainy":"scattered-thunderstorms",partlycloudy:"cloudy-day-3",pouring:"rainy-6",rainy:"rainy-5",snowy:"snowy-6","snowy-rainy":"snow-and-sleet-mix",sunny:"clear-day",windy:"wind","windy-variant":"wind"},ke={...Ee,"clear-night":"clear-night"},Se={"clear sky":"day","few clouds":"cloudy-day-1","scattered clouds":"cloudy-day-2","broken clouds":"cloudy-day-3","shower rain":"rainy-3",rain:"rainy-2",thunderstorm:"tropical-storm",snow:"snowy-2",mist:"fog"},Ce={...Se,"clear sky":"day-night","few clouds":"cloudy-night-1","scattered clouds":"cloudy-night-2","broken clouds":"cloudy-night-3"},Ie={freezing_rain_heavy:"rainy-3","heavy freezing rain":"rainy-3",freezing_rain:"rainy-2","freezing rain":"rainy-2",freezing_rain_light:"rainy-1","light freezing rain":"rainy-1",freezing_drizzle:"rain-and-sleet-mix",sleet:"rain-and-sleet-mix","freezing drizzle":"rain-and-sleet-mix",ice_pellets_heavy:"rain-and-snow-mix","heavy ice pellets":"rain-and-snow-mix",ice_pellets:"rain-and-snow-mix","ice pellets":"rain-and-snow-mix",ice_pellets_light:"rain-and-snow-mix","light ice pellets":"rain-and-snow-mix",snow_heavy:"snowy-3","heavy snow":"snowy-3",snow:"snowy-2",snow_light:"snowy-1","light snow":"snowy-1",flurries:"wind",tstorm:"tropical-storm",rain_heavy:"rainy-3","heavy rain":"rainy-3",rain_light:"rainy-1",rainy:"rainy-1","light rain":"rainy-1",rain:"rainy-2",drizzle:"rainy-1",fog_light:"haze","light fog":"haze",fog:"fog",cloudy:"cloudy-original",mostly_cloudy:"cloudy-day-3","mostly cloudy":"cloudy-day-3",partly_cloudy:"cloudy-day-2",partlycloudy:"cloudy-day-2","partly-cloudy-day":"cloudy-day-2","partly cloudy":"cloudy-day-2",mostly_clear:"cloudy-day-1","mostly clear":"cloudy-day-1",clear:"day","clear-day":"day",wind:"wind",windy:"wind",sunny:"day","clear-night":"day"},Ne={...Ie,freezing_rain_heavy:"rainy-6","heavy freezing rain":"rainy-6",freezing_rain:"rainy-5","freezing rain":"rainy-5",freezing_rain_light:"rainy-4","light freezing rain":"rainy-4",snow_heavy:"snowy-6","heavy snow":"snowy-6",snow:"snowy-5",snow_light:"snowy-4","light snow":"snowy-4",rain_heavy:"rainy-6","heavy rain":"rainy-6",rain_light:"rainy-4","light rain":"rainy-4",rain:"rainy-5",drizzle:"rainy-4",mostly_cloudy:"cloudy-night-3","mostly cloudy":"cloudy-night-3",partly_cloudy:"cloudy-night-2",partlycloudy:"cloudy-night-2","partly-cloudy-night":"cloudy-night-2","partly cloudy":"cloudy-night-2",mostly_clear:"cloudy-night-1","mostly clear":"cloudy-night-1",clear:"night","clear-night":"night",sunny:"night"},Pe={pirateweather:{iconsDay:Ie,iconsNight:Ne},climacell:{iconsDay:xe,iconsNight:be},darksky:{iconsDay:Ae,iconsNight:ze},openweathermap:{iconsDay:Se,iconsNight:Ce},buienradar:{iconsDay:we,iconsNight:$e},defaulthass:{iconsDay:Ee,iconsNight:ke}},Te=(e,t)=>{const i=Object.keys(t).find((t=>t.toLowerCase()===e.toLowerCase()));return i?t[i]:e},Ue=e=>{const t={en:0,it:1,nl:2,es:3,de:4,fr:5,"sr-latn":6,pt:7,da:8,"no-no":9,cs:10,ru:11};return{locale:{en:"en-US",it:"it-IT",nl:"nl-NL",es:"es-ES",de:"de-DE",fr:"fr-FR","sr-latn":"sr-Latn",pt:"pt-PT",da:"da-DK","no-no":"nb-NO",cs:"cs-CZ",ru:"ru-RU"}[e]||e,timezone:{en:"America/New_York",it:"Europe/Rome",nl:"Europe/Amsterdam",es:"Europe/Madrid",de:"Europe/Berlin",fr:"Europe/Paris","sr-latn":"Europe/Belgrade",ja:"Asia/Tokyo",pt:"Europe/Lisbon",da:"Europe/Copenhagen","no-no":"Europe/Oslo",cs:"Europe/Prague",ru:"Europe/Moscow"}[e]||"UTC",...e in t&&{cwc:t[e]}}},De=e=>({it:"it-IT",en:"en-US",fr:"fr-FR",de:"de-DE",es:"es-ES",ja:"ja-JP",zh:"zh-CN"}[e]||`${e}-${e.toUpperCase()}`),Oe=({stringNumber:e,lang:t="en",fractionDigits:i=1,useGrouping:n=!1})=>{const a=parseFloat(e);if(Number.isNaN(a))return"";const s=((e="en-US",t=1,i=!1)=>new Intl.NumberFormat(e,{minimumFractionDigits:t,maximumFractionDigits:t,useGrouping:i}))(De(t),i,n);return s.format(a)};const Me=(e,t)=>t&&e.states[t]?.state,Le=(e,t,i)=>t&&e.states[t]?.attributes[i],je=({entityId:e,hass:t,lang:i="en",decimals:n=0}={})=>{const a=t&&e&&t.states[e]?.state;return void 0!==a?Oe({stringNumber:a,fractionDigits:n,lang:i}):void 0},Re=(e,t)=>t&&e.states[t]?.attributes?.unit_of_measurement,He=(e,t)=>t&&e.states[t]?.attributes?.icon,Fe=(e,t)=>{const i="number"==typeof e?e:parseFloat(e);if(Number.isNaN(i))return t[e]??null;if(i<0||i>360)return console.error(`Invalid wind direction: '${e}'. Valid values are between 0 and 360 degrees.`),null;return t[["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"][Math.floor((i+11.25)%360/22.5)]]??null};function Ve(e,t=5e3){return new Promise((i=>{const n=new Image,a=setTimeout((()=>{n.src="",i(!1)}),t);n.onload=()=>{clearTimeout(a),i(!0)},n.onerror=()=>{clearTimeout(a),i(!1)},n.src=e}))}function We(e,...t){console.info(e,...t.length?t:[])}function Be(e,t="en-US"){if("number"==typeof e)return e;const i=e.replace(/\./g,"").replace(",",".");return Number(i)}const qe={new_moon:"🌑",new:"🌑",waxing_crescent:"🌒",first_quarter:"🌓",waxing_gibbous:"🌔",full:"🌕",full_moon:"🌕",waning_gibbous:"🌖",third_quarter:"🌗",last_quarter:"🌗",waning_crescent:"🌘"},Ze=o`
ha-card {
cursor: pointer;
position: relative;
width: 100%;
}
.ha-card-weather-conditions {
width: 100%;
box-sizing: border-box;
background-color: var(--card-background-color, #1c1c1c);
color: var(--primary-text-color, #ffffff);
border-radius: var(--ha-card-border-radius, 12px);
box-shadow: var(--ha-card-box-shadow, 0 2px 6px rgba(0, 0, 0, 0.2));
overflow: hidden;
padding: 0;
display: flex;
flex-direction: column;
}
.nd-container {
width: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
padding: 16px 20px; /* ← padding orizzontale più ampio */
gap: 12px;
background-size: cover;
background-position: center;
transition: background-image 0.3s ease-in-out;
}
/* Esempio di stile dinamico aggiuntivo se habgImage è una classe */
.nd-container.sunny {
background-image: url('/local/images/sunny-bg.jpg');
}
.nd-container.rainy {
background-image: url('/local/images/rainy-bg.jpg');
}
/* -------------- */
`,Je=o`
.summary-grid-container {
position: relative;
z-index: 1;
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* <-- 3 colonne reali */
grid-template-rows: auto auto;
width: 100%;
max-width: 600px;
// background: #1c1c1c;
// color: white;
gap: 4px;
padding: 0px;
box-sizing: border-box;
// border: 1px solid #444; /* debug */
}
.summary-col-left {
grid-column: 1;
grid-row: 1 / span 2;
// background: #2c2c2c;
padding-top: 0px;
padding-right: 0px;
padding-bottom: 0px;
padding-left: 0px;
display: flex; /* Attiva Flexbox */
justify-content: center; /* Centra orizzontalmente */
align-items: center; /* Centra verticalmente */
width: 100%;
max-width: 100%;
aspect-ratio: 1 / 1; /* opzionale: mantiene forma quadrata */
overflow: hidden;
}
.summary-top-right {
grid-column: 2 / span 2; /* occupa colonne 2 e 3 */
grid-row: 1;
// background: #3c3c3c;
padding-top: 0px;
padding-right: 8px;
padding-bottom: 0px;
padding-left: 8px;
display: flex; /* aggiunto */
align-items: center; /* centra verticalmente */
justify-content: flex-start; /* allinea a sinistra */
}
.summary-bottom-right-left {
grid-column: 2;
grid-row: 2;
// background: #4c4c4c;
padding-top: 0px;
padding-right: 8px;
padding-bottom: 0px;
padding-left: 8px;
display: flex; /* Attiva Flexbox */
justify-content: center; /* Centra orizzontalmente */
align-items: center; /* Centra verticalmente */
}
.summary-bottom-right-right {
grid-column: 3;
grid-row: 2;
// background: #5c5c5c;
padding-top: 0px;
padding-right: 8px;
padding-bottom: 0px;
padding-left: 8px;
}
.weather-condition-icon {
width: 100%;
height: auto;
max-width: 100%;
max-height: 100%;
object-fit: contain;
// max-width: 100%;
// max-height: 100%;
// width: 72px;
// height: 72px;
// object-fit: contain;
transition: transform 0.2s ease;
}
.summary-col-left:hover .weather-condition-icon {
transform: scale(1.05);
}
.weather-city-name {
font-size: clamp(1em, 2vw, 1.2em);
text-align: left;
}
.moon-row {
display: flex;
align-items: center;
gap: 6px;
// font-size: 0.95em;
// color: #eeeeee;
}
.summary-moon-icon {
font-size: 1.8em;
display: inline-block;
}
.temperature-block {
display: flex;
flex-direction: column;
align-items: flex-end;
text-align: right;
}
.temperature {
font-size: 1.6em;
font-weight: bold;
}
.temp-unit {
font-size: 0.95em;
vertical-align: super;
margin-left: 2px;
}
.feels-like {
font-size: 0.85em;
// color: #aaaaaa;
}
.summary-wrapper {
position: relative;
width: 100%;
height: 100%;
min-height: 100px; /* oppure clamp() dinamico */
overflow: visible;
}
.lightning-background {
position: absolute;
inset: 0; /* top: 0; right: 0; bottom: 0; left: 0 */
pointer-events: none;
z-index: 0;
}
.lightning-flash {
position: absolute;
width: 2px;
background: white;
opacity: 0.7;
transform: translate(-50%, -50%);
animation-name: flash-blink;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
border-radius: 1px;
filter: blur(0.5px);
box-shadow: 0 0 4px rgba(255,255,255,0.6);
z-index: 0;
}
@keyframes flash-blink {
0%, 100% {
opacity: 0.1;
}
50% {
opacity: 0.9;
}
}
.lightning-flash-zigzag {
position: absolute;
width: 2px;
height: 0;
background: linear-gradient(to bottom, yellow, white);
clip-path: polygon(var(--points));
animation: flash-zigzag linear forwards;
z-index: 3;
}
@keyframes flash-zigzag {
0% {
opacity: 1;
transform: scaleY(1);
}
100% {
opacity: 0;
transform: scaleY(1.2);
}
}
.lightning-svg {
position: absolute;
transform: translate(-50%, 0);
opacity: 0;
filter: drop-shadow(0 0 4px rgba(98, 61, 173, 0.6));
animation-name: flash-zigzag-svg;
animation-timing-function: ease-in-out;
animation-iteration-count: 1;
z-index: 3;
}
@keyframes flash-zigzag-svg {
0%, 100% {
opacity: 0;
}
40% {
opacity: 1;
}
60% {
opacity: 0.5;
}
}
`,Ye=o`
.present-grid-container {
display: flex;
flex-direction: column;
gap: 4px;
}
.present-row {
display: flex;
justify-content: space-between;
gap: 16px;
}
.present-left,
.present-right {
flex: 1;
}
.present-left {
display: flex;
justify-content: flex-start;
}
.present-right {
display: flex;
justify-content: flex-end;
}
.present-value-block {
display: flex;
align-items: center;
gap: 4px;
}
.present-unit {
font-size: 0.9em;
opacity: 0.8;
}
`,Qe=o`
.ultraviolet-grid-container {
display: flex;
flex-direction: column;
gap: 4px;
}
.ultraviolet-row {
display: flex;
justify-content: space-between;
gap: 16px;
}
.ultraviolet-left,
.present-right {
flex: 1;
}
.ultraviolet-left {
display: flex;
justify-content: flex-start;
}
.ultraviolet-right {
display: flex;
justify-content: flex-end;
}
.ultraviolet-value-block {
display: flex;
align-items: center;
gap: 4px;
}
.ultraviolet-unit {
font-size: 0.9em;
opacity: 0.8;
}
------------------------------------------------------------------
// .ultraviolet-grid-container {
// display: flex;
// flex-direction: column;
// gap: 12px;
// }
// .ultraviolet-row {
// display: flex;
// justify-content: space-between;
// padding: 4px 0;
// }
// .ultraviolet-value-block {
// display: flex;
// align-items: center;
// gap: 4px;
// }
// .ultraviolet-unit {
// font-size: 0.9em;
// opacity: 0.7;
// }
.ultraviolet-skin-type-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
gap: 8px;
margin-top: 8px;
}
.ultraviolet-skin-type-cell {
flex: 1;
min-width: 48px;
height: 48px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 6px;
font-family: 'Segoe UI', sans-serif;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
color: black;
}
.ultraviolet-skin-type-label {
font-weight: bold;
font-size: 0.95em;
line-height: 1em;
}
.ultraviolet-exposure-time {
font-size: 0.75em;
margin-top: 2px;
color: #222;
opacity: 0.85;
}
`,Ke=o`
.pollen-grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
gap: 8px 12px;
width: 100%;
justify-items: center;
align-items: end;
padding: 8px 4px;
box-sizing: border-box;
}
.pollen-stack {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
min-width: 48px;
}
.levels {
display: flex;
flex-direction: column-reverse;
gap: clamp(1px, 0.2vw, 2px);
}
.level {
width: clamp(16px, 3.5vw, 24px);
height: clamp(5px, 0.7vw, 8px); /* 👈 anche in altezza */
border-radius: 3px;
opacity: 0.3;
transition: opacity 0.2s ease;
}
.level.active {
opacity: 1;
outline: 1px solid #333;
}
.molto-alto {
background-color: #f44336;
}
.alto {
background-color: #ff9800;
}
.moderato {
background-color: #ffeb3b;
}
.basso {
background-color: #4caf50;
}
.pollen-name {
font-size: clamp(0.55em, 1.3vw, 0.85em); /* 👈 stringe di più */
// font-weight: 500;
text-align: center;
// color: #333;
white-space: nowrap;
}
.label {
width: 100%;
text-align: center;
font-size: clamp(0.55em, 1.3vw, 0.85em);
// font-weight: 500;
margin-top: clamp(4px, 0.5vw, 8px);
}
`,Ge=o`
.camera-container {
margin-top: 10px;
width: 100%;
display: flex;
align-items: stretch;
}
.camera-image {
aspect-ratio: 16 / 9;
width: 100%;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.camera-image > img {
width: 100%;
height: 100%;
object-fit: cover;
}
`,Xe=o`
.weather-forecast-grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
column-gap: 2px; /* spazio orizzontale tra i giorni */
row-gap: 6px; /* spazio verticale tra righe, se ci sono */
align-items: stretch;
font-family: 'Segoe UI', sans-serif;
width: 100%;
}
.weather-forecast-grid-wrapper {
display: flex;
flex-direction: column;
align-items: center; /* centrare il titolo orizzontalmente */
}
.weather-forecast-title {
font-size: clamp(0.85em, 1vw, 0.95em);
font-weight: bold;
// margin-bottom: 0.5em;
text-align: center;
}
.weather-forecast-slot {
text-align: center;
padding: 8px 4px;
min-width: 0;
overflow: hidden;
}
.weather-forecast-slot:last-child {
border-right: none;
}
.weather-forecast-label-slot {
font-size: 0.9em;
font-weight: bold;
margin-bottom: 6px; /* ridotto */
}
.weather-forecast-icon {
font-size: 1.6rem; /* ridotto */
/* margin: 6px 0; ridotto */
height: 32px;
}
.weather-forecast-temperature {
font-size: clamp(0.8em, 1vw, 0.9em); /* leggermente più piccolo */
margin: 4px 0; /* meno margine */
}
.weather-forecast-temperature .high {
font-weight: bold;
}
.weather-forecast-precipitation {
font-size: clamp(0.65em, 1vw, 0.75em);
line-height: 1.2; /* compatta verticalmente */
}
.weather-forecast-precipitation .mm {
font-weight: bold;
}
`,et=o`
.meteodcpalarm-grid-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 16px;
padding: 12px;
}
.meteodcpalarm-group {
display: flex;
flex-direction: column;
align-items: center;
flex: 1 1 72px; /* 👈 cresce, ma non scende sotto i 72px */
max-width: 220px; /* 👈 opzionale: previene allargamento eccessivo */
text-align: center;
}
.meteodcpalarm-group ha-icon {
--mdc-icon-size: 36px;
}
.meteodcpalarm-label {
margin-top: 6px;
font-size: 0.85em;
color: var(--primary-text-color);
}
`,tt=(e,t,i)=>{const n="below_horizon"===i,a=(n?t.iconsNight:t.iconsDay)[e];return t.path||console.info("Image path not found."),a?`${t.path}/${t.iconType}/${a}.svg`:(console.info(`Icons issue. Model=${t.icons_model}, Time=${n?"night":"day"}, Condition=${e}`),"")};function it(e){return!!e&&e.themes.darkMode}async function nt(){const[e,t]=await Promise.all([Ve(`${me}/static/cloudy.svg`),Ve(`${ge}/static/cloudy.svg`)]);let i=null;if(i=e?me:t?ge:null,!i)return We(`${pe} - Impossibile determinare il path immagini.`),{translations:[],imagePath:null};const n=`${i}/../transl/`;return{translations:await Promise.all(["en","it","nl","es","de","fr","sr-latn","pt","da","no-NO","cs"].map((e=>async function(e){try{const t=await fetch(e);if(!t.ok){const i=`ERROR retrieving JSON file: '${e}', status: ${t.status} ${t.statusText}`;throw console.info(i),new Error(i)}return console.info(`Locale '${e}' loaded`),await t.text()}catch(t){throw console.info(`Fetch failed for '${e}':`,t),t}}(`${n}${e}.json`)))),imagePath:i}}class at extends oe{constructor(){super(...arguments),this.isPanel=!1,this.editMode=!1,this.invalidConfig=!1,this._hasPresent=!1,this._hasDailyForecasts=!1,this._hasHourlyForecasts=!1,this._hasMarineDailyForecasts=!1,this._hasMarineHourlyForecasts=!1,this._hasMetealarm=!1,this._hasDPCalarm=!1,this._hasMeteogram=!1,this._hasAirQuality=!1,this._hasPollen=!1,this._hasUltraviolet=!1,this._hasAlert=!1,this._hasSea=!1,this._hasCamera=!1}updated(e){if(super.updated(e),e.has("hass")&&this.hass){const t=it(e.get("hass")),i=it(this.hass);t!==i&&this.toggleAttribute("dark-mode",i)}}static get styles(){return[o`
:host {
${he}
}
:host([dark-mode]) {
${ue}
}
${o`
${Ze}
${Je}
${Ye}
${Xe}
${Qe}
${Ke}
${Ge}
${et}
`}
`]}async setConfig(e){if(!e)throw this.invalidConfig=!0,new Error("Invalid configuration");if(!this._translations?.length||!this._imagesPath){const{translations:e,imagePath:t}=await nt();this._translations=e,this._imagesPath=t}this._name=e?.weather?.name??void 0,this._language=e.language?.toLowerCase()||"en",this._loadTranslations(this._language),this._detectDataSections(e),this._setupIcons(e.weather?.icons_model),this._config=e,We(`${pe} - Config loaded.`)}getCardSize(){return 1}_loadTranslations(e){try{const t=JSON.parse(this._translations[_e[e]]);this._terms={windDirections:t.cwcLocWindDirections,words:t.cwcTerms},We(`${pe}%c card "${this._name}", locale is '${e}'.`,ye,fe,ve)}catch(t){const i="en",n=JSON.parse(this._translations[_e[i]]);this._terms={windDirections:n.cwcLocWindDirections,words:n.cwcTerms},We(`${pe}%c card "${this._name}" unable to use '${e}' locale, set as default '${i}'.`,ye,fe,ve)}}_detectDataSections(e){this._hasPresent=!!e.weather?.present,this._hasDailyForecasts=!!e.weather?.daily_forecasts,this._hasHourlyForecasts=!!e.weather?.hourly_forecasts,this._hasMarineDailyForecasts=!!e.weather?.marine_daily_forecasts,this._hasMarineHourlyForecasts=!!e.weather?.marine_hourly_forecasts,this._hasMetealarm=!!e.weather?.meteoalarm,this._hasDPCalarm=!!e.weather?.dpcalarm,this._hasAirQuality=!!e.airquality,this._hasPollen=e.pollen&&Array.isArray(e.pollen.entities)&&e.pollen.entities.length>0,this._hasUltraviolet=!!e.ultraviolet,this._hasCamera=!!e.camera}_setupIcons(e){if(this._iconsConfig={path:this._imagesPath,iconType:this._config?.weather?.animation?"animated":"static",icons_model:e||"pirateweather",iconsDay:Ie,iconsNight:Ne},e){const t=(e=>{const t=e.toLowerCase()??"climacell";if(t in Pe){const{iconsDay:e,iconsNight:i}=Pe[t];return{iconsModel:t,iconsDay:e,iconsNight:i}}console.warn(`Unknown icons model: ${t}. Falling back to 'climacell'.`);const i=Pe.climacell;return{iconsModel:"climacell",iconsDay:i.iconsDay,iconsNight:i.iconsNight}})(e);this._iconsConfig.icons_model=t.iconsModel,this._iconsConfig.iconsDay=t.iconsDay,this._iconsConfig.iconsNight=t.iconsNight}}render(){return this.invalidConfig?F`
Configuration ERROR!
`:this._render()}}e([de({attribute:!1})],at.prototype,"hass",void 0),e([de({attribute:!1})],at.prototype,"_config",void 0);const st=(e,t,i,n,a,s,o,r)=>{const l=Me(e,r),c=l?qe[l.toLowerCase()]:"";const d=Me(e,o),h=Me(e,s.condition)?.toLowerCase()||"na",u=s.temperature?je({entityId:s.temperature,hass:e,lang:t})??void 0:void 0,p=s.temperature_feelslike?je({entityId:s.temperature_feelslike,hass:e,lang:t})??void 0:void 0,m=e.states[s.temperature_feelslike]?.attributes.icon??"";return(({title:e,moonText:t,moonIcon:i,conditionText:n,conditionIcon:a,temperature:s,temperatureUnit:o,feelsLikeTerm:r,temperatureFeelsLike:l,temperatureFeelsLikeIcon:c})=>a||t||s?F`
${W}
${a?F`
`:W}
${e?F`
${e}
`:W}
${t?F`
`:W}
${s?F`
`:W}
`:F``)({title:a??void 0,moonText:r?Te(l,i.words):void 0,moonIcon:c,conditionText:h,conditionIcon:tt(h,n,d),temperature:u,temperatureUnit:Re(e,s.temperature),feelsLikeTerm:Te("Feels Like",i.words),temperatureFeelsLike:p,temperatureFeelsLikeIcon:m})},ot=e=>"string"==typeof e||"number"==typeof e,rt=(e,t)=>{const i=[],n=e.precipitationIntensity?.value,a=e.precipitationProbability?.value;if(ot(n)&&ot(a)){const s=De(t),o=Be(n,s),r=Be(a,s);!Number.isNaN(Number(o))&&!Number.isNaN(Number(r))&&o>0&&r>0&&i.push({icon:e.precipitationIntensity.icon||e.precipitationProbability.icon||"mdi:weather-rainy",value:`${e.precipitationIntensity.value} ${e.precipitationIntensity.unit} / ${e.precipitationProbability.value} ${e.precipitationProbability.unit}`})}void 0!==e.temperatureLow?.value&&void 0!==e.temperatureHigh?.value&&i.push({icon:e.temperatureLow.icon||e.temperatureHigh.icon||"mdi:thermometer",value:`${e.temperatureLow.value} / ${e.temperatureHigh.value}`,unit:e.temperatureLow.unit||e.temperatureHigh.unit});return["humidity","pressure","visibility"].forEach((t=>{return n=e[t],void(void 0!==n?.value&&i.push(n));var n})),void 0===e.windSpeed?.value&&void 0===e.windBearing?.value||i.push({icon:e.windSpeed?.icon||"mdi:weather-windy",value:`${e.windBearing?.value?`${e.windBearing.value} `:""}${e.windSpeed?.value??""}`,unit:e.windSpeed?.unit?`${e.windSpeed.unit}`:""}),["nextRising","nextSetting"].forEach((t=>{const n=e[t];n?.value&&i.push({icon:n.icon,value:n.value,unit:""})})),i},lt=(e,t)=>{const i=[];return["epa_aqi","epa_primary_pollutant","pm25","pm10","o3","no2","co","so2"].forEach((t=>{return n=e[t],void(void 0!==n?.value&&i.push(n));var n})),i},ct=(e,t)=>{const i=[],n=e=>F`
${e.value}${e.unit?F`${e.unit} `:""}
`;i.push(...rt(e,t),...lt(e));const a=[];for(let e=0;e
${t?(s=t,F`
${s.value}${s.unit?F`${s.unit} `:""}
`):F``}
${o?n(o):F``}
`)}var s;return a.length>0?F`
${a}
`:F``},dt=(e,t,i,n,a)=>{const s=t||e.selectedLanguage||e.language,o=((e,t,i,n,a)=>{const s=Ue(t),o=a?e.states[a]:void 0,{next_rising:r,next_setting:l}=o?.attributes??{};return{nextRising:{value:r?new Date(r).toLocaleTimeString(s.locale,{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1,timeZone:s.timezone}):void 0,icon:"mdi:weather-sunset-up"},nextSetting:{value:r?new Date(l).toLocaleTimeString(s.locale,{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1,timeZone:s.timezone}):void 0,icon:"mdi:weather-sunset-down"},precipitationIntensity:{value:je({entityId:n.precipitation_intensity,hass:e,lang:t,decimals:2}),unit:Re(e,n.precipitation_intensity),icon:"mdi:weather-rainy"},precipitationProbability:{value:je({entityId:n.precipitation_probability,hass:e,lang:t,decimals:0}),unit:Re(e,n.precipitation_probability),icon:"mdi:weather-rainy"},humidity:{value:je({entityId:n.humidity,hass:e,lang:t,decimals:0}),unit:Re(e,n.humidity),icon:"mdi:water-percent"},windBearing:{value:Fe(Me(e,n.wind_bearing),i)},windSpeed:{value:je({entityId:n.wind_speed,hass:e,lang:t,decimals:0}),unit:Re(e,n.wind_speed),icon:"mdi:weather-windy"},pressure:{value:je({entityId:n.pressure,hass:e,lang:t,decimals:0}),unit:Re(e,n.pressure),icon:"mdi:gauge"},visibility:{value:je({entityId:n.visibility,hass:e,lang:t,decimals:0}),unit:Re(e,n.visibility),icon:"mdi:weather-fog"},temperatureHigh:{value:je({entityId:n.temperature_max,hass:e,lang:t,decimals:0}),unit:Re(e,n.temperature_max),icon:"mdi:thermometer"},temperatureLow:{value:je({entityId:n.temperature_min,hass:e,lang:t,decimals:0}),unit:Re(e,n.temperature_min),icon:"mdi:thermometer"}}})(e,s,i.windDirections,n,a);return ct({...o},s)},ht=["I","II","III","IV","V","VI"],ut=["#F1D1B1","#E4B590","#CF9F7D","#B67851","#A15E2D","#513938"],pt=(e,t)=>{const i=[],n=e=>F`
${e.value}${e.unit?F`${e.unit} `:""}
`,a=(e,t)=>{void 0!==t?.value&&i.push(t)};let s=["protectionWindow","currentUVLevel"];s.forEach((t=>a(0,e[t]))),void 0!==e.currentUVIndex?.value&&void 0!==e.maxUVIndex?.value&&i.push({icon:e.currentUVIndex.icon||e.maxUVIndex.icon||"mdi:weather-sunny",value:`${e.currentUVIndex.value} / ${e.maxUVIndex.value}`,unit:e.currentUVIndex.unit||e.maxUVIndex.unit}),s=["currentOzoneLevel"],s.forEach((t=>a(0,e[t])));const o=[];for(let e=0;e
${t?(r=t,F`
${r.value}${r.unit?F`${r.unit} `:""}
`):F``}
${a?n(a):F``}
`)}var r;const l=[t.skinType1,t.skinType2,t.skinType3,t.skinType4,t.skinType5,t.skinType6],c=F`
${l.map(((e,t)=>{const i=ut[t],n=(e=>{const t=e.replace("#","");return(299*parseInt(t.substr(0,2),16)+587*parseInt(t.substr(2,2),16)+114*parseInt(t.substr(4,2),16))/1e3>125?"#000":"#fff"})(i);return F`
${ht[t]}
${e.value||"--"}
`}))}
`;return F`
${o}
${c}
`},mt=e=>{const t="string"==typeof e&&"unknown"===e.toLowerCase()?NaN:Number(e);if(!Number.isFinite(t)||t<0)return"--";const i=Math.floor(t/60),n=t%60;return i>0?`${i}:${function(e,t,i="0"){return e.toString().padStart(t,i)}(n,2)} h`:`${n} m`},gt=(e,t,i)=>({protectionWindow:{value:Me(e,i.protection_window)&&"unknown"!==Me(e,i.protection_window)?Me(e,i.protection_window):"off",icon:"mdi:sunglasses"},currentUVLevel:{value:Me(e,i.uv_level),icon:"mdi:weather-sunny"},currentUVIndex:{value:je({entityId:i.uv_index,hass:e,lang:t}),unit:"UV Idx",icon:"mdi:weather-sunny"},maxUVIndex:{value:je({entityId:i.max_uv_index,hass:e,lang:t}),unit:"UV Idx",icon:"mdi:weather-sunny"},currentOzoneLevel:{value:je({entityId:i.ozone_level,hass:e,lang:t}),unit:"DU",icon:"mdi:vector-triangle"}}),yt=(e,t,i)=>({skinType1:{value:mt(je({entityId:i.set_skin_type_1,hass:e,lang:t}))},skinType2:{value:mt(je({entityId:i.set_skin_type_2,hass:e,lang:t}))},skinType3:{value:mt(je({entityId:i.set_skin_type_3,hass:e,lang:t}))},skinType4:{value:mt(je({entityId:i.set_skin_type_4,hass:e,lang:t}))},skinType5:{value:mt(je({entityId:i.set_skin_type_5,hass:e,lang:t}))},skinType6:{value:mt(je({entityId:i.set_skin_type_6,hass:e,lang:t}))}}),ft=["basso","moderato","alto","molto-alto","estremo"],vt=(e,t,i)=>{const n=i-t+1,a=ft.slice(0,n);return 0===e.length?F``:F`
${e.map((e=>{const n=((e,t,i)=>{const n=(i-t+1)/ft.length,a=Math.floor((e-t)/n);return Math.min(a,ft.length-1)})(e.value,t,i);return F`
`}))}
`},_t=(e,t,i)=>{const n=[];return Array.isArray(i.entities)&&i.entities.length>0&&i.entities.forEach((t=>{const a=Me(e,t.entity);if(a&&"unknown"!==a&&"unavailable"!==a){let a=((e,t="en-US")=>{if("number"==typeof e)return e;const i=new Intl.NumberFormat(t).formatToParts(1234567.89),n=i.find((e=>"group"===e.type))?.value||"",a=i.find((e=>"decimal"===e.type))?.value||".",s=e.replace(new RegExp(`\\${n}`,"g"),"").replace(new RegExp(`\\${a}`),".");return Number(s)})(Me(e,t.entity));(Number.isNaN(a)||ai.max)&&(a=0),n.push({name:t.name,value:a})}})),vt(n,i.min,i.max)},wt=(e,t)=>{const i=t.map((e=>{const t=e.reference?.value,i=e.condition?.img,n=e.condition?.icon,a=e.condition?.iconColor,s=e.temperature_low?.value,o=e.temperature_high?.value,r=e.temperature_high?.unit||e.temperature_low?.unit,l=Number(e.precipitation_probability?.value??0),c=e.precipitation_intensity?.value,d=e.precipitation_intensity?.unit,h=e.temperature?.value,u=e.temperature?.unit||e.temperature_feelslike?.unit,p=e.temperature_feelslike?.value,m=e.wind_speed?.value,g=e.wind_speed?.unit,y=e.wind_bearing?.value,f=e.wind_wave_height_max?.value,v=e.swell_wave_height_max?.value,_=e.wave_height_max?.value,w=e.wave_direction?.value,$=e.wave_direction?.icon,x=e.wave_height_max?.unit;return F`
${t?F`
${t}
`:""}
${i?F`
`:""}
${n?F`
`:""}
${void 0!==s&&void 0!==o?F`
${s} / ${o}${r?` ${r}`:""}
`:""}
${void 0!==h&&void 0!==p?F`
${h} / ${p}${u?` ${u}`:""}
`:""}
${void 0!==m&&void 0!==y?F`
${m} ${g} ${y}
`:""}
${void 0!==_?F`
${_} ${x?` ${x}`:""}
`:""}
${void 0!==w?F`
${$?F` `:""} ${w}
`:""}
${void 0!==f&&void 0!==v?F`
${v} / ${f} ${x?` ${x}`:""}
`:""}
${void 0!==l&&void 0!==c&&0!==l?F`
${l} % / ${c}${d?` ${d}`:""}
`:""}
`}));let n="Daily";return 1===e?n="Hourly":2===e?n="Marine daily":3===e&&(n="Marine hourly"),F`
`},$t=e=>e.includes("temperature")?"mdi:thermometer":e.includes("precipitation")?"mdi:weather-rainy":"mdi:help-circle-outline",xt=(e,t,i,n,a,s,o,r,l,c)=>{const d=[],h=Me(e,c);let u=d;if(n){u=Object.keys(n.condition||n.temperature_high||n.temperature_low||n.precipitation_intensity||n.precipitation_probability||{}).map((i=>((e,t,i,n,a,s,o)=>{const r={},l=Ue(t);let c;if(i.condition&&i.condition[o]&&(r.condition={img:tt(Me(e,i.condition[o]),a,s)}),["temperature_high","temperature_low","precipitation_intensity","precipitation_probability"].forEach((n=>{const a=i[n],s=a?.[o];let l=0;s&&("precipitation_intensity"===n&&(l=2),c=new Date(Le(e,s,"datetime")),r[n]={value:je({entityId:s,hass:e,lang:t,decimals:l}),unit:Re(e,s),img:He(e,s)||$t(n)})})),c&&Object.keys(r).length>0){const e=c.toLocaleDateString(l.locale,{weekday:"short",timeZone:"UTC"}),t=c.toLocaleTimeString(l.locale,{hour:"2-digit",minute:"2-digit",timeZone:l.timezone});r.reference={value:0===n?e.toUpperCase():t}}return r})(e,t,n,r,l,h,i)))}let p=d;if(a){p=Object.keys(a.condition||a.temperature||a.temperature_feelslike||a.precipitation_intensity||a.precipitation_probability||{}).map((n=>((e,t,i,n,a,s,o,r)=>{const l={},c=Ue(t);let d;if(n.condition&&n.condition[r]&&(l.condition={img:tt(Me(e,n.condition[r]),s,o)}),n.wind_bearing&&n.wind_bearing[r]&&(l.wind_bearing={value:Fe(Me(e,n.wind_bearing[r]),i)}),["temperature","temperature_feelslike","precipitation_intensity","precipitation_probability","wind_speed"].forEach((i=>{const a=n[i],s=a?.[r];let o=0;s&&("precipitation_intensity"===i&&(o=2),d=new Date(Le(e,s,"datetime")),l[i]={value:je({entityId:s,hass:e,lang:t,decimals:o}),unit:Re(e,s),img:He(e,s)||$t(i)})})),d&&Object.keys(l).length>0){const e=d.toLocaleTimeString(c.locale,{hour:"2-digit",minute:"2-digit",timeZone:c.timezone});l.reference={value:e}}return l})(e,t,i.windDirections,a,0,l,h,n)))}let m=d;if(s){m=Object.keys(s.swell_wave_height_max||s.wave_direction||s.wave_height_max||s.wind_wave_height_max||{}).map((n=>((e,t,i,n,a,s,o,r)=>{const l={},c=Ue(t);let d;var h,u,p;if(n.wave_height_max&&n.swell_wave_height_max&&n.wind_wave_height_max&&n.swell_wave_height_max[r]&&n.wind_wave_height_max[r]&&(l.condition={icon:"mdi:flag-variant",iconColor:(h=n.wave_height_max[r],u=n.swell_wave_height_max[r],p=n.wind_wave_height_max[r],h>=1.8||u>=1.5&&p>=.8?"red":h>=1||u>=.8||p>=.6?"yellow":"green")}),n.wave_direction&&n.wave_direction[r]&&(l.wave_direction={value:Fe(Me(e,n.wave_direction[r]),i),icon:Me(e,n.wave_direction[r])}),["wave_height_max","swell_wave_height_max","wind_wave_height_max"].forEach((i=>{const a=n[i],s=a?.[r];s&&(d=new Date(Le(e,s,"datetime")),l[i]={value:je({entityId:s,hass:e,lang:t,decimals:1}),unit:Re(e,s),img:He(e,s)||$t(i)})})),d&&Object.keys(l).length>0){const e=d.toLocaleDateString(c.locale,{weekday:"short",timeZone:"UTC"}),t=d.toLocaleTimeString(c.locale,{hour:"2-digit",minute:"2-digit",timeZone:c.timezone});l.reference={value:2===a?e.toUpperCase():t}}return l})(e,t,i.windDirections,s,r,0,0,n)))}switch(r){case 0:return wt(r,u);case 1:return wt(r,p);case 2:return wt(r,m);default:return wt(r,d)}},bt=(e,t,i,n,a)=>{const s=a&&e.states[a],o=s?.attributes?.entity_picture;return((e,t,i,n)=>i?F`
`:F``)(n,a,o,s?.attributes?.friendly_name??a)};const At=(e,t,i,n)=>{const a={wind:"mdi:weather-windy","snow-ice":"mdi:snowflake-alert",thunderstorm:"mdi:weather-lightning",fog:"mdi:weather-fog","high-temperature":"mdi:weather-sunny-alert","low-temperature":"mdi:thermometer-low","coastal-event":"mdi:home-flood","forest-fire":"mdi:pine-tree-fire",avalanche:"mdi:image-filter-hdr",rain:"mdi:weather-pouring",flood:"mdi:home-flood","rain-flood":"mdi:weather-pouring","marine-hazard":"mdi:weather-hurricane",drought:"mdi:water-off"},s={green:"green",yellow:"#ffa600",orange:"orange",red:"red"},o=n&&e.states[n];if(!o?.attributes)return{};const r={};if("on"===o.state&&o.attributes){const e=Ue(t),{event:i,severity:n,awareness_type:l,awareness_level:c,effective:d}=o.attributes,h=l?.split(";")[1]?.trim().toLowerCase()||"",u=c?.split(";")[1]?.trim().toLowerCase()||"",p=i||"",m=n?.split(";")[1]?.trim()||"";(e=>{const t=new Date(e),i=new Date,n=new Date(i.getFullYear(),i.getMonth(),i.getDate()),a=new Date(t.getFullYear(),t.getMonth(),t.getDate()),s=Math.round((a.getTime()-n.getTime())/864e5);let o;o=0===s?"oggi":1===s?"domani":2===s?"dopodomani":void 0})(d),r.meteoalarm={event:p,severity:m,icon:a[h]||"mdi:alert",icon_color:s[u]||"grey",datetime:new Date(d).toLocaleDateString(e.locale,{weekday:"short",timeZone:e.timezone}).toLocaleUpperCase()}}return r},zt=(e,t,i,n)=>{if(!n)return{};const a=Ue(t),s={0:"gray",1:"green",2:"#ffa600",3:"orange",4:"red"},o={};return["thunderstorms","hydraulic","hydrogeological"].forEach((t=>{const i=n[t],r=i&&e.states[i];if(r&&"on"===r.state&&r.attributes){const{level:e,info:i,icon:n}=r.attributes;o[t]={event:i,severity:e,icon:n,icon_color:s[e],datetime:(new Date).toLocaleDateString(a.locale,{weekday:"short",timeZone:a.timezone}).toLocaleUpperCase()}}})),o},Et=(e,t,i,n,a)=>{const s={...At(e,t,0,n),...zt(e,t,0,a)};return(o=s)&&0!==Object.keys(o).length?F`
${Object.entries(o).map((([e,t])=>F`
`))}
`:F``;var o},{translations:kt,imagePath:St}=await nt();let Ct=class extends at{constructor(){super(...arguments),this._translations=kt,this._imagesPath=St}_render(){return F`
${this._buildTemplate()}
`}_buildTemplate(){let e=F``,t=F``,i=F``,n=F``,a=F``,s=F``,o=F``,r=F``,l=F``,c=F``,d=F``;const h=e=>xt(this.hass,this._language,this._terms,this._config.weather.daily_forecasts,this._config.weather.hourly_forecasts,this._config.weather.marine_daily_forecasts,this._config.weather.marine_hourly_forecasts,e,this._iconsConfig,this._config.weather.sun);var u,p,m;return this._hasPresent&&(e=st(this.hass,this._language,this._terms,this._iconsConfig,this._config.weather?.name,this._config?.weather?.present||null,this._config?.weather?.sun,this._config?.weather?.moonphase)),this._hasPresent&&(t=dt(this.hass,this._language,this._terms,this._config?.weather?.present||{},this._config?.weather?.sun)),(this._hasMetealarm||this._hasDPCalarm)&&(o=Et(this.hass,this._language,this._terms,this._config?.weather?.meteoalarm,this._config?.weather?.dpcalarm)),this._hasDailyForecasts&&(i=h(0)),this._hasHourlyForecasts&&(n=h(1)),this._hasMarineDailyForecasts&&(a=h(2)),this._hasMarineHourlyForecasts&&(s=h(3)),this._hasUltraviolet&&(u=this.hass,p=this._language,m=this._config.ultraviolet,r=pt({...gt(u,p,m)},{...yt(u,p,m)})),this._hasPollen&&(l=_t(this.hass,this._language,this._config.pollen)),this._hasAirQuality&&(c=((e,t,i)=>{const n=t||e.selectedLanguage||e.language,a=je({entityId:i.pm25,hass:e,lang:t,decimals:0}),s=je({entityId:i.pm10,hass:e,lang:t,decimals:0}),o=je({entityId:i.o3,hass:e,lang:t,decimals:1}),r=je({entityId:i.no2,hass:e,lang:t,decimals:0}),l=je({entityId:i.co,hass:e,lang:t,decimals:1}),c=je({entityId:i.so2,hass:e,lang:t,decimals:0}),d=je({entityId:i.epa_aqi,hass:e,lang:t,decimals:0}),h=Me(e,i.epa_primary_pollutant),u={pm25:{value:a?`pm2.5 ${a}`:a,unit:Re(e,i.pm25)||"µg/m³",icon:"mdi:weather-hazy"},pm10:{value:s?`pm10 ${s}`:s,unit:Re(e,i.pm10)||"µg/m³",icon:"mdi:weather-hazy"},o3:{value:o?`o3 ${o}`:o,unit:Re(e,i.o3)||"µg/m³",icon:"mdi:molecule"},no2:{value:r?`no2 ${r}`:r,unit:Re(e,i.no2)||"µg/m³",icon:"mdi:molecule"},co:{value:l?`co ${l}`:l,unit:Re(e,i.co)||"µg/m³",icon:"mdi:molecule"},so2:{value:c?`so2 ${c}`:c,unit:Re(e,i.so2)||"µg/m³",icon:"mdi:molecule"},epa_aqi:{value:d?`Air Quality Index ${d}`:d,icon:"mdi:weather-hazy",icon_color:(p=Number(Me(e,i.epa_aqi)),p<=50?"#009966":p<=100?"#ffde33":p<=150?"#ff9933":p<=200?"#cc0033":p<=300?"#660099":"#7e0023")},epa_primary_pollutant:{value:h?`Primary ${h}`:h,icon:"mdi:weather-hazy"}};var p;return ct(u,n)})(this.hass,this._language,this._config.airquality)),this._hasCamera&&(d=bt(this.hass,this._language,this._terms,this._handlePopup.bind(this),this._config.camera)),F`
${e}
${t}
${n}
${i}
${s}
${a}
${o}
${l}
${r}
${c}
${d}`}_handlePopup(e,t){e.stopPropagation();const i=new Event("hass-more-info",{composed:!0});i.detail={entityId:t},this.dispatchEvent(i)}};Ct=e([(e=>(t,i)=>{void 0!==i?i.addInitializer((()=>{customElements.define(e,t)})):customElements.define(e,t)})("ha-card-weather-conditions")],Ct);export{Ct as HaCardWeatherConditions};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGEtY2FyZC13ZWF0aGVyLWNvbmRpdGlvbnMuanMiLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy90c2xpYi90c2xpYi5lczYuanMiLCIuLi9ub2RlX21vZHVsZXMvQGxpdC9yZWFjdGl2ZS1lbGVtZW50L2Nzcy10YWcuanMiLCIuLi9ub2RlX21vZHVsZXMvQGxpdC9yZWFjdGl2ZS1lbGVtZW50L3JlYWN0aXZlLWVsZW1lbnQuanMiLCIuLi9ub2RlX21vZHVsZXMvbGl0LWh0bWwvbGl0LWh0bWwuanMiLCIuLi9ub2RlX21vZHVsZXMvbGl0LWVsZW1lbnQvbGl0LWVsZW1lbnQuanMiLCIuLi9ub2RlX21vZHVsZXMvQGxpdC9yZWFjdGl2ZS1lbGVtZW50L2RlY29yYXRvcnMvY3VzdG9tLWVsZW1lbnQuanMiLCIuLi9ub2RlX21vZHVsZXMvQGxpdC9yZWFjdGl2ZS1lbGVtZW50L2RlY29yYXRvcnMvcHJvcGVydHkuanMiLCIuLi9zcmMvdXRpbHMvY29sb3JzLnRzIiwiLi4vc3JjL3V0aWxzL2NvbnN0LnRzIiwiLi4vc3JjL2ljb25tb2RlbHMvaW0tYnVpZW5yYWRhci50cyIsIi4uL3NyYy9pY29ubW9kZWxzL2ltLWNsaW1hY2VsbC50cyIsIi4uL3NyYy9pY29ubW9kZWxzL2ltLWRhcmtza3kudHMiLCIuLi9zcmMvaWNvbm1vZGVscy9pbS1oYXNzLnRzIiwiLi4vc3JjL2ljb25tb2RlbHMvaW0tb3BlbndlYXRoZXJtYXAudHMiLCIuLi9zcmMvaWNvbm1vZGVscy9pbS1waXJhdGV3ZWF0aGVyLnRzIiwiLi4vYmFja3VwL3R5cGVzLnRzIiwiLi4vc3JjL3V0aWxzL2hlbHBlci50cyIsIi4uL2JhY2t1cC9oYS1jd2MtY29uc3RzLnRzIiwiLi4vc3JjL2Nzcy9jc3MtYmFzZS1jYXJkLnRzIiwiLi4vc3JjL2Nzcy9jc3Mtc3VtbWFyeS50cyIsIi4uL3NyYy9jc3MvY3NzLXByZXNlbnQudHMiLCIuLi9zcmMvY3NzL2Nzcy11bHRyYXZpb2xldC50cyIsIi4uL3NyYy9jc3MvY3NzLXBvbGxlbi50cyIsIi4uL3NyYy9jc3MvY3NzLWNhbWVyYS50cyIsIi4uL3NyYy9jc3MvY3NzLXdlYXRoZXItZm9yZWNhc3QudHMiLCIuLi9zcmMvY3NzL2Nzcy1tZXRlb2FsYXJtLnRzIiwiLi4vc3JjL3V0aWxzL2hlbHBlci1yZW5kZXIudHMiLCIuLi9zcmMvYmFzZS9sb3ZlbGFjZS1iYXNlLnRzIiwiLi4vc3JjL3RlbXBsYXRlcy90LXN1bW1hcnkudHMiLCIuLi9zcmMvYnVpbGRlci9iLXN1bW1hcnkudHMiLCIuLi9zcmMvdGVtcGxhdGVzL3QtcHJlc2VudC50cyIsIi4uL3NyYy9idWlsZGVyL2ItcHJlc2VudC50cyIsIi4uL3NyYy90ZW1wbGF0ZXMvdC11bHRyYXZpb2xldC50cyIsIi4uL3NyYy9idWlsZGVyL2ItdWx0cmF2aW9sZXQudHMiLCIuLi9zcmMvdGVtcGxhdGVzL3QtcG9sbGVuLnRzIiwiLi4vc3JjL2J1aWxkZXIvYi1wb2xsZW4udHMiLCIuLi9zcmMvdGVtcGxhdGVzL3Qtd2VhdGhlci1mb3JlY2FzdC50cyIsIi4uL3NyYy9idWlsZGVyL2Itd2VhdGhlci1mb3JlY2FzdC50cyIsIi4uL3NyYy9idWlsZGVyL2ItY2FtZXJhLnRzIiwiLi4vc3JjL3RlbXBsYXRlcy90LWNhbWVyYS50cyIsIi4uL3NyYy9idWlsZGVyL2ItYWlycXVhbGl0eS50cyIsIi4uL3NyYy9idWlsZGVyL2ItbWV0ZW9hbGFybS50cyIsIi4uL3NyYy90ZW1wbGF0ZXMvdC1tZXRlb2FsYXJtLnRzIiwiLi4vc3JjL2hhLXdlYXRoZXItZWNhcmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlLCBTdXBwcmVzc2VkRXJyb3IsIFN5bWJvbCwgSXRlcmF0b3IgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXNEZWNvcmF0ZShjdG9yLCBkZXNjcmlwdG9ySW4sIGRlY29yYXRvcnMsIGNvbnRleHRJbiwgaW5pdGlhbGl6ZXJzLCBleHRyYUluaXRpYWxpemVycykge1xyXG4gICAgZnVuY3Rpb24gYWNjZXB0KGYpIHsgaWYgKGYgIT09IHZvaWQgMCAmJiB0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRnVuY3Rpb24gZXhwZWN0ZWRcIik7IHJldHVybiBmOyB9XHJcbiAgICB2YXIga2luZCA9IGNvbnRleHRJbi5raW5kLCBrZXkgPSBraW5kID09PSBcImdldHRlclwiID8gXCJnZXRcIiA6IGtpbmQgPT09IFwic2V0dGVyXCIgPyBcInNldFwiIDogXCJ2YWx1ZVwiO1xyXG4gICAgdmFyIHRhcmdldCA9ICFkZXNjcmlwdG9ySW4gJiYgY3RvciA/IGNvbnRleHRJbltcInN0YXRpY1wiXSA/IGN0b3IgOiBjdG9yLnByb3RvdHlwZSA6IG51bGw7XHJcbiAgICB2YXIgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JJbiB8fCAodGFyZ2V0ID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGNvbnRleHRJbi5uYW1lKSA6IHt9KTtcclxuICAgIHZhciBfLCBkb25lID0gZmFsc2U7XHJcbiAgICBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgIHZhciBjb250ZXh0ID0ge307XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4pIGNvbnRleHRbcF0gPSBwID09PSBcImFjY2Vzc1wiID8ge30gOiBjb250ZXh0SW5bcF07XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4uYWNjZXNzKSBjb250ZXh0LmFjY2Vzc1twXSA9IGNvbnRleHRJbi5hY2Nlc3NbcF07XHJcbiAgICAgICAgY29udGV4dC5hZGRJbml0aWFsaXplciA9IGZ1bmN0aW9uIChmKSB7IGlmIChkb25lKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGFkZCBpbml0aWFsaXplcnMgYWZ0ZXIgZGVjb3JhdGlvbiBoYXMgY29tcGxldGVkXCIpOyBleHRyYUluaXRpYWxpemVycy5wdXNoKGFjY2VwdChmIHx8IG51bGwpKTsgfTtcclxuICAgICAgICB2YXIgcmVzdWx0ID0gKDAsIGRlY29yYXRvcnNbaV0pKGtpbmQgPT09IFwiYWNjZXNzb3JcIiA/IHsgZ2V0OiBkZXNjcmlwdG9yLmdldCwgc2V0OiBkZXNjcmlwdG9yLnNldCB9IDogZGVzY3JpcHRvcltrZXldLCBjb250ZXh0KTtcclxuICAgICAgICBpZiAoa2luZCA9PT0gXCJhY2Nlc3NvclwiKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHZvaWQgMCkgY29udGludWU7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgdHlwZW9mIHJlc3VsdCAhPT0gXCJvYmplY3RcIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZFwiKTtcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmdldCkpIGRlc2NyaXB0b3IuZ2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LnNldCkpIGRlc2NyaXB0b3Iuc2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmluaXQpKSBpbml0aWFsaXplcnMudW5zaGlmdChfKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoXyA9IGFjY2VwdChyZXN1bHQpKSB7XHJcbiAgICAgICAgICAgIGlmIChraW5kID09PSBcImZpZWxkXCIpIGluaXRpYWxpemVycy51bnNoaWZ0KF8pO1xyXG4gICAgICAgICAgICBlbHNlIGRlc2NyaXB0b3Jba2V5XSA9IF87XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRhcmdldCkgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgY29udGV4dEluLm5hbWUsIGRlc2NyaXB0b3IpO1xyXG4gICAgZG9uZSA9IHRydWU7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19ydW5Jbml0aWFsaXplcnModGhpc0FyZywgaW5pdGlhbGl6ZXJzLCB2YWx1ZSkge1xyXG4gICAgdmFyIHVzZVZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRpYWxpemVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhbHVlID0gdXNlVmFsdWUgPyBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnLCB2YWx1ZSkgOiBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB1c2VWYWx1ZSA/IHZhbHVlIDogdm9pZCAwO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcHJvcEtleSh4KSB7XHJcbiAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3ltYm9sXCIgPyB4IDogXCJcIi5jb25jYXQoeCk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zZXRGdW5jdGlvbk5hbWUoZiwgbmFtZSwgcHJlZml4KSB7XHJcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3ltYm9sXCIpIG5hbWUgPSBuYW1lLmRlc2NyaXB0aW9uID8gXCJbXCIuY29uY2F0KG5hbWUuZGVzY3JpcHRpb24sIFwiXVwiKSA6IFwiXCI7XHJcbiAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGYsIFwibmFtZVwiLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHByZWZpeCA/IFwiXCIuY29uY2F0KHByZWZpeCwgXCIgXCIsIG5hbWUpIDogbmFtZSB9KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGcgPSBPYmplY3QuY3JlYXRlKCh0eXBlb2YgSXRlcmF0b3IgPT09IFwiZnVuY3Rpb25cIiA/IEl0ZXJhdG9yIDogT2JqZWN0KS5wcm90b3R5cGUpO1xyXG4gICAgcmV0dXJuIGcubmV4dCA9IHZlcmIoMCksIGdbXCJ0aHJvd1wiXSA9IHZlcmIoMSksIGdbXCJyZXR1cm5cIl0gPSB2ZXJiKDIpLCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XHJcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xyXG4gICAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XHJcbiAgICB9XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcclxuICAgIGZvciAodmFyIHMgPSAwLCBpID0gMCwgaWwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWw7IGkrKykgcyArPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG4gICAgZm9yICh2YXIgciA9IEFycmF5KHMpLCBrID0gMCwgaSA9IDA7IGkgPCBpbDsgaSsrKVxyXG4gICAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxyXG4gICAgICAgICAgICByW2tdID0gYVtqXTtcclxuICAgIHJldHVybiByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheSh0bywgZnJvbSwgcGFjaykge1xyXG4gICAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XHJcbiAgICAgICAgICAgIGlmICghYXIpIGFyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSwgMCwgaSk7XHJcbiAgICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IE9iamVjdC5jcmVhdGUoKHR5cGVvZiBBc3luY0l0ZXJhdG9yID09PSBcImZ1bmN0aW9uXCIgPyBBc3luY0l0ZXJhdG9yIDogT2JqZWN0KS5wcm90b3R5cGUpLCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIsIGF3YWl0UmV0dXJuKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gYXdhaXRSZXR1cm4oZikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGYsIHJlamVjdCk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpZiAoZ1tuXSkgeyBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyBpZiAoZikgaVtuXSA9IGYoaVtuXSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IGZhbHNlIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbnZhciBvd25LZXlzID0gZnVuY3Rpb24obykge1xyXG4gICAgb3duS2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIHx8IGZ1bmN0aW9uIChvKSB7XHJcbiAgICAgICAgdmFyIGFyID0gW107XHJcbiAgICAgICAgZm9yICh2YXIgayBpbiBvKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIGspKSBhclthci5sZW5ndGhdID0gaztcclxuICAgICAgICByZXR1cm4gYXI7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIG93bktleXMobyk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayA9IG93bktleXMobW9kKSwgaSA9IDA7IGkgPCBrLmxlbmd0aDsgaSsrKSBpZiAoa1tpXSAhPT0gXCJkZWZhdWx0XCIpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwga1tpXSk7XHJcbiAgICBfX3NldE1vZHVsZURlZmF1bHQocmVzdWx0LCBtb2QpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcclxuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgZGVmYXVsdDogbW9kIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkSW4oc3RhdGUsIHJlY2VpdmVyKSB7XHJcbiAgICBpZiAocmVjZWl2ZXIgPT09IG51bGwgfHwgKHR5cGVvZiByZWNlaXZlciAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgcmVjZWl2ZXIgIT09IFwiZnVuY3Rpb25cIikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgdXNlICdpbicgb3BlcmF0b3Igb24gbm9uLW9iamVjdFwiKTtcclxuICAgIHJldHVybiB0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyID09PSBzdGF0ZSA6IHN0YXRlLmhhcyhyZWNlaXZlcik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FkZERpc3Bvc2FibGVSZXNvdXJjZShlbnYsIHZhbHVlLCBhc3luYykge1xyXG4gICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB2b2lkIDApIHtcclxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiB2YWx1ZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiT2JqZWN0IGV4cGVjdGVkLlwiKTtcclxuICAgICAgICB2YXIgZGlzcG9zZSwgaW5uZXI7XHJcbiAgICAgICAgaWYgKGFzeW5jKSB7XHJcbiAgICAgICAgICAgIGlmICghU3ltYm9sLmFzeW5jRGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0Rpc3Bvc2UgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgICAgICAgICBkaXNwb3NlID0gdmFsdWVbU3ltYm9sLmFzeW5jRGlzcG9zZV07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChkaXNwb3NlID09PSB2b2lkIDApIHtcclxuICAgICAgICAgICAgaWYgKCFTeW1ib2wuZGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5kaXNwb3NlIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgICAgICAgICAgZGlzcG9zZSA9IHZhbHVlW1N5bWJvbC5kaXNwb3NlXTtcclxuICAgICAgICAgICAgaWYgKGFzeW5jKSBpbm5lciA9IGRpc3Bvc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0eXBlb2YgZGlzcG9zZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiT2JqZWN0IG5vdCBkaXNwb3NhYmxlLlwiKTtcclxuICAgICAgICBpZiAoaW5uZXIpIGRpc3Bvc2UgPSBmdW5jdGlvbigpIHsgdHJ5IHsgaW5uZXIuY2FsbCh0aGlzKTsgfSBjYXRjaCAoZSkgeyByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7IH0gfTtcclxuICAgICAgICBlbnYuc3RhY2sucHVzaCh7IHZhbHVlOiB2YWx1ZSwgZGlzcG9zZTogZGlzcG9zZSwgYXN5bmM6IGFzeW5jIH0pO1xyXG4gICAgfVxyXG4gICAgZWxzZSBpZiAoYXN5bmMpIHtcclxuICAgICAgICBlbnYuc3RhY2sucHVzaCh7IGFzeW5jOiB0cnVlIH0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHZhbHVlO1xyXG5cclxufVxyXG5cclxudmFyIF9TdXBwcmVzc2VkRXJyb3IgPSB0eXBlb2YgU3VwcHJlc3NlZEVycm9yID09PSBcImZ1bmN0aW9uXCIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbiAoZXJyb3IsIHN1cHByZXNzZWQsIG1lc3NhZ2UpIHtcclxuICAgIHZhciBlID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xyXG4gICAgcmV0dXJuIGUubmFtZSA9IFwiU3VwcHJlc3NlZEVycm9yXCIsIGUuZXJyb3IgPSBlcnJvciwgZS5zdXBwcmVzc2VkID0gc3VwcHJlc3NlZCwgZTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2Rpc3Bvc2VSZXNvdXJjZXMoZW52KSB7XHJcbiAgICBmdW5jdGlvbiBmYWlsKGUpIHtcclxuICAgICAgICBlbnYuZXJyb3IgPSBlbnYuaGFzRXJyb3IgPyBuZXcgX1N1cHByZXNzZWRFcnJvcihlLCBlbnYuZXJyb3IsIFwiQW4gZXJyb3Igd2FzIHN1cHByZXNzZWQgZHVyaW5nIGRpc3Bvc2FsLlwiKSA6IGU7XHJcbiAgICAgICAgZW52Lmhhc0Vycm9yID0gdHJ1ZTtcclxuICAgIH1cclxuICAgIHZhciByLCBzID0gMDtcclxuICAgIGZ1bmN0aW9uIG5leHQoKSB7XHJcbiAgICAgICAgd2hpbGUgKHIgPSBlbnYuc3RhY2sucG9wKCkpIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIGlmICghci5hc3luYyAmJiBzID09PSAxKSByZXR1cm4gcyA9IDAsIGVudi5zdGFjay5wdXNoKHIpLCBQcm9taXNlLnJlc29sdmUoKS50aGVuKG5leHQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHIuZGlzcG9zZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSByLmRpc3Bvc2UuY2FsbChyLnZhbHVlKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoci5hc3luYykgcmV0dXJuIHMgfD0gMiwgUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCkudGhlbihuZXh0LCBmdW5jdGlvbihlKSB7IGZhaWwoZSk7IHJldHVybiBuZXh0KCk7IH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSBzIHw9IDE7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIGZhaWwoZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHMgPT09IDEpIHJldHVybiBlbnYuaGFzRXJyb3IgPyBQcm9taXNlLnJlamVjdChlbnYuZXJyb3IpIDogUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgaWYgKGVudi5oYXNFcnJvcikgdGhyb3cgZW52LmVycm9yO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5leHQoKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmV3cml0ZVJlbGF0aXZlSW1wb3J0RXh0ZW5zaW9uKHBhdGgsIHByZXNlcnZlSnN4KSB7XHJcbiAgICBpZiAodHlwZW9mIHBhdGggPT09IFwic3RyaW5nXCIgJiYgL15cXC5cXC4/XFwvLy50ZXN0KHBhdGgpKSB7XHJcbiAgICAgICAgcmV0dXJuIHBhdGgucmVwbGFjZSgvXFwuKHRzeCkkfCgoPzpcXC5kKT8pKCg/OlxcLlteLi9dKz8pPylcXC4oW2NtXT8pdHMkL2ksIGZ1bmN0aW9uIChtLCB0c3gsIGQsIGV4dCwgY20pIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRzeCA/IHByZXNlcnZlSnN4ID8gXCIuanN4XCIgOiBcIi5qc1wiIDogZCAmJiAoIWV4dCB8fCAhY20pID8gbSA6IChkICsgZXh0ICsgXCIuXCIgKyBjbS50b0xvd2VyQ2FzZSgpICsgXCJqc1wiKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuICAgIHJldHVybiBwYXRoO1xyXG59XHJcblxyXG5leHBvcnQgZGVmYXVsdCB7XHJcbiAgICBfX2V4dGVuZHM6IF9fZXh0ZW5kcyxcclxuICAgIF9fYXNzaWduOiBfX2Fzc2lnbixcclxuICAgIF9fcmVzdDogX19yZXN0LFxyXG4gICAgX19kZWNvcmF0ZTogX19kZWNvcmF0ZSxcclxuICAgIF9fcGFyYW06IF9fcGFyYW0sXHJcbiAgICBfX2VzRGVjb3JhdGU6IF9fZXNEZWNvcmF0ZSxcclxuICAgIF9fcnVuSW5pdGlhbGl6ZXJzOiBfX3J1bkluaXRpYWxpemVycyxcclxuICAgIF9fcHJvcEtleTogX19wcm9wS2V5LFxyXG4gICAgX19zZXRGdW5jdGlvbk5hbWU6IF9fc2V0RnVuY3Rpb25OYW1lLFxyXG4gICAgX19tZXRhZGF0YTogX19tZXRhZGF0YSxcclxuICAgIF9fYXdhaXRlcjogX19hd2FpdGVyLFxyXG4gICAgX19nZW5lcmF0b3I6IF9fZ2VuZXJhdG9yLFxyXG4gICAgX19jcmVhdGVCaW5kaW5nOiBfX2NyZWF0ZUJpbmRpbmcsXHJcbiAgICBfX2V4cG9ydFN0YXI6IF9fZXhwb3J0U3RhcixcclxuICAgIF9fdmFsdWVzOiBfX3ZhbHVlcyxcclxuICAgIF9fcmVhZDogX19yZWFkLFxyXG4gICAgX19zcHJlYWQ6IF9fc3ByZWFkLFxyXG4gICAgX19zcHJlYWRBcnJheXM6IF9fc3ByZWFkQXJyYXlzLFxyXG4gICAgX19zcHJlYWRBcnJheTogX19zcHJlYWRBcnJheSxcclxuICAgIF9fYXdhaXQ6IF9fYXdhaXQsXHJcbiAgICBfX2FzeW5jR2VuZXJhdG9yOiBfX2FzeW5jR2VuZXJhdG9yLFxyXG4gICAgX19hc3luY0RlbGVnYXRvcjogX19hc3luY0RlbGVnYXRvcixcclxuICAgIF9fYXN5bmNWYWx1ZXM6IF9fYXN5bmNWYWx1ZXMsXHJcbiAgICBfX21ha2VUZW1wbGF0ZU9iamVjdDogX19tYWtlVGVtcGxhdGVPYmplY3QsXHJcbiAgICBfX2ltcG9ydFN0YXI6IF9faW1wb3J0U3RhcixcclxuICAgIF9faW1wb3J0RGVmYXVsdDogX19pbXBvcnREZWZhdWx0LFxyXG4gICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldDogX19jbGFzc1ByaXZhdGVGaWVsZEdldCxcclxuICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQ6IF9fY2xhc3NQcml2YXRlRmllbGRTZXQsXHJcbiAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkSW46IF9fY2xhc3NQcml2YXRlRmllbGRJbixcclxuICAgIF9fYWRkRGlzcG9zYWJsZVJlc291cmNlOiBfX2FkZERpc3Bvc2FibGVSZXNvdXJjZSxcclxuICAgIF9fZGlzcG9zZVJlc291cmNlczogX19kaXNwb3NlUmVzb3VyY2VzLFxyXG4gICAgX19yZXdyaXRlUmVsYXRpdmVJbXBvcnRFeHRlbnNpb246IF9fcmV3cml0ZVJlbGF0aXZlSW1wb3J0RXh0ZW5zaW9uLFxyXG59O1xyXG4iLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlXG4gKi9cbmNvbnN0IHQ9Z2xvYmFsVGhpcyxlPXQuU2hhZG93Um9vdCYmKHZvaWQgMD09PXQuU2hhZHlDU1N8fHQuU2hhZHlDU1MubmF0aXZlU2hhZG93KSYmXCJhZG9wdGVkU3R5bGVTaGVldHNcImluIERvY3VtZW50LnByb3RvdHlwZSYmXCJyZXBsYWNlXCJpbiBDU1NTdHlsZVNoZWV0LnByb3RvdHlwZSxzPVN5bWJvbCgpLG89bmV3IFdlYWtNYXA7Y2xhc3Mgbntjb25zdHJ1Y3Rvcih0LGUsbyl7aWYodGhpcy5fJGNzc1Jlc3VsdCQ9ITAsbyE9PXMpdGhyb3cgRXJyb3IoXCJDU1NSZXN1bHQgaXMgbm90IGNvbnN0cnVjdGFibGUuIFVzZSBgdW5zYWZlQ1NTYCBvciBgY3NzYCBpbnN0ZWFkLlwiKTt0aGlzLmNzc1RleHQ9dCx0aGlzLnQ9ZX1nZXQgc3R5bGVTaGVldCgpe2xldCB0PXRoaXMubztjb25zdCBzPXRoaXMudDtpZihlJiZ2b2lkIDA9PT10KXtjb25zdCBlPXZvaWQgMCE9PXMmJjE9PT1zLmxlbmd0aDtlJiYodD1vLmdldChzKSksdm9pZCAwPT09dCYmKCh0aGlzLm89dD1uZXcgQ1NTU3R5bGVTaGVldCkucmVwbGFjZVN5bmModGhpcy5jc3NUZXh0KSxlJiZvLnNldChzLHQpKX1yZXR1cm4gdH10b1N0cmluZygpe3JldHVybiB0aGlzLmNzc1RleHR9fWNvbnN0IHI9dD0+bmV3IG4oXCJzdHJpbmdcIj09dHlwZW9mIHQ/dDp0K1wiXCIsdm9pZCAwLHMpLGk9KHQsLi4uZSk9Pntjb25zdCBvPTE9PT10Lmxlbmd0aD90WzBdOmUucmVkdWNlKCgoZSxzLG8pPT5lKyh0PT57aWYoITA9PT10Ll8kY3NzUmVzdWx0JClyZXR1cm4gdC5jc3NUZXh0O2lmKFwibnVtYmVyXCI9PXR5cGVvZiB0KXJldHVybiB0O3Rocm93IEVycm9yKFwiVmFsdWUgcGFzc2VkIHRvICdjc3MnIGZ1bmN0aW9uIG11c3QgYmUgYSAnY3NzJyBmdW5jdGlvbiByZXN1bHQ6IFwiK3QrXCIuIFVzZSAndW5zYWZlQ1NTJyB0byBwYXNzIG5vbi1saXRlcmFsIHZhbHVlcywgYnV0IHRha2UgY2FyZSB0byBlbnN1cmUgcGFnZSBzZWN1cml0eS5cIil9KShzKSt0W28rMV0pLHRbMF0pO3JldHVybiBuZXcgbihvLHQscyl9LFM9KHMsbyk9PntpZihlKXMuYWRvcHRlZFN0eWxlU2hlZXRzPW8ubWFwKCh0PT50IGluc3RhbmNlb2YgQ1NTU3R5bGVTaGVldD90OnQuc3R5bGVTaGVldCkpO2Vsc2UgZm9yKGNvbnN0IGUgb2Ygbyl7Y29uc3Qgbz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3R5bGVcIiksbj10LmxpdE5vbmNlO3ZvaWQgMCE9PW4mJm8uc2V0QXR0cmlidXRlKFwibm9uY2VcIixuKSxvLnRleHRDb250ZW50PWUuY3NzVGV4dCxzLmFwcGVuZENoaWxkKG8pfX0sYz1lP3Q9PnQ6dD0+dCBpbnN0YW5jZW9mIENTU1N0eWxlU2hlZXQ/KHQ9PntsZXQgZT1cIlwiO2Zvcihjb25zdCBzIG9mIHQuY3NzUnVsZXMpZSs9cy5jc3NUZXh0O3JldHVybiByKGUpfSkodCk6dDtleHBvcnR7biBhcyBDU1NSZXN1bHQsUyBhcyBhZG9wdFN0eWxlcyxpIGFzIGNzcyxjIGFzIGdldENvbXBhdGlibGVTdHlsZSxlIGFzIHN1cHBvcnRzQWRvcHRpbmdTdHlsZVNoZWV0cyxyIGFzIHVuc2FmZUNTU307XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jc3MtdGFnLmpzLm1hcFxuIiwiaW1wb3J0e2dldENvbXBhdGlibGVTdHlsZSBhcyB0LGFkb3B0U3R5bGVzIGFzIHN9ZnJvbVwiLi9jc3MtdGFnLmpzXCI7ZXhwb3J0e0NTU1Jlc3VsdCxjc3Msc3VwcG9ydHNBZG9wdGluZ1N0eWxlU2hlZXRzLHVuc2FmZUNTU31mcm9tXCIuL2Nzcy10YWcuanNcIjtcbi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMy1DbGF1c2VcbiAqL2NvbnN0e2lzOmksZGVmaW5lUHJvcGVydHk6ZSxnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I6aCxnZXRPd25Qcm9wZXJ0eU5hbWVzOnIsZ2V0T3duUHJvcGVydHlTeW1ib2xzOm8sZ2V0UHJvdG90eXBlT2Y6bn09T2JqZWN0LGE9Z2xvYmFsVGhpcyxjPWEudHJ1c3RlZFR5cGVzLGw9Yz9jLmVtcHR5U2NyaXB0OlwiXCIscD1hLnJlYWN0aXZlRWxlbWVudFBvbHlmaWxsU3VwcG9ydCxkPSh0LHMpPT50LHU9e3RvQXR0cmlidXRlKHQscyl7c3dpdGNoKHMpe2Nhc2UgQm9vbGVhbjp0PXQ/bDpudWxsO2JyZWFrO2Nhc2UgT2JqZWN0OmNhc2UgQXJyYXk6dD1udWxsPT10P3Q6SlNPTi5zdHJpbmdpZnkodCl9cmV0dXJuIHR9LGZyb21BdHRyaWJ1dGUodCxzKXtsZXQgaT10O3N3aXRjaChzKXtjYXNlIEJvb2xlYW46aT1udWxsIT09dDticmVhaztjYXNlIE51bWJlcjppPW51bGw9PT10P251bGw6TnVtYmVyKHQpO2JyZWFrO2Nhc2UgT2JqZWN0OmNhc2UgQXJyYXk6dHJ5e2k9SlNPTi5wYXJzZSh0KX1jYXRjaCh0KXtpPW51bGx9fXJldHVybiBpfX0sZj0odCxzKT0+IWkodCxzKSxiPXthdHRyaWJ1dGU6ITAsdHlwZTpTdHJpbmcsY29udmVydGVyOnUscmVmbGVjdDohMSx1c2VEZWZhdWx0OiExLGhhc0NoYW5nZWQ6Zn07U3ltYm9sLm1ldGFkYXRhPz89U3ltYm9sKFwibWV0YWRhdGFcIiksYS5saXRQcm9wZXJ0eU1ldGFkYXRhPz89bmV3IFdlYWtNYXA7Y2xhc3MgeSBleHRlbmRzIEhUTUxFbGVtZW50e3N0YXRpYyBhZGRJbml0aWFsaXplcih0KXt0aGlzLl8kRWkoKSwodGhpcy5sPz89W10pLnB1c2godCl9c3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKXtyZXR1cm4gdGhpcy5maW5hbGl6ZSgpLHRoaXMuXyRFaCYmWy4uLnRoaXMuXyRFaC5rZXlzKCldfXN0YXRpYyBjcmVhdGVQcm9wZXJ0eSh0LHM9Yil7aWYocy5zdGF0ZSYmKHMuYXR0cmlidXRlPSExKSx0aGlzLl8kRWkoKSx0aGlzLnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eSh0KSYmKChzPU9iamVjdC5jcmVhdGUocykpLndyYXBwZWQ9ITApLHRoaXMuZWxlbWVudFByb3BlcnRpZXMuc2V0KHQscyksIXMubm9BY2Nlc3Nvcil7Y29uc3QgaT1TeW1ib2woKSxoPXRoaXMuZ2V0UHJvcGVydHlEZXNjcmlwdG9yKHQsaSxzKTt2b2lkIDAhPT1oJiZlKHRoaXMucHJvdG90eXBlLHQsaCl9fXN0YXRpYyBnZXRQcm9wZXJ0eURlc2NyaXB0b3IodCxzLGkpe2NvbnN0e2dldDplLHNldDpyfT1oKHRoaXMucHJvdG90eXBlLHQpPz97Z2V0KCl7cmV0dXJuIHRoaXNbc119LHNldCh0KXt0aGlzW3NdPXR9fTtyZXR1cm57Z2V0OmUsc2V0KHMpe2NvbnN0IGg9ZT8uY2FsbCh0aGlzKTtyPy5jYWxsKHRoaXMscyksdGhpcy5yZXF1ZXN0VXBkYXRlKHQsaCxpKX0sY29uZmlndXJhYmxlOiEwLGVudW1lcmFibGU6ITB9fXN0YXRpYyBnZXRQcm9wZXJ0eU9wdGlvbnModCl7cmV0dXJuIHRoaXMuZWxlbWVudFByb3BlcnRpZXMuZ2V0KHQpPz9ifXN0YXRpYyBfJEVpKCl7aWYodGhpcy5oYXNPd25Qcm9wZXJ0eShkKFwiZWxlbWVudFByb3BlcnRpZXNcIikpKXJldHVybjtjb25zdCB0PW4odGhpcyk7dC5maW5hbGl6ZSgpLHZvaWQgMCE9PXQubCYmKHRoaXMubD1bLi4udC5sXSksdGhpcy5lbGVtZW50UHJvcGVydGllcz1uZXcgTWFwKHQuZWxlbWVudFByb3BlcnRpZXMpfXN0YXRpYyBmaW5hbGl6ZSgpe2lmKHRoaXMuaGFzT3duUHJvcGVydHkoZChcImZpbmFsaXplZFwiKSkpcmV0dXJuO2lmKHRoaXMuZmluYWxpemVkPSEwLHRoaXMuXyRFaSgpLHRoaXMuaGFzT3duUHJvcGVydHkoZChcInByb3BlcnRpZXNcIikpKXtjb25zdCB0PXRoaXMucHJvcGVydGllcyxzPVsuLi5yKHQpLC4uLm8odCldO2Zvcihjb25zdCBpIG9mIHMpdGhpcy5jcmVhdGVQcm9wZXJ0eShpLHRbaV0pfWNvbnN0IHQ9dGhpc1tTeW1ib2wubWV0YWRhdGFdO2lmKG51bGwhPT10KXtjb25zdCBzPWxpdFByb3BlcnR5TWV0YWRhdGEuZ2V0KHQpO2lmKHZvaWQgMCE9PXMpZm9yKGNvbnN0W3QsaV1vZiBzKXRoaXMuZWxlbWVudFByb3BlcnRpZXMuc2V0KHQsaSl9dGhpcy5fJEVoPW5ldyBNYXA7Zm9yKGNvbnN0W3Qsc11vZiB0aGlzLmVsZW1lbnRQcm9wZXJ0aWVzKXtjb25zdCBpPXRoaXMuXyRFdSh0LHMpO3ZvaWQgMCE9PWkmJnRoaXMuXyRFaC5zZXQoaSx0KX10aGlzLmVsZW1lbnRTdHlsZXM9dGhpcy5maW5hbGl6ZVN0eWxlcyh0aGlzLnN0eWxlcyl9c3RhdGljIGZpbmFsaXplU3R5bGVzKHMpe2NvbnN0IGk9W107aWYoQXJyYXkuaXNBcnJheShzKSl7Y29uc3QgZT1uZXcgU2V0KHMuZmxhdCgxLzApLnJldmVyc2UoKSk7Zm9yKGNvbnN0IHMgb2YgZSlpLnVuc2hpZnQodChzKSl9ZWxzZSB2b2lkIDAhPT1zJiZpLnB1c2godChzKSk7cmV0dXJuIGl9c3RhdGljIF8kRXUodCxzKXtjb25zdCBpPXMuYXR0cmlidXRlO3JldHVybiExPT09aT92b2lkIDA6XCJzdHJpbmdcIj09dHlwZW9mIGk/aTpcInN0cmluZ1wiPT10eXBlb2YgdD90LnRvTG93ZXJDYXNlKCk6dm9pZCAwfWNvbnN0cnVjdG9yKCl7c3VwZXIoKSx0aGlzLl8kRXA9dm9pZCAwLHRoaXMuaXNVcGRhdGVQZW5kaW5nPSExLHRoaXMuaGFzVXBkYXRlZD0hMSx0aGlzLl8kRW09bnVsbCx0aGlzLl8kRXYoKX1fJEV2KCl7dGhpcy5fJEVTPW5ldyBQcm9taXNlKCh0PT50aGlzLmVuYWJsZVVwZGF0aW5nPXQpKSx0aGlzLl8kQUw9bmV3IE1hcCx0aGlzLl8kRV8oKSx0aGlzLnJlcXVlc3RVcGRhdGUoKSx0aGlzLmNvbnN0cnVjdG9yLmw/LmZvckVhY2goKHQ9PnQodGhpcykpKX1hZGRDb250cm9sbGVyKHQpeyh0aGlzLl8kRU8/Pz1uZXcgU2V0KS5hZGQodCksdm9pZCAwIT09dGhpcy5yZW5kZXJSb290JiZ0aGlzLmlzQ29ubmVjdGVkJiZ0Lmhvc3RDb25uZWN0ZWQ/LigpfXJlbW92ZUNvbnRyb2xsZXIodCl7dGhpcy5fJEVPPy5kZWxldGUodCl9XyRFXygpe2NvbnN0IHQ9bmV3IE1hcCxzPXRoaXMuY29uc3RydWN0b3IuZWxlbWVudFByb3BlcnRpZXM7Zm9yKGNvbnN0IGkgb2Ygcy5rZXlzKCkpdGhpcy5oYXNPd25Qcm9wZXJ0eShpKSYmKHQuc2V0KGksdGhpc1tpXSksZGVsZXRlIHRoaXNbaV0pO3Quc2l6ZT4wJiYodGhpcy5fJEVwPXQpfWNyZWF0ZVJlbmRlclJvb3QoKXtjb25zdCB0PXRoaXMuc2hhZG93Um9vdD8/dGhpcy5hdHRhY2hTaGFkb3codGhpcy5jb25zdHJ1Y3Rvci5zaGFkb3dSb290T3B0aW9ucyk7cmV0dXJuIHModCx0aGlzLmNvbnN0cnVjdG9yLmVsZW1lbnRTdHlsZXMpLHR9Y29ubmVjdGVkQ2FsbGJhY2soKXt0aGlzLnJlbmRlclJvb3Q/Pz10aGlzLmNyZWF0ZVJlbmRlclJvb3QoKSx0aGlzLmVuYWJsZVVwZGF0aW5nKCEwKSx0aGlzLl8kRU8/LmZvckVhY2goKHQ9PnQuaG9zdENvbm5lY3RlZD8uKCkpKX1lbmFibGVVcGRhdGluZyh0KXt9ZGlzY29ubmVjdGVkQ2FsbGJhY2soKXt0aGlzLl8kRU8/LmZvckVhY2goKHQ9PnQuaG9zdERpc2Nvbm5lY3RlZD8uKCkpKX1hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sodCxzLGkpe3RoaXMuXyRBSyh0LGkpfV8kRVQodCxzKXtjb25zdCBpPXRoaXMuY29uc3RydWN0b3IuZWxlbWVudFByb3BlcnRpZXMuZ2V0KHQpLGU9dGhpcy5jb25zdHJ1Y3Rvci5fJEV1KHQsaSk7aWYodm9pZCAwIT09ZSYmITA9PT1pLnJlZmxlY3Qpe2NvbnN0IGg9KHZvaWQgMCE9PWkuY29udmVydGVyPy50b0F0dHJpYnV0ZT9pLmNvbnZlcnRlcjp1KS50b0F0dHJpYnV0ZShzLGkudHlwZSk7dGhpcy5fJEVtPXQsbnVsbD09aD90aGlzLnJlbW92ZUF0dHJpYnV0ZShlKTp0aGlzLnNldEF0dHJpYnV0ZShlLGgpLHRoaXMuXyRFbT1udWxsfX1fJEFLKHQscyl7Y29uc3QgaT10aGlzLmNvbnN0cnVjdG9yLGU9aS5fJEVoLmdldCh0KTtpZih2b2lkIDAhPT1lJiZ0aGlzLl8kRW0hPT1lKXtjb25zdCB0PWkuZ2V0UHJvcGVydHlPcHRpb25zKGUpLGg9XCJmdW5jdGlvblwiPT10eXBlb2YgdC5jb252ZXJ0ZXI/e2Zyb21BdHRyaWJ1dGU6dC5jb252ZXJ0ZXJ9OnZvaWQgMCE9PXQuY29udmVydGVyPy5mcm9tQXR0cmlidXRlP3QuY29udmVydGVyOnU7dGhpcy5fJEVtPWUsdGhpc1tlXT1oLmZyb21BdHRyaWJ1dGUocyx0LnR5cGUpPz90aGlzLl8kRWo/LmdldChlKT8/bnVsbCx0aGlzLl8kRW09bnVsbH19cmVxdWVzdFVwZGF0ZSh0LHMsaSl7aWYodm9pZCAwIT09dCl7Y29uc3QgZT10aGlzLmNvbnN0cnVjdG9yLGg9dGhpc1t0XTtpZihpPz89ZS5nZXRQcm9wZXJ0eU9wdGlvbnModCksISgoaS5oYXNDaGFuZ2VkPz9mKShoLHMpfHxpLnVzZURlZmF1bHQmJmkucmVmbGVjdCYmaD09PXRoaXMuXyRFaj8uZ2V0KHQpJiYhdGhpcy5oYXNBdHRyaWJ1dGUoZS5fJEV1KHQsaSkpKSlyZXR1cm47dGhpcy5DKHQscyxpKX0hMT09PXRoaXMuaXNVcGRhdGVQZW5kaW5nJiYodGhpcy5fJEVTPXRoaXMuXyRFUCgpKX1DKHQscyx7dXNlRGVmYXVsdDppLHJlZmxlY3Q6ZSx3cmFwcGVkOmh9LHIpe2kmJiEodGhpcy5fJEVqPz89bmV3IE1hcCkuaGFzKHQpJiYodGhpcy5fJEVqLnNldCh0LHI/P3M/P3RoaXNbdF0pLCEwIT09aHx8dm9pZCAwIT09cil8fCh0aGlzLl8kQUwuaGFzKHQpfHwodGhpcy5oYXNVcGRhdGVkfHxpfHwocz12b2lkIDApLHRoaXMuXyRBTC5zZXQodCxzKSksITA9PT1lJiZ0aGlzLl8kRW0hPT10JiYodGhpcy5fJEVxPz89bmV3IFNldCkuYWRkKHQpKX1hc3luYyBfJEVQKCl7dGhpcy5pc1VwZGF0ZVBlbmRpbmc9ITA7dHJ5e2F3YWl0IHRoaXMuXyRFU31jYXRjaCh0KXtQcm9taXNlLnJlamVjdCh0KX1jb25zdCB0PXRoaXMuc2NoZWR1bGVVcGRhdGUoKTtyZXR1cm4gbnVsbCE9dCYmYXdhaXQgdCwhdGhpcy5pc1VwZGF0ZVBlbmRpbmd9c2NoZWR1bGVVcGRhdGUoKXtyZXR1cm4gdGhpcy5wZXJmb3JtVXBkYXRlKCl9cGVyZm9ybVVwZGF0ZSgpe2lmKCF0aGlzLmlzVXBkYXRlUGVuZGluZylyZXR1cm47aWYoIXRoaXMuaGFzVXBkYXRlZCl7aWYodGhpcy5yZW5kZXJSb290Pz89dGhpcy5jcmVhdGVSZW5kZXJSb290KCksdGhpcy5fJEVwKXtmb3IoY29uc3RbdCxzXW9mIHRoaXMuXyRFcCl0aGlzW3RdPXM7dGhpcy5fJEVwPXZvaWQgMH1jb25zdCB0PXRoaXMuY29uc3RydWN0b3IuZWxlbWVudFByb3BlcnRpZXM7aWYodC5zaXplPjApZm9yKGNvbnN0W3MsaV1vZiB0KXtjb25zdHt3cmFwcGVkOnR9PWksZT10aGlzW3NdOyEwIT09dHx8dGhpcy5fJEFMLmhhcyhzKXx8dm9pZCAwPT09ZXx8dGhpcy5DKHMsdm9pZCAwLGksZSl9fWxldCB0PSExO2NvbnN0IHM9dGhpcy5fJEFMO3RyeXt0PXRoaXMuc2hvdWxkVXBkYXRlKHMpLHQ/KHRoaXMud2lsbFVwZGF0ZShzKSx0aGlzLl8kRU8/LmZvckVhY2goKHQ9PnQuaG9zdFVwZGF0ZT8uKCkpKSx0aGlzLnVwZGF0ZShzKSk6dGhpcy5fJEVNKCl9Y2F0Y2gocyl7dGhyb3cgdD0hMSx0aGlzLl8kRU0oKSxzfXQmJnRoaXMuXyRBRShzKX13aWxsVXBkYXRlKHQpe31fJEFFKHQpe3RoaXMuXyRFTz8uZm9yRWFjaCgodD0+dC5ob3N0VXBkYXRlZD8uKCkpKSx0aGlzLmhhc1VwZGF0ZWR8fCh0aGlzLmhhc1VwZGF0ZWQ9ITAsdGhpcy5maXJzdFVwZGF0ZWQodCkpLHRoaXMudXBkYXRlZCh0KX1fJEVNKCl7dGhpcy5fJEFMPW5ldyBNYXAsdGhpcy5pc1VwZGF0ZVBlbmRpbmc9ITF9Z2V0IHVwZGF0ZUNvbXBsZXRlKCl7cmV0dXJuIHRoaXMuZ2V0VXBkYXRlQ29tcGxldGUoKX1nZXRVcGRhdGVDb21wbGV0ZSgpe3JldHVybiB0aGlzLl8kRVN9c2hvdWxkVXBkYXRlKHQpe3JldHVybiEwfXVwZGF0ZSh0KXt0aGlzLl8kRXEmJj10aGlzLl8kRXEuZm9yRWFjaCgodD0+dGhpcy5fJEVUKHQsdGhpc1t0XSkpKSx0aGlzLl8kRU0oKX11cGRhdGVkKHQpe31maXJzdFVwZGF0ZWQodCl7fX15LmVsZW1lbnRTdHlsZXM9W10seS5zaGFkb3dSb290T3B0aW9ucz17bW9kZTpcIm9wZW5cIn0seVtkKFwiZWxlbWVudFByb3BlcnRpZXNcIildPW5ldyBNYXAseVtkKFwiZmluYWxpemVkXCIpXT1uZXcgTWFwLHA/Lih7UmVhY3RpdmVFbGVtZW50Onl9KSwoYS5yZWFjdGl2ZUVsZW1lbnRWZXJzaW9ucz8/PVtdKS5wdXNoKFwiMi4xLjBcIik7ZXhwb3J0e3kgYXMgUmVhY3RpdmVFbGVtZW50LHMgYXMgYWRvcHRTdHlsZXMsdSBhcyBkZWZhdWx0Q29udmVydGVyLHQgYXMgZ2V0Q29tcGF0aWJsZVN0eWxlLGYgYXMgbm90RXF1YWx9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cmVhY3RpdmUtZWxlbWVudC5qcy5tYXBcbiIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMy1DbGF1c2VcbiAqL1xuY29uc3QgdD1nbG9iYWxUaGlzLGk9dC50cnVzdGVkVHlwZXMscz1pP2kuY3JlYXRlUG9saWN5KFwibGl0LWh0bWxcIix7Y3JlYXRlSFRNTDp0PT50fSk6dm9pZCAwLGU9XCIkbGl0JFwiLGg9YGxpdCQke01hdGgucmFuZG9tKCkudG9GaXhlZCg5KS5zbGljZSgyKX0kYCxvPVwiP1wiK2gsbj1gPCR7b30+YCxyPWRvY3VtZW50LGw9KCk9PnIuY3JlYXRlQ29tbWVudChcIlwiKSxjPXQ9Pm51bGw9PT10fHxcIm9iamVjdFwiIT10eXBlb2YgdCYmXCJmdW5jdGlvblwiIT10eXBlb2YgdCxhPUFycmF5LmlzQXJyYXksdT10PT5hKHQpfHxcImZ1bmN0aW9uXCI9PXR5cGVvZiB0Py5bU3ltYm9sLml0ZXJhdG9yXSxkPVwiWyBcXHRcXG5cXGZcXHJdXCIsZj0vPCg/OighLS18XFwvW15hLXpBLVpdKXwoXFwvP1thLXpBLVpdW14+XFxzXSopfChcXC8/JCkpL2csdj0vLS0+L2csXz0vPi9nLG09UmVnRXhwKGA+fCR7ZH0oPzooW15cXFxcc1wiJz49L10rKSgke2R9Kj0ke2R9Kig/OlteIFxcdFxcblxcZlxcclwiJ1xcYDw+PV18KFwifCcpfCkpfCQpYCxcImdcIikscD0vJy9nLGc9L1wiL2csJD0vXig/OnNjcmlwdHxzdHlsZXx0ZXh0YXJlYXx0aXRsZSkkL2kseT10PT4oaSwuLi5zKT0+KHtfJGxpdFR5cGUkOnQsc3RyaW5nczppLHZhbHVlczpzfSkseD15KDEpLGI9eSgyKSx3PXkoMyksVD1TeW1ib2wuZm9yKFwibGl0LW5vQ2hhbmdlXCIpLEU9U3ltYm9sLmZvcihcImxpdC1ub3RoaW5nXCIpLEE9bmV3IFdlYWtNYXAsQz1yLmNyZWF0ZVRyZWVXYWxrZXIociwxMjkpO2Z1bmN0aW9uIFAodCxpKXtpZighYSh0KXx8IXQuaGFzT3duUHJvcGVydHkoXCJyYXdcIikpdGhyb3cgRXJyb3IoXCJpbnZhbGlkIHRlbXBsYXRlIHN0cmluZ3MgYXJyYXlcIik7cmV0dXJuIHZvaWQgMCE9PXM/cy5jcmVhdGVIVE1MKGkpOml9Y29uc3QgVj0odCxpKT0+e2NvbnN0IHM9dC5sZW5ndGgtMSxvPVtdO2xldCByLGw9Mj09PWk/XCI8c3ZnPlwiOjM9PT1pP1wiPG1hdGg+XCI6XCJcIixjPWY7Zm9yKGxldCBpPTA7aTxzO2krKyl7Y29uc3Qgcz10W2ldO2xldCBhLHUsZD0tMSx5PTA7Zm9yKDt5PHMubGVuZ3RoJiYoYy5sYXN0SW5kZXg9eSx1PWMuZXhlYyhzKSxudWxsIT09dSk7KXk9Yy5sYXN0SW5kZXgsYz09PWY/XCIhLS1cIj09PXVbMV0/Yz12OnZvaWQgMCE9PXVbMV0/Yz1fOnZvaWQgMCE9PXVbMl0/KCQudGVzdCh1WzJdKSYmKHI9UmVnRXhwKFwiPC9cIit1WzJdLFwiZ1wiKSksYz1tKTp2b2lkIDAhPT11WzNdJiYoYz1tKTpjPT09bT9cIj5cIj09PXVbMF0/KGM9cj8/ZixkPS0xKTp2b2lkIDA9PT11WzFdP2Q9LTI6KGQ9Yy5sYXN0SW5kZXgtdVsyXS5sZW5ndGgsYT11WzFdLGM9dm9pZCAwPT09dVszXT9tOidcIic9PT11WzNdP2c6cCk6Yz09PWd8fGM9PT1wP2M9bTpjPT09dnx8Yz09PV8/Yz1mOihjPW0scj12b2lkIDApO2NvbnN0IHg9Yz09PW0mJnRbaSsxXS5zdGFydHNXaXRoKFwiLz5cIik/XCIgXCI6XCJcIjtsKz1jPT09Zj9zK246ZD49MD8oby5wdXNoKGEpLHMuc2xpY2UoMCxkKStlK3Muc2xpY2UoZCkraCt4KTpzK2grKC0yPT09ZD9pOngpfXJldHVybltQKHQsbCsodFtzXXx8XCI8Pz5cIikrKDI9PT1pP1wiPC9zdmc+XCI6Mz09PWk/XCI8L21hdGg+XCI6XCJcIikpLG9dfTtjbGFzcyBOe2NvbnN0cnVjdG9yKHtzdHJpbmdzOnQsXyRsaXRUeXBlJDpzfSxuKXtsZXQgcjt0aGlzLnBhcnRzPVtdO2xldCBjPTAsYT0wO2NvbnN0IHU9dC5sZW5ndGgtMSxkPXRoaXMucGFydHMsW2Ysdl09Vih0LHMpO2lmKHRoaXMuZWw9Ti5jcmVhdGVFbGVtZW50KGYsbiksQy5jdXJyZW50Tm9kZT10aGlzLmVsLmNvbnRlbnQsMj09PXN8fDM9PT1zKXtjb25zdCB0PXRoaXMuZWwuY29udGVudC5maXJzdENoaWxkO3QucmVwbGFjZVdpdGgoLi4udC5jaGlsZE5vZGVzKX1mb3IoO251bGwhPT0ocj1DLm5leHROb2RlKCkpJiZkLmxlbmd0aDx1Oyl7aWYoMT09PXIubm9kZVR5cGUpe2lmKHIuaGFzQXR0cmlidXRlcygpKWZvcihjb25zdCB0IG9mIHIuZ2V0QXR0cmlidXRlTmFtZXMoKSlpZih0LmVuZHNXaXRoKGUpKXtjb25zdCBpPXZbYSsrXSxzPXIuZ2V0QXR0cmlidXRlKHQpLnNwbGl0KGgpLGU9LyhbLj9AXSk/KC4qKS8uZXhlYyhpKTtkLnB1c2goe3R5cGU6MSxpbmRleDpjLG5hbWU6ZVsyXSxzdHJpbmdzOnMsY3RvcjpcIi5cIj09PWVbMV0/SDpcIj9cIj09PWVbMV0/STpcIkBcIj09PWVbMV0/TDprfSksci5yZW1vdmVBdHRyaWJ1dGUodCl9ZWxzZSB0LnN0YXJ0c1dpdGgoaCkmJihkLnB1c2goe3R5cGU6NixpbmRleDpjfSksci5yZW1vdmVBdHRyaWJ1dGUodCkpO2lmKCQudGVzdChyLnRhZ05hbWUpKXtjb25zdCB0PXIudGV4dENvbnRlbnQuc3BsaXQoaCkscz10Lmxlbmd0aC0xO2lmKHM+MCl7ci50ZXh0Q29udGVudD1pP2kuZW1wdHlTY3JpcHQ6XCJcIjtmb3IobGV0IGk9MDtpPHM7aSsrKXIuYXBwZW5kKHRbaV0sbCgpKSxDLm5leHROb2RlKCksZC5wdXNoKHt0eXBlOjIsaW5kZXg6KytjfSk7ci5hcHBlbmQodFtzXSxsKCkpfX19ZWxzZSBpZig4PT09ci5ub2RlVHlwZSlpZihyLmRhdGE9PT1vKWQucHVzaCh7dHlwZToyLGluZGV4OmN9KTtlbHNle2xldCB0PS0xO2Zvcig7LTEhPT0odD1yLmRhdGEuaW5kZXhPZihoLHQrMSkpOylkLnB1c2goe3R5cGU6NyxpbmRleDpjfSksdCs9aC5sZW5ndGgtMX1jKyt9fXN0YXRpYyBjcmVhdGVFbGVtZW50KHQsaSl7Y29uc3Qgcz1yLmNyZWF0ZUVsZW1lbnQoXCJ0ZW1wbGF0ZVwiKTtyZXR1cm4gcy5pbm5lckhUTUw9dCxzfX1mdW5jdGlvbiBTKHQsaSxzPXQsZSl7aWYoaT09PVQpcmV0dXJuIGk7bGV0IGg9dm9pZCAwIT09ZT9zLl8kQ28/LltlXTpzLl8kQ2w7Y29uc3Qgbz1jKGkpP3ZvaWQgMDppLl8kbGl0RGlyZWN0aXZlJDtyZXR1cm4gaD8uY29uc3RydWN0b3IhPT1vJiYoaD8uXyRBTz8uKCExKSx2b2lkIDA9PT1vP2g9dm9pZCAwOihoPW5ldyBvKHQpLGguXyRBVCh0LHMsZSkpLHZvaWQgMCE9PWU/KHMuXyRDbz8/PVtdKVtlXT1oOnMuXyRDbD1oKSx2b2lkIDAhPT1oJiYoaT1TKHQsaC5fJEFTKHQsaS52YWx1ZXMpLGgsZSkpLGl9Y2xhc3MgTXtjb25zdHJ1Y3Rvcih0LGkpe3RoaXMuXyRBVj1bXSx0aGlzLl8kQU49dm9pZCAwLHRoaXMuXyRBRD10LHRoaXMuXyRBTT1pfWdldCBwYXJlbnROb2RlKCl7cmV0dXJuIHRoaXMuXyRBTS5wYXJlbnROb2RlfWdldCBfJEFVKCl7cmV0dXJuIHRoaXMuXyRBTS5fJEFVfXUodCl7Y29uc3R7ZWw6e2NvbnRlbnQ6aX0scGFydHM6c309dGhpcy5fJEFELGU9KHQ/LmNyZWF0aW9uU2NvcGU/P3IpLmltcG9ydE5vZGUoaSwhMCk7Qy5jdXJyZW50Tm9kZT1lO2xldCBoPUMubmV4dE5vZGUoKSxvPTAsbj0wLGw9c1swXTtmb3IoO3ZvaWQgMCE9PWw7KXtpZihvPT09bC5pbmRleCl7bGV0IGk7Mj09PWwudHlwZT9pPW5ldyBSKGgsaC5uZXh0U2libGluZyx0aGlzLHQpOjE9PT1sLnR5cGU/aT1uZXcgbC5jdG9yKGgsbC5uYW1lLGwuc3RyaW5ncyx0aGlzLHQpOjY9PT1sLnR5cGUmJihpPW5ldyB6KGgsdGhpcyx0KSksdGhpcy5fJEFWLnB1c2goaSksbD1zWysrbl19byE9PWw/LmluZGV4JiYoaD1DLm5leHROb2RlKCksbysrKX1yZXR1cm4gQy5jdXJyZW50Tm9kZT1yLGV9cCh0KXtsZXQgaT0wO2Zvcihjb25zdCBzIG9mIHRoaXMuXyRBVil2b2lkIDAhPT1zJiYodm9pZCAwIT09cy5zdHJpbmdzPyhzLl8kQUkodCxzLGkpLGkrPXMuc3RyaW5ncy5sZW5ndGgtMik6cy5fJEFJKHRbaV0pKSxpKyt9fWNsYXNzIFJ7Z2V0IF8kQVUoKXtyZXR1cm4gdGhpcy5fJEFNPy5fJEFVPz90aGlzLl8kQ3Z9Y29uc3RydWN0b3IodCxpLHMsZSl7dGhpcy50eXBlPTIsdGhpcy5fJEFIPUUsdGhpcy5fJEFOPXZvaWQgMCx0aGlzLl8kQUE9dCx0aGlzLl8kQUI9aSx0aGlzLl8kQU09cyx0aGlzLm9wdGlvbnM9ZSx0aGlzLl8kQ3Y9ZT8uaXNDb25uZWN0ZWQ/PyEwfWdldCBwYXJlbnROb2RlKCl7bGV0IHQ9dGhpcy5fJEFBLnBhcmVudE5vZGU7Y29uc3QgaT10aGlzLl8kQU07cmV0dXJuIHZvaWQgMCE9PWkmJjExPT09dD8ubm9kZVR5cGUmJih0PWkucGFyZW50Tm9kZSksdH1nZXQgc3RhcnROb2RlKCl7cmV0dXJuIHRoaXMuXyRBQX1nZXQgZW5kTm9kZSgpe3JldHVybiB0aGlzLl8kQUJ9XyRBSSh0LGk9dGhpcyl7dD1TKHRoaXMsdCxpKSxjKHQpP3Q9PT1FfHxudWxsPT10fHxcIlwiPT09dD8odGhpcy5fJEFIIT09RSYmdGhpcy5fJEFSKCksdGhpcy5fJEFIPUUpOnQhPT10aGlzLl8kQUgmJnQhPT1UJiZ0aGlzLl8odCk6dm9pZCAwIT09dC5fJGxpdFR5cGUkP3RoaXMuJCh0KTp2b2lkIDAhPT10Lm5vZGVUeXBlP3RoaXMuVCh0KTp1KHQpP3RoaXMuayh0KTp0aGlzLl8odCl9Tyh0KXtyZXR1cm4gdGhpcy5fJEFBLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHQsdGhpcy5fJEFCKX1UKHQpe3RoaXMuXyRBSCE9PXQmJih0aGlzLl8kQVIoKSx0aGlzLl8kQUg9dGhpcy5PKHQpKX1fKHQpe3RoaXMuXyRBSCE9PUUmJmModGhpcy5fJEFIKT90aGlzLl8kQUEubmV4dFNpYmxpbmcuZGF0YT10OnRoaXMuVChyLmNyZWF0ZVRleHROb2RlKHQpKSx0aGlzLl8kQUg9dH0kKHQpe2NvbnN0e3ZhbHVlczppLF8kbGl0VHlwZSQ6c309dCxlPVwibnVtYmVyXCI9PXR5cGVvZiBzP3RoaXMuXyRBQyh0KToodm9pZCAwPT09cy5lbCYmKHMuZWw9Ti5jcmVhdGVFbGVtZW50KFAocy5oLHMuaFswXSksdGhpcy5vcHRpb25zKSkscyk7aWYodGhpcy5fJEFIPy5fJEFEPT09ZSl0aGlzLl8kQUgucChpKTtlbHNle2NvbnN0IHQ9bmV3IE0oZSx0aGlzKSxzPXQudSh0aGlzLm9wdGlvbnMpO3QucChpKSx0aGlzLlQocyksdGhpcy5fJEFIPXR9fV8kQUModCl7bGV0IGk9QS5nZXQodC5zdHJpbmdzKTtyZXR1cm4gdm9pZCAwPT09aSYmQS5zZXQodC5zdHJpbmdzLGk9bmV3IE4odCkpLGl9ayh0KXthKHRoaXMuXyRBSCl8fCh0aGlzLl8kQUg9W10sdGhpcy5fJEFSKCkpO2NvbnN0IGk9dGhpcy5fJEFIO2xldCBzLGU9MDtmb3IoY29uc3QgaCBvZiB0KWU9PT1pLmxlbmd0aD9pLnB1c2gocz1uZXcgUih0aGlzLk8obCgpKSx0aGlzLk8obCgpKSx0aGlzLHRoaXMub3B0aW9ucykpOnM9aVtlXSxzLl8kQUkoaCksZSsrO2U8aS5sZW5ndGgmJih0aGlzLl8kQVIocyYmcy5fJEFCLm5leHRTaWJsaW5nLGUpLGkubGVuZ3RoPWUpfV8kQVIodD10aGlzLl8kQUEubmV4dFNpYmxpbmcsaSl7Zm9yKHRoaXMuXyRBUD8uKCExLCEwLGkpO3QmJnQhPT10aGlzLl8kQUI7KXtjb25zdCBpPXQubmV4dFNpYmxpbmc7dC5yZW1vdmUoKSx0PWl9fXNldENvbm5lY3RlZCh0KXt2b2lkIDA9PT10aGlzLl8kQU0mJih0aGlzLl8kQ3Y9dCx0aGlzLl8kQVA/Lih0KSl9fWNsYXNzIGt7Z2V0IHRhZ05hbWUoKXtyZXR1cm4gdGhpcy5lbGVtZW50LnRhZ05hbWV9Z2V0IF8kQVUoKXtyZXR1cm4gdGhpcy5fJEFNLl8kQVV9Y29uc3RydWN0b3IodCxpLHMsZSxoKXt0aGlzLnR5cGU9MSx0aGlzLl8kQUg9RSx0aGlzLl8kQU49dm9pZCAwLHRoaXMuZWxlbWVudD10LHRoaXMubmFtZT1pLHRoaXMuXyRBTT1lLHRoaXMub3B0aW9ucz1oLHMubGVuZ3RoPjJ8fFwiXCIhPT1zWzBdfHxcIlwiIT09c1sxXT8odGhpcy5fJEFIPUFycmF5KHMubGVuZ3RoLTEpLmZpbGwobmV3IFN0cmluZyksdGhpcy5zdHJpbmdzPXMpOnRoaXMuXyRBSD1FfV8kQUkodCxpPXRoaXMscyxlKXtjb25zdCBoPXRoaXMuc3RyaW5ncztsZXQgbz0hMTtpZih2b2lkIDA9PT1oKXQ9Uyh0aGlzLHQsaSwwKSxvPSFjKHQpfHx0IT09dGhpcy5fJEFIJiZ0IT09VCxvJiYodGhpcy5fJEFIPXQpO2Vsc2V7Y29uc3QgZT10O2xldCBuLHI7Zm9yKHQ9aFswXSxuPTA7bjxoLmxlbmd0aC0xO24rKylyPVModGhpcyxlW3Mrbl0saSxuKSxyPT09VCYmKHI9dGhpcy5fJEFIW25dKSxvfHw9IWMocil8fHIhPT10aGlzLl8kQUhbbl0scj09PUU/dD1FOnQhPT1FJiYodCs9KHI/P1wiXCIpK2hbbisxXSksdGhpcy5fJEFIW25dPXJ9byYmIWUmJnRoaXMuaih0KX1qKHQpe3Q9PT1FP3RoaXMuZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUodGhpcy5uYW1lKTp0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKHRoaXMubmFtZSx0Pz9cIlwiKX19Y2xhc3MgSCBleHRlbmRzIGt7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMudHlwZT0zfWoodCl7dGhpcy5lbGVtZW50W3RoaXMubmFtZV09dD09PUU/dm9pZCAwOnR9fWNsYXNzIEkgZXh0ZW5kcyBre2NvbnN0cnVjdG9yKCl7c3VwZXIoLi4uYXJndW1lbnRzKSx0aGlzLnR5cGU9NH1qKHQpe3RoaXMuZWxlbWVudC50b2dnbGVBdHRyaWJ1dGUodGhpcy5uYW1lLCEhdCYmdCE9PUUpfX1jbGFzcyBMIGV4dGVuZHMga3tjb25zdHJ1Y3Rvcih0LGkscyxlLGgpe3N1cGVyKHQsaSxzLGUsaCksdGhpcy50eXBlPTV9XyRBSSh0LGk9dGhpcyl7aWYoKHQ9Uyh0aGlzLHQsaSwwKT8/RSk9PT1UKXJldHVybjtjb25zdCBzPXRoaXMuXyRBSCxlPXQ9PT1FJiZzIT09RXx8dC5jYXB0dXJlIT09cy5jYXB0dXJlfHx0Lm9uY2UhPT1zLm9uY2V8fHQucGFzc2l2ZSE9PXMucGFzc2l2ZSxoPXQhPT1FJiYocz09PUV8fGUpO2UmJnRoaXMuZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRoaXMubmFtZSx0aGlzLHMpLGgmJnRoaXMuZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRoaXMubmFtZSx0aGlzLHQpLHRoaXMuXyRBSD10fWhhbmRsZUV2ZW50KHQpe1wiZnVuY3Rpb25cIj09dHlwZW9mIHRoaXMuXyRBSD90aGlzLl8kQUguY2FsbCh0aGlzLm9wdGlvbnM/Lmhvc3Q/P3RoaXMuZWxlbWVudCx0KTp0aGlzLl8kQUguaGFuZGxlRXZlbnQodCl9fWNsYXNzIHp7Y29uc3RydWN0b3IodCxpLHMpe3RoaXMuZWxlbWVudD10LHRoaXMudHlwZT02LHRoaXMuXyRBTj12b2lkIDAsdGhpcy5fJEFNPWksdGhpcy5vcHRpb25zPXN9Z2V0IF8kQVUoKXtyZXR1cm4gdGhpcy5fJEFNLl8kQVV9XyRBSSh0KXtTKHRoaXMsdCl9fWNvbnN0IFo9e006ZSxQOmgsQTpvLEM6MSxMOlYsUjpNLEQ6dSxWOlMsSTpSLEg6ayxOOkksVTpMLEI6SCxGOnp9LGo9dC5saXRIdG1sUG9seWZpbGxTdXBwb3J0O2o/LihOLFIpLCh0LmxpdEh0bWxWZXJzaW9ucz8/PVtdKS5wdXNoKFwiMy4zLjBcIik7Y29uc3QgQj0odCxpLHMpPT57Y29uc3QgZT1zPy5yZW5kZXJCZWZvcmU/P2k7bGV0IGg9ZS5fJGxpdFBhcnQkO2lmKHZvaWQgMD09PWgpe2NvbnN0IHQ9cz8ucmVuZGVyQmVmb3JlPz9udWxsO2UuXyRsaXRQYXJ0JD1oPW5ldyBSKGkuaW5zZXJ0QmVmb3JlKGwoKSx0KSx0LHZvaWQgMCxzPz97fSl9cmV0dXJuIGguXyRBSSh0KSxofTtleHBvcnR7WiBhcyBfJExILHggYXMgaHRtbCx3IGFzIG1hdGhtbCxUIGFzIG5vQ2hhbmdlLEUgYXMgbm90aGluZyxCIGFzIHJlbmRlcixiIGFzIHN2Z307XG4vLyMgc291cmNlTWFwcGluZ1VSTD1saXQtaHRtbC5qcy5tYXBcbiIsImltcG9ydHtSZWFjdGl2ZUVsZW1lbnQgYXMgdH1mcm9tXCJAbGl0L3JlYWN0aXZlLWVsZW1lbnRcIjtleHBvcnQqZnJvbVwiQGxpdC9yZWFjdGl2ZS1lbGVtZW50XCI7aW1wb3J0e3JlbmRlciBhcyBlLG5vQ2hhbmdlIGFzIHJ9ZnJvbVwibGl0LWh0bWxcIjtleHBvcnQqZnJvbVwibGl0LWh0bWxcIjtcbi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMy1DbGF1c2VcbiAqL2NvbnN0IHM9Z2xvYmFsVGhpcztjbGFzcyBpIGV4dGVuZHMgdHtjb25zdHJ1Y3Rvcigpe3N1cGVyKC4uLmFyZ3VtZW50cyksdGhpcy5yZW5kZXJPcHRpb25zPXtob3N0OnRoaXN9LHRoaXMuXyREbz12b2lkIDB9Y3JlYXRlUmVuZGVyUm9vdCgpe2NvbnN0IHQ9c3VwZXIuY3JlYXRlUmVuZGVyUm9vdCgpO3JldHVybiB0aGlzLnJlbmRlck9wdGlvbnMucmVuZGVyQmVmb3JlPz89dC5maXJzdENoaWxkLHR9dXBkYXRlKHQpe2NvbnN0IHI9dGhpcy5yZW5kZXIoKTt0aGlzLmhhc1VwZGF0ZWR8fCh0aGlzLnJlbmRlck9wdGlvbnMuaXNDb25uZWN0ZWQ9dGhpcy5pc0Nvbm5lY3RlZCksc3VwZXIudXBkYXRlKHQpLHRoaXMuXyREbz1lKHIsdGhpcy5yZW5kZXJSb290LHRoaXMucmVuZGVyT3B0aW9ucyl9Y29ubmVjdGVkQ2FsbGJhY2soKXtzdXBlci5jb25uZWN0ZWRDYWxsYmFjaygpLHRoaXMuXyREbz8uc2V0Q29ubmVjdGVkKCEwKX1kaXNjb25uZWN0ZWRDYWxsYmFjaygpe3N1cGVyLmRpc2Nvbm5lY3RlZENhbGxiYWNrKCksdGhpcy5fJERvPy5zZXRDb25uZWN0ZWQoITEpfXJlbmRlcigpe3JldHVybiByfX1pLl8kbGl0RWxlbWVudCQ9ITAsaVtcImZpbmFsaXplZFwiXT0hMCxzLmxpdEVsZW1lbnRIeWRyYXRlU3VwcG9ydD8uKHtMaXRFbGVtZW50Oml9KTtjb25zdCBvPXMubGl0RWxlbWVudFBvbHlmaWxsU3VwcG9ydDtvPy4oe0xpdEVsZW1lbnQ6aX0pO2NvbnN0IG49e18kQUs6KHQsZSxyKT0+e3QuXyRBSyhlLHIpfSxfJEFMOnQ9PnQuXyRBTH07KHMubGl0RWxlbWVudFZlcnNpb25zPz89W10pLnB1c2goXCI0LjIuMFwiKTtleHBvcnR7aSBhcyBMaXRFbGVtZW50LG4gYXMgXyRMRX07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1saXQtZWxlbWVudC5qcy5tYXBcbiIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMy1DbGF1c2VcbiAqL1xuY29uc3QgdD10PT4oZSxvKT0+e3ZvaWQgMCE9PW8/by5hZGRJbml0aWFsaXplcigoKCk9PntjdXN0b21FbGVtZW50cy5kZWZpbmUodCxlKX0pKTpjdXN0b21FbGVtZW50cy5kZWZpbmUodCxlKX07ZXhwb3J0e3QgYXMgY3VzdG9tRWxlbWVudH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jdXN0b20tZWxlbWVudC5qcy5tYXBcbiIsImltcG9ydHtkZWZhdWx0Q29udmVydGVyIGFzIHQsbm90RXF1YWwgYXMgZX1mcm9tXCIuLi9yZWFjdGl2ZS1lbGVtZW50LmpzXCI7XG4vKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlXG4gKi9jb25zdCBvPXthdHRyaWJ1dGU6ITAsdHlwZTpTdHJpbmcsY29udmVydGVyOnQscmVmbGVjdDohMSxoYXNDaGFuZ2VkOmV9LHI9KHQ9byxlLHIpPT57Y29uc3R7a2luZDpuLG1ldGFkYXRhOml9PXI7bGV0IHM9Z2xvYmFsVGhpcy5saXRQcm9wZXJ0eU1ldGFkYXRhLmdldChpKTtpZih2b2lkIDA9PT1zJiZnbG9iYWxUaGlzLmxpdFByb3BlcnR5TWV0YWRhdGEuc2V0KGkscz1uZXcgTWFwKSxcInNldHRlclwiPT09biYmKCh0PU9iamVjdC5jcmVhdGUodCkpLndyYXBwZWQ9ITApLHMuc2V0KHIubmFtZSx0KSxcImFjY2Vzc29yXCI9PT1uKXtjb25zdHtuYW1lOm99PXI7cmV0dXJue3NldChyKXtjb25zdCBuPWUuZ2V0LmNhbGwodGhpcyk7ZS5zZXQuY2FsbCh0aGlzLHIpLHRoaXMucmVxdWVzdFVwZGF0ZShvLG4sdCl9LGluaXQoZSl7cmV0dXJuIHZvaWQgMCE9PWUmJnRoaXMuQyhvLHZvaWQgMCx0LGUpLGV9fX1pZihcInNldHRlclwiPT09bil7Y29uc3R7bmFtZTpvfT1yO3JldHVybiBmdW5jdGlvbihyKXtjb25zdCBuPXRoaXNbb107ZS5jYWxsKHRoaXMsciksdGhpcy5yZXF1ZXN0VXBkYXRlKG8sbix0KX19dGhyb3cgRXJyb3IoXCJVbnN1cHBvcnRlZCBkZWNvcmF0b3IgbG9jYXRpb246IFwiK24pfTtmdW5jdGlvbiBuKHQpe3JldHVybihlLG8pPT5cIm9iamVjdFwiPT10eXBlb2Ygbz9yKHQsZSxvKTooKHQsZSxvKT0+e2NvbnN0IHI9ZS5oYXNPd25Qcm9wZXJ0eShvKTtyZXR1cm4gZS5jb25zdHJ1Y3Rvci5jcmVhdGVQcm9wZXJ0eShvLHQpLHI/T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihlLG8pOnZvaWQgMH0pKHQsZSxvKX1leHBvcnR7biBhcyBwcm9wZXJ0eSxyIGFzIHN0YW5kYXJkUHJvcGVydHl9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cHJvcGVydHkuanMubWFwXG4iLCJpbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuaW1wb3J0ICogYXMgQ29sb3IgZnJvbSAnY29sb3InO1xuXG5leHBvcnQgY29uc3QgQ09MT1JTID0gW1xuICAncHJpbWFyeScsXG4gICdhY2NlbnQnLFxuICAncmVkJyxcbiAgJ3BpbmsnLFxuICAncHVycGxlJyxcbiAgJ2RlZXAtcHVycGxlJyxcbiAgJ2luZGlnbycsXG4gICdibHVlJyxcbiAgJ2xpZ2h0LWJsdWUnLFxuICAnY3lhbicsXG4gICd0ZWFsJyxcbiAgJ2dyZWVuJyxcbiAgJ2xpZ2h0LWdyZWVuJyxcbiAgJ2xpbWUnLFxuICAneWVsbG93JyxcbiAgJ2FtYmVyJyxcbiAgJ29yYW5nZScsXG4gICdkZWVwLW9yYW5nZScsXG4gICdicm93bicsXG4gICdsaWdodC1ncmV5JyxcbiAgJ2dyZXknLFxuICAnZGFyay1ncmV5JyxcbiAgJ2JsdWUtZ3JleScsXG4gICdibGFjaycsXG4gICd3aGl0ZScsXG4gICdkaXNhYmxlZCcsXG5dO1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVJnYkNvbG9yKGNvbG9yOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoY29sb3IgPT09ICdwcmltYXJ5JyB8fCBjb2xvciA9PT0gJ2FjY2VudCcpIHtcbiAgICByZXR1cm4gYHZhcigtLXJnYi0ke2NvbG9yfS1jb2xvcilgO1xuICB9XG4gIGlmIChDT0xPUlMuaW5jbHVkZXMoY29sb3IpKSB7XG4gICAgcmV0dXJuIGB2YXIoLS1yZ2ItJHtjb2xvcn0pYDtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWVsc2UtcmV0dXJuXG4gIH0gZWxzZSBpZiAoY29sb3Iuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBDb2xvci5yZ2IoY29sb3IpLnJnYigpLmFycmF5KCkuam9pbignLCAnKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNvbG9yO1xufVxuXG5mdW5jdGlvbiBjYXBpdGFsaXplRmlyc3RMZXR0ZXIoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlQ29sb3JOYW1lKGNvbG9yOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gY29sb3JcbiAgICAuc3BsaXQoJy0nKVxuICAgIC5tYXAoKHMpID0+IGNhcGl0YWxpemVGaXJzdExldHRlcihzKSlcbiAgICAuam9pbignICcpO1xufVxuXG5leHBvcnQgY29uc3QgZGVmYXVsdENvbG9yQ3NzID0gY3NzYFxuICAtLWRlZmF1bHQtcmVkOiAyNDQsIDY3LCA1NDtcbiAgLS1kZWZhdWx0LXBpbms6IDIzMywgMzAsIDk5O1xuICAtLWRlZmF1bHQtcHVycGxlOiAxNDYsIDEwNywgMTk5O1xuICAtLWRlZmF1bHQtZGVlcC1wdXJwbGU6IDExMCwgNjUsIDE3MTtcbiAgLS1kZWZhdWx0LWluZGlnbzogNjMsIDgxLCAxODE7XG4gIC0tZGVmYXVsdC1ibHVlOiAzMywgMTUwLCAyNDM7XG4gIC0tZGVmYXVsdC1saWdodC1ibHVlOiAzLCAxNjksIDI0NDtcbiAgLS1kZWZhdWx0LWN5YW46IDAsIDE4OCwgMjEyO1xuICAtLWRlZmF1bHQtdGVhbDogMCwgMTUwLCAxMzY7XG4gIC0tZGVmYXVsdC1ncmVlbjogNzYsIDE3NSwgODA7XG4gIC0tZGVmYXVsdC1saWdodC1ncmVlbjogMTM5LCAxOTUsIDc0O1xuICAtLWRlZmF1bHQtbGltZTogMjA1LCAyMjAsIDU3O1xuICAtLWRlZmF1bHQteWVsbG93OiAyNTUsIDIzNSwgNTk7XG4gIC0tZGVmYXVsdC1hbWJlcjogMjU1LCAxOTMsIDc7XG4gIC0tZGVmYXVsdC1vcmFuZ2U6IDI1NSwgMTUyLCAwO1xuICAtLWRlZmF1bHQtZGVlcC1vcmFuZ2U6IDI1NSwgMTExLCAzNDtcbiAgLS1kZWZhdWx0LWJyb3duOiAxMjEsIDg1LCA3MjtcbiAgLS1kZWZhdWx0LWxpZ2h0LWdyZXk6IDE4OSwgMTg5LCAxODk7XG4gIC0tZGVmYXVsdC1ncmV5OiAxNTgsIDE1OCwgMTU4O1xuICAtLWRlZmF1bHQtZGFyay1ncmV5OiA5NiwgOTYsIDk2O1xuICAtLWRlZmF1bHQtYmx1ZS1ncmV5OiA5NiwgMTI1LCAxMzk7XG4gIC0tZGVmYXVsdC1ibGFjazogMCwgMCwgMDtcbiAgLS1kZWZhdWx0LXdoaXRlOiAyNTUsIDI1NSwgMjU1O1xuICAtLWRlZmF1bHQtZGlzYWJsZWQ6IDE4OSwgMTg5LCAxODk7XG5gO1xuXG5leHBvcnQgY29uc3QgZGVmYXVsdERhcmtDb2xvckNzcyA9IGNzc2BcbiAgLS1kZWZhdWx0LWRpc2FibGVkOiAxMTEsIDExMSwgMTExO1xuYDtcbiIsImV4cG9ydCBjb25zdCBsb2dvOiBzdHJpbmcgPSAnJWMgV0VBVEhFUi1DT05ESVRJT04tQ0FSRCAlYyAyLjAuMCc7XG5cbmV4cG9ydCBjb25zdCBoYWNzSW1hZ2VQYXRoOiBzdHJpbmcgPSAnL2xvY2FsL2NvbW11bml0eS9oYS1jYXJkLXdlYXRoZXItY29uZGl0aW9ucy9pY29ucyc7XG5leHBvcnQgY29uc3QgbWFuSW1hZ2VQYXRoOiBzdHJpbmcgPSAnL2xvY2FsL2hhLWNhcmQtd2VhdGhlci1jb25kaXRpb25zL2ljb25zJztcblxuZXhwb3J0IGNvbnN0IG9wdENvbnNvbGVQYXJhbTE6IHN0cmluZyA9ICdjb2xvcjogd2hpdGU7IGJhY2tncm91bmQ6IGdyZWVuOyBmb250LXdlaWdodDogNzAwOyc7XG5leHBvcnQgY29uc3Qgb3B0Q29uc29sZVBhcmFtMjogc3RyaW5nID0gJ2NvbG9yOiBncmVlbjsgYmFja2dyb3VuZDogd2hpdGU7IGZvbnQtd2VpZ2h0OiA3MDA7JztcbmV4cG9ydCBjb25zdCBvcHRDb25zb2xlUGFyYW0zOiBzdHJpbmcgPSAnY29sb3I6IGJsYWNrOyBiYWNrZ3JvdW5kOiB3aGl0ZTsgZm9udC13ZWlnaHQ6IDcwMDsnO1xuXG5leHBvcnQgY29uc3QgaWNvblRlbXBlcmF0dXJlOiBzdHJpbmcgPSAnbWRpOnRoZXJtb21ldGVyJztcbmV4cG9ydCBjb25zdCBpY29uUHJlY2lwaXRhdGlvbjogc3RyaW5nID0gJ21kaTp3ZWF0aGVyLXJhaW55JztcblxuZXhwb3J0IGNvbnN0IGN3Y0xvY2FsZSA9IHtcbiAgZW46IDAsXG4gIGl0OiAxLFxuICBubDogMixcbiAgZXM6IDMsXG4gIGRlOiA0LFxuICBmcjogNSxcbiAgJ3NyLWxhdG4nOiA2LFxuICBwdDogNyxcbiAgZGE6IDgsXG4gICduby1ubyc6IDksXG4gIGNzOiAxMCxcbiAgcnU6IDExLFxufTtcblxuLy8g8J+MkSDwn4ySIPCfjJMg8J+MlCDwn4yVIPCfjJYg8J+MlyDwn4yYIPCfjJFcbmV4cG9ydCBjb25zdCBjd2NNb29uUGhhc2VJY29ucyA9IHtcbiAgbmV3X21vb246ICfwn4yRJyxcbiAgbmV3OiAn8J+MkScsXG4gIHdheGluZ19jcmVzY2VudDogJ/CfjJInLFxuICBmaXJzdF9xdWFydGVyOiAn8J+MkycsXG4gIHdheGluZ19naWJib3VzOiAn8J+MlCcsXG4gIGZ1bGw6ICfwn4yVJyxcbiAgZnVsbF9tb29uOiAn8J+MlScsXG4gIHdhbmluZ19naWJib3VzOiAn8J+MlicsXG4gIHRoaXJkX3F1YXJ0ZXI6ICfwn4yXJyxcbiAgbGFzdF9xdWFydGVyOiAn8J+MlycsXG4gIHdhbmluZ19jcmVzY2VudDogJ/CfjJgnLFxufTtcbiIsIi8vIGNsZWFyPW9rLCBwYXJ0bHljbG91ZHk9b2ssIGNsb3VkeT1vaywgcGFydGx5Y2xvdWR5LWZvZz1vaywgcGFydGx5Y2xvdWR5LWxpZ2h0LXJhaW49b2ssIHBhcnRseWNsb3VkeS1yYWluPW9rLFxuLy8gbGlnaHQtcmFpbj1vaywgcmFpbnk9b2ssIHNub3d5LXJhaW55PW9rLCBwYXJ0bHljbG91ZHktbGlnaHQtc25vdz1vaywgcGFydGx5Y2xvdWR5LXNub3c9b2ssIGxpZ2h0LXNub3c9b2ssIHNub3d5PW9rLFxuLy8gcGFydGx5Y2xvdWR5LWxpZ2h0bmluZz1vayBvciBsaWdodG5pbmdcblxuZXhwb3J0IGNvbnN0IGN3Y0J1aWVucmFkYXJEYXlJY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmc7IH0gPSB7XG4gIC8vIGZyZWV6aW5nX3JhaW5faGVhdnk6ICdyYWlueS0zJyxcbiAgLy8gZnJlZXppbmdfcmFpbjogJ3JhaW55LTInLFxuICAvLyBmcmVlemluZ19yYWluX2xpZ2h0OiAncmFpbnktMScsXG4gIC8vIGZyZWV6aW5nX2RyaXp6bGU6ICdyYWluLWFuZC1zbGVldC1taXgnLFxuICAvLyBpY2VfcGVsbGV0c19oZWF2eTogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgLy8gaWNlX3BlbGxldHM6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gIC8vIGljZV9wZWxsZXRzX2xpZ2h0OiAncmFpbi1hbmQtc25vdy1taXgnLFxuICBzbm93eTogJ3Nub3d5LTMnLFxuICAnbGlnaHQtc25vdyc6ICdzbm93eS0yJyxcbiAgJ3Nub3d5LXJhaW55JzogJ3Nub3d5LTEnLFxuICAncGFydGx5Y2xvdWR5LWxpZ2h0LXNub3cnOiAnc25vd3ktMScsXG4gICdwYXJ0bHljbG91ZHktc25vdyc6ICdzbm93eS0xJyxcbiAgLy8gZmx1cnJpZXM6ICd3aW5kJyxcbiAgLy8gdHN0b3JtOiAndHJvcGljYWwtc3Rvcm0nLFxuICAvLyByYWluX2hlYXZ5OiAncmFpbnktMycsXG4gICdwYXJ0bHljbG91ZHktbGlnaHQtcmFpbic6ICdyYWlueS0xJyxcbiAgJ2xpZ2h0LXJhaW4nOiAncmFpbnktMScsXG4gIHJhaW55OiAncmFpbnktMicsXG4gICdwYXJ0bHljbG91ZHktcmFpbic6ICdyYWlueS0xJyxcbiAgLy8gZm9nX2xpZ2h0OiAnaGF6ZScsXG4gICdwYXJ0bHljbG91ZHktZm9nJzogJ2ZvZycsXG4gIGNsb3VkeTogJ2Nsb3VkeS1vcmlnaW5hbCcsXG4gIC8vIG1vc3RseV9jbG91ZHk6ICdjbG91ZHktZGF5LTMnLFxuICBwYXJ0bHljbG91ZHk6ICdjbG91ZHktZGF5LTInLFxuICAncGFydGx5Y2xvdWR5LWxpZ2h0bmluZyc6ICdjbG91ZHktZGF5LTEnLFxuICBsaWdodG5pbmc6ICdjbG91ZHktZGF5LTEnLFxuICAvLyBtb3N0bHlfY2xlYXI6ICdjbG91ZHktZGF5LTEnLFxuICBjbGVhcjogJ2RheScsXG59O1xuXG5leHBvcnQgY29uc3QgY3djQnVpZW5yYWRhck5pZ2h0SWNvbnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nOyB9ID0ge1xuICAuLi5jd2NCdWllbnJhZGFyRGF5SWNvbnMsXG4gIC8vIGZyZWV6aW5nX3JhaW5faGVhdnk6ICdyYWlueS02JyxcbiAgLy8gZnJlZXppbmdfcmFpbjogJ3JhaW55LTUnLFxuICAvLyBmcmVlemluZ19yYWluX2xpZ2h0OiAncmFpbnktNCcsXG4gIC8vIGZyZWV6aW5nX2RyaXp6bGU6ICdyYWluLWFuZC1zbGVldC1taXgnLFxuICAvLyBpY2VfcGVsbGV0c19oZWF2eTogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgLy8gaWNlX3BlbGxldHM6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gIC8vIGljZV9wZWxsZXRzX2xpZ2h0OiAncmFpbi1hbmQtc25vdy1taXgnLFxuICAvLyBzbm93X2hlYXZ5OiAnc25vd3ktNicsXG4gIC8vIHNub3c6ICdub3d5LTUnLFxuICAvLyBzbm93X2xpZ2h0OiAnbm93eS00JyxcbiAgLy8gZmx1cnJpZXM6ICd3aW5kJyxcbiAgLy8gdHN0b3JtOiAndHJvcGljYWwtc3Rvcm0nLFxuICAvLyByYWluX2hlYXZ5OiAncmFpbnktNicsXG4gIC8vIHJhaW5fbGlnaHQ6ICdyYWlueS00JyxcbiAgLy8gcmFpbjogJ3JhaW55LTUnLFxuICAvLyBkcml6emxlOiAncmFpbnktNCcsXG4gIC8vIGZvZ19saWdodDogJ2hhemUnLFxuICAvLyBmb2c6ICdmb2cnLFxuICAvLyBjbG91ZHk6ICdjbG91ZHknLFxuICAvLyBtb3N0bHlfY2xvdWR5OiAnY2xvdWR5LW5pZ2h0LTMnLFxuICAvLyBwYXJ0bHlfY2xvdWR5OiAnY2xvdWR5LW5pZ2h0LTInLFxuICAvLyBtb3N0bHlfY2xlYXI6ICdjbG91ZHktbmlnaHQtMScsXG4gIC8vIGNsZWFyOiAnbmlnaHQnXG59O1xuIiwiZXhwb3J0IGNvbnN0IGN3Y0NsaW1hY2VsbERheUljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZzsgfSA9IHtcbiAgZnJlZXppbmdfcmFpbl9oZWF2eTogJ3JhaW55LTMnLFxuICAnaGVhdnkgZnJlZXppbmcgcmFpbic6ICdyYWlueS0zJyxcbiAgZnJlZXppbmdfcmFpbjogJ3JhaW55LTInLFxuICAnZnJlZXppbmcgcmFpbic6ICdyYWlueS0yJyxcbiAgZnJlZXppbmdfcmFpbl9saWdodDogJ3JhaW55LTEnLFxuICAnbGlnaHQgZnJlZXppbmcgcmFpbic6ICdyYWlueS0xJyxcbiAgZnJlZXppbmdfZHJpenpsZTogJ3JhaW4tYW5kLXNsZWV0LW1peCcsXG4gICdmcmVlemluZyBkcml6emxlJzogJ3JhaW4tYW5kLXNsZWV0LW1peCcsXG4gIGljZV9wZWxsZXRzX2hlYXZ5OiAncmFpbi1hbmQtc25vdy1taXgnLFxuICAnaGVhdnkgaWNlIHBlbGxldHMnOiAncmFpbi1hbmQtc25vdy1taXgnLFxuICBpY2VfcGVsbGV0czogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgJ2ljZSBwZWxsZXRzJzogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgaWNlX3BlbGxldHNfbGlnaHQ6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gICdsaWdodCBpY2UgcGVsbGV0cyc6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gIHNub3dfaGVhdnk6ICdzbm93eS0zJyxcbiAgJ2hlYXZ5IHNub3cnOiAnc25vd3ktMycsXG4gIHNub3c6ICdzbm93eS0yJyxcbiAgc25vd19saWdodDogJ3Nub3d5LTEnLFxuICAnbGlnaHQgc25vdyc6ICdzbm93eS0xJyxcbiAgZmx1cnJpZXM6ICd3aW5kJyxcbiAgdHN0b3JtOiAndHJvcGljYWwtc3Rvcm0nLFxuICByYWluX2hlYXZ5OiAncmFpbnktMycsXG4gICdoZWF2eSByYWluJzogJ3JhaW55LTMnLFxuICByYWluX2xpZ2h0OiAncmFpbnktMScsXG4gICdsaWdodCByYWluJzogJ3JhaW55LTEnLFxuICByYWluOiAncmFpbnktMicsXG4gIGRyaXp6bGU6ICdyYWlueS0xJyxcbiAgZm9nX2xpZ2h0OiAnaGF6ZScsXG4gICdsaWdodCBmb2cnOiAnaGF6ZScsXG4gIGZvZzogJ2ZvZycsXG4gIGNsb3VkeTogJ2Nsb3VkeS1vcmlnaW5hbCcsXG4gIG1vc3RseV9jbG91ZHk6ICdjbG91ZHktZGF5LTMnLFxuICAnbW9zdGx5IGNsb3VkeSc6ICdjbG91ZHktZGF5LTMnLFxuICBwYXJ0bHlfY2xvdWR5OiAnY2xvdWR5LWRheS0yJyxcbiAgJ3BhcnRseSBjbG91ZHknOiAnY2xvdWR5LWRheS0yJyxcbiAgbW9zdGx5X2NsZWFyOiAnY2xvdWR5LWRheS0xJyxcbiAgJ21vc3RseSBjbGVhcic6ICdjbG91ZHktZGF5LTEnLFxuICBjbGVhcjogJ2RheScsXG59O1xuXG5leHBvcnQgY29uc3QgY3djQ2xpbWFjZWxsTmlnaHRJY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmc7IH0gPSB7XG4gIC4uLmN3Y0NsaW1hY2VsbERheUljb25zLFxuICBmcmVlemluZ19yYWluX2hlYXZ5OiAncmFpbnktNicsXG4gICdoZWF2eSBmcmVlemluZyByYWluJzogJ3JhaW55LTYnLFxuICBmcmVlemluZ19yYWluOiAncmFpbnktNScsXG4gICdmcmVlemluZyByYWluJzogJ3JhaW55LTUnLFxuICBmcmVlemluZ19yYWluX2xpZ2h0OiAncmFpbnktNCcsXG4gICdsaWdodCBmcmVlemluZyByYWluJzogJ3JhaW55LTQnLFxuICAvLyBmcmVlemluZ19kcml6emxlOiAncmFpbi1hbmQtc2xlZXQtbWl4JyxcbiAgLy8gaWNlX3BlbGxldHNfaGVhdnk6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gIC8vIGljZV9wZWxsZXRzOiAncmFpbi1hbmQtc25vdy1taXgnLFxuICAvLyBpY2VfcGVsbGV0c19saWdodDogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgc25vd19oZWF2eTogJ3Nub3d5LTYnLFxuICAnaGVhdnkgc25vdyc6ICdzbm93eS02JyxcbiAgc25vdzogJ3Nub3d5LTUnLFxuICBzbm93X2xpZ2h0OiAnc25vd3ktNCcsXG4gICdsaWdodCBzbm93JzogJ3Nub3d5LTQnLFxuICAvLyBmbHVycmllczogJ3dpbmQnLFxuICAvLyB0c3Rvcm06ICd0cm9waWNhbC1zdG9ybScsXG4gIHJhaW5faGVhdnk6ICdyYWlueS02JyxcbiAgJ2hlYXZ5IHJhaW4nOiAncmFpbnktNicsXG4gIHJhaW5fbGlnaHQ6ICdyYWlueS00JyxcbiAgJ2xpZ2h0IHJhaW4nOiAncmFpbnktNCcsXG4gIHJhaW46ICdyYWlueS01JyxcbiAgZHJpenpsZTogJ3JhaW55LTQnLFxuICAvLyBmb2dfbGlnaHQ6ICdoYXplJyxcbiAgLy8gZm9nOiAnZm9nJyxcbiAgLy8gY2xvdWR5OiAnY2xvdWR5JyxcbiAgbW9zdGx5X2Nsb3VkeTogJ2Nsb3VkeS1uaWdodC0zJyxcbiAgJ21vc3RseSBjbG91ZHknOiAnY2xvdWR5LW5pZ2h0LTMnLFxuICBwYXJ0bHlfY2xvdWR5OiAnY2xvdWR5LW5pZ2h0LTInLFxuICAncGFydGx5IGNsb3VkeSc6ICdjbG91ZHktbmlnaHQtMicsXG4gIG1vc3RseV9jbGVhcjogJ2Nsb3VkeS1uaWdodC0xJyxcbiAgJ21vc3RseSBjbGVhcic6ICdjbG91ZHktbmlnaHQtMScsXG4gIGNsZWFyOiAnbmlnaHQnLFxuICBzdW5ueTogJ25pZ2h0Jyxcbn07XG5cbmV4cG9ydCBjb25zdCBjd2NDbGltYWNlbGxEYXlCZzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmc7IH0gPSB7XG4gIGZyZWV6aW5nX3JhaW5faGVhdnk6ICdyYWlueS0zJyxcbiAgZnJlZXppbmdfcmFpbjogJ3JhaW55LTInLFxuICBmcmVlemluZ19yYWluX2xpZ2h0OiAncmFpbnktMScsXG4gIGZyZWV6aW5nX2RyaXp6bGU6ICdyYWluLWFuZC1zbGVldC1taXgnLFxuICBpY2VfcGVsbGV0c19oZWF2eTogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgaWNlX3BlbGxldHM6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gIGljZV9wZWxsZXRzX2xpZ2h0OiAncmFpbi1hbmQtc25vdy1taXgnLFxuICBzbm93X2hlYXZ5OiAnc25vd3ktMycsXG4gIHNub3c6ICdzbm93eS0yJyxcbiAgc25vd19saWdodDogJ3Nub3d5LTEnLFxuICBmbHVycmllczogJ3dpbmQnLFxuICB0c3Rvcm06ICd0cm9waWNhbC1zdG9ybScsXG4gIHJhaW5faGVhdnk6ICdyYWlueS0zJyxcbiAgcmFpbl9saWdodDogJ3JhaW55LTEnLFxuICByYWluOiAncmFpbnktMicsXG4gIGRyaXp6bGU6ICdyYWlueS0xJyxcbiAgZm9nX2xpZ2h0OiAnaGF6ZScsXG4gIGZvZzogJ2ZvZycsXG4gIGNsb3VkeTogJ2Nsb3VkeS1vcmlnaW5hbCcsXG4gIG1vc3RseV9jbG91ZHk6ICdkYXktY2xvdWQtMy5qcGcnLFxuICBwYXJ0bHlfY2xvdWR5OiAnZGF5LWNsb3VkLTIuanBnJyxcbiAgbW9zdGx5X2NsZWFyOiAnZGF5LWNsb3VkLTEuanBnJyxcbiAgY2xlYXI6ICdkYXktY2xlYXIuanBnJyxcbn07XG4iLCJleHBvcnQgY29uc3QgY3djRGFya3NreURheUljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZzsgfSA9IHtcbiAgY2xlYXI6ICdkYXknLFxuICAnY2xlYXItZGF5JzogJ2RheScsXG4gIHJhaW46ICdyYWlueS0yJyxcbiAgc25vdzogJ3Nub3d5LTInLFxuICBzbGVldDogJ3JhaW4tYW5kLXNsZWV0LW1peCcsXG4gIHdpbmQ6ICdjbG91ZHktZGF5LTEnLFxuICBmb2c6ICdmb2cnLFxuICBjbG91ZHk6ICdjbG91ZHktb3JpZ2luYWwnLFxuICAncGFydGx5LWNsb3VkeS1kYXknOiAnY2xvdWR5LWRheS0yJyxcbn07XG5cbmV4cG9ydCBjb25zdCBjd2NEYXJrc2t5TmlnaHRJY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmc7IH0gPSB7XG4gIC4uLmN3Y0Rhcmtza3lEYXlJY29ucyxcbiAgY2xlYXI6ICduaWdodCcsXG4gICdjbGVhci1uaWdodCc6ICduaWdodCcsXG4gIHdpbmQ6ICdjbG91ZHktbmlnaHQtMScsXG4gICdwYXJ0bHktY2xvdWR5LWRheSc6ICdjbG91ZHktbmlnaHQtMicsXG4gICdwYXJ0bHktY2xvdWR5LW5pZ2h0JzogJ2Nsb3VkeS1uaWdodC0yJyxcbn07XG4iLCJleHBvcnQgY29uc3QgY3djRGVmYXVsdEhhc3NEYXlJY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgY2xvdWR5OiAnY2xvdWR5LWRheS0zJyxcbiAgZXhjZXB0aW9uYWw6ICdzZXZlcmUtdGh1bmRlcnN0b3JtJyxcbiAgZm9nOiAnZm9nJyxcbiAgaGFpbDogJ3Nub3ctYW5kLXNsZWV0LW1peCcsXG4gIGxpZ2h0bmluZzogJ3NldmVyZS10aHVuZGVyc3Rvcm0nLFxuICAnbGlnaHRuaW5nLXJhaW55JzogJ3NjYXR0ZXJlZC10aHVuZGVyc3Rvcm1zJyxcbiAgcGFydGx5Y2xvdWR5OiAnY2xvdWR5LWRheS0zJyxcbiAgcG91cmluZzogJ3JhaW55LTYnLFxuICByYWlueTogJ3JhaW55LTUnLFxuICBzbm93eTogJ3Nub3d5LTYnLFxuICAnc25vd3ktcmFpbnknOiAnc25vdy1hbmQtc2xlZXQtbWl4JyxcbiAgc3Vubnk6ICdjbGVhci1kYXknLFxuICB3aW5keTogJ3dpbmQnLFxuICAnd2luZHktdmFyaWFudCc6ICd3aW5kJyxcbn07XG5cbmV4cG9ydCBjb25zdCBjd2NEZWZhdWx0SGFzc05pZ2h0SWNvbnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gIC4uLmN3Y0RlZmF1bHRIYXNzRGF5SWNvbnMsXG4gICdjbGVhci1uaWdodCc6ICdjbGVhci1uaWdodCcsXG59O1xuIiwiZXhwb3J0IGNvbnN0IGN3Y09wZW5XZWF0aGVyTWFwRGF5SWNvbnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nOyB9ID0ge1xuICAnY2xlYXIgc2t5JzogJ2RheScsXG4gICdmZXcgY2xvdWRzJzogJ2Nsb3VkeS1kYXktMScsXG4gICdzY2F0dGVyZWQgY2xvdWRzJzogJ2Nsb3VkeS1kYXktMicsXG4gICdicm9rZW4gY2xvdWRzJzogJ2Nsb3VkeS1kYXktMycsXG4gICdzaG93ZXIgcmFpbic6ICdyYWlueS0zJyxcbiAgcmFpbjogJ3JhaW55LTInLFxuICB0aHVuZGVyc3Rvcm06ICd0cm9waWNhbC1zdG9ybScsXG4gIHNub3c6ICdzbm93eS0yJyxcbiAgbWlzdDogJ2ZvZycsXG59O1xuXG5leHBvcnQgY29uc3QgY3djT3BlbldlYXRoZXJNYXBOaWdodEljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZzsgfSA9IHtcbiAgLi4uY3djT3BlbldlYXRoZXJNYXBEYXlJY29ucyxcbiAgJ2NsZWFyIHNreSc6ICdkYXktbmlnaHQnLFxuICAnZmV3IGNsb3Vkcyc6ICdjbG91ZHktbmlnaHQtMScsXG4gICdzY2F0dGVyZWQgY2xvdWRzJzogJ2Nsb3VkeS1uaWdodC0yJyxcbiAgJ2Jyb2tlbiBjbG91ZHMnOiAnY2xvdWR5LW5pZ2h0LTMnLFxufTtcbiIsIi8vIFBpcmF0ZSBXZWF0aGVyIEljb25zXG4vLyBjbGVhci1kYXksIGNsZWFyLW5pZ2h0LCByYWluLCBzbm93LCBzbGVldCwgd2luZCwgZm9nLCBjbG91ZHksIHBhcnRseS1jbG91ZHktZGF5IGFuZCBwYXJ0bHktY2xvdWR5LW5pZ2h0XG4vLyBtb3N0bHktY2xlYXItZGF5LCBtb3N0bHktY2xlYXItbmlnaHQsIG1vc3RseS1jbG91ZHktZGF5LCBtb3N0bHktY2xvdWR5LW5pZ2h0LCBwb3NzaWJsZS1yYWluLWRheSwgcG9zc2libGUtcmFpbi1uaWdodFxuLy8gcG9zc2libGUtc25vdy1kYXksIHBvc3NpYmxlLXNub3ctbmlnaHQsIHBvc3NpYmxlLXNsZWV0LWRheSwgcG9zc2libGUtc2xlZXQtbmlnaHQsIHBvc3NpYmxlLXByZWNpcGl0YXRpb24tZGF5XG4vLyBwb3NzaWJsZS1wcmVjaXBpdGF0aW9uLW5pZ2h0LCBwcmVjaXBpdGF0aW9uLCBkcml6emxlLCBsaWdodC1yYWluLCBoZWF2eS1yYWluLCBmbHVycmllcywgbGlnaHQtc25vdywgaGVhdnktc25vd1xuLy8gdmVyeS1saWdodC1zbGVldCwgbGlnaHQtc2xlZXQsIGhlYXZ5LXNsZWV0LCBicmVlenksIGRhbmdlcm91cy13aW5kXG5cbmV4cG9ydCBjb25zdCBjd2NEYXl0aW1lUGlyYXRlV2VhdGhlckljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZzsgfSA9IHtcbiAgZnJlZXppbmdfcmFpbl9oZWF2eTogJ3JhaW55LTMnLFxuICAnaGVhdnkgZnJlZXppbmcgcmFpbic6ICdyYWlueS0zJyxcbiAgZnJlZXppbmdfcmFpbjogJ3JhaW55LTInLFxuICAnZnJlZXppbmcgcmFpbic6ICdyYWlueS0yJyxcbiAgZnJlZXppbmdfcmFpbl9saWdodDogJ3JhaW55LTEnLFxuICAnbGlnaHQgZnJlZXppbmcgcmFpbic6ICdyYWlueS0xJyxcbiAgZnJlZXppbmdfZHJpenpsZTogJ3JhaW4tYW5kLXNsZWV0LW1peCcsXG4gIHNsZWV0OiAncmFpbi1hbmQtc2xlZXQtbWl4JyxcbiAgJ2ZyZWV6aW5nIGRyaXp6bGUnOiAncmFpbi1hbmQtc2xlZXQtbWl4JyxcbiAgaWNlX3BlbGxldHNfaGVhdnk6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gICdoZWF2eSBpY2UgcGVsbGV0cyc6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gIGljZV9wZWxsZXRzOiAncmFpbi1hbmQtc25vdy1taXgnLFxuICAnaWNlIHBlbGxldHMnOiAncmFpbi1hbmQtc25vdy1taXgnLFxuICBpY2VfcGVsbGV0c19saWdodDogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgJ2xpZ2h0IGljZSBwZWxsZXRzJzogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgc25vd19oZWF2eTogJ3Nub3d5LTMnLFxuICAnaGVhdnkgc25vdyc6ICdzbm93eS0zJyxcbiAgc25vdzogJ3Nub3d5LTInLFxuICBzbm93X2xpZ2h0OiAnc25vd3ktMScsXG4gICdsaWdodCBzbm93JzogJ3Nub3d5LTEnLFxuICBmbHVycmllczogJ3dpbmQnLFxuICB0c3Rvcm06ICd0cm9waWNhbC1zdG9ybScsXG4gIHJhaW5faGVhdnk6ICdyYWlueS0zJyxcbiAgJ2hlYXZ5IHJhaW4nOiAncmFpbnktMycsXG4gIHJhaW5fbGlnaHQ6ICdyYWlueS0xJyxcbiAgcmFpbnk6ICdyYWlueS0xJyxcbiAgJ2xpZ2h0IHJhaW4nOiAncmFpbnktMScsXG4gIHJhaW46ICdyYWlueS0yJyxcbiAgZHJpenpsZTogJ3JhaW55LTEnLFxuICBmb2dfbGlnaHQ6ICdoYXplJyxcbiAgJ2xpZ2h0IGZvZyc6ICdoYXplJyxcbiAgZm9nOiAnZm9nJyxcbiAgY2xvdWR5OiAnY2xvdWR5LW9yaWdpbmFsJyxcbiAgbW9zdGx5X2Nsb3VkeTogJ2Nsb3VkeS1kYXktMycsXG4gICdtb3N0bHkgY2xvdWR5JzogJ2Nsb3VkeS1kYXktMycsXG4gIHBhcnRseV9jbG91ZHk6ICdjbG91ZHktZGF5LTInLFxuICBwYXJ0bHljbG91ZHk6ICdjbG91ZHktZGF5LTInLFxuICAncGFydGx5LWNsb3VkeS1kYXknOiAnY2xvdWR5LWRheS0yJyxcbiAgJ3BhcnRseSBjbG91ZHknOiAnY2xvdWR5LWRheS0yJyxcbiAgbW9zdGx5X2NsZWFyOiAnY2xvdWR5LWRheS0xJyxcbiAgJ21vc3RseSBjbGVhcic6ICdjbG91ZHktZGF5LTEnLFxuICBjbGVhcjogJ2RheScsXG4gICdjbGVhci1kYXknOiAnZGF5JyxcbiAgd2luZDogJ3dpbmQnLFxuICB3aW5keTogJ3dpbmQnLFxuICBzdW5ueTogJ2RheScsXG4gICdjbGVhci1uaWdodCc6ICdkYXknLFxufTtcblxuZXhwb3J0IGNvbnN0IGN3Y05pZ2h0bHlQaXJhdGVXZWF0ZXJJY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmc7IH0gPSB7XG4gIC4uLmN3Y0RheXRpbWVQaXJhdGVXZWF0aGVySWNvbnMsXG4gIGZyZWV6aW5nX3JhaW5faGVhdnk6ICdyYWlueS02JyxcbiAgJ2hlYXZ5IGZyZWV6aW5nIHJhaW4nOiAncmFpbnktNicsXG4gIGZyZWV6aW5nX3JhaW46ICdyYWlueS01JyxcbiAgJ2ZyZWV6aW5nIHJhaW4nOiAncmFpbnktNScsXG4gIGZyZWV6aW5nX3JhaW5fbGlnaHQ6ICdyYWlueS00JyxcbiAgJ2xpZ2h0IGZyZWV6aW5nIHJhaW4nOiAncmFpbnktNCcsXG4gIC8vIGZyZWV6aW5nX2RyaXp6bGU6ICdyYWluLWFuZC1zbGVldC1taXgnLFxuICAvLyBpY2VfcGVsbGV0c19oZWF2eTogJ3JhaW4tYW5kLXNub3ctbWl4JyxcbiAgLy8gaWNlX3BlbGxldHM6ICdyYWluLWFuZC1zbm93LW1peCcsXG4gIC8vIGljZV9wZWxsZXRzX2xpZ2h0OiAncmFpbi1hbmQtc25vdy1taXgnLFxuICBzbm93X2hlYXZ5OiAnc25vd3ktNicsXG4gICdoZWF2eSBzbm93JzogJ3Nub3d5LTYnLFxuICBzbm93OiAnc25vd3ktNScsXG4gIHNub3dfbGlnaHQ6ICdzbm93eS00JyxcbiAgJ2xpZ2h0IHNub3cnOiAnc25vd3ktNCcsXG4gIC8vIGZsdXJyaWVzOiAnd2luZCcsXG4gIC8vIHRzdG9ybTogJ3Ryb3BpY2FsLXN0b3JtJyxcbiAgcmFpbl9oZWF2eTogJ3JhaW55LTYnLFxuICAnaGVhdnkgcmFpbic6ICdyYWlueS02JyxcbiAgcmFpbl9saWdodDogJ3JhaW55LTQnLFxuICAnbGlnaHQgcmFpbic6ICdyYWlueS00JyxcbiAgcmFpbjogJ3JhaW55LTUnLFxuICBkcml6emxlOiAncmFpbnktNCcsXG4gIC8vIGZvZ19saWdodDogJ2hhemUnLFxuICAvLyBmb2c6ICdmb2cnLFxuICAvLyBjbG91ZHk6ICdjbG91ZHknLFxuICBtb3N0bHlfY2xvdWR5OiAnY2xvdWR5LW5pZ2h0LTMnLFxuICAnbW9zdGx5IGNsb3VkeSc6ICdjbG91ZHktbmlnaHQtMycsXG4gIHBhcnRseV9jbG91ZHk6ICdjbG91ZHktbmlnaHQtMicsXG4gIHBhcnRseWNsb3VkeTogJ2Nsb3VkeS1uaWdodC0yJyxcbiAgJ3BhcnRseS1jbG91ZHktbmlnaHQnOiAnY2xvdWR5LW5pZ2h0LTInLFxuICAncGFydGx5IGNsb3VkeSc6ICdjbG91ZHktbmlnaHQtMicsXG4gIG1vc3RseV9jbGVhcjogJ2Nsb3VkeS1uaWdodC0xJyxcbiAgJ21vc3RseSBjbGVhcic6ICdjbG91ZHktbmlnaHQtMScsXG4gIGNsZWFyOiAnbmlnaHQnLFxuICAnY2xlYXItbmlnaHQnOiAnbmlnaHQnLFxuICBzdW5ueTogJ25pZ2h0Jyxcbn07XG4iLCJpbXBvcnQgeyBjd2NCdWllbnJhZGFyRGF5SWNvbnMsIGN3Y0J1aWVucmFkYXJOaWdodEljb25zIH0gZnJvbSAnLi4vc3JjL2ljb25tb2RlbHMvaW0tYnVpZW5yYWRhcic7XG5pbXBvcnQgeyBjd2NDbGltYWNlbGxEYXlJY29ucywgY3djQ2xpbWFjZWxsTmlnaHRJY29ucyB9IGZyb20gJy4uL3NyYy9pY29ubW9kZWxzL2ltLWNsaW1hY2VsbCc7XG5pbXBvcnQgeyBjd2NEYXJrc2t5RGF5SWNvbnMsIGN3Y0Rhcmtza3lOaWdodEljb25zIH0gZnJvbSAnLi4vc3JjL2ljb25tb2RlbHMvaW0tZGFya3NreSc7XG5pbXBvcnQgeyBjd2NEZWZhdWx0SGFzc0RheUljb25zLCBjd2NEZWZhdWx0SGFzc05pZ2h0SWNvbnMgfSBmcm9tICcuLi9zcmMvaWNvbm1vZGVscy9pbS1oYXNzJztcbmltcG9ydCB7IGN3Y09wZW5XZWF0aGVyTWFwRGF5SWNvbnMsIGN3Y09wZW5XZWF0aGVyTWFwTmlnaHRJY29ucyB9IGZyb20gJy4uL3NyYy9pY29ubW9kZWxzL2ltLW9wZW53ZWF0aGVybWFwJztcbmltcG9ydCB7IGN3Y0RheXRpbWVQaXJhdGVXZWF0aGVySWNvbnMsIGN3Y05pZ2h0bHlQaXJhdGVXZWF0ZXJJY29ucyB9IGZyb20gJy4uL3NyYy9pY29ubW9kZWxzL2ltLXBpcmF0ZXdlYXRoZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFsZXJ0SXRlbSB7XG4gIGVudGl0eTogc3RyaW5nXG4gIGljb24/OiBzdHJpbmcgO1xuICBtaW4/OiBudW1iZXIgO1xuICBtYXg/OiBudW1iZXIgO1xuICBzaG93X2lmX29uPzogYm9vbGVhbiA7XG4gIHNob3dfaWZfZ2U/OiBudW1iZXIgO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBvbGxlbkl0ZW0ge1xuICBlbnRpdHk6IHN0cmluZyA7XG4gIGljb24/OiBzdHJpbmcgO1xuICBtaW46IG51bWJlciA7XG4gIG1heDogbnVtYmVyIDtcbiAgbG93PzogbnVtYmVyIDtcbiAgaGlnaD86IG51bWJlciA7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9sbGVuIHtcbiAgdHJlZT86IFBvbGxlbkl0ZW0gO1xuICB3ZWVkPzogUG9sbGVuSXRlbSA7XG4gIGdyYXNzPzogUG9sbGVuSXRlbSA7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWlyUXVhbGl0eSB7XG4gIHBtMjU/OiBzdHJpbmcgO1xuICBwbTEwPzogc3RyaW5nIDtcbiAgbzM/OiBzdHJpbmcgO1xuICBubzI/OiBzdHJpbmcgO1xuICBjbz86IHN0cmluZyA7XG4gIHNvMj86IHN0cmluZyA7XG4gIGVwYV9hcWk/OiBzdHJpbmcgO1xuICBlcGFfcHJpbWFyeV9wb2xsdXRhbnQ/OiBzdHJpbmcgO1xuICBlcGFfaGVhbHRoX2NvbmNlcm4/OiBzdHJpbmcgO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFV2IHtcbiAgcHJvdGVjdGlvbl93aW5kb3c/OiBzdHJpbmcgO1xuICBvem9uZV9sZXZlbD86IHN0cmluZyA7XG4gIHV2X2luZGV4Pzogc3RyaW5nIDtcbiAgdXZfbGV2ZWw/OiBzdHJpbmcgO1xuICBtYXhfdXZfaW5kZXg/OiBzdHJpbmcgO1xuICBzZXRfc2tpbl90eXBlXzE/OiBzdHJpbmcgO1xuICBzZXRfc2tpbl90eXBlXzI/OiBzdHJpbmcgO1xuICBzZXRfc2tpbl90eXBlXzM/OiBzdHJpbmcgO1xuICBzZXRfc2tpbl90eXBlXzQ/OiBzdHJpbmcgO1xuICBzZXRfc2tpbl90eXBlXzU/OiBzdHJpbmcgO1xuICBzZXRfc2tpbl90eXBlXzY/OiBzdHJpbmcgO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERheXMge1xuICBkYXlfMTogc3RyaW5nIDtcbiAgZGF5XzI6IHN0cmluZyA7XG4gIGRheV8zOiBzdHJpbmcgO1xuICBkYXlfNDogc3RyaW5nIDtcbiAgZGF5XzU6IHN0cmluZyA7XG4gIGRheV82OiBzdHJpbmcgO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEN1cnJlbnQge1xuICBzdW4/OiBzdHJpbmcgO1xuICBtb29uX3BoYXNlPzogc3RyaW5nIDtcbiAgLy8gZGFpbHlfc3VtbWFyeT86IHN0cmluZyA7XG4gIGN1cnJlbnRfY29uZGl0aW9ucz86IHN0cmluZ1xuICBodW1pZGl0eT86IHN0cmluZyA7XG4gIHByZXNzdXJlPzogc3RyaW5nIDtcbiAgdGVtcGVyYXR1cmU/OiBzdHJpbmcgO1xuICBmZWVsc19saWtlPzogc3RyaW5nIDtcbiAgdmlzaWJpbGl0eT86IHN0cmluZyA7XG4gIHdpbmRfYmVhcmluZz86IHN0cmluZyA7XG4gIHdpbmRfc3BlZWQ/OiBzdHJpbmcgO1xuICBwcmVjaXBpdGF0aW9uPzogc3RyaW5nIDtcbiAgZm9yZWNhc3Q/OiBib29sZWFuIDtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgRm9yZWNhc3Qge1xuICBtZXRlb2dyYW0/OiBzdHJpbmcgO1xuICB0ZW1wZXJhdHVyZV9oaWdoPzogRGF5cyA7XG4gIHRlbXBlcmF0dXJlX2xvdz86IERheXMgO1xuICBzdW1tYXJ5PzogRGF5cyA7XG4gIGljb25zPzogRGF5cyA7XG4gIHByZWNpcGl0YXRpb25fcHJvYmFiaWxpdHk/OiBEYXlzIDtcbiAgcHJlY2lwaXRhdGlvbl9pbnRlbnNpdHk/OiBEYXlzIDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXZWF0aGVyIHtcbiAgaWNvbnNfbW9kZWw6IHN0cmluZyA7XG4gIGN1cnJlbnQ6IEN1cnJlbnQgO1xuICBmb3JlY2FzdD86IEZvcmVjYXN0IDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIb3VycyB7XG4gIGhvdXJfMTogc3RyaW5nIDtcbiAgaG91cl8yOiBzdHJpbmcgO1xuICBob3VyXzM6IHN0cmluZyA7XG4gIGhvdXJfNDogc3RyaW5nIDtcbiAgaG91cl81OiBzdHJpbmcgO1xuICBob3VyXzY6IHN0cmluZyA7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSWNvbnNDb25maWcge1xuICBwYXRoOiBzdHJpbmcgO1xuICBpY29uVHlwZTogc3RyaW5nIDtcbiAgaWNvbnNfbW9kZWw6IHN0cmluZyA7XG4gIGljb25zRGF5OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZzsgfSA7XG4gIGljb25zTmlnaHQ6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nOyB9IDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJVGVybXMge1xuICAgd2luZERpcmVjdGlvbnM7XG4gICB3b3Jkcztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBbGVydCB7XG4gIGZpcmVfcmlzaz86IEFsZXJ0SXRlbSA7XG4gIHRodW5kZXJzdG9ybXNfcmlzaz86IEFsZXJ0SXRlbSA7XG4gIGh5ZHJhdWxpY19yaXNrPzogQWxlcnRJdGVtIDtcbiAgaHlkcm9nZW9sb2dpY2FsX3Jpc2s/OiBBbGVydEl0ZW0gO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlYSB7XG4gIHN3ZWxsX2RpcmVjdGlvbj86IEhvdXJzIDtcbiAgc3dlbGxfaGVpZ2h0PzogSG91cnMgO1xuICBzd2VsbF9wZXJpb2Q/OiBIb3VycyA7XG4gIHdpbmRfZGlyZWN0aW9uOiBIb3VycyA7XG4gIHdpbmRfc3BlZWQ6IEhvdXJzIDtcbiAgYWlyX3RlbXBlcmF0dXJlOiBIb3VycyA7XG4gIHdhdGVyX3RlbXBlcmF0dXJlOiBIb3VycyA7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FyZENvbmZpZyB7XG4gIHR5cGU6IHN0cmluZyA7XG4gIG5hbWU/OiBzdHJpbmcgO1xuICBsYW5ndWFnZT86IHN0cmluZyA7XG4gIGFuaW1hdGlvbj86IGJvb2xlYW4gO1xuICBkaXNwbGF5OiBzdHJpbmdbXVxuICB1dj86IFV2IDtcbiAgYWlyX3F1YWxpdHk/OiBBaXJRdWFsaXR5IDtcbiAgcG9sbGVuPzogUG9sbGVuIDtcbiAgd2VhdGhlcjogV2VhdGhlciA7XG4gIGNhbWVyYT86IHN0cmluZyA7XG4gIGFsZXJ0OiBBbGVydCA7XG4gIHNlYTogU2VhIDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJY29uc01vZGVsQ29uZmlnIHtcbiAgaWNvbnNEYXk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGljb25zTmlnaHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59XG5cbmV4cG9ydCBjb25zdCBpY29uc01vZGVsczogUmVjb3JkPHN0cmluZywgSWNvbnNNb2RlbENvbmZpZz4gPSB7XG4gIHBpcmF0ZXdlYXRoZXI6IHtcbiAgICBpY29uc0RheTogY3djRGF5dGltZVBpcmF0ZVdlYXRoZXJJY29ucyxcbiAgICBpY29uc05pZ2h0OiBjd2NOaWdodGx5UGlyYXRlV2VhdGVySWNvbnMsXG4gIH0sXG4gIGNsaW1hY2VsbDoge1xuICAgIGljb25zRGF5OiBjd2NDbGltYWNlbGxEYXlJY29ucyxcbiAgICBpY29uc05pZ2h0OiBjd2NDbGltYWNlbGxOaWdodEljb25zLFxuICB9LFxuICBkYXJrc2t5OiB7XG4gICAgaWNvbnNEYXk6IGN3Y0Rhcmtza3lEYXlJY29ucyxcbiAgICBpY29uc05pZ2h0OiBjd2NEYXJrc2t5TmlnaHRJY29ucyxcbiAgfSxcbiAgb3BlbndlYXRoZXJtYXA6IHtcbiAgICBpY29uc0RheTogY3djT3BlbldlYXRoZXJNYXBEYXlJY29ucyxcbiAgICBpY29uc05pZ2h0OiBjd2NPcGVuV2VhdGhlck1hcE5pZ2h0SWNvbnMsXG4gIH0sXG4gIGJ1aWVucmFkYXI6IHtcbiAgICBpY29uc0RheTogY3djQnVpZW5yYWRhckRheUljb25zLFxuICAgIGljb25zTmlnaHQ6IGN3Y0J1aWVucmFkYXJOaWdodEljb25zLFxuICB9LFxuICBkZWZhdWx0aGFzczoge1xuICAgIGljb25zRGF5OiBjd2NEZWZhdWx0SGFzc0RheUljb25zLFxuICAgIGljb25zTmlnaHQ6IGN3Y0RlZmF1bHRIYXNzTmlnaHRJY29ucyxcbiAgfSxcbn07XG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBjYW1lbGNhc2UgKi9cbmltcG9ydCB7IEhvbWVBc3Npc3RhbnQgfSBmcm9tICdjdXN0b20tY2FyZC1oZWxwZXJzL2Rpc3QnO1xuaW1wb3J0IHsgaWNvbnNNb2RlbHMgfSBmcm9tICcuLi8uLi9iYWNrdXAvdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEljb25zQ29uZmlnUmVzdWx0IHtcbiAgaWNvbnNNb2RlbDogc3RyaW5nO1xuICBpY29uc0RheTogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgaWNvbnNOaWdodDogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn1cblxuLy8gZXhwb3J0IGNvbnN0IGdldEVudGl0eVN0YXRlID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIGVudGl0eUlkPzogc3RyaW5nKSA9PiAoXG4vLyAgIGVudGl0eUlkID8gaGFzcy5zdGF0ZXNbZW50aXR5SWRdPy5zdGF0ZSA6IHVuZGVmaW5lZFxuLy8gKTtcblxuLyoqXG4gKiBSZXN0aXR1aXNjZSBsYSB0cmFkdXppb25lIGRpIHVuIHRlcm1pbmUgdXNhbmRvIHVuIGRpemlvbmFyaW8sIGluIG1vZG8gY2FzZS1pbnNlbnNpdGl2ZS5cbiAqIFNlIGlsIHRlcm1pbmUgbm9uIMOoIHRyb3ZhdG8sIHJlc3RpdHVpc2NlIGwnb3JpZ2luYWxlLlxuICovXG5leHBvcnQgY29uc3QgdHJhbnNsYXRlID0gKHRlcm06IHN0cmluZywgZGljdGlvbmFyeTogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGtleSA9IE9iamVjdC5rZXlzKGRpY3Rpb25hcnkpLmZpbmQoKGspID0+IGsudG9Mb3dlckNhc2UoKSA9PT0gdGVybS50b0xvd2VyQ2FzZSgpKTtcbiAgcmV0dXJuIGtleSA/IGRpY3Rpb25hcnlba2V5XSA6IHRlcm07XG59O1xuXG50eXBlIExvY2FsZUluZm8gPSB7XG4gIGxvY2FsZTogc3RyaW5nO1xuICB0aW1lem9uZTogc3RyaW5nO1xuICBjd2M/OiBudW1iZXI7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0TG9jYWxlSW5mbyA9IChsYW5nOiBzdHJpbmcpOiBMb2NhbGVJbmZvID0+IHtcbiAgY29uc3QgbG9jYWxlTWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgIGVuOiAnZW4tVVMnLFxuICAgIGl0OiAnaXQtSVQnLFxuICAgIG5sOiAnbmwtTkwnLFxuICAgIGVzOiAnZXMtRVMnLFxuICAgIGRlOiAnZGUtREUnLFxuICAgIGZyOiAnZnItRlInLFxuICAgICdzci1sYXRuJzogJ3NyLUxhdG4nLFxuICAgIHB0OiAncHQtUFQnLFxuICAgIGRhOiAnZGEtREsnLFxuICAgICduby1ubyc6ICduYi1OTycsXG4gICAgY3M6ICdjcy1DWicsXG4gICAgcnU6ICdydS1SVScsXG4gIH07XG5cbiAgY29uc3QgdGltZXpvbmVNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgZW46ICdBbWVyaWNhL05ld19Zb3JrJyxcbiAgICBpdDogJ0V1cm9wZS9Sb21lJyxcbiAgICBubDogJ0V1cm9wZS9BbXN0ZXJkYW0nLFxuICAgIGVzOiAnRXVyb3BlL01hZHJpZCcsXG4gICAgZGU6ICdFdXJvcGUvQmVybGluJyxcbiAgICBmcjogJ0V1cm9wZS9QYXJpcycsXG4gICAgJ3NyLWxhdG4nOiAnRXVyb3BlL0JlbGdyYWRlJyxcbiAgICBqYTogJ0FzaWEvVG9reW8nLFxuICAgIHB0OiAnRXVyb3BlL0xpc2JvbicsXG4gICAgZGE6ICdFdXJvcGUvQ29wZW5oYWdlbicsXG4gICAgJ25vLW5vJzogJ0V1cm9wZS9Pc2xvJyxcbiAgICBjczogJ0V1cm9wZS9QcmFndWUnLFxuICAgIHJ1OiAnRXVyb3BlL01vc2NvdycsXG4gIH07XG5cbiAgY29uc3QgY3djTG9jYWxlOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge1xuICAgIGVuOiAwLFxuICAgIGl0OiAxLFxuICAgIG5sOiAyLFxuICAgIGVzOiAzLFxuICAgIGRlOiA0LFxuICAgIGZyOiA1LFxuICAgICdzci1sYXRuJzogNixcbiAgICBwdDogNyxcbiAgICBkYTogOCxcbiAgICAnbm8tbm8nOiA5LFxuICAgIGNzOiAxMCxcbiAgICBydTogMTEsXG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBsb2NhbGU6IGxvY2FsZU1hcFtsYW5nXSB8fCBsYW5nLFxuICAgIHRpbWV6b25lOiB0aW1lem9uZU1hcFtsYW5nXSB8fCAnVVRDJyxcbiAgICAuLi4obGFuZyBpbiBjd2NMb2NhbGUgJiYgeyBjd2M6IGN3Y0xvY2FsZVtsYW5nXSB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRMb2NhbGUgPSAobGFuZzogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IG1hcCA9IHtcbiAgICBpdDogJ2l0LUlUJyxcbiAgICBlbjogJ2VuLVVTJyxcbiAgICBmcjogJ2ZyLUZSJyxcbiAgICBkZTogJ2RlLURFJyxcbiAgICBlczogJ2VzLUVTJyxcbiAgICBqYTogJ2phLUpQJyxcbiAgICB6aDogJ3poLUNOJyxcbiAgICAvLyBBZ2dpdW5naSBhbHRyaSBzZSBzZXJ2b25vXG4gIH07XG4gIHJldHVybiBtYXBbbGFuZ10gfHwgYCR7bGFuZ30tJHtsYW5nLnRvVXBwZXJDYXNlKCl9YDsgLy8gZmFsbGJhY2sgZ2VuZXJpY29cbn07XG5cbmV4cG9ydCBjb25zdCBnZXRGb3JtYXR0ZXIgPSAoXG4gIGxvY2FsZTogc3RyaW5nID0gJ2VuLVVTJyxcbiAgZnJhY3Rpb25EaWdpdHM6IG51bWJlciA9IDEsXG4gIHVzZUdyb3VwaW5nOiBib29sZWFuID0gZmFsc2UsXG4pOiBJbnRsLk51bWJlckZvcm1hdCA9PiBuZXcgSW50bC5OdW1iZXJGb3JtYXQobG9jYWxlLCB7XG4gIG1pbmltdW1GcmFjdGlvbkRpZ2l0czogZnJhY3Rpb25EaWdpdHMsXG4gIG1heGltdW1GcmFjdGlvbkRpZ2l0czogZnJhY3Rpb25EaWdpdHMsXG4gIHVzZUdyb3VwaW5nLFxufSk7XG5cbmV4cG9ydCBjb25zdCBmb3JtYXROdW1iZXIgPSAoXG4gIHtcbiAgICBzdHJpbmdOdW1iZXIsXG4gICAgbGFuZyA9ICdlbicsXG4gICAgZnJhY3Rpb25EaWdpdHMgPSAxLFxuICAgIHVzZUdyb3VwaW5nID0gZmFsc2UsXG4gIH06IHtcbiAgICBzdHJpbmdOdW1iZXI6IHN0cmluZztcbiAgICBsYW5nPzogc3RyaW5nO1xuICAgIGZyYWN0aW9uRGlnaXRzPzogbnVtYmVyO1xuICAgIHVzZUdyb3VwaW5nPzogYm9vbGVhbjtcbiAgfSxcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IG51bWJlciA9IHBhcnNlRmxvYXQoc3RyaW5nTnVtYmVyKTtcbiAgaWYgKE51bWJlci5pc05hTihudW1iZXIpKSByZXR1cm4gJyc7XG5cbiAgY29uc3QgZWZmZWN0aXZlRm9ybWF0dGVyID0gZ2V0Rm9ybWF0dGVyKGdldExvY2FsZShsYW5nKSwgZnJhY3Rpb25EaWdpdHMsIHVzZUdyb3VwaW5nKTtcbiAgLy8gY29uc29sZS5kZWJ1ZyhgPj4+fHwgJHtudW1iZXJ9ICR7ZWZmZWN0aXZlRm9ybWF0dGVyLmZvcm1hdChudW1iZXIpfWApO1xuICByZXR1cm4gZWZmZWN0aXZlRm9ybWF0dGVyLmZvcm1hdChudW1iZXIpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEljb25Nb2RlbERhdGEgPSAoaWNvbnNNb2RlbDogc3RyaW5nKTogSWNvbnNDb25maWdSZXN1bHQgPT4ge1xuICBjb25zdCBtb2RlbE5hbWUgPSBpY29uc01vZGVsLnRvTG93ZXJDYXNlKCkgPz8gJ2NsaW1hY2VsbCc7XG5cbiAgaWYgKG1vZGVsTmFtZSBpbiBpY29uc01vZGVscykge1xuICAgIGNvbnN0IHsgaWNvbnNEYXksIGljb25zTmlnaHQgfSA9IGljb25zTW9kZWxzW21vZGVsTmFtZV07XG4gICAgcmV0dXJuIHtcbiAgICAgIGljb25zTW9kZWw6IG1vZGVsTmFtZSxcbiAgICAgIGljb25zRGF5LFxuICAgICAgaWNvbnNOaWdodCxcbiAgICB9O1xuICB9XG5cbiAgY29uc29sZS53YXJuKGBVbmtub3duIGljb25zIG1vZGVsOiAke21vZGVsTmFtZX0uIEZhbGxpbmcgYmFjayB0byAnY2xpbWFjZWxsJy5gKTtcblxuICBjb25zdCBmYWxsYmFjayA9IGljb25zTW9kZWxzWydjbGltYWNlbGwnXTtcbiAgcmV0dXJuIHtcbiAgICBpY29uc01vZGVsOiAnY2xpbWFjZWxsJyxcbiAgICBpY29uc0RheTogZmFsbGJhY2suaWNvbnNEYXksXG4gICAgaWNvbnNOaWdodDogZmFsbGJhY2suaWNvbnNOaWdodCxcbiAgfTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBwYWQobjogbnVtYmVyIHwgc3RyaW5nLCB3aWR0aDogbnVtYmVyLCB6ID0gJzAnKTogc3RyaW5nIHtcbiAgcmV0dXJuIG4udG9TdHJpbmcoKS5wYWRTdGFydCh3aWR0aCwgeik7XG59XG5cbi8qKlxuICogQ29udmVydGUgdW5hIHN0cmluZ2EgbnVtZXJpY2EgbG9jYWxpenphdGEgaW4gdW4gbnVtZXJvLlxuICogRXNlbXBpbzogJzEuMjM0LDU2JyAoaXQtSVQpIOKGkiAxMjM0LjU2XG4gKiBAcGFyYW0gaW5wdXQgLSBMYSBzdHJpbmdhIG8gbnVtZXJvIGRhIGNvbnZlcnRpcmUuXG4gKiBAcGFyYW0gbG9jYWxlIC0gSWwgbG9jYWxlIGRhIHV0aWxpenphcmUgcGVyIGRldGVybWluYXJlIGkgc2VwYXJhdG9yaS5cbiAqIEByZXR1cm5zIElsIG51bWVybyBjb252ZXJ0aXRvIG8gTmFOIHNlIGxhIGNvbnZlcnNpb25lIGZhbGxpc2NlLlxuICovXG5leHBvcnQgY29uc3Qgc3RyaW5nMk51bWJlciA9IChpbnB1dDogc3RyaW5nIHwgbnVtYmVyLCBsb2NhbGU6IHN0cmluZyA9ICdlbi1VUycpOiBudW1iZXIgPT4ge1xuICBpZiAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJykgcmV0dXJuIGlucHV0O1xuXG4gIGNvbnN0IGZvcm1hdHRlciA9IG5ldyBJbnRsLk51bWJlckZvcm1hdChsb2NhbGUpO1xuICBjb25zdCBwYXJ0cyA9IGZvcm1hdHRlci5mb3JtYXRUb1BhcnRzKDEyMzQ1NjcuODkpO1xuXG4gIGNvbnN0IGdyb3VwID0gcGFydHMuZmluZCgocGFydCkgPT4gcGFydC50eXBlID09PSAnZ3JvdXAnKT8udmFsdWUgfHwgJyc7XG4gIGNvbnN0IGRlY2ltYWwgPSBwYXJ0cy5maW5kKChwYXJ0KSA9PiBwYXJ0LnR5cGUgPT09ICdkZWNpbWFsJyk/LnZhbHVlIHx8ICcuJztcblxuICAvLyBSaW11b3ZlIGkgc2VwYXJhdG9yaSBkZWxsZSBtaWdsaWFpYSBlIHNvc3RpdHVpc2NlIGlsIHNlcGFyYXRvcmUgZGVjaW1hbGUgY29uICcuJ1xuICBjb25zdCBub3JtYWxpemVkID0gaW5wdXRcbiAgICAucmVwbGFjZShuZXcgUmVnRXhwKGBcXFxcJHtncm91cH1gLCAnZycpLCAnJylcbiAgICAucmVwbGFjZShuZXcgUmVnRXhwKGBcXFxcJHtkZWNpbWFsfWApLCAnLicpO1xuXG4gIHJldHVybiBOdW1iZXIobm9ybWFsaXplZCk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0RW50aXR5UmF3VmFsdWUgPSAoaGFzczogSG9tZUFzc2lzdGFudCwgZW50aXR5SWQ/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4gKFxuICBlbnRpdHlJZCAmJiBoYXNzLnN0YXRlc1tlbnRpdHlJZF0/LnN0YXRlXG4pO1xuXG5leHBvcnQgY29uc3QgZ2V0RW50aXR5UmF3QXR0cmlidXRlID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIGVudGl0eUlkOiBzdHJpbmcsIGF0dHJpYnV0ZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IChcbiAgZW50aXR5SWQgJiYgaGFzcy5zdGF0ZXNbZW50aXR5SWRdPy5hdHRyaWJ1dGVzW2F0dHJpYnV0ZV1cbik7XG5cbmV4cG9ydCBjb25zdCBnZXRFbnRpdHlOdW1lcmljVmFsdWUgPSAoXG4gIHtcbiAgICBlbnRpdHlJZCxcbiAgICBoYXNzLFxuICAgIGxhbmcgPSAnZW4nLFxuICAgIGRlY2ltYWxzID0gMCxcbiAgfToge1xuICAgIGVudGl0eUlkPzogc3RyaW5nO1xuICAgIGhhc3M/OiBIb21lQXNzaXN0YW50O1xuICAgIGxhbmc/OiBzdHJpbmc7XG4gICAgZGVjaW1hbHM/OiBudW1iZXI7XG4gIH0gPSB7fSxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IHN0YXRlID0gaGFzcyAmJiBlbnRpdHlJZCAmJiBoYXNzLnN0YXRlc1tlbnRpdHlJZF0/LnN0YXRlO1xuICByZXR1cm4gc3RhdGUgIT09IHVuZGVmaW5lZCA/IGZvcm1hdE51bWJlcih7IHN0cmluZ051bWJlcjogc3RhdGUsIGZyYWN0aW9uRGlnaXRzOiBkZWNpbWFscywgbGFuZyB9KSA6IHVuZGVmaW5lZDtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRFbnRpdHlVbml0ID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIGVudGl0eUlkPzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IChcbiAgZW50aXR5SWQgJiYgaGFzcy5zdGF0ZXNbZW50aXR5SWRdPy5hdHRyaWJ1dGVzPy51bml0X29mX21lYXN1cmVtZW50XG4pO1xuXG5leHBvcnQgY29uc3QgZ2V0RW50aXR5SWNvbiA9IChoYXNzOiBIb21lQXNzaXN0YW50LCBlbnRpdHlJZD86IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiAoXG4gIGVudGl0eUlkICYmIGhhc3Muc3RhdGVzW2VudGl0eUlkXT8uYXR0cmlidXRlcz8uaWNvblxuKTtcblxuZXhwb3J0IGNvbnN0IGdldFdpbmREaXJlY3Rpb25zID0gKFxuICB3ZDogbnVtYmVyIHwgc3RyaW5nLFxuICBjd2NMb2NXaW5kRGlyZWN0aW9ucyxcbik6IHN0cmluZyB8IG51bGwgPT4ge1xuICBjb25zdCB3ZE51bWJlciA9IHR5cGVvZiB3ZCA9PT0gJ251bWJlcicgPyB3ZCA6IHBhcnNlRmxvYXQod2QpO1xuXG4gIGlmIChOdW1iZXIuaXNOYU4od2ROdW1iZXIpKSB7XG4gICAgcmV0dXJuIGN3Y0xvY1dpbmREaXJlY3Rpb25zW3dkXSA/PyBudWxsO1xuICB9XG5cbiAgaWYgKHdkTnVtYmVyIDwgMCB8fCB3ZE51bWJlciA+IDM2MCkge1xuICAgIGNvbnNvbGUuZXJyb3IoYEludmFsaWQgd2luZCBkaXJlY3Rpb246ICcke3dkfScuIFZhbGlkIHZhbHVlcyBhcmUgYmV0d2VlbiAwIGFuZCAzNjAgZGVncmVlcy5gKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRpcmVjdGlvbnMgPSBbXG4gICAgJ04nLCAnTk5FJywgJ05FJywgJ0VORScsICdFJywgJ0VTRScsXG4gICAgJ1NFJywgJ1NTRScsICdTJywgJ1NTVycsICdTVycsICdXU1cnLFxuICAgICdXJywgJ1dOVycsICdOVycsICdOTlcnLFxuICBdO1xuXG4gIGNvbnN0IGluZGV4ID0gTWF0aC5mbG9vcigoKHdkTnVtYmVyICsgMTEuMjUpICUgMzYwKSAvIDIyLjUpO1xuXG4gIGNvbnN0IGRpcktleSA9IGRpcmVjdGlvbnNbaW5kZXhdO1xuXG4gIHJldHVybiBjd2NMb2NXaW5kRGlyZWN0aW9uc1tkaXJLZXldID8/IG51bGw7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gaW1hZ2VFeGlzdChpbWFnZVNyYzogc3RyaW5nLCB0aW1lb3V0ID0gNTAwMCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8Ym9vbGVhbj4oKHJlc29sdmUpID0+IHtcbiAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaW1nLnNyYyA9ICcnOyAvLyBmb3J6YSBzdG9wXG4gICAgICByZXNvbHZlKGZhbHNlKTtcbiAgICB9LCB0aW1lb3V0KTtcblxuICAgIGltZy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgcmVzb2x2ZSh0cnVlKTtcbiAgICB9O1xuICAgIGltZy5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgIH07XG4gICAgaW1nLnNyYyA9IGltYWdlU3JjO1xuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvYWRKU09OKGZ1bGxfcGF0aF9maWxlOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goZnVsbF9wYXRoX2ZpbGUpO1xuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIGNvbnN0IGVyciA9IGBFUlJPUiByZXRyaWV2aW5nIEpTT04gZmlsZTogJyR7ZnVsbF9wYXRoX2ZpbGV9Jywgc3RhdHVzOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWA7XG4gICAgICBjb25zb2xlLmluZm8oZXJyKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihlcnIpO1xuICAgIH1cbiAgICBjb25zb2xlLmluZm8oYExvY2FsZSAnJHtmdWxsX3BhdGhfZmlsZX0nIGxvYWRlZGApO1xuICAgIHJldHVybiBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5pbmZvKGBGZXRjaCBmYWlsZWQgZm9yICcke2Z1bGxfcGF0aF9maWxlfSc6YCwgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dJbmZvKG1lc3NhZ2U6IHN0cmluZywgLi4uc3R5bGVzOiB1bmtub3duW10pIHtcbiAgY29uc29sZS5pbmZvKG1lc3NhZ2UsIC4uLihzdHlsZXMubGVuZ3RoID8gc3R5bGVzIDogW10pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlTG9jYWxpemVkTnVtYmVyKHZhbHVlOiBzdHJpbmcgfCBudW1iZXIsIGxvY2FsZSA9ICdlbi1VUycpOiBudW1iZXIge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykgcmV0dXJuIHZhbHVlO1xuXG4gIC8vIFNlbXBsaWZpY2F6aW9uZSBzb2xvIHBlciAnaXQtSVQnOiB1c2EgdmlyZ29sYSBjb21lIHNlcGFyYXRvcmUgZGVjaW1hbGVcbiAgY29uc3Qgbm9ybWFsaXplZCA9IHZhbHVlLnJlcGxhY2UoL1xcLi9nLCAnJykucmVwbGFjZSgnLCcsICcuJyk7XG4gIHJldHVybiBOdW1iZXIobm9ybWFsaXplZCk7XG59XG4iLCIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgb2JqZWN0LWN1cmx5LW5ld2xpbmVcbmV4cG9ydCBjb25zdCBjd2NMb2NhbGUgPSB7IGVuOiAwLCBpdDogMSwgbmw6IDIsIGVzOiAzLCBkZTogNCwgZnI6IDUsICdzci1sYXRuJzogNiwgcHQ6IDcsIGRhOiA4LCAnbm8tbm8nOiA5LCBjczogMTAgfTtcblxuLy8gZXhwb3J0IGxldCBjd2NMb2NXaW5kRGlyZWN0aW9ucyA9IHtcbi8vICAgJ04nOiBbJ04nLCAnTicsICdOJywgJ04nLCAnTicsICdOJywgJ1MnXSxcbi8vICAgJ05ORSc6IFsnTk5FJywgJ05ORScsICdOTk8nLCAnTk5FJywgJ05OTycsICdOTkUnLCAnU1NJJ10sXG4vLyAgICdORSc6IFsnTkUnLCAnTkUnLCAnTk8nLCAnTkUnLCAnTk8nLCAnTkUnLCAnU0knXSxcbi8vICAgJ0VORSc6IFsnRU5FJywgJ0VORScsICdPTk8nLCAnRU5FJywgJ09OTycsICdFTkUnLCAnSVNJJ10sXG4vLyAgICdFJzogWydFJywgJ0UnLCAnTycsICdFJywgJ08nLCAnRScsICdJJ10sXG4vLyAgICdFU0UnOiBbJ0VTRScsICdFU0UnLCAnT1pPJywgJ0VTRScsICdPU08nLCAnRVNFJywgJ0lKSSddLFxuLy8gICAnU0UnOiBbJ1NFJywgJ1NFJywgJ1pPJywgJ1NFJywgJ1NPJywgJ1NFJywgJ0pJJ10sXG4vLyAgICdTU0UnOiBbJ1NTRScsICdTU0UnLCAnWlpPJywgJ1NTRScsICdTU08nLCAnU1NFJywgJ0pKSSddLFxuLy8gICAnUyc6IFsnUycsICdTJywgJ1onLCAnUycsICdTJywgJ1MnLCAnSiddLFxuLy8gICAnU1NXJzogWydTU1cnLCAnU1NPJywgJ1paVycsICdTU08nLCAnU1NXJywgJ1NTTycsICdKSlonXSxcbi8vICAgJ1NXJzogWydTVycsICdTTycsICdaVycsICdTTycsICdTVycsICdTTycsICdKWiddLFxuLy8gICAnV1NXJzogWydXU1cnLCAnT1NPJywgJ1daVycsICdPU08nLCAnV1NXJywgJ09TTycsICdaU1onXSxcbi8vICAgJ1cnOiBbJ1cnLCAnTycsICdXJywgJ08nLCAnVycsICdPJywgJ1onXSxcbi8vICAgJ1dOVyc6IFsnV05XJywgJ09OTycsICdXTlcnLCAnT05PJywgJ1dOVycsICdPTk8nLCAnWlNaJ10sXG4vLyAgICdOVyc6IFsnTlcnLCAnTk8nLCAnTlcnLCAnTk8nLCAnTlcnLCAnTk8nLCAnU1onXSxcbi8vICAgJ05OVyc6IFsnTk5XJywgJ05OTycsICdOTlcnLCAnTk5PJywgJ05OVycsICdOTk8nLCAnU1NaJ10sXG4vLyB9O1xuXG4vLyBleHBvcnQgbGV0IGN3Y1Rlcm1zID0ge1xuLy8gICAnRmVlbHMgTGlrZScgOiBbJ0ZlZWxzIExpa2UnLCAnUGVyY2VwaXRhJywgJ1ZvZWx0IEFscycsICdQYXJlY2UgcXVlJywgJ0dlZiZ1dW1sO2hsdCcsXG4vLyAgICAgJ1Jlc3NlbnRpZScsICdTdWJqZWt0aXZuaSBvc2XEh2FqJ10sXG4vLyAgICduZXdfbW9vbic6IFsgJ05ldyBtb29uJywgJ05vdmlsdW5pbycsICdOaWV1d2UgbWFhbicsICdMdW5hIG51ZXZhJywgJ05ldW1vbmQnLFxuLy8gICAgICdOb3V2ZWxsZSBsdW5lJywgJ01sYWQgbWVzZWMnXSxcbi8vICAgJ25ldyc6IFsgJ05ldyBtb29uJywgJ05vdmlsdW5pbycsICdOaWV1d2UgbWFhbicsICdMdW5hIG51ZXZhJywgJ05ldW1vbmQnLFxuLy8gICAgICdOb3V2ZWxsZSBsdW5lJywgJ01sYWQgbWVzZWMnXSxcbi8vICAgJ3dheGluZ19jcmVzY2VudCc6IFsnV2F4aW5nIGNyZXNjZW50JywgJ0x1bmEgY3Jlc2NlbnRlJywgJ1dhc3NlbmRlIHNpa2tlbCcsICdNZWRpYSBsdW5hIGRlIGNlcmEnLCAnWnVuZWhtZW5kZSBTaWNoZWwnLFxuLy8gICAgICdQcmVtaWVyIGNyb2lzc2FudCcsICdQcnZhIG9zbWluYSddLFxuLy8gICAnZmlyc3RfcXVhcnRlcic6IFsnRmlyc3QgcXVhcnRlcicsICdQcmltbyBRdWFydG8nLCAnRWVyc3RlIGt3YXJ0YWFsJywgJ1ByaW1lciB0cmltZXN0cmUnLCAnRXJzdGVzIFZpZXJ0ZWwnLFxuLy8gICAgICdQcmVtaWVyIHF1YXJ0aWVyJywgJ1BydmEgxI1ldHZydCddLFxuLy8gICAnd2F4aW5nX2dpYmJvdXMnOiBbJ1dheGluZyBHaWJib3VzJywgJ0dpYmJvc2EgY3Jlc2NlbnRlJywgJ1dhc3NlbiBHaWJib3VzJywgJ0VuY2VyYWRvIEdpYmJvdXMnLCAnWnVuZWhtZW5kZXIgSGFsYm1vbmQnLFxuLy8gICAgICdHaWJiZXVzZSBjcm9pc3NhbnRlJywgJ1RyZcSHYSBvc21pbmEnXSxcbi8vICAgJ2Z1bGwnOiBbJ0Z1bGwnLCAnTHVuYSBwaWVuYScsICdWb2xsZWRpZycsICdDb21wbGV0bycsICdWb2xsbW9uZCcsXG4vLyAgICAgJ1BsZWluZSBsdW5lJywgJ1B1biBtZXNlYyddLFxuLy8gICAnd2FuaW5nX2dpYmJvdXMnOiBbJ1dhbmluZyBHaWJib3VzJywgJ0dpYmJvc2EgY2FsYW50ZScsICdad2VtbWVuZGUgR2liYm91cycsICdXYW5pbmcgR2liYm91cycsICdBYm5laG1lbmRlciBIYWxibW9uZCcsXG4vLyAgICAgJ0dpYmJldXNlIGTDqWNyb2lzc2FudGUnLCAnUGV0YSBvc21pbmEnXSxcbi8vICAgJ3RoaXJkX3F1YXJ0ZXInOiBbJ1RoaXJkIFF1YXJ0ZXInLCAnVWx0aW1vIHF1YXJ0bycsICdEZXJkZSBLd2FydGllcicsICdUZXJjZXIgY3VhcnRvJywgJ0RyaXR0ZXMgVmllcnRlbCcsXG4vLyAgICAgJ0Rlcm5pZXIgcXVhcnRpZXInLCAnVHJlxIdhIMSNZXR2cnRpbmEnXSxcbi8vICAgJ2xhc3RfcXVhcnRlcic6IFsnTGFzdCBRdWFydGVyJywgJ1VsdGltbyBxdWFydG8nLCAnTGFhdHN0ZSBLd2FydGllcicsICfDmmx0aW1vIGN1YXJ0bycsICdMZXR6dGVzIFZpZXJ0ZWwnLFxuLy8gICAgICdEZXJuaWVyIHF1YXJ0aWVyJywgJ1phZG5qYSDEjWV0dnJ0aW5hJ10sXG4vLyAgICd3YW5pbmdfY3Jlc2NlbnQnOiBbJ1dhbmluZyBDcmVzY2VudCcsICdMdW5hIGNhbGFudGUnLCAnWndlbW1lbmRlIHNpa2tlbCcsICdXYW5pbmcgQ3Jlc2NlbnQnLCAnQWJuZWhtZW5kZSBTaWNoZWwnLFxuLy8gICAgICdMdW5lIGTDqWNyb2lzc2FudGUnLCAnU2VkbWEgb3NtaW5hJ10sXG4vLyB9IDtcblxuLy8g8J+MkSDwn4ySIPCfjJMg8J+MlCDwn4yVIPCfjJYg8J+MlyDwn4yYIPCfjJFcbmV4cG9ydCBjb25zdCBjd2NNb29uUGhhc2VJY29ucyA9IHtcbiAgbmV3X21vb246ICfwn4yRJyxcbiAgbmV3OiAn8J+MkScsXG4gIHdheGluZ19jcmVzY2VudDogJ/CfjJInLFxuICBmaXJzdF9xdWFydGVyOiAn8J+MkycsXG4gIHdheGluZ19naWJib3VzOiAn8J+MlCcsXG4gIGZ1bGw6ICfwn4yVJyxcbiAgZnVsbF9tb29uOiAn8J+MlScsXG4gIHdhbmluZ19naWJib3VzOiAn8J+MlicsXG4gIHRoaXJkX3F1YXJ0ZXI6ICfwn4yXJyxcbiAgbGFzdF9xdWFydGVyOiAn8J+MlycsXG4gIHdhbmluZ19jcmVzY2VudDogJ/CfjJgnLFxufTtcbiIsImltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5cbmNvbnN0IGNhcmRTdHlsZSA9IGNzc2BcbiAgaGEtY2FyZCB7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICB3aWR0aDogMTAwJTtcbiAgfVxuXG4gIC5oYS1jYXJkLXdlYXRoZXItY29uZGl0aW9ucyB7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1jYXJkLWJhY2tncm91bmQtY29sb3IsICMxYzFjMWMpO1xuICAgIGNvbG9yOiB2YXIoLS1wcmltYXJ5LXRleHQtY29sb3IsICNmZmZmZmYpO1xuICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLWhhLWNhcmQtYm9yZGVyLXJhZGl1cywgMTJweCk7XG4gICAgYm94LXNoYWRvdzogdmFyKC0taGEtY2FyZC1ib3gtc2hhZG93LCAwIDJweCA2cHggcmdiYSgwLCAwLCAwLCAwLjIpKTtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIHBhZGRpbmc6IDA7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICB9XG5cbiAgLm5kLWNvbnRhaW5lciB7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgcGFkZGluZzogMTZweCAyMHB4OyAvKiDihpAgcGFkZGluZyBvcml6em9udGFsZSBwacO5IGFtcGlvICovXG4gICAgZ2FwOiAxMnB4O1xuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7XG4gICAgYmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyO1xuICAgIHRyYW5zaXRpb246IGJhY2tncm91bmQtaW1hZ2UgMC4zcyBlYXNlLWluLW91dDtcbiAgfVxuXG4gIC8qIEVzZW1waW8gZGkgc3RpbGUgZGluYW1pY28gYWdnaXVudGl2byBzZSBoYWJnSW1hZ2Ugw6ggdW5hIGNsYXNzZSAqL1xuICAubmQtY29udGFpbmVyLnN1bm55IHtcbiAgICBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoJy9sb2NhbC9pbWFnZXMvc3VubnktYmcuanBnJyk7XG4gIH1cblxuICAubmQtY29udGFpbmVyLnJhaW55IHtcbiAgICBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoJy9sb2NhbC9pbWFnZXMvcmFpbnktYmcuanBnJyk7XG4gIH1cblxuICAvKiAtLS0tLS0tLS0tLS0tLSAqL1xuXG5gO1xuXG5leHBvcnQgZGVmYXVsdCBjYXJkU3R5bGU7XG4iLCJpbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuXG5jb25zdCBzdW1tYXJ5U3R5bGUgPSBjc3NgXG5cbi5zdW1tYXJ5LWdyaWQtY29udGFpbmVyIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICB6LWluZGV4OiAxO1xuICBkaXNwbGF5OiBncmlkO1xuICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmciAxZnIgMWZyOyAvKiA8LS0gMyBjb2xvbm5lIHJlYWxpICovXG4gIGdyaWQtdGVtcGxhdGUtcm93czogYXV0byBhdXRvO1xuICB3aWR0aDogMTAwJTtcbiAgbWF4LXdpZHRoOiA2MDBweDtcbiAgLy8gYmFja2dyb3VuZDogIzFjMWMxYztcbiAgLy8gY29sb3I6IHdoaXRlO1xuICBnYXA6IDRweDtcbiAgcGFkZGluZzogMHB4O1xuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAvLyBib3JkZXI6IDFweCBzb2xpZCAjNDQ0OyAvKiBkZWJ1ZyAqL1xufVxuXG4uc3VtbWFyeS1jb2wtbGVmdCB7XG4gIGdyaWQtY29sdW1uOiAxO1xuICBncmlkLXJvdzogMSAvIHNwYW4gMjtcbiAgLy8gYmFja2dyb3VuZDogIzJjMmMyYztcbiAgcGFkZGluZy10b3A6IDBweDtcbiAgcGFkZGluZy1yaWdodDogMHB4O1xuICBwYWRkaW5nLWJvdHRvbTogMHB4O1xuICBwYWRkaW5nLWxlZnQ6IDBweDtcbiAgXG4gIGRpc3BsYXk6IGZsZXg7ICAgICAgICAgICAgICAgICAvKiBBdHRpdmEgRmxleGJveCAqL1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsgICAgICAvKiBDZW50cmEgb3JpenpvbnRhbG1lbnRlICovXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7ICAgICAgICAgIC8qIENlbnRyYSB2ZXJ0aWNhbG1lbnRlICovXG5cbiAgd2lkdGg6IDEwMCU7XG4gIG1heC13aWR0aDogMTAwJTtcbiAgYXNwZWN0LXJhdGlvOiAxIC8gMTsgLyogb3B6aW9uYWxlOiBtYW50aWVuZSBmb3JtYSBxdWFkcmF0YSAqL1xuICBvdmVyZmxvdzogaGlkZGVuO1xufVxuXG4uc3VtbWFyeS10b3AtcmlnaHQge1xuICBncmlkLWNvbHVtbjogMiAvIHNwYW4gMjsgLyogb2NjdXBhIGNvbG9ubmUgMiBlIDMgKi9cbiAgZ3JpZC1yb3c6IDE7XG4gIC8vIGJhY2tncm91bmQ6ICMzYzNjM2M7XG4gIHBhZGRpbmctdG9wOiAwcHg7XG4gIHBhZGRpbmctcmlnaHQ6IDhweDtcbiAgcGFkZGluZy1ib3R0b206IDBweDtcbiAgcGFkZGluZy1sZWZ0OiA4cHg7XG4gIGRpc3BsYXk6IGZsZXg7ICAgICAgICAgICAgLyogYWdnaXVudG8gKi9cbiAgYWxpZ24taXRlbXM6IGNlbnRlcjsgICAgICAvKiBjZW50cmEgdmVydGljYWxtZW50ZSAqL1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtc3RhcnQ7IC8qIGFsbGluZWEgYSBzaW5pc3RyYSAqL1xufVxuXG4uc3VtbWFyeS1ib3R0b20tcmlnaHQtbGVmdCB7XG4gIGdyaWQtY29sdW1uOiAyO1xuICBncmlkLXJvdzogMjtcbiAgLy8gYmFja2dyb3VuZDogIzRjNGM0YztcbiAgcGFkZGluZy10b3A6IDBweDtcbiAgcGFkZGluZy1yaWdodDogOHB4O1xuICBwYWRkaW5nLWJvdHRvbTogMHB4O1xuICBwYWRkaW5nLWxlZnQ6IDhweDtcblxuICBkaXNwbGF5OiBmbGV4OyAgICAgICAgICAgICAgICAgLyogQXR0aXZhIEZsZXhib3ggKi9cbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7ICAgICAgLyogQ2VudHJhIG9yaXp6b250YWxtZW50ZSAqL1xuICBhbGlnbi1pdGVtczogY2VudGVyOyAgICAgICAgICAvKiBDZW50cmEgdmVydGljYWxtZW50ZSAqL1xufVxuXG4uc3VtbWFyeS1ib3R0b20tcmlnaHQtcmlnaHQge1xuICBncmlkLWNvbHVtbjogMztcbiAgZ3JpZC1yb3c6IDI7XG4gIC8vIGJhY2tncm91bmQ6ICM1YzVjNWM7XG4gIHBhZGRpbmctdG9wOiAwcHg7XG4gIHBhZGRpbmctcmlnaHQ6IDhweDtcbiAgcGFkZGluZy1ib3R0b206IDBweDtcbiAgcGFkZGluZy1sZWZ0OiA4cHg7XG59XG5cbi53ZWF0aGVyLWNvbmRpdGlvbi1pY29uIHtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogYXV0bztcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBtYXgtaGVpZ2h0OiAxMDAlO1xuICBvYmplY3QtZml0OiBjb250YWluO1xuICAvLyBtYXgtd2lkdGg6IDEwMCU7XG4gIC8vIG1heC1oZWlnaHQ6IDEwMCU7XG4gIC8vIHdpZHRoOiA3MnB4O1xuICAvLyBoZWlnaHQ6IDcycHg7XG4gIC8vIG9iamVjdC1maXQ6IGNvbnRhaW47XG5cbiAgdHJhbnNpdGlvbjogdHJhbnNmb3JtIDAuMnMgZWFzZTtcbn1cbiAgXG4uc3VtbWFyeS1jb2wtbGVmdDpob3ZlciAud2VhdGhlci1jb25kaXRpb24taWNvbiB7XG4gIHRyYW5zZm9ybTogc2NhbGUoMS4wNSk7XG59XG5cbi53ZWF0aGVyLWNpdHktbmFtZSB7XG4gIGZvbnQtc2l6ZTogY2xhbXAoMWVtLCAydncsIDEuMmVtKTtcbiAgdGV4dC1hbGlnbjogbGVmdDtcbn1cblxuLm1vb24tcm93IHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiA2cHg7XG4gIC8vIGZvbnQtc2l6ZTogMC45NWVtO1xuICAvLyBjb2xvcjogI2VlZWVlZTtcbn1cblxuLnN1bW1hcnktbW9vbi1pY29uIHtcbiAgZm9udC1zaXplOiAxLjhlbTtcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xufVxuXG4udGVtcGVyYXR1cmUtYmxvY2sge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XG4gIHRleHQtYWxpZ246IHJpZ2h0O1xufVxuXG4udGVtcGVyYXR1cmUge1xuICBmb250LXNpemU6IDEuNmVtO1xuICBmb250LXdlaWdodDogYm9sZDtcbn1cblxuLnRlbXAtdW5pdCB7XG4gIGZvbnQtc2l6ZTogMC45NWVtO1xuICB2ZXJ0aWNhbC1hbGlnbjogc3VwZXI7XG4gIG1hcmdpbi1sZWZ0OiAycHg7XG59XG5cbi5mZWVscy1saWtlIHtcbiAgZm9udC1zaXplOiAwLjg1ZW07XG4gIC8vIGNvbG9yOiAjYWFhYWFhO1xufVxuXG4uc3VtbWFyeS13cmFwcGVyIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xuICBtaW4taGVpZ2h0OiAxMDBweDsgLyogb3BwdXJlIGNsYW1wKCkgZGluYW1pY28gKi9cbiAgb3ZlcmZsb3c6IHZpc2libGU7XG59XG5cbi5saWdodG5pbmctYmFja2dyb3VuZCB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgaW5zZXQ6IDA7IC8qIHRvcDogMDsgcmlnaHQ6IDA7IGJvdHRvbTogMDsgbGVmdDogMCAqL1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbiAgei1pbmRleDogMDtcbn1cblxuLmxpZ2h0bmluZy1mbGFzaCB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgd2lkdGg6IDJweDtcbiAgYmFja2dyb3VuZDogd2hpdGU7XG4gIG9wYWNpdHk6IDAuNztcbiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XG4gIGFuaW1hdGlvbi1uYW1lOiBmbGFzaC1ibGluaztcbiAgYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogZWFzZS1pbi1vdXQ7XG4gIGFuaW1hdGlvbi1pdGVyYXRpb24tY291bnQ6IGluZmluaXRlO1xuICBib3JkZXItcmFkaXVzOiAxcHg7XG4gIGZpbHRlcjogYmx1cigwLjVweCk7XG4gIGJveC1zaGFkb3c6IDAgMCA0cHggcmdiYSgyNTUsMjU1LDI1NSwwLjYpO1xuXG4gIHotaW5kZXg6IDA7XG59XG5cbkBrZXlmcmFtZXMgZmxhc2gtYmxpbmsge1xuICAwJSwgMTAwJSB7XG4gICAgb3BhY2l0eTogMC4xO1xuICB9XG4gIDUwJSB7XG4gICAgb3BhY2l0eTogMC45O1xuICB9XG59XG5cbi5saWdodG5pbmctZmxhc2gtemlnemFnIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB3aWR0aDogMnB4O1xuICBoZWlnaHQ6IDA7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCh0byBib3R0b20sIHllbGxvdywgd2hpdGUpO1xuICBjbGlwLXBhdGg6IHBvbHlnb24odmFyKC0tcG9pbnRzKSk7XG4gIGFuaW1hdGlvbjogZmxhc2gtemlnemFnIGxpbmVhciBmb3J3YXJkcztcbiAgei1pbmRleDogMztcbn1cblxuQGtleWZyYW1lcyBmbGFzaC16aWd6YWcge1xuICAwJSB7XG4gICAgb3BhY2l0eTogMTtcbiAgICB0cmFuc2Zvcm06IHNjYWxlWSgxKTtcbiAgfVxuICAxMDAlIHtcbiAgICBvcGFjaXR5OiAwO1xuICAgIHRyYW5zZm9ybTogc2NhbGVZKDEuMik7XG4gIH1cbn1cblxuLmxpZ2h0bmluZy1zdmcge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIDApO1xuICBvcGFjaXR5OiAwO1xuICBmaWx0ZXI6IGRyb3Atc2hhZG93KDAgMCA0cHggcmdiYSg5OCwgNjEsIDE3MywgMC42KSk7XG4gIGFuaW1hdGlvbi1uYW1lOiBmbGFzaC16aWd6YWctc3ZnO1xuICBhbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOiBlYXNlLWluLW91dDtcbiAgYW5pbWF0aW9uLWl0ZXJhdGlvbi1jb3VudDogMTtcbiAgei1pbmRleDogMztcbn1cblxuQGtleWZyYW1lcyBmbGFzaC16aWd6YWctc3ZnIHtcbiAgMCUsIDEwMCUge1xuICAgIG9wYWNpdHk6IDA7XG4gIH1cbiAgNDAlIHtcbiAgICBvcGFjaXR5OiAxO1xuICB9XG4gIDYwJSB7XG4gICAgb3BhY2l0eTogMC41O1xuICB9XG59XG5gO1xuXG5leHBvcnQgZGVmYXVsdCBzdW1tYXJ5U3R5bGU7XG4iLCJpbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuXG5jb25zdCBwcmVzZW50U3R5bGUgPSBjc3NgXG4ucHJlc2VudC1ncmlkLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGdhcDogNHB4O1xufVxuXG4ucHJlc2VudC1yb3cge1xuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIGdhcDogMTZweDtcbn1cblxuLnByZXNlbnQtbGVmdCxcbi5wcmVzZW50LXJpZ2h0IHtcbiAgZmxleDogMTtcbn1cblxuLnByZXNlbnQtbGVmdCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcbn1cblxuLnByZXNlbnQtcmlnaHQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kO1xufVxuXG4ucHJlc2VudC12YWx1ZS1ibG9jayB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogNHB4O1xufVxuXG4ucHJlc2VudC11bml0IHtcbiAgZm9udC1zaXplOiAwLjllbTtcbiAgb3BhY2l0eTogMC44O1xufVxuYDtcblxuZXhwb3J0IGRlZmF1bHQgcHJlc2VudFN0eWxlO1xuIiwiaW1wb3J0IHsgY3NzIH0gZnJvbSAnbGl0JztcblxuY29uc3QgdWx0cmF2aW9sZXRTdHlsZSA9IGNzc2Bcbi51bHRyYXZpb2xldC1ncmlkLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGdhcDogNHB4O1xufVxuXG4udWx0cmF2aW9sZXQtcm93IHtcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBnYXA6IDE2cHg7XG59XG5cbi51bHRyYXZpb2xldC1sZWZ0LFxuLnByZXNlbnQtcmlnaHQge1xuICBmbGV4OiAxO1xufVxuXG4udWx0cmF2aW9sZXQtbGVmdCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcbn1cblxuLnVsdHJhdmlvbGV0LXJpZ2h0IHtcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcbn1cblxuLnVsdHJhdmlvbGV0LXZhbHVlLWJsb2NrIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiA0cHg7XG59XG5cbi51bHRyYXZpb2xldC11bml0IHtcbiAgZm9udC1zaXplOiAwLjllbTtcbiAgb3BhY2l0eTogMC44O1xufVxuXG4tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLy8gLnVsdHJhdmlvbGV0LWdyaWQtY29udGFpbmVyIHtcbi8vICAgZGlzcGxheTogZmxleDtcbi8vICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbi8vICAgZ2FwOiAxMnB4O1xuLy8gfVxuXG4vLyAudWx0cmF2aW9sZXQtcm93IHtcbi8vICAgZGlzcGxheTogZmxleDtcbi8vICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuLy8gICBwYWRkaW5nOiA0cHggMDtcbi8vIH1cblxuLy8gLnVsdHJhdmlvbGV0LXZhbHVlLWJsb2NrIHtcbi8vICAgZGlzcGxheTogZmxleDtcbi8vICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbi8vICAgZ2FwOiA0cHg7XG4vLyB9XG5cbi8vIC51bHRyYXZpb2xldC11bml0IHtcbi8vICAgZm9udC1zaXplOiAwLjllbTtcbi8vICAgb3BhY2l0eTogMC43O1xuLy8gfVxuXG4udWx0cmF2aW9sZXQtc2tpbi10eXBlLWdyaWQge1xuICBkaXNwbGF5OiBncmlkO1xuICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IHJlcGVhdChhdXRvLWZpdCwgbWlubWF4KDQ4cHgsIDFmcikpO1xuICBnYXA6IDhweDtcbiAgbWFyZ2luLXRvcDogOHB4O1xufVxuXG4udWx0cmF2aW9sZXQtc2tpbi10eXBlLWNlbGwge1xuICBmbGV4OiAxO1xuICBtaW4td2lkdGg6IDQ4cHg7XG4gIGhlaWdodDogNDhweDtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGJvcmRlci1yYWRpdXM6IDZweDtcbiAgZm9udC1mYW1pbHk6ICdTZWdvZSBVSScsIHNhbnMtc2VyaWY7XG4gIGJveC1zaGFkb3c6IDAgMXB4IDNweCByZ2JhKDAsIDAsIDAsIDAuMik7XG4gIGNvbG9yOiBibGFjaztcbn1cblxuLnVsdHJhdmlvbGV0LXNraW4tdHlwZS1sYWJlbCB7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICBmb250LXNpemU6IDAuOTVlbTtcbiAgbGluZS1oZWlnaHQ6IDFlbTtcbn1cblxuLnVsdHJhdmlvbGV0LWV4cG9zdXJlLXRpbWUge1xuICBmb250LXNpemU6IDAuNzVlbTtcbiAgbWFyZ2luLXRvcDogMnB4O1xuICBjb2xvcjogIzIyMjtcbiAgb3BhY2l0eTogMC44NTtcbn1cblxuXG5cblxuXG5cbmA7XG5cbmV4cG9ydCBkZWZhdWx0IHVsdHJhdmlvbGV0U3R5bGU7XG4iLCJpbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuXG5jb25zdCBwb2xsZW5TdHlsZSA9IGNzc2Bcbi5wb2xsZW4tZ3JpZC1jb250YWluZXIge1xuICBkaXNwbGF5OiBncmlkO1xuICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IHJlcGVhdChhdXRvLWZpdCwgbWlubWF4KDQ4cHgsIDFmcikpO1xuICBnYXA6IDhweCAxMnB4O1xuICB3aWR0aDogMTAwJTtcbiAganVzdGlmeS1pdGVtczogY2VudGVyO1xuICBhbGlnbi1pdGVtczogZW5kO1xuICBwYWRkaW5nOiA4cHggNHB4O1xuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xufVxuXG5cbi5wb2xsZW4tc3RhY2sge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDRweDtcbiAgbWluLXdpZHRoOiA0OHB4O1xufVxuXG5cbiAgLmxldmVscyB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uLXJldmVyc2U7XG4gICAgZ2FwOiBjbGFtcCgxcHgsIDAuMnZ3LCAycHgpO1xuICB9XG5cbiAgLmxldmVsIHtcbiAgICB3aWR0aDogY2xhbXAoMTZweCwgMy41dncsIDI0cHgpO1xuICAgIGhlaWdodDogY2xhbXAoNXB4LCAwLjd2dywgOHB4KTsgICAgIC8qIPCfkYggYW5jaGUgaW4gYWx0ZXp6YSAqL1xuICAgIGJvcmRlci1yYWRpdXM6IDNweDtcbiAgICBvcGFjaXR5OiAwLjM7XG4gICAgdHJhbnNpdGlvbjogb3BhY2l0eSAwLjJzIGVhc2U7XG4gIH1cblxuICAubGV2ZWwuYWN0aXZlIHtcbiAgICBvcGFjaXR5OiAxO1xuICAgIG91dGxpbmU6IDFweCBzb2xpZCAjMzMzO1xuICB9XG5cbiAgLm1vbHRvLWFsdG8ge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNmNDQzMzY7XG4gIH1cblxuICAuYWx0byB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmOTgwMDtcbiAgfVxuXG4gIC5tb2RlcmF0byB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZWIzYjtcbiAgfVxuXG4gIC5iYXNzbyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzRjYWY1MDtcbiAgfVxuXG4gIC5wb2xsZW4tbmFtZSB7XG4gICAgZm9udC1zaXplOiBjbGFtcCgwLjU1ZW0sIDEuM3Z3LCAwLjg1ZW0pOyAvKiDwn5GIIHN0cmluZ2UgZGkgcGnDuSAqL1xuICAgIC8vIGZvbnQtd2VpZ2h0OiA1MDA7XG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xuICAgIC8vIGNvbG9yOiAjMzMzO1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gIH1cblxuICAubGFiZWwge1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICBmb250LXNpemU6IGNsYW1wKDAuNTVlbSwgMS4zdncsIDAuODVlbSk7XG4gICAgLy8gZm9udC13ZWlnaHQ6IDUwMDtcbiAgICBtYXJnaW4tdG9wOiBjbGFtcCg0cHgsIDAuNXZ3LCA4cHgpO1xuICB9XG5gO1xuXG5leHBvcnQgZGVmYXVsdCBwb2xsZW5TdHlsZTtcbiIsImltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5cbmNvbnN0IGNhbWVyYVN0eWxlID0gY3NzYFxuICAuY2FtZXJhLWNvbnRhaW5lciB7XG4gICAgbWFyZ2luLXRvcDogMTBweDtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBzdHJldGNoO1xuICB9XG5cbiAgLmNhbWVyYS1pbWFnZSB7XG4gICAgYXNwZWN0LXJhdGlvOiAxNiAvIDk7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICB9XG5cbiAgLmNhbWVyYS1pbWFnZSA+IGltZyB7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgaGVpZ2h0OiAxMDAlO1xuICAgIG9iamVjdC1maXQ6IGNvdmVyO1xuICB9XG5gO1xuXG5leHBvcnQgZGVmYXVsdCBjYW1lcmFTdHlsZTtcbiIsImltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5cbmNvbnN0IHdlYXRoZXJGb3JlY2FzdFN0eWxlID0gY3NzYFxuXG4ud2VhdGhlci1mb3JlY2FzdC1ncmlkLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGdyaWQ7XG4gIGdyaWQtdGVtcGxhdGUtY29sdW1uczogcmVwZWF0KGF1dG8tZml0LCBtaW5tYXgoNzhweCwgMWZyKSk7XG4gIGNvbHVtbi1nYXA6IDJweDsgLyogc3BhemlvIG9yaXp6b250YWxlIHRyYSBpIGdpb3JuaSAqL1xuICByb3ctZ2FwOiA2cHg7ICAgIC8qIHNwYXppbyB2ZXJ0aWNhbGUgdHJhIHJpZ2hlLCBzZSBjaSBzb25vICovXG4gIGFsaWduLWl0ZW1zOiBzdHJldGNoO1xuICBmb250LWZhbWlseTogJ1NlZ29lIFVJJywgc2Fucy1zZXJpZjtcbiAgd2lkdGg6IDEwMCU7XG59XG4gIFxuLndlYXRoZXItZm9yZWNhc3QtZ3JpZC13cmFwcGVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjsgLyogY2VudHJhcmUgaWwgdGl0b2xvIG9yaXp6b250YWxtZW50ZSAqL1xufVxuXG4ud2VhdGhlci1mb3JlY2FzdC10aXRsZSB7XG4gIGZvbnQtc2l6ZTogY2xhbXAoMC44NWVtLCAxdncsIDAuOTVlbSk7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICAvLyBtYXJnaW4tYm90dG9tOiAwLjVlbTtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xufVxuXG4ud2VhdGhlci1mb3JlY2FzdC1zbG90IHtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xuICBwYWRkaW5nOiA4cHggNHB4O1xuICBtaW4td2lkdGg6IDA7XG4gIG92ZXJmbG93OiBoaWRkZW47XG59XG5cbi53ZWF0aGVyLWZvcmVjYXN0LXNsb3Q6bGFzdC1jaGlsZCB7XG4gIGJvcmRlci1yaWdodDogbm9uZTtcbn1cblxuLndlYXRoZXItZm9yZWNhc3QtbGFiZWwtc2xvdCB7XG4gIGZvbnQtc2l6ZTogMC45ZW07XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICBtYXJnaW4tYm90dG9tOiA2cHg7IC8qIHJpZG90dG8gKi9cbn1cblxuLndlYXRoZXItZm9yZWNhc3QtaWNvbiB7XG4gIGZvbnQtc2l6ZTogMS42cmVtOyAvKiByaWRvdHRvICovXG4gIC8qIG1hcmdpbjogNnB4IDA7IHJpZG90dG8gKi9cbiAgaGVpZ2h0OiAzMnB4O1xufVxuXG4ud2VhdGhlci1mb3JlY2FzdC10ZW1wZXJhdHVyZSB7XG4gIGZvbnQtc2l6ZTogY2xhbXAoMC44ZW0sIDF2dywgMC45ZW0pOyAvKiBsZWdnZXJtZW50ZSBwacO5IHBpY2NvbG8gKi9cbiAgbWFyZ2luOiA0cHggMDsgLyogbWVubyBtYXJnaW5lICovXG59XG5cbi53ZWF0aGVyLWZvcmVjYXN0LXRlbXBlcmF0dXJlIC5oaWdoIHtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG5cbi53ZWF0aGVyLWZvcmVjYXN0LXByZWNpcGl0YXRpb24ge1xuICBmb250LXNpemU6IGNsYW1wKDAuNjVlbSwgMXZ3LCAwLjc1ZW0pO1xuICBsaW5lLWhlaWdodDogMS4yOyAvKiBjb21wYXR0YSB2ZXJ0aWNhbG1lbnRlICovXG59XG5cbi53ZWF0aGVyLWZvcmVjYXN0LXByZWNpcGl0YXRpb24gLm1tIHtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG5gO1xuXG5leHBvcnQgZGVmYXVsdCB3ZWF0aGVyRm9yZWNhc3RTdHlsZTtcbiIsImltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5cbmNvbnN0IG1ldGVvZGNwYWxhcm1TdHlsZSA9IGNzc2Bcbi5tZXRlb2RjcGFsYXJtLWdyaWQtY29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC13cmFwOiB3cmFwO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgZ2FwOiAxNnB4O1xuICBwYWRkaW5nOiAxMnB4O1xufVxuXG4ubWV0ZW9kY3BhbGFybS1ncm91cCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGZsZXg6IDEgMSA3MnB4OyAgICAgLyog8J+RiCBjcmVzY2UsIG1hIG5vbiBzY2VuZGUgc290dG8gaSA3MnB4ICovXG4gIG1heC13aWR0aDogMjIwcHg7ICAgLyog8J+RiCBvcHppb25hbGU6IHByZXZpZW5lIGFsbGFyZ2FtZW50byBlY2Nlc3Npdm8gKi9cbiAgdGV4dC1hbGlnbjogY2VudGVyO1xufVxuXG4ubWV0ZW9kY3BhbGFybS1ncm91cCBoYS1pY29uIHtcbiAgLS1tZGMtaWNvbi1zaXplOiAzNnB4O1xufVxuXG4ubWV0ZW9kY3BhbGFybS1sYWJlbCB7XG4gIG1hcmdpbi10b3A6IDZweDtcbiAgZm9udC1zaXplOiAwLjg1ZW07XG4gIGNvbG9yOiB2YXIoLS1wcmltYXJ5LXRleHQtY29sb3IpO1xufVxuXG5cbmA7XG5cbmV4cG9ydCBkZWZhdWx0IG1ldGVvZGNwYWxhcm1TdHlsZTtcbiIsImltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG4vLyBpbXBvcnQgeyBIb21lQXNzaXN0YW50IH0gZnJvbSAnY3VzdG9tLWNhcmQtaGVscGVycy9kaXN0JztcblxuaW1wb3J0IHsgY3djTW9vblBoYXNlSWNvbnMgfSBmcm9tICcuLi8uLi9iYWNrdXAvaGEtY3djLWNvbnN0cyc7XG5cbmltcG9ydCBjYXJkU3R5bGUgZnJvbSAnLi4vY3NzL2Nzcy1iYXNlLWNhcmQnO1xuaW1wb3J0IHN1bW1hcnlTdHlsZXMgZnJvbSAnLi4vY3NzL2Nzcy1zdW1tYXJ5JztcbmltcG9ydCBwcmVzZW50U3R5bGUgZnJvbSAnLi4vY3NzL2Nzcy1wcmVzZW50JztcbmltcG9ydCB1bHRyYXZpb2xldFN0eWxlIGZyb20gJy4uL2Nzcy9jc3MtdWx0cmF2aW9sZXQnO1xuaW1wb3J0IHBvbGxlblN0eWxlIGZyb20gJy4uL2Nzcy9jc3MtcG9sbGVuJztcbmltcG9ydCBjYW1lcmFTdHlsZSBmcm9tICcuLi9jc3MvY3NzLWNhbWVyYSc7XG5pbXBvcnQgeyBpSWNvbnNDb25maWcgfSBmcm9tICcuLi9iYXNlL2xvdmVsYWNlLWJhc2UnO1xuaW1wb3J0IHdlYXRoZXJGb3JlY2FzdFN0eWxlIGZyb20gJy4uL2Nzcy9jc3Mtd2VhdGhlci1mb3JlY2FzdCc7XG5pbXBvcnQgbWV0ZW9kY3BhbGFybVN0eWxlIGZyb20gJy4uL2Nzcy9jc3MtbWV0ZW9hbGFybSc7XG5cbmV4cG9ydCBjb25zdCBnZXRNb29uSWNvbiA9IChwaGFzZTogc3RyaW5nKTogc3RyaW5nID0+IGN3Y01vb25QaGFzZUljb25zW3BoYXNlLnRvTG93ZXJDYXNlKCldO1xuXG5leHBvcnQgY29uc3QgZ2V0V2VhdGhlckljb24gPSAoXG4gIGNvbmRpdGlvbjogc3RyaW5nLFxuICBpY29uc0NvbmZpZzogaUljb25zQ29uZmlnLFxuICBzdW5TdGF0ZTogc3RyaW5nLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgaXNOaWdodCA9IHN1blN0YXRlID09PSAnYmVsb3dfaG9yaXpvbic7XG4gIGNvbnN0IGljb25NYXAgPSBpc05pZ2h0ID8gaWNvbnNDb25maWcuaWNvbnNOaWdodCA6IGljb25zQ29uZmlnLmljb25zRGF5O1xuICBjb25zdCBpY29uTmFtZSA9IGljb25NYXBbY29uZGl0aW9uXTtcblxuICBpZiAoIWljb25zQ29uZmlnLnBhdGgpIHtcbiAgICBjb25zb2xlLmluZm8oJ0ltYWdlIHBhdGggbm90IGZvdW5kLicpO1xuICB9XG5cbiAgaWYgKCFpY29uTmFtZSkge1xuICAgIGNvbnNvbGUuaW5mbyhcbiAgICAgIGBJY29ucyBpc3N1ZS4gTW9kZWw9JHtpY29uc0NvbmZpZy5pY29uc19tb2RlbH0sIFRpbWU9JHtpc05pZ2h0ID8gJ25pZ2h0JyA6ICdkYXknfSwgQ29uZGl0aW9uPSR7Y29uZGl0aW9ufWAsXG4gICAgKTtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICByZXR1cm4gYCR7aWNvbnNDb25maWcucGF0aH0vJHtpY29uc0NvbmZpZy5pY29uVHlwZX0vJHtpY29uTmFtZX0uc3ZnYDtcbn07XG5cbi8vIGV4cG9ydCBjb25zdCBnZXRTZW5zb3JVbml0ID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIG1lYXN1cmU6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4vLyAgIGNvbnN0IGxlbmd0aFVuaXQgPSBoYXNzLmNvbmZpZy51bml0X3N5c3RlbS5sZW5ndGg7XG5cbi8vICAgY29uc3QgdW5pdE92ZXJyaWRlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbi8vICAgICBhaXJfcHJlc3N1cmU6IGxlbmd0aFVuaXQgPT09ICdrbScgPyAnaFBhJyA6ICdpbkhnJyxcbi8vICAgICBwcmVjaXBpdGF0aW9uOiBsZW5ndGhVbml0ID09PSAna20nID8gJ21tJyA6ICdpbicsXG4vLyAgICAgbGVuZ3RoOiBsZW5ndGhVbml0LFxuLy8gICB9O1xuXG4vLyAgIGlmIChtZWFzdXJlIGluIHVuaXRPdmVycmlkZXMpIHtcbi8vICAgICByZXR1cm4gdW5pdE92ZXJyaWRlc1ttZWFzdXJlXTtcbi8vICAgfVxuXG4vLyAgIGNvbnN0IHVuaXQgPSAoaGFzcy5jb25maWcudW5pdF9zeXN0ZW0gYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPilbbWVhc3VyZV07XG5cbi8vICAgaWYgKHVuaXQgIT09IHVuZGVmaW5lZCkge1xuLy8gICAgIHJldHVybiB1bml0O1xuLy8gICB9XG5cbi8vICAgY29uc29sZS53YXJuKGBVbml0IGZvciAnJHttZWFzdXJlfScgbm90IGZvdW5kIGluIGhhc3MuY29uZmlnLnVuaXRfc3lzdGVtLmApO1xuLy8gICByZXR1cm4gJyc7XG4vLyB9O1xuXG5leHBvcnQgY29uc3QgZ2V0Q2FyZFN0eWxlcyA9ICgpID0+IGNzc2BcbiR7Y2FyZFN0eWxlfVxuJHtzdW1tYXJ5U3R5bGVzfVxuJHtwcmVzZW50U3R5bGV9XG4ke3dlYXRoZXJGb3JlY2FzdFN0eWxlfVxuJHt1bHRyYXZpb2xldFN0eWxlfVxuJHtwb2xsZW5TdHlsZX1cbiR7Y2FtZXJhU3R5bGV9XG4ke21ldGVvZGNwYWxhcm1TdHlsZX1cbmA7XG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBuby11bmRlcnNjb3JlLWRhbmdsZSAqL1xuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuaW1wb3J0IHtcbiAgY3NzLFxuICBDU1NSZXN1bHRHcm91cCxcbiAgaHRtbCxcbiAgTGl0RWxlbWVudCxcbiAgUHJvcGVydHlWYWx1ZXMsXG4gIFRlbXBsYXRlUmVzdWx0LFxufSBmcm9tICdsaXQnO1xuaW1wb3J0IHsgcHJvcGVydHkgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBIb21lQXNzaXN0YW50IH0gZnJvbSAnY3VzdG9tLWNhcmQtaGVscGVycyc7XG5cbmltcG9ydCB7IGRlZmF1bHRDb2xvckNzcywgZGVmYXVsdERhcmtDb2xvckNzcyB9IGZyb20gJy4uL3V0aWxzL2NvbG9ycyc7XG5pbXBvcnQgeyBpQ2FyZENvbmZpZywgaUxvdmVsYWNlQ2FyZENvbmZpZyB9IGZyb20gJy4uL3V0aWxzL2NvbmZpZy1zY2hlbWEnO1xuaW1wb3J0IHtcbiAgY3djTG9jYWxlLFxuICBoYWNzSW1hZ2VQYXRoLFxuICBsb2dvLFxuICBtYW5JbWFnZVBhdGgsXG4gIG9wdENvbnNvbGVQYXJhbTEsXG4gIG9wdENvbnNvbGVQYXJhbTIsXG4gIG9wdENvbnNvbGVQYXJhbTMsXG59IGZyb20gJy4uL3V0aWxzL2NvbnN0JztcbmltcG9ydCB7XG4gIGdldEljb25Nb2RlbERhdGEsXG4gIGltYWdlRXhpc3QsXG4gIGxvYWRKU09OLFxuICBsb2dJbmZvLFxufSBmcm9tICcuLi91dGlscy9oZWxwZXInO1xuaW1wb3J0IHsgY3djQ2xpbWFjZWxsRGF5SWNvbnMsIGN3Y0NsaW1hY2VsbE5pZ2h0SWNvbnMgfSBmcm9tICcuLi9pY29ubW9kZWxzL2ltLWNsaW1hY2VsbCc7XG5pbXBvcnQgeyBnZXRDYXJkU3R5bGVzIH0gZnJvbSAnLi4vdXRpbHMvaGVscGVyLXJlbmRlcic7XG5pbXBvcnQgeyBjd2NEYXl0aW1lUGlyYXRlV2VhdGhlckljb25zLCBjd2NOaWdodGx5UGlyYXRlV2VhdGVySWNvbnMgfSBmcm9tICcuLi9pY29ubW9kZWxzL2ltLXBpcmF0ZXdlYXRoZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIGlUZXJtcyB7XG4gICB3aW5kRGlyZWN0aW9uczogc3RyaW5nO1xuICAgd29yZHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgaUljb25zQ29uZmlnIHtcbiAgcGF0aDogc3RyaW5nIDtcbiAgaWNvblR5cGU6IHN0cmluZyA7XG4gIGljb25zX21vZGVsOiBzdHJpbmcgO1xuICBpY29uc0RheTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmc7IH0gO1xuICBpY29uc05pZ2h0OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZzsgfSA7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgaUxvdmVsYWNlQ2FyZCBleHRlbmRzIEhUTUxFbGVtZW50IHtcbiAgaGFzcz86IEhvbWVBc3Npc3RhbnQ7XG4gIGlzUGFuZWw/OiBib29sZWFuO1xuICBlZGl0TW9kZT86IGJvb2xlYW47XG4gIGdldENhcmRTaXplKCk6IG51bWJlciB8IFByb21pc2U8bnVtYmVyPjtcbiAgc2V0Q29uZmlnKGNvbmZpZzogaUxvdmVsYWNlQ2FyZENvbmZpZyk6IHZvaWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlRGFya01vZGUoaGFzcz86IEhvbWVBc3Npc3RhbnQpOiBib29sZWFuIHtcbiAgaWYgKCFoYXNzKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiAoaGFzcy50aGVtZXMgYXMgYW55KS5kYXJrTW9kZSBhcyBib29sZWFuO1xufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLSBWQVJJQUJJTEkgR0xPQkFMSSAtLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuLy8gbGV0IGxvYWRlZFRyYW5zbGF0aW9uczogYW55W10gPSBbXTtcbi8vIGxldCByZXNvbHZlZEltYWdlUGF0aDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcmVsb2FkUmVzb3VyY2VzKCk6IFByb21pc2U8eyB0cmFuc2xhdGlvbnM6IGFueVtdOyBpbWFnZVBhdGg6IHN0cmluZyB8IG51bGwgfT4ge1xuICBjb25zdCBbaGFjc1Jlc3VsdCwgbWFuUmVzdWx0XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBpbWFnZUV4aXN0KGAke2hhY3NJbWFnZVBhdGh9L3N0YXRpYy9jbG91ZHkuc3ZnYCksXG4gICAgaW1hZ2VFeGlzdChgJHttYW5JbWFnZVBhdGh9L3N0YXRpYy9jbG91ZHkuc3ZnYCksXG4gIF0pO1xuXG4gIGxldCBpbWFnZVBhdGg6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIGlmIChoYWNzUmVzdWx0KSB7XG4gICAgaW1hZ2VQYXRoID0gaGFjc0ltYWdlUGF0aDtcbiAgfSBlbHNlIGlmIChtYW5SZXN1bHQpIHtcbiAgICBpbWFnZVBhdGggPSBtYW5JbWFnZVBhdGg7XG4gIH0gZWxzZSB7XG4gICAgaW1hZ2VQYXRoID0gbnVsbDtcbiAgfVxuXG4gIGlmICghaW1hZ2VQYXRoKSB7XG4gICAgbG9nSW5mbyhgJHtsb2dvfSAtIEltcG9zc2liaWxlIGRldGVybWluYXJlIGlsIHBhdGggaW1tYWdpbmkuYCk7XG4gICAgcmV0dXJuIHsgdHJhbnNsYXRpb25zOiBbXSwgaW1hZ2VQYXRoOiBudWxsIH07XG4gIH1cblxuICBjb25zdCBsYW5ncyA9IFsnZW4nLCAnaXQnLCAnbmwnLCAnZXMnLCAnZGUnLCAnZnInLCAnc3ItbGF0bicsICdwdCcsICdkYScsICduby1OTycsICdjcyddO1xuICBjb25zdCB0cmFuc2xQYXRoID0gYCR7aW1hZ2VQYXRofS8uLi90cmFuc2wvYDtcbiAgY29uc3QgdHJhbnNsYXRpb25zID0gYXdhaXQgUHJvbWlzZS5hbGwobGFuZ3MubWFwKChsYW5nKSA9PiBsb2FkSlNPTihgJHt0cmFuc2xQYXRofSR7bGFuZ30uanNvbmApKSk7XG5cbiAgcmV0dXJuIHsgdHJhbnNsYXRpb25zLCBpbWFnZVBhdGggfTtcbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIExvdmVsYWNlQmFzZUVsZW1lbnQgZXh0ZW5kcyBMaXRFbGVtZW50IHtcbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiBmYWxzZSB9KSBwdWJsaWMgaGFzcyE6IEhvbWVBc3Npc3RhbnQ7XG5cbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiBmYWxzZSB9KSBwcm90ZWN0ZWQgX2NvbmZpZz86IGlDYXJkQ29uZmlnO1xuXG4gIHB1YmxpYyBpc1BhbmVsPzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHB1YmxpYyBlZGl0TW9kZT86IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwdWJsaWMgaW52YWxpZENvbmZpZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBfaWNvbnNDb25maWc6IGlJY29uc0NvbmZpZztcblxuICBwcm90ZWN0ZWQgX2ltYWdlc1BhdGg6IHN0cmluZztcblxuICBwcm90ZWN0ZWQgX25hbWU6IHN0cmluZztcblxuICBwcm90ZWN0ZWQgX2xhbmd1YWdlOiBzdHJpbmc7XG5cbiAgcHJvdGVjdGVkIF90cmFuc2xhdGlvbnM6IHN0cmluZ1tdO1xuXG4gIHByb3RlY3RlZCBfdGVybXM6IGlUZXJtcztcblxuICBwcm90ZWN0ZWQgX2hhc1ByZXNlbnQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgX2hhc0RhaWx5Rm9yZWNhc3RzOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJvdGVjdGVkIF9oYXNIb3VybHlGb3JlY2FzdHM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgX2hhc01hcmluZURhaWx5Rm9yZWNhc3RzOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJvdGVjdGVkIF9oYXNNYXJpbmVIb3VybHlGb3JlY2FzdHM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgX2hhc01ldGVhbGFybTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBfaGFzRFBDYWxhcm06IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgX2hhc01ldGVvZ3JhbTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBfaGFzQWlyUXVhbGl0eTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBfaGFzUG9sbGVuOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJvdGVjdGVkIF9oYXNVbHRyYXZpb2xldDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBfaGFzQWxlcnQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgX2hhc1NlYTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBfaGFzQ2FtZXJhOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJvdGVjdGVkIHVwZGF0ZWQoY2hhbmdlZFByb3BzOiBQcm9wZXJ0eVZhbHVlcyk6IHZvaWQge1xuICAgIHN1cGVyLnVwZGF0ZWQoY2hhbmdlZFByb3BzKTtcbiAgICBpZiAoY2hhbmdlZFByb3BzLmhhcygnaGFzcycpICYmIHRoaXMuaGFzcykge1xuICAgICAgY29uc3QgY3VycmVudERhcmtNb2RlID0gY29tcHV0ZURhcmtNb2RlKGNoYW5nZWRQcm9wcy5nZXQoJ2hhc3MnKSk7XG4gICAgICBjb25zdCBuZXdEYXJrTW9kZSA9IGNvbXB1dGVEYXJrTW9kZSh0aGlzLmhhc3MpO1xuICAgICAgaWYgKGN1cnJlbnREYXJrTW9kZSAhPT0gbmV3RGFya01vZGUpIHtcbiAgICAgICAgdGhpcy50b2dnbGVBdHRyaWJ1dGUoJ2RhcmstbW9kZScsIG5ld0RhcmtNb2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IHN0eWxlcygpOiBDU1NSZXN1bHRHcm91cCB7XG4gICAgcmV0dXJuIFtcbiAgICAgIC8vIGFuaW1hdGlvbnMsXG4gICAgICBjc3NgXG4gICAgICAgIDpob3N0IHtcbiAgICAgICAgICAke2RlZmF1bHRDb2xvckNzc31cbiAgICAgICAgfVxuICAgICAgICA6aG9zdChbZGFyay1tb2RlXSkge1xuICAgICAgICAgICR7ZGVmYXVsdERhcmtDb2xvckNzc31cbiAgICAgICAgfVxuICAgICAgICAke2dldENhcmRTdHlsZXMoKX1cbiAgICAgIGAsXG4gICAgXTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzZXRDb25maWcoY29uZmlnOiBpQ2FyZENvbmZpZykge1xuICAgIGlmICghY29uZmlnKSB7XG4gICAgICB0aGlzLmludmFsaWRDb25maWcgPSB0cnVlO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbmZpZ3VyYXRpb24nKTtcbiAgICB9XG5cbiAgICAvLyBjb25zb2xlLmxvZyh7IGNhcmRfY29uZmlnOiBjb25maWcgfSk7XG5cbiAgICBpZiAoIXRoaXMuX3RyYW5zbGF0aW9ucz8ubGVuZ3RoIHx8ICF0aGlzLl9pbWFnZXNQYXRoKSB7XG4gICAgICBjb25zdCB7IHRyYW5zbGF0aW9ucywgaW1hZ2VQYXRoIH0gPSBhd2FpdCBwcmVsb2FkUmVzb3VyY2VzKCk7XG4gICAgICB0aGlzLl90cmFuc2xhdGlvbnMgPSB0cmFuc2xhdGlvbnM7XG4gICAgICB0aGlzLl9pbWFnZXNQYXRoID0gaW1hZ2VQYXRoO1xuICAgIH1cblxuICAgIHRoaXMuX25hbWUgPSBjb25maWc/LndlYXRoZXI/Lm5hbWUgPz8gdW5kZWZpbmVkO1xuICAgIHRoaXMuX2xhbmd1YWdlID0gY29uZmlnLmxhbmd1YWdlPy50b0xvd2VyQ2FzZSgpIHx8ICdlbic7XG5cbiAgICB0aGlzLl9sb2FkVHJhbnNsYXRpb25zKHRoaXMuX2xhbmd1YWdlKTtcbiAgICAvLyB0aGlzLl9pbml0TnVtYmVyRm9ybWF0dGVycyh0aGlzLl9sYW5ndWFnZSk7XG5cbiAgICAvLyB0aGlzLl9zZXR1cERpc3BsYXlTZWN0aW9ucyhjb25maWcuZGlzcGxheSA/PyBbXSk7XG4gICAgdGhpcy5fZGV0ZWN0RGF0YVNlY3Rpb25zKGNvbmZpZyk7XG5cbiAgICB0aGlzLl9zZXR1cEljb25zKGNvbmZpZy53ZWF0aGVyPy5pY29uc19tb2RlbCk7XG4gICAgdGhpcy5fY29uZmlnID0gY29uZmlnO1xuXG4gICAgbG9nSW5mbyhgJHtsb2dvfSAtIENvbmZpZyBsb2FkZWQuYCk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuICBwdWJsaWMgZ2V0Q2FyZFNpemUoKTogbnVtYmVyIHwgUHJvbWlzZTxudW1iZXI+IHtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvYWRUcmFuc2xhdGlvbnMobGFuZzogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRyYW5zbHMgPSBKU09OLnBhcnNlKHRoaXMuX3RyYW5zbGF0aW9uc1tjd2NMb2NhbGVbbGFuZ11dKTtcbiAgICAgIHRoaXMuX3Rlcm1zID0ge1xuICAgICAgICB3aW5kRGlyZWN0aW9uczogdHJhbnNscy5jd2NMb2NXaW5kRGlyZWN0aW9ucyxcbiAgICAgICAgd29yZHM6IHRyYW5zbHMuY3djVGVybXMsXG4gICAgICB9O1xuXG4gICAgICBsb2dJbmZvKFxuICAgICAgICBgJHtsb2dvfSVjIGNhcmQgXCIke3RoaXMuX25hbWV9XCIsIGxvY2FsZSBpcyAnJHtsYW5nfScuYCxcbiAgICAgICAgb3B0Q29uc29sZVBhcmFtMSxcbiAgICAgICAgb3B0Q29uc29sZVBhcmFtMixcbiAgICAgICAgb3B0Q29uc29sZVBhcmFtMyxcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc3QgZmFsbGJhY2sgPSAnZW4nO1xuICAgICAgY29uc3QgdHJhbnNscyA9IEpTT04ucGFyc2UodGhpcy5fdHJhbnNsYXRpb25zW2N3Y0xvY2FsZVtmYWxsYmFja11dKTtcbiAgICAgIHRoaXMuX3Rlcm1zID0ge1xuICAgICAgICB3aW5kRGlyZWN0aW9uczogdHJhbnNscy5jd2NMb2NXaW5kRGlyZWN0aW9ucyxcbiAgICAgICAgd29yZHM6IHRyYW5zbHMuY3djVGVybXMsXG4gICAgICB9O1xuXG4gICAgICBsb2dJbmZvKFxuICAgICAgICBgJHtsb2dvfSVjIGNhcmQgXCIke3RoaXMuX25hbWV9XCIgdW5hYmxlIHRvIHVzZSAnJHtsYW5nfScgbG9jYWxlLCBzZXQgYXMgZGVmYXVsdCAnJHtmYWxsYmFja30nLmAsXG4gICAgICAgIG9wdENvbnNvbGVQYXJhbTEsXG4gICAgICAgIG9wdENvbnNvbGVQYXJhbTIsXG4gICAgICAgIG9wdENvbnNvbGVQYXJhbTMsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2RldGVjdERhdGFTZWN0aW9ucyhjb25maWc6IGlDYXJkQ29uZmlnKSB7XG4gICAgdGhpcy5faGFzUHJlc2VudCA9ICEhY29uZmlnLndlYXRoZXI/LnByZXNlbnQ7XG4gICAgdGhpcy5faGFzRGFpbHlGb3JlY2FzdHMgPSAhIWNvbmZpZy53ZWF0aGVyPy5kYWlseV9mb3JlY2FzdHM7XG4gICAgdGhpcy5faGFzSG91cmx5Rm9yZWNhc3RzID0gISFjb25maWcud2VhdGhlcj8uaG91cmx5X2ZvcmVjYXN0cztcbiAgICB0aGlzLl9oYXNNYXJpbmVEYWlseUZvcmVjYXN0cyA9ICEhY29uZmlnLndlYXRoZXI/Lm1hcmluZV9kYWlseV9mb3JlY2FzdHM7XG4gICAgdGhpcy5faGFzTWFyaW5lSG91cmx5Rm9yZWNhc3RzID0gISFjb25maWcud2VhdGhlcj8ubWFyaW5lX2hvdXJseV9mb3JlY2FzdHM7XG4gICAgdGhpcy5faGFzTWV0ZWFsYXJtID0gISFjb25maWcud2VhdGhlcj8ubWV0ZW9hbGFybTtcbiAgICB0aGlzLl9oYXNEUENhbGFybSA9ICEhY29uZmlnLndlYXRoZXI/LmRwY2FsYXJtO1xuICAgIC8vIHRoaXMuX2hhc01ldGVvZ3JhbSA9ICEhY29uZmlnLndlYXRoZXI/LmZvcmVjYXN0Py5tZXRlb2dyYW07XG4gICAgdGhpcy5faGFzQWlyUXVhbGl0eSA9ICEhY29uZmlnLmFpcnF1YWxpdHk7XG4gICAgdGhpcy5faGFzUG9sbGVuID0gY29uZmlnLnBvbGxlbiAmJiBBcnJheS5pc0FycmF5KGNvbmZpZy5wb2xsZW4uZW50aXRpZXMpICYmIGNvbmZpZy5wb2xsZW4uZW50aXRpZXMubGVuZ3RoID4gMDtcbiAgICB0aGlzLl9oYXNVbHRyYXZpb2xldCA9ICEhY29uZmlnLnVsdHJhdmlvbGV0O1xuICAgIHRoaXMuX2hhc0NhbWVyYSA9ICEhY29uZmlnLmNhbWVyYTtcbiAgICAvLyB0aGlzLl9oYXNBbGVydCA9ICEhY29uZmlnLmFsZXJ0O1xuICB9XG5cbiAgcHJpdmF0ZSBfc2V0dXBJY29ucyhpY29uc01vZGVsPzogc3RyaW5nKSB7XG4gICAgdGhpcy5faWNvbnNDb25maWcgPSB7XG4gICAgICBwYXRoOiB0aGlzLl9pbWFnZXNQYXRoLFxuICAgICAgaWNvblR5cGU6IHRoaXMuX2NvbmZpZz8ud2VhdGhlcj8uYW5pbWF0aW9uID8gJ2FuaW1hdGVkJyA6ICdzdGF0aWMnLFxuICAgICAgaWNvbnNfbW9kZWw6IGljb25zTW9kZWwgfHwgJ3BpcmF0ZXdlYXRoZXInLFxuICAgICAgaWNvbnNEYXk6IGN3Y0RheXRpbWVQaXJhdGVXZWF0aGVySWNvbnMsXG4gICAgICBpY29uc05pZ2h0OiBjd2NOaWdodGx5UGlyYXRlV2VhdGVySWNvbnMsXG4gICAgfTtcblxuICAgIGlmIChpY29uc01vZGVsKSB7XG4gICAgICBjb25zdCBtb2RlbERhdGEgPSBnZXRJY29uTW9kZWxEYXRhKGljb25zTW9kZWwpO1xuICAgICAgdGhpcy5faWNvbnNDb25maWcuaWNvbnNfbW9kZWwgPSBtb2RlbERhdGEuaWNvbnNNb2RlbDtcbiAgICAgIHRoaXMuX2ljb25zQ29uZmlnLmljb25zRGF5ID0gbW9kZWxEYXRhLmljb25zRGF5O1xuICAgICAgdGhpcy5faWNvbnNDb25maWcuaWNvbnNOaWdodCA9IG1vZGVsRGF0YS5pY29uc05pZ2h0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBnZW5lcmF0ZXMgdGhlIGNhcmQgSFRNTFxuICAgKiBAcmV0dXJuIHtUZW1wbGF0ZVJlc3VsdH1cbiAgICovXG4gIHB1YmxpYyByZW5kZXIoKTogVGVtcGxhdGVSZXN1bHQge1xuICAgIGlmICh0aGlzLmludmFsaWRDb25maWcpIHtcbiAgICAgIHJldHVybiBodG1sYFxuICAgICAgICA8aGEtY2FyZCBjbGFzcz1cImhhLWNhcmQtd2VhdGhlci1jb25kaXRpb25zXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPSdiYW5uZXInPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXJcIj5oYS1jYXJkLXdlYXRoZXItY29uZGl0aW9uczwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPSdjb250ZW50Jz5cbiAgICAgICAgICAgICAgICBDb25maWd1cmF0aW9uIEVSUk9SIVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvaGEtY2FyZD5cbiAgICBgO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9yZW5kZXIoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBfcmVuZGVyKCk6IFRlbXBsYXRlUmVzdWx0O1xufVxuIiwiaW1wb3J0IHsgaHRtbCwgbm90aGluZyB9IGZyb20gJ2xpdCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2VhdGhlclN1bW1hcnlJbnRlcmZhY2Uge1xuICB0aXRsZT86IHN0cmluZztcbiAgbW9vblRleHQ/OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIG1vb25JY29uPzogc3RyaW5nO1xuICBjb25kaXRpb25UZXh0OiBzdHJpbmc7XG4gIGNvbmRpdGlvbkljb246IHN0cmluZztcbiAgdGVtcGVyYXR1cmU/OiBzdHJpbmc7XG4gIHRlbXBlcmF0dXJlVW5pdD86IHN0cmluZztcbiAgZmVlbHNMaWtlVGVybT86IHN0cmluZztcbiAgdGVtcGVyYXR1cmVGZWVsc0xpa2U/OiBzdHJpbmc7XG4gIHRlbXBlcmF0dXJlRmVlbHNMaWtlSWNvbj86IHN0cmluZztcbn1cblxuY29uc3QgcmVuZGVyTGlnaHRuaW5nRmxhc2haaWd6YWcgPSAoeFBlcmNlbnQ6IG51bWJlciwgeVBlcmNlbnQ6IG51bWJlciwgc2VnbWVudHM6IG51bWJlciA9IDcpID0+IHtcbiAgY29uc3Qgd2lkdGggPSAxMDsgLy8gbGFyZ2hlenphIGluIHBpeGVsIGRlbGxhIHZpZXdwb3J0IFNWR1xuICBjb25zdCBoZWlnaHQgPSAyMCArIE1hdGgucmFuZG9tKCkgKiA1MDtcblxuICBjb25zdCBwb2ludHMgPSBbXTtcbiAgbGV0IHggPSB3aWR0aCAvIDI7XG4gIGxldCB5ID0gMDtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNlZ21lbnRzOyBpICs9IDEpIHtcbiAgICAvLyB4ICs9IChNYXRoLnJhbmRvbSgpICogd2lkdGggLSB3aWR0aCAvIDIpO1xuICAgIC8vIHkgKz0gaGVpZ2h0IC8gc2VnbWVudHM7XG4gICAgeCArPSAoTWF0aC5yYW5kb20oKSAqIHdpZHRoICogMS41IC0gd2lkdGggKiAwLjc1KTsgLy8gbWFnZ2lvcmUgemlnemFnXG4gICAgeSArPSAoaGVpZ2h0IC8gc2VnbWVudHMpICogKDAuNyArIE1hdGgucmFuZG9tKCkgKiAwLjYpOyAvLyBsdW5naGV6emEgdmFyaWFiaWxlXG4gICAgcG9pbnRzLnB1c2goYCR7eH0sJHt5fWApO1xuICB9XG5cbiAgY29uc3QgcGF0aEQgPSBgTSR7d2lkdGggLyAyfSwwICR7cG9pbnRzLm1hcCgocCkgPT4gYEwke3B9YCkuam9pbignICcpfWA7XG5cbiAgY29uc3QgZGVsYXkgPSBNYXRoLnJhbmRvbSgpICogMTUuNTtcbiAgY29uc3QgZHVyYXRpb24gPSAwLjIgKyBNYXRoLnJhbmRvbSgpICogMC4zICogMzM7XG5cbiAgcmV0dXJuIGh0bWxgXG4gICAgPHN2Z1xuICAgICAgY2xhc3M9XCJsaWdodG5pbmctc3ZnXCJcbiAgICAgIHN0eWxlPVwiXG4gICAgICAgIHRvcDogJHt5UGVyY2VudH0lO1xuICAgICAgICBsZWZ0OiAke3hQZXJjZW50fSU7XG4gICAgICAgIGFuaW1hdGlvbi1kZWxheTogJHtkZWxheX1zO1xuICAgICAgICBhbmltYXRpb24tZHVyYXRpb246ICR7ZHVyYXRpb259cztcbiAgICAgIFwiXG4gICAgICB3aWR0aD1cIiR7d2lkdGh9XCIgaGVpZ2h0PVwiJHtoZWlnaHR9XCIgdmlld0JveD1cIjAgMCAke3dpZHRofSAke2hlaWdodH1cIj5cbiAgICAgIDxwYXRoIGQ9XCIke3BhdGhEfVwiIHN0cm9rZT1cIndoaXRlXCIgc3Ryb2tlLXdpZHRoPVwiMS41XCIgZmlsbD1cIm5vbmVcIiAvPlxuICAgIDwvc3ZnPlxuICBgO1xufTtcblxuY29uc3QgcmVuZGVyTGlnaHRuaW5nRmxhc2hlcyA9IChhemltdXRoOiBudW1iZXIsIGRpc3RhbmNlOiBudW1iZXIsIHN0cmlrZXM6IG51bWJlcikgPT4ge1xuICBjb25zdCBmbGFzaGVzID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaWtlczsgaSArPSAxKSB7XG4gICAgY29uc3QgeCA9IE1hdGgucmFuZG9tKCkgKiAxMDA7XG4gICAgY29uc3QgeSA9IE1hdGgucmFuZG9tKCkgKiAyMDtcbiAgICBmbGFzaGVzLnB1c2gocmVuZGVyTGlnaHRuaW5nRmxhc2haaWd6YWcoeCwgeSkpO1xuICB9XG4gIHJldHVybiBmbGFzaGVzO1xufTtcblxuY29uc3QgcmVuZGVyV2VhdGhlclN1bW1hcnkgPSAoe1xuICB0aXRsZSxcbiAgbW9vblRleHQsXG4gIG1vb25JY29uLFxuICBjb25kaXRpb25UZXh0LFxuICBjb25kaXRpb25JY29uLFxuICB0ZW1wZXJhdHVyZSxcbiAgdGVtcGVyYXR1cmVVbml0LFxuICBmZWVsc0xpa2VUZXJtLFxuICB0ZW1wZXJhdHVyZUZlZWxzTGlrZSxcbiAgdGVtcGVyYXR1cmVGZWVsc0xpa2VJY29uLFxufTogV2VhdGhlclN1bW1hcnlJbnRlcmZhY2UpID0+IHtcbiAgY29uc3QgbGlnaHRuaW5nQXppbXV0aCA9IDA7IC8vIFJlcGxhY2Ugd2l0aCBhY3R1YWwgZGF0YVxuICBjb25zdCBsaWdodG5pbmdEaXN0YW5jZUttID0gMDsgLy8gUmVwbGFjZSB3aXRoIGFjdHVhbCBkYXRhXG4gIGNvbnN0IGxpZ2h0bmluZ1N0cmlrZXMgPSAwOyAvLyBSZXBsYWNlIHdpdGggYWN0dWFsIGRhdGFcblxuICBjb25zdCBzaG93TGlnaHRuaW5nID1cbiAgbGlnaHRuaW5nU3RyaWtlcyA+IDAgJiZcbiAgdHlwZW9mIGxpZ2h0bmluZ0F6aW11dGggPT09ICdudW1iZXInICYmXG4gIHR5cGVvZiBsaWdodG5pbmdEaXN0YW5jZUttID09PSAnbnVtYmVyJztcblxuICBpZiAoY29uZGl0aW9uSWNvbiB8fCBtb29uVGV4dCB8fCB0ZW1wZXJhdHVyZSkge1xuICAgIHJldHVybiBodG1sYFxuICAgIDxkaXYgY2xhc3M9XCJzdW1tYXJ5LXdyYXBwZXJcIj5cbiAgICAgICR7c2hvd0xpZ2h0bmluZyA/IGh0bWxgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJsaWdodG5pbmctYmFja2dyb3VuZFwiPlxuICAgICAgICAgICR7cmVuZGVyTGlnaHRuaW5nRmxhc2hlcyhsaWdodG5pbmdBemltdXRoISwgbGlnaHRuaW5nRGlzdGFuY2VLbSEsIGxpZ2h0bmluZ1N0cmlrZXMpfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIGAgOiBub3RoaW5nfVxuICAgICAgPGRpdiBjbGFzcz1cInN1bW1hcnktZ3JpZC1jb250YWluZXJcIj5cbiAgICAgICAgJHtjb25kaXRpb25JY29uID8gaHRtbGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS1jb2wtbGVmdFwiPlxuICAgICAgICAgICAgPGltZyBjbGFzcz1cIndlYXRoZXItY29uZGl0aW9uLWljb25cIiBzcmM9XCIke2NvbmRpdGlvbkljb259XCIgYWx0PVwiJHtjb25kaXRpb25UZXh0fVwiIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIGAgOiBub3RoaW5nfVxuICAgICAgICAke3RpdGxlID8gaHRtbGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS10b3AtcmlnaHRcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwid2VhdGhlci1jaXR5LW5hbWVcIj4ke3RpdGxlfTwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj4gICAgXG4gICAgICAgIGAgOiBub3RoaW5nfVxuICAgICAgICAke21vb25UZXh0ID8gaHRtbGBcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS1ib3R0b20tcmlnaHQtbGVmdFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1vb24tcm93XCI+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3VtbWFyeS1tb29uLWljb25cIj4ke21vb25JY29ufTwvc3Bhbj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzdW1tYXJ5LW1vb24tdGV4dFwiPiR7bW9vblRleHR9PC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+ICBcbiAgICAgICAgICA8L2Rpdj4gICBcbiAgICAgICAgYCA6IG5vdGhpbmd9XG4gICAgICAgICR7dGVtcGVyYXR1cmUgPyBodG1sYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdW1tYXJ5LWJvdHRvbS1yaWdodC1yaWdodFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRlbXBlcmF0dXJlLWJsb2NrXCI+XG4gICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZW1wZXJhdHVyZVwiPiR7dGVtcGVyYXR1cmV9PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGVtcC11bml0XCI+JHt0ZW1wZXJhdHVyZVVuaXR9PC9zcGFuPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgJHt0ZW1wZXJhdHVyZUZlZWxzTGlrZSAmJiBodG1sYDxkaXYgY2xhc3M9XCJmZWVscy1saWtlXCI+JHtmZWVsc0xpa2VUZXJtfSA8ZGl2PiR7dGVtcGVyYXR1cmVGZWVsc0xpa2V9ICR7dGVtcGVyYXR1cmVVbml0fTwvZGl2PjwvZGl2PmB9XG4gICAgICAgICAgICA8L2Rpdj4gIFxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIGAgOiBub3RoaW5nfVxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgYDtcbiAgfVxuXG4gIHJldHVybiBodG1sYGA7XG59O1xuXG5leHBvcnQgZGVmYXVsdCByZW5kZXJXZWF0aGVyU3VtbWFyeTtcbiIsImltcG9ydCB7IEhvbWVBc3Npc3RhbnQgfSBmcm9tICdjdXN0b20tY2FyZC1oZWxwZXJzL2Rpc3QnO1xuXG5pbXBvcnQgcmVuZGVyV2VhdGhlclN1bW1hcnkgZnJvbSAnLi4vdGVtcGxhdGVzL3Qtc3VtbWFyeSc7XG5pbXBvcnQge1xuICBnZXRFbnRpdHlOdW1lcmljVmFsdWUsXG4gIGdldEVudGl0eVJhd1ZhbHVlLFxuICBnZXRFbnRpdHlVbml0LFxuICB0cmFuc2xhdGUsXG59IGZyb20gJy4uL3V0aWxzL2hlbHBlcic7XG5cbmltcG9ydCB7IGdldE1vb25JY29uLCBnZXRXZWF0aGVySWNvbiB9IGZyb20gJy4uL3V0aWxzL2hlbHBlci1yZW5kZXInO1xuaW1wb3J0IHsgaVByZXNlbnREYXRhIH0gZnJvbSAnLi4vdXRpbHMvY29uZmlnLXNjaGVtYSc7XG5pbXBvcnQgeyBpSWNvbnNDb25maWcsIGlUZXJtcyB9IGZyb20gJy4uL2Jhc2UvbG92ZWxhY2UtYmFzZSc7XG5cbmNvbnN0IGJ1aWxkV2VhdGhlclN1bW1hcnkgPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmd1YWdlOiBzdHJpbmcsXG4gIHRlcm1zOiBpVGVybXMsXG4gIGljb25zQ29uZmlnOiBpSWNvbnNDb25maWcsXG4gIG5hbWU6IHN0cmluZyxcbiAgcHJlc2VudERhdGE6IGlQcmVzZW50RGF0YSxcbiAgc3VuSWQ6IHN0cmluZyxcbiAgbW9vbnBoYXNlOiBzdHJpbmcsXG4pID0+IHtcbiAgY29uc3QgbW9vblBoYXNlID0gZ2V0RW50aXR5UmF3VmFsdWUoaGFzcywgbW9vbnBoYXNlKTtcbiAgY29uc3QgbW9vbkljb246IHN0cmluZyA9IG1vb25QaGFzZSA/IGdldE1vb25JY29uKG1vb25QaGFzZSkgOiAnJztcbiAgY29uc3Qgc3VuID0gZ2V0RW50aXR5UmF3VmFsdWUoaGFzcywgc3VuSWQpO1xuICBjb25zdCBjdXJyZW50Q29uZGl0aW9ucyA9IGdldEVudGl0eVJhd1ZhbHVlKGhhc3MsIHByZXNlbnREYXRhLmNvbmRpdGlvbik/LnRvTG93ZXJDYXNlKCkgfHwgJ25hJztcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgY29uc3QgdGVtcGVyYXR1cmUgPSBwcmVzZW50RGF0YS50ZW1wZXJhdHVyZSA/IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBwcmVzZW50RGF0YS50ZW1wZXJhdHVyZSwgaGFzcywgbGFuZzogbGFuZ3VhZ2UgfSkgPz8gdW5kZWZpbmVkIDogdW5kZWZpbmVkO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICBjb25zdCB0ZW1wZXJhdHVyZUZlZWxzTGlrZSA9IHByZXNlbnREYXRhLnRlbXBlcmF0dXJlX2ZlZWxzbGlrZSA/IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBwcmVzZW50RGF0YS50ZW1wZXJhdHVyZV9mZWVsc2xpa2UsIGhhc3MsIGxhbmc6IGxhbmd1YWdlIH0pID8/IHVuZGVmaW5lZCA6IHVuZGVmaW5lZDtcbiAgY29uc3QgdGVtcGVyYXR1cmVGZWVsc0xpa2VJY29uID0gaGFzcy5zdGF0ZXNbcHJlc2VudERhdGEudGVtcGVyYXR1cmVfZmVlbHNsaWtlXT8uYXR0cmlidXRlcy5pY29uID8/ICcnO1xuXG4gIHJldHVybiByZW5kZXJXZWF0aGVyU3VtbWFyeSh7XG4gICAgdGl0bGU6IG5hbWUgPz8gdW5kZWZpbmVkLCAvLyAnVmVya2huZW5vdm9rdXRsdW1iZXR5ZXZvJyxcbiAgICBtb29uVGV4dDogKG1vb25waGFzZSA/IHRyYW5zbGF0ZShtb29uUGhhc2UsIHRlcm1zLndvcmRzKSA6IHVuZGVmaW5lZCksXG4gICAgbW9vbkljb24sXG4gICAgY29uZGl0aW9uVGV4dDogY3VycmVudENvbmRpdGlvbnMsXG4gICAgY29uZGl0aW9uSWNvbjogZ2V0V2VhdGhlckljb24oY3VycmVudENvbmRpdGlvbnMsIGljb25zQ29uZmlnLCBzdW4pLFxuICAgIHRlbXBlcmF0dXJlLFxuICAgIHRlbXBlcmF0dXJlVW5pdDogZ2V0RW50aXR5VW5pdChoYXNzLCBwcmVzZW50RGF0YS50ZW1wZXJhdHVyZSksXG4gICAgZmVlbHNMaWtlVGVybTogdHJhbnNsYXRlKCdGZWVscyBMaWtlJywgdGVybXMud29yZHMpLFxuICAgIHRlbXBlcmF0dXJlRmVlbHNMaWtlLFxuICAgIHRlbXBlcmF0dXJlRmVlbHNMaWtlSWNvbixcbiAgfSk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBidWlsZFdlYXRoZXJTdW1tYXJ5O1xuIiwiaW1wb3J0IHsgaHRtbCB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBnZXRMb2NhbGUsIHBhcnNlTG9jYWxpemVkTnVtYmVyIH0gZnJvbSAnLi4vdXRpbHMvaGVscGVyJztcblxuZXhwb3J0IGludGVyZmFjZSBpUmVuZGVyRGF0YUl0ZW0ge1xuICB2YWx1ZT86IG51bWJlciB8IHN0cmluZyB8IERhdGU7XG4gIHVuaXQ/OiBzdHJpbmc7XG4gIGljb24/OiBzdHJpbmc7XG4gIGljb25fY29sb3I/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2VhdGhlckRhdGEge1xuICB0ZW1wZXJhdHVyZUhpZ2g/OiBpUmVuZGVyRGF0YUl0ZW07XG4gIHRlbXBlcmF0dXJlTG93PzogaVJlbmRlckRhdGFJdGVtO1xuICBwcmVjaXBpdGF0aW9uUHJvYmFiaWxpdHk/OiBpUmVuZGVyRGF0YUl0ZW07XG4gIHByZWNpcGl0YXRpb25JbnRlbnNpdHk/OiBpUmVuZGVyRGF0YUl0ZW07XG4gIG5leHRSaXNpbmc/OiBpUmVuZGVyRGF0YUl0ZW07XG4gIG5leHRTZXR0aW5nPzogaVJlbmRlckRhdGFJdGVtO1xuXG4gIC8vIHByZWNpcGl0YXRpb24/OiBpUmVuZGVyRGF0YUl0ZW07XG4gIGh1bWlkaXR5PzogaVJlbmRlckRhdGFJdGVtO1xuICB3aW5kQmVhcmluZz86IGlSZW5kZXJEYXRhSXRlbTtcbiAgd2luZFNwZWVkPzogaVJlbmRlckRhdGFJdGVtO1xuICBwcmVzc3VyZT86IGlSZW5kZXJEYXRhSXRlbTtcbiAgdmlzaWJpbGl0eT86IGlSZW5kZXJEYXRhSXRlbTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBpQWlyUXVhbGl0eURhdGEge1xuICBwbTI1OiBpUmVuZGVyRGF0YUl0ZW0sXG4gIHBtMTA6aVJlbmRlckRhdGFJdGVtLFxuICBvMzogaVJlbmRlckRhdGFJdGVtLFxuICBubzI6IGlSZW5kZXJEYXRhSXRlbSxcbiAgY286IGlSZW5kZXJEYXRhSXRlbSxcbiAgc28yOiBpUmVuZGVyRGF0YUl0ZW0sXG4gIGVwYV9hcWk6IGlSZW5kZXJEYXRhSXRlbSxcbiAgZXBhX3ByaW1hcnlfcG9sbHV0YW50OiBpUmVuZGVyRGF0YUl0ZW0sXG59XG5cbmNvbnN0IGlzVmFsaWRJbnB1dCA9ICh2YWw6IHVua25vd24pOiB2YWwgaXMgc3RyaW5nIHwgbnVtYmVyID0+IHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWwgPT09ICdudW1iZXInO1xuXG5jb25zdCBwcmVwYXJlV2VhdGhlclByZXNlbnQgPSAoZGF0YTogV2VhdGhlckRhdGEsIGxhbmd1YWdlOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgYWxsSXRlbXM6IGlSZW5kZXJEYXRhSXRlbVtdID0gW107XG5cbiAgY29uc3QgYWRkSWZWYWxpZCA9IChrZXk6IGtleW9mIFdlYXRoZXJEYXRhLCBpdGVtPzogaVJlbmRlckRhdGFJdGVtKSA9PiB7XG4gICAgaWYgKGl0ZW0/LnZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybjtcblxuICAgIGFsbEl0ZW1zLnB1c2goaXRlbSk7XG4gIH07XG5cbiAgY29uc3QgcGkgPSBkYXRhLnByZWNpcGl0YXRpb25JbnRlbnNpdHk/LnZhbHVlO1xuICBjb25zdCBwcCA9IGRhdGEucHJlY2lwaXRhdGlvblByb2JhYmlsaXR5Py52YWx1ZTtcblxuICBpZiAoaXNWYWxpZElucHV0KHBpKSAmJiBpc1ZhbGlkSW5wdXQocHApKSB7XG4gICAgY29uc3QgbG9jYWxlID0gZ2V0TG9jYWxlKGxhbmd1YWdlKTtcbiAgICBjb25zdCBwYXJzZWRQSSA9IHBhcnNlTG9jYWxpemVkTnVtYmVyKHBpLCBsb2NhbGUpO1xuICAgIGNvbnN0IHBhcnNlZFBQID0gcGFyc2VMb2NhbGl6ZWROdW1iZXIocHAsIGxvY2FsZSk7XG5cbiAgICBpZiAoIU51bWJlci5pc05hTihOdW1iZXIocGFyc2VkUEkpKSAmJiAhTnVtYmVyLmlzTmFOKE51bWJlcihwYXJzZWRQUCkpICYmIHBhcnNlZFBJID4gMCAmJiBwYXJzZWRQUCA+IDApIHtcbiAgICAgIGFsbEl0ZW1zLnB1c2goe1xuICAgICAgICBpY29uOlxuICAgICAgICAgIGRhdGEucHJlY2lwaXRhdGlvbkludGVuc2l0eS5pY29uIHx8XG4gICAgICAgICAgZGF0YS5wcmVjaXBpdGF0aW9uUHJvYmFiaWxpdHkuaWNvbiB8fFxuICAgICAgICAgICdtZGk6d2VhdGhlci1yYWlueScsXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICAgIHZhbHVlOiBgJHtkYXRhLnByZWNpcGl0YXRpb25JbnRlbnNpdHkudmFsdWV9ICR7ZGF0YS5wcmVjaXBpdGF0aW9uSW50ZW5zaXR5LnVuaXR9IC8gJHtkYXRhLnByZWNpcGl0YXRpb25Qcm9iYWJpbGl0eS52YWx1ZX0gJHtkYXRhLnByZWNpcGl0YXRpb25Qcm9iYWJpbGl0eS51bml0fWAsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvLyBUZW1wZXJhdHVyYSBtaW4vbWF4IGNvbWJpbmF0YVxuICBpZiAoXG4gICAgZGF0YS50ZW1wZXJhdHVyZUxvdz8udmFsdWUgIT09IHVuZGVmaW5lZCAmJlxuICAgIGRhdGEudGVtcGVyYXR1cmVIaWdoPy52YWx1ZSAhPT0gdW5kZWZpbmVkXG4gICkge1xuICAgIGFsbEl0ZW1zLnB1c2goe1xuICAgICAgaWNvbjogZGF0YS50ZW1wZXJhdHVyZUxvdy5pY29uIHx8IGRhdGEudGVtcGVyYXR1cmVIaWdoLmljb24gfHwgJ21kaTp0aGVybW9tZXRlcicsXG4gICAgICB2YWx1ZTogYCR7ZGF0YS50ZW1wZXJhdHVyZUxvdy52YWx1ZX0gLyAke2RhdGEudGVtcGVyYXR1cmVIaWdoLnZhbHVlfWAsXG4gICAgICB1bml0OiBkYXRhLnRlbXBlcmF0dXJlTG93LnVuaXQgfHwgZGF0YS50ZW1wZXJhdHVyZUhpZ2gudW5pdCxcbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0IGtleXM6IChrZXlvZiBXZWF0aGVyRGF0YSlbXSA9IFtcbiAgICAnaHVtaWRpdHknLFxuICAgICdwcmVzc3VyZScsXG4gICAgJ3Zpc2liaWxpdHknLFxuICBdO1xuICBrZXlzLmZvckVhY2goKGspID0+IGFkZElmVmFsaWQoaywgZGF0YVtrXSkpO1xuXG4gIC8vIFdpbmQgKGJlYXJpbmcgKyBzcGVlZClcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgaWYgKGRhdGEud2luZFNwZWVkPy52YWx1ZSAhPT0gdW5kZWZpbmVkIHx8IGRhdGEud2luZEJlYXJpbmc/LnZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICBhbGxJdGVtcy5wdXNoKHtcbiAgICAgIGljb246IGRhdGEud2luZFNwZWVkPy5pY29uIHx8ICdtZGk6d2VhdGhlci13aW5keScsXG4gICAgICB2YWx1ZTogYCR7ZGF0YS53aW5kQmVhcmluZz8udmFsdWUgPyBgJHtkYXRhLndpbmRCZWFyaW5nLnZhbHVlfSBgIDogJyd9JHtkYXRhLndpbmRTcGVlZD8udmFsdWUgPz8gJyd9YCxcbiAgICAgIHVuaXQ6IGRhdGEud2luZFNwZWVkPy51bml0ID8gYCR7ZGF0YS53aW5kU3BlZWQudW5pdH1gIDogJycsXG4gICAgfSk7XG4gIH1cblxuICAvLyBTdW4gdGltZXNcbiAgWyduZXh0UmlzaW5nJywgJ25leHRTZXR0aW5nJ10uZm9yRWFjaCgoaykgPT4ge1xuICAgIGNvbnN0IGl0ZW0gPSBkYXRhW2sgYXMga2V5b2YgV2VhdGhlckRhdGFdO1xuICAgIGlmIChpdGVtPy52YWx1ZSkge1xuICAgICAgYWxsSXRlbXMucHVzaCh7XG4gICAgICAgIGljb246IGl0ZW0uaWNvbixcbiAgICAgICAgdmFsdWU6IGl0ZW0udmFsdWUsXG4gICAgICAgIHVuaXQ6ICcnLFxuICAgICAgfSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gYWxsSXRlbXM7XG59O1xuXG5jb25zdCBwcmVwYXJlQWlyUXVhbGl0eSA9IChkYXRhOiBpQWlyUXVhbGl0eURhdGEsIGxhbmd1YWdlOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgYWxsSXRlbXM6IGlSZW5kZXJEYXRhSXRlbVtdID0gW107XG5cbiAgY29uc3QgYWRkSWZWYWxpZCA9IChrZXk6IGtleW9mIGlBaXJRdWFsaXR5RGF0YSwgaXRlbT86IGlSZW5kZXJEYXRhSXRlbSkgPT4ge1xuICAgIGlmIChpdGVtPy52YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICBhbGxJdGVtcy5wdXNoKGl0ZW0pO1xuICB9O1xuXG4gIGNvbnN0IGtleXM6IChrZXlvZiBpQWlyUXVhbGl0eURhdGEpW10gPSBbXG4gICAgJ2VwYV9hcWknLFxuICAgICdlcGFfcHJpbWFyeV9wb2xsdXRhbnQnLFxuICAgICdwbTI1JyxcbiAgICAncG0xMCcsXG4gICAgJ28zJyxcbiAgICAnbm8yJyxcbiAgICAnY28nLFxuICAgICdzbzInLFxuICBdO1xuICBrZXlzLmZvckVhY2goKGspID0+IGFkZElmVmFsaWQoaywgZGF0YVtrXSkpO1xuXG4gIHJldHVybiBhbGxJdGVtcztcbn07XG5cbmV4cG9ydCBjb25zdCByZW5kZXJXZWF0aGVyUHJlc2VudCA9IChkYXRhLCBsYW5ndWFnZTogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IGFsbEl0ZW1zOiBpUmVuZGVyRGF0YUl0ZW1bXSA9IFtdO1xuXG4gIGNvbnN0IGJ1aWxkQmxvY2tMZWZ0ID0gKGl0ZW06IGlSZW5kZXJEYXRhSXRlbSkgPT4gaHRtbGBcbiAgICA8c3BhbiBjbGFzcz1cInByZXNlbnQtdmFsdWUtYmxvY2tcIj5cbiAgICAgIDxoYS1pY29uIGljb249XCIke2l0ZW0uaWNvbn1cIiBzdHlsZT0ke2l0ZW0uaWNvbl9jb2xvciA/IGBjb2xvcjogJHtpdGVtLmljb25fY29sb3J9YCA6ICcnfT48L2hhLWljb24+XG4gICAgICAke2l0ZW0udmFsdWV9JHtpdGVtLnVuaXQgPyBodG1sYDxzcGFuIGNsYXNzPVwicHJlc2VudC11bml0XCI+JHtpdGVtLnVuaXR9PC9zcGFuPmAgOiAnJ31cbiAgICA8L3NwYW4+XG4gIGA7XG5cbiAgY29uc3QgYnVpbGRCbG9ja1JpZ2h0ID0gKGl0ZW06IGlSZW5kZXJEYXRhSXRlbSkgPT4gaHRtbGBcbiAgICA8c3BhbiBjbGFzcz1cInByZXNlbnQtdmFsdWUtYmxvY2tcIj5cbiAgICAgICR7aXRlbS52YWx1ZX0ke2l0ZW0udW5pdCA/IGh0bWxgPHNwYW4gY2xhc3M9XCJwcmVzZW50LXVuaXRcIj4ke2l0ZW0udW5pdH08L3NwYW4+YCA6ICcnfVxuICAgICAgPGhhLWljb24gaWNvbj1cIiR7aXRlbS5pY29ufVwiIHN0eWxlPSR7aXRlbS5pY29uX2NvbG9yID8gYGNvbG9yOiAke2l0ZW0uaWNvbl9jb2xvcn1gIDogJyd9PjwvaGEtaWNvbj5cbiAgICA8L3NwYW4+XG4gIGA7XG5cbiAgYWxsSXRlbXMucHVzaCguLi5wcmVwYXJlV2VhdGhlclByZXNlbnQoZGF0YSwgbGFuZ3VhZ2UpLCAuLi5wcmVwYXJlQWlyUXVhbGl0eShkYXRhLCBsYW5ndWFnZSkpO1xuXG4gIGNvbnN0IHJvd3MgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhbGxJdGVtcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIGNvbnN0IGxlZnQgPSBhbGxJdGVtc1tpXTtcbiAgICBjb25zdCByaWdodCA9IGFsbEl0ZW1zW2kgKyAxXTtcblxuICAgIGlmICgobGVmdCAmJiBsZWZ0LnZhbHVlKSB8fCAocmlnaHQgJiYgcmlnaHQudmFsdWUpKSB7XG4gICAgICByb3dzLnB1c2goaHRtbGBcbiAgICAgICAgPGRpdiBjbGFzcz1cInByZXNlbnQtcm93XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInByZXNlbnQtbGVmdFwiPiR7bGVmdCA/IGJ1aWxkQmxvY2tMZWZ0KGxlZnQpIDogaHRtbGBgfTwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcmVzZW50LXJpZ2h0XCI+JHtyaWdodCA/IGJ1aWxkQmxvY2tSaWdodChyaWdodCkgOiBodG1sYGB9PC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgYCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJvd3MubGVuZ3RoID4gMCA/IGh0bWxgXG4gICAgPGRpdiBjbGFzcz1cInByZXNlbnQtZ3JpZC1jb250YWluZXJcIj5cbiAgICAgICR7cm93c31cbiAgICA8L2Rpdj5cbiAgYCA6IGh0bWxgYDtcbn07XG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBjYW1lbGNhc2UgKi9cbmltcG9ydCB7IEhvbWVBc3Npc3RhbnQgfSBmcm9tICdjdXN0b20tY2FyZC1oZWxwZXJzL2Rpc3QnO1xuaW1wb3J0IHtcbiAgZ2V0RW50aXR5TnVtZXJpY1ZhbHVlLFxuICBnZXRFbnRpdHlSYXdWYWx1ZSxcbiAgZ2V0RW50aXR5VW5pdCxcbiAgZ2V0TG9jYWxlSW5mbyxcbiAgZ2V0V2luZERpcmVjdGlvbnMsXG59IGZyb20gJy4uL3V0aWxzL2hlbHBlcic7XG4vLyBpbXBvcnQgeyBnZXRTZW5zb3JVbml0IH0gZnJvbSAnLi4vdXRpbHMvaGVscGVyLXJlbmRlcic7XG5pbXBvcnQgeyByZW5kZXJXZWF0aGVyUHJlc2VudCB9IGZyb20gJy4uL3RlbXBsYXRlcy90LXByZXNlbnQnO1xuaW1wb3J0IHsgaVByZXNlbnREYXRhIH0gZnJvbSAnLi4vdXRpbHMvY29uZmlnLXNjaGVtYSc7XG5pbXBvcnQgeyBpVGVybXMgfSBmcm9tICcuLi9iYXNlL2xvdmVsYWNlLWJhc2UnO1xuXG5jb25zdCBwcmVzZW50ID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIGxhbmd1YWdlOiBzdHJpbmcsIGN3Y0xvY1dpbmREaXJlY3Rpb25zLCBwcmVzZW50RGF0YTogaVByZXNlbnREYXRhLCBzdW5JZDogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IGxvY2FsZUluZm8gPSBnZXRMb2NhbGVJbmZvKGxhbmd1YWdlKTtcbiAgY29uc3Qgc3VuRW50aXR5ID0gc3VuSWQgPyBoYXNzLnN0YXRlc1tzdW5JZF0gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHsgbmV4dF9yaXNpbmcsIG5leHRfc2V0dGluZyB9ID0gc3VuRW50aXR5Py5hdHRyaWJ1dGVzID8/IHt9O1xuXG4gIGNvbnN0IG5leHRfcmlzaW5nX2Zvcm1hdHRlZCA9IG5leHRfcmlzaW5nID8gbmV3IERhdGUobmV4dF9yaXNpbmcpLnRvTG9jYWxlVGltZVN0cmluZyhsb2NhbGVJbmZvLmxvY2FsZSwge1xuICAgIGhvdXI6ICcyLWRpZ2l0JyxcbiAgICBtaW51dGU6ICcyLWRpZ2l0JyxcbiAgICBzZWNvbmQ6ICcyLWRpZ2l0JyxcbiAgICBob3VyMTI6IGZhbHNlLFxuICAgIHRpbWVab25lOiBsb2NhbGVJbmZvLnRpbWV6b25lLFxuICB9KSA6IHVuZGVmaW5lZDtcblxuICBjb25zdCBuZXh0X3NldHRpbmdfZm9ybWF0dGVkID0gbmV4dF9yaXNpbmcgPyBuZXcgRGF0ZShuZXh0X3NldHRpbmcpLnRvTG9jYWxlVGltZVN0cmluZyhsb2NhbGVJbmZvLmxvY2FsZSwge1xuICAgIGhvdXI6ICcyLWRpZ2l0JyxcbiAgICBtaW51dGU6ICcyLWRpZ2l0JyxcbiAgICBzZWNvbmQ6ICcyLWRpZ2l0JyxcbiAgICBob3VyMTI6IGZhbHNlLFxuICAgIHRpbWVab25lOiBsb2NhbGVJbmZvLnRpbWV6b25lLFxuICB9KSA6IHVuZGVmaW5lZDtcblxuICByZXR1cm4ge1xuICAgIG5leHRSaXNpbmc6IHsgdmFsdWU6IG5leHRfcmlzaW5nX2Zvcm1hdHRlZCwgaWNvbjogJ21kaTp3ZWF0aGVyLXN1bnNldC11cCcgfSxcbiAgICBuZXh0U2V0dGluZzogeyB2YWx1ZTogbmV4dF9zZXR0aW5nX2Zvcm1hdHRlZCwgaWNvbjogJ21kaTp3ZWF0aGVyLXN1bnNldC1kb3duJyB9LFxuXG4gICAgcHJlY2lwaXRhdGlvbkludGVuc2l0eToge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG9iamVjdC1jdXJseS1uZXdsaW5lXG4gICAgICB2YWx1ZTogZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IHByZXNlbnREYXRhLnByZWNpcGl0YXRpb25faW50ZW5zaXR5LCBoYXNzLCBsYW5nOiBsYW5ndWFnZSwgZGVjaW1hbHM6IDIgfSksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIHByZXNlbnREYXRhLnByZWNpcGl0YXRpb25faW50ZW5zaXR5KSxcbiAgICAgIGljb246ICdtZGk6d2VhdGhlci1yYWlueScsXG4gICAgfSxcbiAgICBwcmVjaXBpdGF0aW9uUHJvYmFiaWxpdHk6IHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBvYmplY3QtY3VybHktbmV3bGluZVxuICAgICAgdmFsdWU6IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBwcmVzZW50RGF0YS5wcmVjaXBpdGF0aW9uX3Byb2JhYmlsaXR5LCBoYXNzLCBsYW5nOiBsYW5ndWFnZSwgZGVjaW1hbHM6IDAgfSksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIHByZXNlbnREYXRhLnByZWNpcGl0YXRpb25fcHJvYmFiaWxpdHkpLFxuICAgICAgaWNvbjogJ21kaTp3ZWF0aGVyLXJhaW55JyxcbiAgICB9LFxuICAgIGh1bWlkaXR5OiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgb2JqZWN0LWN1cmx5LW5ld2xpbmVcbiAgICAgIHZhbHVlOiBnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogcHJlc2VudERhdGEuaHVtaWRpdHksIGhhc3MsIGxhbmc6IGxhbmd1YWdlLCBkZWNpbWFsczogMCB9KSxcbiAgICAgIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgcHJlc2VudERhdGEuaHVtaWRpdHkpLFxuICAgICAgaWNvbjogJ21kaTp3YXRlci1wZXJjZW50JyxcbiAgICB9LFxuICAgIHdpbmRCZWFyaW5nOiB7IHZhbHVlOiBnZXRXaW5kRGlyZWN0aW9ucyhnZXRFbnRpdHlSYXdWYWx1ZShoYXNzLCBwcmVzZW50RGF0YS53aW5kX2JlYXJpbmcpLCBjd2NMb2NXaW5kRGlyZWN0aW9ucykgfSxcbiAgICB3aW5kU3BlZWQ6IHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBvYmplY3QtY3VybHktbmV3bGluZVxuICAgICAgdmFsdWU6IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBwcmVzZW50RGF0YS53aW5kX3NwZWVkLCBoYXNzLCBsYW5nOiBsYW5ndWFnZSwgZGVjaW1hbHM6IDAgfSksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIHByZXNlbnREYXRhLndpbmRfc3BlZWQpLFxuICAgICAgaWNvbjogJ21kaTp3ZWF0aGVyLXdpbmR5JyxcbiAgICB9LFxuICAgIHByZXNzdXJlOiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgb2JqZWN0LWN1cmx5LW5ld2xpbmVcbiAgICAgIHZhbHVlOiBnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogcHJlc2VudERhdGEucHJlc3N1cmUsIGhhc3MsIGxhbmc6IGxhbmd1YWdlLCBkZWNpbWFsczogMCB9KSxcbiAgICAgIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgcHJlc2VudERhdGEucHJlc3N1cmUpLFxuICAgICAgaWNvbjogJ21kaTpnYXVnZScsXG4gICAgfSxcbiAgICB2aXNpYmlsaXR5OiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgb2JqZWN0LWN1cmx5LW5ld2xpbmVcbiAgICAgIHZhbHVlOiBnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogcHJlc2VudERhdGEudmlzaWJpbGl0eSwgaGFzcywgbGFuZzogbGFuZ3VhZ2UsIGRlY2ltYWxzOiAwIH0pLFxuICAgICAgdW5pdDogZ2V0RW50aXR5VW5pdChoYXNzLCBwcmVzZW50RGF0YS52aXNpYmlsaXR5KSxcbiAgICAgIGljb246ICdtZGk6d2VhdGhlci1mb2cnLFxuICAgIH0sXG4gICAgdGVtcGVyYXR1cmVIaWdoOiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgb2JqZWN0LWN1cmx5LW5ld2xpbmVcbiAgICAgIHZhbHVlOiBnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogcHJlc2VudERhdGEudGVtcGVyYXR1cmVfbWF4LCBoYXNzLCBsYW5nOiBsYW5ndWFnZSwgZGVjaW1hbHM6IDAgfSksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIHByZXNlbnREYXRhLnRlbXBlcmF0dXJlX21heCksXG4gICAgICBpY29uOiAnbWRpOnRoZXJtb21ldGVyJyxcbiAgICB9LFxuICAgIHRlbXBlcmF0dXJlTG93OiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgb2JqZWN0LWN1cmx5LW5ld2xpbmVcbiAgICAgIHZhbHVlOiBnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogcHJlc2VudERhdGEudGVtcGVyYXR1cmVfbWluLCBoYXNzLCBsYW5nOiBsYW5ndWFnZSwgZGVjaW1hbHM6IDAgfSksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIHByZXNlbnREYXRhLnRlbXBlcmF0dXJlX21pbiksXG4gICAgICBpY29uOiAnbWRpOnRoZXJtb21ldGVyJyxcbiAgICB9LFxuICB9O1xufTtcblxuLy8gY29uc3QgcHJlc2VudEZyb21Gb3JlY2FzdERhdGEgPSAoaGFzczogSG9tZUFzc2lzdGFudCwgbGFuZ3VhZ2U6IHN0cmluZywgZm9yZWNhc3RDZmc6IEZvcmVjYXN0KSA9PiB7XG4vLyAgIGNvbnN0IGdldFZhbHVlID0gKG9iajogUmVjb3JkPHN0cmluZywgc3RyaW5nPikgPT4ge1xuLy8gICAgIGNvbnN0IFtrZXksIGVudGl0eUlkXSA9IE9iamVjdC5lbnRyaWVzKG9iailbMF0gPz8gW107XG4vLyAgICAgY29uc3Qgc3RhdGUgPSBlbnRpdHlJZCAmJiBoYXNzLnN0YXRlc1tlbnRpdHlJZF0/LnN0YXRlO1xuLy8gICAgIHJldHVybiBzdGF0ZSAhPT0gdW5kZWZpbmVkID8gZm9ybWF0TnVtYmVyKHsgc3RyaW5nTnVtYmVyOiBzdGF0ZSwgbGFuZzogbGFuZ3VhZ2UsIGZyYWN0aW9uRGlnaXRzOiAwIH0pIDogdW5kZWZpbmVkO1xuLy8gICB9O1xuXG4vLyAgIGNvbnN0IHtcbi8vICAgICB0ZW1wZXJhdHVyZV9oaWdoID0ge30sXG4vLyAgICAgdGVtcGVyYXR1cmVfbG93ID0ge30sXG4vLyAgICAgcHJlY2lwaXRhdGlvbl9wcm9iYWJpbGl0eSA9IHt9LFxuLy8gICAgIHByZWNpcGl0YXRpb25faW50ZW5zaXR5ID0ge30sXG4vLyAgIH0gPSBmb3JlY2FzdENmZztcblxuLy8gICByZXR1cm4ge1xuLy8gICAgIHRlbXBlcmF0dXJlSGlnaDogeyB2YWx1ZTogZ2V0VmFsdWUodGVtcGVyYXR1cmVfaGlnaCksIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgdGVtcGVyYXR1cmVfaGlnaCksIGljb246ICdtZGk6dGhlcm1vbWV0ZXInIH0sXG4vLyAgICAgdGVtcGVyYXR1cmVMb3c6IHsgdmFsdWU6IGdldFZhbHVlKHRlbXBlcmF0dXJlX2xvdyksIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgJ3RlbXBlcmF0dXJlJyksIGljb246ICdtZGk6dGhlcm1vbWV0ZXInIH0sXG4vLyAgICAgcHJlY2lwaXRhdGlvblByb2JhYmlsaXR5OiB7IHZhbHVlOiBnZXRWYWx1ZShwcmVjaXBpdGF0aW9uX3Byb2JhYmlsaXR5KSwgdW5pdDogJyUnLCBpY29uOiAnbWRpOndlYXRoZXItcmFpbnknIH0sXG4vLyAgICAgcHJlY2lwaXRhdGlvbkludGVuc2l0eTogeyB2YWx1ZTogZ2V0VmFsdWUocHJlY2lwaXRhdGlvbl9pbnRlbnNpdHkpLCB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsICdwcmVjaXBpdGF0aW9uJyksIGljb246ICdtZGk6d2VhdGhlci1yYWlueScgfSxcbi8vICAgfTtcbi8vIH07XG5cbmNvbnN0IGJ1aWxkV2VhdGhlclByZXNlbnQgPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmd1YWdlOiBzdHJpbmcsXG4gIHRlcm1zOiBpVGVybXMsXG4gIHByZXNlbnREYXRhOiBpUHJlc2VudERhdGEsXG4gIHN1bklkOiBzdHJpbmcsXG4pID0+IHtcbiAgY29uc3QgbGFuZyA9IGxhbmd1YWdlIHx8IGhhc3Muc2VsZWN0ZWRMYW5ndWFnZSB8fCBoYXNzLmxhbmd1YWdlO1xuXG4gIGNvbnN0IHByZXNlbnRPYmogPSBwcmVzZW50KGhhc3MsIGxhbmcsIHRlcm1zLndpbmREaXJlY3Rpb25zLCBwcmVzZW50RGF0YSwgc3VuSWQpO1xuICAvLyBjb25zdCBwcmVzZW50RnJvbUZvcmVjYXN0T2JqID0gcHJlc2VudEZyb21Gb3JlY2FzdERhdGEoaGFzcywgbGFuZ3VhZ2UsIGZvcmVjYXN0Q2ZnKTtcblxuICAvLyBjb25zb2xlLmRlYnVnKCdidWlsZFdlYXRoZXJQcmVzZW50JywgeyBwcmVzZW50T2JqIH0pO1xuICByZXR1cm4gcmVuZGVyV2VhdGhlclByZXNlbnQoeyAuLi5wcmVzZW50T2JqIH0sIGxhbmcpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgYnVpbGRXZWF0aGVyUHJlc2VudDtcbiIsImltcG9ydCB7IGh0bWwgfSBmcm9tICdsaXQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlbmRlckRhdGFJdGVtIHtcbiAgdmFsdWU/OiBudW1iZXIgfCBzdHJpbmcgfCBEYXRlO1xuICB1bml0Pzogc3RyaW5nO1xuICBpY29uPzogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBSZW5kZXJEYXRhIHtcbiAgcHJvdGVjdGlvbldpbmRvdz86IFJlbmRlckRhdGFJdGVtLFxuICBjdXJyZW50VVZMZXZlbD86IFJlbmRlckRhdGFJdGVtLFxuICBjdXJyZW50VVZJbmRleD86IFJlbmRlckRhdGFJdGVtLFxuICBtYXhVVkluZGV4PzogUmVuZGVyRGF0YUl0ZW0sXG4gIGN1cnJlbnRPem9uZUxldmVsPzogUmVuZGVyRGF0YUl0ZW0sXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVuZGVyU2tpbkRhdGEge1xuICBza2luVHlwZTE6IFJlbmRlckRhdGFJdGVtLFxuICBza2luVHlwZTI6IFJlbmRlckRhdGFJdGVtLFxuICBza2luVHlwZTM6IFJlbmRlckRhdGFJdGVtLFxuICBza2luVHlwZTQ6IFJlbmRlckRhdGFJdGVtLFxuICBza2luVHlwZTU6IFJlbmRlckRhdGFJdGVtLFxuICBza2luVHlwZTY6IFJlbmRlckRhdGFJdGVtLFxufVxuXG5jb25zdCBudW0gPSBbJ0knLCAnSUknLCAnSUlJJywgJ0lWJywgJ1YnLCAnVkknXTtcbmNvbnN0IGNvbG9ycyA9IFsnI0YxRDFCMScsICcjRTRCNTkwJywgJyNDRjlGN0QnLCAnI0I2Nzg1MScsICcjQTE1RTJEJywgJyM1MTM5MzgnXTtcblxuY29uc3QgZ2V0VGV4dENvbG9yID0gKGhleDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgY29uc3QgYyA9IGhleC5yZXBsYWNlKCcjJywgJycpO1xuICBjb25zdCByID0gcGFyc2VJbnQoYy5zdWJzdHIoMCwgMiksIDE2KTtcbiAgY29uc3QgZyA9IHBhcnNlSW50KGMuc3Vic3RyKDIsIDIpLCAxNik7XG4gIGNvbnN0IGIgPSBwYXJzZUludChjLnN1YnN0cig0LCAyKSwgMTYpO1xuICBjb25zdCBicmlnaHRuZXNzID0gKHIgKiAyOTkgKyBnICogNTg3ICsgYiAqIDExNCkgLyAxMDAwO1xuICByZXR1cm4gYnJpZ2h0bmVzcyA+IDEyNSA/ICcjMDAwJyA6ICcjZmZmJztcbn07XG5cbmNvbnN0IHJlbmRlclVsdHJhdmlvbGV0ID0gKGRhdGE6IFJlbmRlckRhdGEsIHNraW5EYXRhOiBSZW5kZXJTa2luRGF0YSkgPT4ge1xuICBjb25zdCBhbGxJdGVtczogUmVuZGVyRGF0YUl0ZW1bXSA9IFtdO1xuXG4gIGNvbnN0IGJ1aWxkQmxvY2tMZWZ0ID0gKGl0ZW06IFJlbmRlckRhdGFJdGVtKSA9PiBodG1sYFxuICAgIDxzcGFuIGNsYXNzPVwidWx0cmF2aW9sZXQtdmFsdWUtYmxvY2tcIj5cbiAgICAgIDxoYS1pY29uIGljb249XCIke2l0ZW0uaWNvbn1cIiBzdHlsZT1cIiR7aXRlbS52YWx1ZSA9PT0gJ29uJyA/ICdjb2xvcjogcmVkOycgOiAnJ31cIj48L2hhLWljb24+XG4gICAgICAke2l0ZW0udmFsdWV9JHtpdGVtLnVuaXQgPyBodG1sYDxzcGFuIGNsYXNzPVwidWx0cmF2aW9sZXQtdW5pdFwiPiR7aXRlbS51bml0fTwvc3Bhbj5gIDogJyd9XG4gICAgPC9zcGFuPlxuICBgO1xuXG4gIGNvbnN0IGJ1aWxkQmxvY2tSaWdodCA9IChpdGVtOiBSZW5kZXJEYXRhSXRlbSkgPT4gaHRtbGBcbiAgICA8c3BhbiBjbGFzcz1cInVsdHJhdmlvbGV0LXZhbHVlLWJsb2NrXCI+XG4gICAgICAke2l0ZW0udmFsdWV9JHtpdGVtLnVuaXQgPyBodG1sYDxzcGFuIGNsYXNzPVwidWx0cmF2aW9sZXQtdW5pdFwiPiR7aXRlbS51bml0fTwvc3Bhbj5gIDogJyd9XG4gICAgICA8aGEtaWNvbiBpY29uPVwiJHtpdGVtLmljb259XCIgc3R5bGU9XCIke2l0ZW0udmFsdWUgPT09ICdvbicgPyAnY29sb3I6IHJlZDsnIDogJyd9XCI+PC9oYS1pY29uPlxuICAgIDwvc3Bhbj5cbiAgYDtcbiAgXG4gIGNvbnN0IGFkZElmVmFsaWQgPSAoa2V5OiBrZXlvZiBSZW5kZXJEYXRhLCBpdGVtPzogUmVuZGVyRGF0YUl0ZW0pID0+IHtcbiAgICBpZiAoaXRlbT8udmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgYWxsSXRlbXMucHVzaChpdGVtKTtcbiAgfTtcblxuICBsZXQga2V5czogKGtleW9mIFJlbmRlckRhdGEpW10gPSBbXG4gICAgJ3Byb3RlY3Rpb25XaW5kb3cnLFxuICAgICdjdXJyZW50VVZMZXZlbCcsXG4gIF07XG4gIGtleXMuZm9yRWFjaCgoaykgPT4gYWRkSWZWYWxpZChrLCBkYXRhW2tdKSk7XG5cbiAgLy8gVVYgTGV2ZWwgY3VycmVudC9tYXggY29tYmluYXRhXG4gIGlmIChcbiAgICBkYXRhLmN1cnJlbnRVVkluZGV4Py52YWx1ZSAhPT0gdW5kZWZpbmVkICYmXG4gICAgZGF0YS5tYXhVVkluZGV4Py52YWx1ZSAhPT0gdW5kZWZpbmVkXG4gICkge1xuICAgIGFsbEl0ZW1zLnB1c2goe1xuICAgICAgaWNvbjogZGF0YS5jdXJyZW50VVZJbmRleC5pY29uIHx8IGRhdGEubWF4VVZJbmRleC5pY29uIHx8ICdtZGk6d2VhdGhlci1zdW5ueScsXG4gICAgICB2YWx1ZTogYCR7ZGF0YS5jdXJyZW50VVZJbmRleC52YWx1ZX0gLyAke2RhdGEubWF4VVZJbmRleC52YWx1ZX1gLFxuICAgICAgdW5pdDogZGF0YS5jdXJyZW50VVZJbmRleC51bml0IHx8IGRhdGEubWF4VVZJbmRleC51bml0LFxuICAgIH0pO1xuICB9XG5cbiAga2V5cyA9IFtcbiAgICAnY3VycmVudE96b25lTGV2ZWwnLFxuICBdO1xuICBrZXlzLmZvckVhY2goKGspID0+IGFkZElmVmFsaWQoaywgZGF0YVtrXSkpO1xuXG4gIGNvbnN0IHN1bW1hcnlSb3dzID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsSXRlbXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICBjb25zdCBsZWZ0ID0gYWxsSXRlbXNbaV07XG4gICAgY29uc3QgcmlnaHQgPSBhbGxJdGVtc1tpICsgMV07XG4gICAgc3VtbWFyeVJvd3MucHVzaChodG1sYFxuICAgICAgPGRpdiBjbGFzcz1cInVsdHJhdmlvbGV0LXJvd1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidWx0cmF2aW9sZXQtbGVmdFwiPiR7bGVmdCA/IGJ1aWxkQmxvY2tMZWZ0KGxlZnQpIDogaHRtbGBgfTwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwidWx0cmF2aW9sZXQtcmlnaHRcIj4ke3JpZ2h0ID8gYnVpbGRCbG9ja1JpZ2h0KHJpZ2h0KSA6IGh0bWxgYH08L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIGApO1xuICB9XG5cbiAgY29uc3Qgc2tpblR5cGVzID0gW1xuICAgIHNraW5EYXRhLnNraW5UeXBlMSxcbiAgICBza2luRGF0YS5za2luVHlwZTIsXG4gICAgc2tpbkRhdGEuc2tpblR5cGUzLFxuICAgIHNraW5EYXRhLnNraW5UeXBlNCxcbiAgICBza2luRGF0YS5za2luVHlwZTUsXG4gICAgc2tpbkRhdGEuc2tpblR5cGU2LFxuICBdO1xuXG4gIGNvbnN0IHJlbmRlclNraW5HcmlkID0gaHRtbGBcbiAgPGRpdiBjbGFzcz1cInVsdHJhdmlvbGV0LXNraW4tdHlwZS1ncmlkXCI+XG4gICR7c2tpblR5cGVzLm1hcCgoaXRlbSwgaSkgPT4ge1xuICAgIGNvbnN0IGJnQ29sb3IgPSBjb2xvcnNbaV07XG4gICAgY29uc3QgdGV4dENvbG9yID0gZ2V0VGV4dENvbG9yKGJnQ29sb3IpO1xuICAgIHJldHVybiBodG1sYFxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cInVsdHJhdmlvbGV0LXNraW4tdHlwZS1jZWxsXCJcbiAgICAgICAgc3R5bGU9XCJiYWNrZ3JvdW5kOiAke2JnQ29sb3J9O1wiXG4gICAgICAgIHRpdGxlPVwiRm90b3RpcG8gJHtudW1baV19XCJcbiAgICAgID5cbiAgICAgICAgPGRpdiBjbGFzcz1cInVsdHJhdmlvbGV0LXNraW4tdHlwZS1sYWJlbFwiPiR7bnVtW2ldfTwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwidWx0cmF2aW9sZXQtZXhwb3N1cmUtdGltZVwiIHN0eWxlPVwiY29sb3I6ICR7dGV4dENvbG9yfTtcIj4ke2l0ZW0udmFsdWUgfHwgJy0tJ308L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIGA7XG4gIH0pfVxuICA8L2Rpdj5cbiAgYDtcblxuICByZXR1cm4gaHRtbGBcbiAgICA8ZGl2IGNsYXNzPVwidWx0cmF2aW9sZXQtZ3JpZC1jb250YWluZXJcIj5cbiAgICAgICR7c3VtbWFyeVJvd3N9XG4gICAgICAke3JlbmRlclNraW5HcmlkfVxuICAgIDwvZGl2PlxuICBgO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgcmVuZGVyVWx0cmF2aW9sZXQ7XG4iLCJpbXBvcnQgeyBIb21lQXNzaXN0YW50IH0gZnJvbSAnY3VzdG9tLWNhcmQtaGVscGVycy9kaXN0JztcblxuaW1wb3J0IHsgZ2V0RW50aXR5TnVtZXJpY1ZhbHVlLCBnZXRFbnRpdHlSYXdWYWx1ZSwgcGFkIH0gZnJvbSAnLi4vdXRpbHMvaGVscGVyJztcbmltcG9ydCByZW5kZXJVbHRyYXZpb2xldCBmcm9tICcuLi90ZW1wbGF0ZXMvdC11bHRyYXZpb2xldCc7XG5pbXBvcnQgeyBpVWx0cmF2aW9sZXQgfSBmcm9tICcuLi91dGlscy9jb25maWctc2NoZW1hJztcblxuLy8gY29uc3QgZ2V0UmF3VmFsdWUgPSAoaGFzczogSG9tZUFzc2lzdGFudCwgZW50aXR5SWQ/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4gZW50aXR5SWQgJiYgaGFzcy5zdGF0ZXNbZW50aXR5SWRdPy5zdGF0ZTtcbi8vIGNvbnN0IGdldFZhbHVlID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIGVudGl0eUlkPzogc3RyaW5nLCBsYW5nOiBzdHJpbmcgPSAnZW4nLCBkZWNpbWFscyA9IDApOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuLy8gICBjb25zdCBzdGF0ZSA9IGVudGl0eUlkICYmIGhhc3Muc3RhdGVzW2VudGl0eUlkXT8uc3RhdGU7XG4vLyAgIHJldHVybiBzdGF0ZSAhPT0gdW5kZWZpbmVkID8gZm9ybWF0TnVtYmVyKHN0YXRlLCBsYW5nLCBkZWNpbWFscykgOiB1bmRlZmluZWQ7XG4vLyB9O1xuXG5jb25zdCBnZXRUaW1lID0gKHN0YXRlPzogc3RyaW5nIHwgbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgY29uc3QgdmFsdWUgPSB0eXBlb2Ygc3RhdGUgPT09ICdzdHJpbmcnICYmIHN0YXRlLnRvTG93ZXJDYXNlKCkgPT09ICd1bmtub3duJ1xuICAgID8gTmFOXG4gICAgOiBOdW1iZXIoc3RhdGUpO1xuICAvLyBjb25zb2xlLmRlYnVnKHN0YXRlKTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUodmFsdWUpIHx8IHZhbHVlIDwgMCkgcmV0dXJuICctLSc7XG5cbiAgY29uc3QgaG91cnMgPSBNYXRoLmZsb29yKHZhbHVlIC8gNjApO1xuICBjb25zdCBtaW51dGVzID0gdmFsdWUgJSA2MDtcblxuICByZXR1cm4gaG91cnMgPiAwXG4gICAgPyBgJHtob3Vyc306JHtwYWQobWludXRlcywgMil9IGhgXG4gICAgOiBgJHttaW51dGVzfSBtYDtcbn07XG5cbmNvbnN0IHN1bW1hcnlEYXRhID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIGxhbmc6IHN0cmluZywgdXY6IGlVbHRyYXZpb2xldCkgPT4gKHtcbiAgcHJvdGVjdGlvbldpbmRvdzoge1xuICAgIHZhbHVlOiAoIWdldEVudGl0eVJhd1ZhbHVlKGhhc3MsIHV2LnByb3RlY3Rpb25fd2luZG93KSB8fCBnZXRFbnRpdHlSYXdWYWx1ZShoYXNzLCB1di5wcm90ZWN0aW9uX3dpbmRvdykgPT09ICd1bmtub3duJyA/ICdvZmYnIDpcbiAgICAgIGdldEVudGl0eVJhd1ZhbHVlKGhhc3MsIHV2LnByb3RlY3Rpb25fd2luZG93KVxuICAgICksXG4gICAgaWNvbjogJ21kaTpzdW5nbGFzc2VzJyxcbiAgfSxcbiAgY3VycmVudFVWTGV2ZWw6IHsgdmFsdWU6IGdldEVudGl0eVJhd1ZhbHVlKGhhc3MsIHV2LnV2X2xldmVsKSwgaWNvbjogJ21kaTp3ZWF0aGVyLXN1bm55JyB9LFxuICBjdXJyZW50VVZJbmRleDogeyB2YWx1ZTogZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IHV2LnV2X2luZGV4LCBoYXNzLCBsYW5nIH0pLCB1bml0OiAnVVYgSWR4JywgaWNvbjogJ21kaTp3ZWF0aGVyLXN1bm55JyB9LFxuICBtYXhVVkluZGV4OiB7IHZhbHVlOiBnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogdXYubWF4X3V2X2luZGV4LCBoYXNzLCBsYW5nIH0pLCB1bml0OiAnVVYgSWR4JywgaWNvbjogJ21kaTp3ZWF0aGVyLXN1bm55JyB9LFxuICBjdXJyZW50T3pvbmVMZXZlbDogeyB2YWx1ZTogZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IHV2Lm96b25lX2xldmVsLCBoYXNzLCBsYW5nIH0pLCB1bml0OiAnRFUnLCBpY29uOiAnbWRpOnZlY3Rvci10cmlhbmdsZScgfSxcbn0pO1xuXG5jb25zdCBza2luRGF0YSA9IChoYXNzOiBIb21lQXNzaXN0YW50LCBsYW5nOiBzdHJpbmcsIHV2OiBpVWx0cmF2aW9sZXQpID0+ICh7XG4gIHNraW5UeXBlMTogeyB2YWx1ZTogZ2V0VGltZShnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogdXYuc2V0X3NraW5fdHlwZV8xLCBoYXNzLCBsYW5nIH0pKSB9LFxuICBza2luVHlwZTI6IHsgdmFsdWU6IGdldFRpbWUoZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IHV2LnNldF9za2luX3R5cGVfMiwgaGFzcywgbGFuZyB9KSkgfSxcbiAgc2tpblR5cGUzOiB7IHZhbHVlOiBnZXRUaW1lKGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiB1di5zZXRfc2tpbl90eXBlXzMsIGhhc3MsIGxhbmcgfSkpIH0sXG4gIHNraW5UeXBlNDogeyB2YWx1ZTogZ2V0VGltZShnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZDogdXYuc2V0X3NraW5fdHlwZV80LCBoYXNzLCBsYW5nIH0pKSB9LFxuICBza2luVHlwZTU6IHsgdmFsdWU6IGdldFRpbWUoZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IHV2LnNldF9za2luX3R5cGVfNSwgaGFzcywgbGFuZyB9KSkgfSxcbiAgc2tpblR5cGU2OiB7IHZhbHVlOiBnZXRUaW1lKGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiB1di5zZXRfc2tpbl90eXBlXzYsIGhhc3MsIGxhbmcgfSkpIH0sXG59KTtcblxuY29uc3QgYnVpbGRVbHRyYXZpb2xldCA9IChoYXNzOiBIb21lQXNzaXN0YW50LCBsYW5nOiBzdHJpbmcsIHV2OiBpVWx0cmF2aW9sZXQpID0+XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBsaWNpdC1hcnJvdy1saW5lYnJlYWtcbiAgcmVuZGVyVWx0cmF2aW9sZXQoeyAuLi5zdW1tYXJ5RGF0YShoYXNzLCBsYW5nLCB1dikgfSwgeyAuLi5za2luRGF0YShoYXNzLCBsYW5nLCB1dikgfSk7XG5cbmV4cG9ydCBkZWZhdWx0IGJ1aWxkVWx0cmF2aW9sZXQ7XG4iLCJpbXBvcnQgeyBodG1sIH0gZnJvbSAnbGl0JztcblxuZXhwb3J0IGludGVyZmFjZSBpUG9sbGVuRGF0YSB7XG4gIG5hbWU6IHN0cmluZztcbiAgdmFsdWU6IG51bWJlcjtcbn1cblxuY29uc3QgTEVWRUxfTkFNRVMgPSBbJ2Jhc3NvJywgJ21vZGVyYXRvJywgJ2FsdG8nLCAnbW9sdG8tYWx0bycsICdlc3RyZW1vJ107XG5cbmNvbnN0IGdldExldmVsSW5kZXggPSAodmFsdWU6IG51bWJlciwgbGV2ZWxNaW46IG51bWJlciwgbGV2ZWxNYXg6IG51bWJlcik6IG51bWJlciA9PiB7XG4gIGNvbnN0IHJhbmdlID0gbGV2ZWxNYXggLSBsZXZlbE1pbiArIDE7XG4gIGNvbnN0IHN0ZXAgPSByYW5nZSAvIExFVkVMX05BTUVTLmxlbmd0aDtcbiAgY29uc3QgaW5kZXggPSBNYXRoLmZsb29yKCh2YWx1ZSAtIGxldmVsTWluKSAvIHN0ZXApO1xuICByZXR1cm4gTWF0aC5taW4oaW5kZXgsIExFVkVMX05BTUVTLmxlbmd0aCAtIDEpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlbmRlclBvbGxlbiA9IChkYXRhOiBpUG9sbGVuRGF0YVtdLCBsZXZlbE1pbjogbnVtYmVyLCBsZXZlbE1heDogbnVtYmVyKSA9PiB7XG4gIGNvbnN0IG51bUxldmVscyA9IGxldmVsTWF4IC0gbGV2ZWxNaW4gKyAxO1xuICBjb25zdCBsZXZlbHMgPSBMRVZFTF9OQU1FUy5zbGljZSgwLCBudW1MZXZlbHMpO1xuXG4gIGlmIChkYXRhLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBodG1sYGA7XG4gIH1cblxuICByZXR1cm4gaHRtbGBcbiAgICA8ZGl2IGNsYXNzPVwicG9sbGVuLWdyaWQtY29udGFpbmVyXCI+XG4gICAgICAke2RhdGEubWFwKChpdGVtKSA9PiB7XG4gICAgY29uc3QgYWN0aXZlSW5kZXggPSBnZXRMZXZlbEluZGV4KGl0ZW0udmFsdWUsIGxldmVsTWluLCBsZXZlbE1heCk7XG4gICAgcmV0dXJuIGh0bWxgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cInBvbGxlbi1zdGFja1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxldmVsc1wiPlxuICAgICAgICAgICAgICAke2xldmVscy5tYXAoKGxldmVsTmFtZSwgaW5kZXgpID0+IGh0bWxgXG4gICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJsZXZlbCAke2xldmVsTmFtZX0gJHtpbmRleCA9PT0gYWN0aXZlSW5kZXggPyAnYWN0aXZlJyA6ICcnfVwiXG4gICAgICAgICAgICAgICAgICB0aXRsZT1cIiR7bGV2ZWxOYW1lfVwiXG4gICAgICAgICAgICAgICAgPjwvZGl2PlxuICAgICAgICAgICAgICBgKX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBvbGxlbi1uYW1lXCI+JHtpdGVtLm5hbWV9PC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIGA7XG4gIH0pfVxuICAgIDwvZGl2PlxuICBgO1xufTtcbiIsImltcG9ydCB7IEhvbWVBc3Npc3RhbnQgfSBmcm9tICdjdXN0b20tY2FyZC1oZWxwZXJzL2Rpc3QnO1xuaW1wb3J0IHsgaVBvbGxlbiB9IGZyb20gJy4uL3V0aWxzL2NvbmZpZy1zY2hlbWEnO1xuaW1wb3J0IHsgZ2V0RW50aXR5UmF3VmFsdWUsIHN0cmluZzJOdW1iZXIgfSBmcm9tICcuLi91dGlscy9oZWxwZXInO1xuaW1wb3J0IHsgaVBvbGxlbkRhdGEsIHJlbmRlclBvbGxlbiB9IGZyb20gJy4uL3RlbXBsYXRlcy90LXBvbGxlbic7XG5cbmNvbnN0IGJ1aWxkUG9sbGVuID0gKGhhc3M6IEhvbWVBc3Npc3RhbnQsIGxhbmc6IHN0cmluZywgcG9sbGVuOiBpUG9sbGVuKSA9PiB7XG4gIGNvbnN0IGFsbEl0ZW1zOiBpUG9sbGVuRGF0YVtdID0gW107XG4gIGlmIChBcnJheS5pc0FycmF5KHBvbGxlbi5lbnRpdGllcykgJiYgcG9sbGVuLmVudGl0aWVzLmxlbmd0aCA+IDApIHtcbiAgICBwb2xsZW4uZW50aXRpZXMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgY29uc3QgcmF3dmFsdWUgPSBnZXRFbnRpdHlSYXdWYWx1ZShoYXNzLCBpdGVtLmVudGl0eSk7XG4gICAgICBpZiAocmF3dmFsdWUgJiYgcmF3dmFsdWUgIT09ICd1bmtub3duJyAmJiByYXd2YWx1ZSAhPT0gJ3VuYXZhaWxhYmxlJykge1xuICAgICAgICBsZXQgdmFsdWU6IG51bWJlciA9IHN0cmluZzJOdW1iZXIoZ2V0RW50aXR5UmF3VmFsdWUoaGFzcywgaXRlbS5lbnRpdHkpKTtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA8IHBvbGxlbi5taW4gfHwgdmFsdWUgPiBwb2xsZW4ubWF4KSB7XG4gICAgICAgICAgdmFsdWUgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgYWxsSXRlbXMucHVzaCh7XG4gICAgICAgICAgbmFtZTogaXRlbS5uYW1lLFxuICAgICAgICAgIHZhbHVlLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIC8vIGNvbnNvbGUubG9nKGBOb21lOiAke2l0ZW0ubmFtZX0sIEVudGl0w6A6ICR7aXRlbS5lbnRpdHl9YCk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcmVuZGVyUG9sbGVuKGFsbEl0ZW1zLCBwb2xsZW4ubWluLCBwb2xsZW4ubWF4KTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGJ1aWxkUG9sbGVuO1xuIiwiLyogZXNsaW50LWRpc2FibGUgbWF4LWxlbiAqL1xuLyogZXNsaW50LWRpc2FibGUgY2FtZWxjYXNlICovXG5pbXBvcnQgeyBodG1sIH0gZnJvbSAnbGl0JztcblxuZXhwb3J0IGludGVyZmFjZSBpRm9yZWNhc3REYXRhSXRlbSB7XG4gIHZhbHVlPzogbnVtYmVyIHwgc3RyaW5nIHwgRGF0ZTtcbiAgdW5pdD86IHN0cmluZztcbiAgaW1nPzogc3RyaW5nO1xuICBpY29uPzogc3RyaW5nO1xuICBpY29uQ29sb3I/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCByZW5kZXJXZWF0aGVyRm9yZWNhc3QgPSAoZm9yZWNhc3RUeXBlOiBudW1iZXIsIGRhdGE6IFJlY29yZDxzdHJpbmcsIGlGb3JlY2FzdERhdGFJdGVtPltdKSA9PiB7XG4gIGNvbnN0IHJvd3MgPSBkYXRhLm1hcCgoZGF5RGF0YSkgPT4ge1xuICAgIGNvbnN0IGRheSA9IGRheURhdGEucmVmZXJlbmNlPy52YWx1ZTtcbiAgICBjb25zdCBpbWcgPSBkYXlEYXRhLmNvbmRpdGlvbj8uaW1nO1xuICAgIGNvbnN0IGljb24gPSBkYXlEYXRhLmNvbmRpdGlvbj8uaWNvbjtcbiAgICBjb25zdCBpY29uQ29sb3IgPSBkYXlEYXRhLmNvbmRpdGlvbj8uaWNvbkNvbG9yO1xuICAgIGNvbnN0IHRlbXBMb3cgPSBkYXlEYXRhLnRlbXBlcmF0dXJlX2xvdz8udmFsdWU7XG4gICAgY29uc3QgdGVtcEhpZ2ggPSBkYXlEYXRhLnRlbXBlcmF0dXJlX2hpZ2g/LnZhbHVlO1xuICAgIGNvbnN0IHRlbXBITFVuaXQgPSBkYXlEYXRhLnRlbXBlcmF0dXJlX2hpZ2g/LnVuaXQgfHwgZGF5RGF0YS50ZW1wZXJhdHVyZV9sb3c/LnVuaXQ7XG4gICAgY29uc3QgcHJlY2lwUHJvYjogbnVtYmVyID0gTnVtYmVyKGRheURhdGEucHJlY2lwaXRhdGlvbl9wcm9iYWJpbGl0eT8udmFsdWUgPz8gMCk7XG4gICAgY29uc3QgcHJlY2lwSW50ID0gZGF5RGF0YS5wcmVjaXBpdGF0aW9uX2ludGVuc2l0eT8udmFsdWU7XG4gICAgY29uc3QgcHJlY2lwVW5pdCA9IGRheURhdGEucHJlY2lwaXRhdGlvbl9pbnRlbnNpdHk/LnVuaXQ7XG5cbiAgICBjb25zdCB0ZW1wID0gZGF5RGF0YS50ZW1wZXJhdHVyZT8udmFsdWU7XG4gICAgY29uc3QgdGVtcFVuaXQgPSBkYXlEYXRhLnRlbXBlcmF0dXJlPy51bml0IHx8IGRheURhdGEudGVtcGVyYXR1cmVfZmVlbHNsaWtlPy51bml0O1xuICAgIGNvbnN0IHRlbXBfZmVlbHNsaWtlID0gZGF5RGF0YS50ZW1wZXJhdHVyZV9mZWVsc2xpa2U/LnZhbHVlO1xuICAgIGNvbnN0IHdpbmRfc3BlZWQgPSBkYXlEYXRhLndpbmRfc3BlZWQ/LnZhbHVlO1xuICAgIGNvbnN0IHdpbmRfc3BlZWRVbml0ID0gZGF5RGF0YS53aW5kX3NwZWVkPy51bml0O1xuICAgIGNvbnN0IHdpbmRfYmVhcmluZyA9IGRheURhdGEud2luZF9iZWFyaW5nPy52YWx1ZTtcblxuICAgIGNvbnN0IHdpbmRfd2F2ZV9oZWlnaHRfbWF4ID0gZGF5RGF0YS53aW5kX3dhdmVfaGVpZ2h0X21heD8udmFsdWU7XG4gICAgY29uc3Qgc3dlbGxfd2F2ZV9oZWlnaHRfbWF4ID0gZGF5RGF0YS5zd2VsbF93YXZlX2hlaWdodF9tYXg/LnZhbHVlO1xuICAgIGNvbnN0IHdhdmVfaGVpZ2h0X21heCA9IGRheURhdGEud2F2ZV9oZWlnaHRfbWF4Py52YWx1ZTtcbiAgICBjb25zdCB3YXZlX2RpcmVjdGlvbiA9IGRheURhdGEud2F2ZV9kaXJlY3Rpb24/LnZhbHVlO1xuICAgIGNvbnN0IHdhdmVfZGlyZWN0aW9uX2RlZ3JlZXMgPSBkYXlEYXRhLndhdmVfZGlyZWN0aW9uPy5pY29uO1xuICAgIGNvbnN0IHdhdmVfaGVpZ2h0X21heF91bml0ID0gZGF5RGF0YS53YXZlX2hlaWdodF9tYXg/LnVuaXQ7XG5cbiAgICByZXR1cm4gaHRtbGBcbiAgICAgIDxkaXYgY2xhc3M9XCJ3ZWF0aGVyLWZvcmVjYXN0LXNsb3RcIj5cbiAgICAgICAgJHtkYXkgPyBodG1sYDxkaXYgY2xhc3M9XCJ3ZWF0aGVyLWZvcmVjYXN0LWxhYmVsLXNsb3RcIj4ke2RheX08L2Rpdj5gIDogJyd9XG4gICAgICAgICR7aW1nID8gaHRtbGA8aW1nIGNsYXNzPVwid2VhdGhlci1mb3JlY2FzdC1pY29uXCIgc3JjPVwiJHtpbWd9XCIgYWx0PVwiJHtpbWd9XCIgLz5gIDogJyd9XG4gICAgICAgICR7aWNvbiA/IGh0bWxgPGhhLWljb24gaWNvbj1cIiR7aWNvbn1cIiBzdHlsZT0ke2ljb25Db2xvciA/IGBjb2xvcjogJHtpY29uQ29sb3J9YCA6ICcnfT48L2hhLWljb24+YCA6ICcnfVxuICAgICAgICAke1xuICB0ZW1wTG93ICE9PSB1bmRlZmluZWQgJiYgdGVtcEhpZ2ggIT09IHVuZGVmaW5lZFxuICAgID8gaHRtbGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwid2VhdGhlci1mb3JlY2FzdC10ZW1wZXJhdHVyZVwiPlxuICAgICAgICAgICAgICAgICAgJHt0ZW1wTG93fSAvIDxzcGFuIGNsYXNzPVwiaGlnaFwiPiR7dGVtcEhpZ2h9JHt0ZW1wSExVbml0ID8gYCAke3RlbXBITFVuaXR9YCA6ICcnfTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgYFxuICAgIDogJydcbn1cbiAgICAgICAgJHtcbiAgdGVtcCAhPT0gdW5kZWZpbmVkICYmIHRlbXBfZmVlbHNsaWtlICE9PSB1bmRlZmluZWRcbiAgICA/IGh0bWxgXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIndlYXRoZXItZm9yZWNhc3QtdGVtcGVyYXR1cmVcIj5cbiAgICAgICAgICAgICAgICAgICR7dGVtcH0gLyA8c3BhbiBjbGFzcz1cImhpZ2hcIj4ke3RlbXBfZmVlbHNsaWtlfSR7dGVtcFVuaXQgPyBgICR7dGVtcFVuaXR9YCA6ICcnfTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgYFxuICAgIDogJydcbn1cbiAgICAgICAgJHtcbiAgd2luZF9zcGVlZCAhPT0gdW5kZWZpbmVkICYmIHdpbmRfYmVhcmluZyAhPT0gdW5kZWZpbmVkXG4gICAgPyBodG1sYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3ZWF0aGVyLWZvcmVjYXN0LXRlbXBlcmF0dXJlXCI+XG4gICAgICAgICAgICAgICAgICAke3dpbmRfc3BlZWR9ICR7d2luZF9zcGVlZFVuaXR9ICR7d2luZF9iZWFyaW5nfTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgYFxuICAgIDogJydcbn1cbiAgICAgICAgJHtcbiAgd2F2ZV9oZWlnaHRfbWF4ICE9PSB1bmRlZmluZWRcbiAgICA/IGh0bWxgXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIndlYXRoZXItZm9yZWNhc3QtdGVtcGVyYXR1cmVcIj5cbiAgICAgICAgICAgICAgICAgICR7d2F2ZV9oZWlnaHRfbWF4fSAke3dhdmVfaGVpZ2h0X21heF91bml0ID8gYCAke3dhdmVfaGVpZ2h0X21heF91bml0fWAgOiAnJ31cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgYFxuICAgIDogJydcbn1cbiAgICAgICAgJHtcbiAgd2F2ZV9kaXJlY3Rpb24gIT09IHVuZGVmaW5lZFxuICAgID8gaHRtbGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwid2VhdGhlci1mb3JlY2FzdC10ZW1wZXJhdHVyZVwiPlxuICAgICAgICAgICAgICAgICAgJHt3YXZlX2RpcmVjdGlvbl9kZWdyZWVzID8gaHRtbGA8aGEtaWNvblxuICAgICAgICAgICAgICAgICAgICAgICAgaWNvbj1cIm1kaTphcnJvdy11cC10aGluXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlPVwiZGlzcGxheTppbmxpbmUtYmxvY2s7IHRyYW5zZm9ybTogcm90YXRlKCR7d2F2ZV9kaXJlY3Rpb25fZGVncmVlc31kZWcpO1wiXG4gICAgICAgICAgICAgICAgICAgICAgPjwvaGEtaWNvbj5gIDogJyd9ICR7d2F2ZV9kaXJlY3Rpb259XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIGBcbiAgICA6ICcnXG59XG4gICAgICAgICR7XG4gIHdpbmRfd2F2ZV9oZWlnaHRfbWF4ICE9PSB1bmRlZmluZWQgJiYgc3dlbGxfd2F2ZV9oZWlnaHRfbWF4ICE9PSB1bmRlZmluZWRcbiAgICA/IGh0bWxgXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIndlYXRoZXItZm9yZWNhc3QtdGVtcGVyYXR1cmVcIj5cbiAgICAgICAgICAgICAgICAgICR7c3dlbGxfd2F2ZV9oZWlnaHRfbWF4fSAvICR7d2luZF93YXZlX2hlaWdodF9tYXh9ICR7d2F2ZV9oZWlnaHRfbWF4X3VuaXQgPyBgICR7d2F2ZV9oZWlnaHRfbWF4X3VuaXR9YCA6ICcnfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICBgXG4gICAgOiAnJ1xufVxuICAgICAgICAke1xuICBwcmVjaXBQcm9iICE9PSB1bmRlZmluZWQgJiYgcHJlY2lwSW50ICE9PSB1bmRlZmluZWQgJiYgcHJlY2lwUHJvYiAhPT0gMFxuICAgID8gaHRtbGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwid2VhdGhlci1mb3JlY2FzdC1wcmVjaXBpdGF0aW9uXCI+XG4gICAgICAgICAgICAgICAgICAke3ByZWNpcFByb2J9ICUgLyA8c3BhbiBjbGFzcz1cIm1tXCI+JHtwcmVjaXBJbnR9JHtwcmVjaXBVbml0ID8gYCAke3ByZWNpcFVuaXR9YCA6ICcnfTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgYFxuICAgIDogJydcbn1cbiAgICAgIDwvZGl2PlxuICAgIGA7XG4gIH0pO1xuXG4gIGxldCB0aXRsZSA9ICdEYWlseSc7XG4gIGlmIChmb3JlY2FzdFR5cGUgPT09IDEpIHtcbiAgICB0aXRsZSA9ICdIb3VybHknO1xuICB9IGVsc2UgaWYgKGZvcmVjYXN0VHlwZSA9PT0gMikge1xuICAgIHRpdGxlID0gJ01hcmluZSBkYWlseSc7XG4gIH0gZWxzZSBpZiAoZm9yZWNhc3RUeXBlID09PSAzKSB7XG4gICAgdGl0bGUgPSAnTWFyaW5lIGhvdXJseSc7XG4gIH1cblxuICByZXR1cm4gaHRtbGBcbiAgPGRpdiBjbGFzcz1cIndlYXRoZXItZm9yZWNhc3QtZ3JpZC13cmFwcGVyXCI+XG4gICAgPGRpdiBjbGFzcz1cIndlYXRoZXItZm9yZWNhc3QtdGl0bGVcIj4ke3RpdGxlfSBmb3JlY2FzdDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJ3ZWF0aGVyLWZvcmVjYXN0LWdyaWQtY29udGFpbmVyXCI+XG4gICAgICAke3Jvd3N9XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICBgO1xufTtcbiIsImltcG9ydCB7IEhvbWVBc3Npc3RhbnQgfSBmcm9tICdjdXN0b20tY2FyZC1oZWxwZXJzL2Rpc3QnO1xuaW1wb3J0IHsgZ2V0V2VhdGhlckljb24gfSBmcm9tICcuLi91dGlscy9oZWxwZXItcmVuZGVyJztcbmltcG9ydCB7IGlJY29uc0NvbmZpZywgaVRlcm1zIH0gZnJvbSAnLi4vYmFzZS9sb3ZlbGFjZS1iYXNlJztcbmltcG9ydCB7XG4gIGdldEVudGl0eUljb24sXG4gIGdldEVudGl0eU51bWVyaWNWYWx1ZSxcbiAgZ2V0RW50aXR5UmF3QXR0cmlidXRlLFxuICBnZXRFbnRpdHlSYXdWYWx1ZSxcbiAgZ2V0RW50aXR5VW5pdCxcbiAgZ2V0TG9jYWxlSW5mbyxcbiAgZ2V0V2luZERpcmVjdGlvbnMsXG59IGZyb20gJy4uL3V0aWxzL2hlbHBlcic7XG5pbXBvcnQgeyBpY29uUHJlY2lwaXRhdGlvbiwgaWNvblRlbXBlcmF0dXJlIH0gZnJvbSAnLi4vdXRpbHMvY29uc3QnO1xuaW1wb3J0IHsgaUZvcmVjYXN0RGF0YUl0ZW0sIHJlbmRlcldlYXRoZXJGb3JlY2FzdCB9IGZyb20gJy4uL3RlbXBsYXRlcy90LXdlYXRoZXItZm9yZWNhc3QnO1xuaW1wb3J0IHtcbiAgaURhaWx5Rm9yZWNhc3QsXG4gIGlIb3VybHlGb3JlY2FzdCxcbiAgaU1hcmluZURhaWx5Rm9yZWNhc3QsXG4gIGlNYXJpbmVIb3VybHlGb3JlY2FzdCxcbn0gZnJvbSAnLi4vdXRpbHMvY29uZmlnLXNjaGVtYSc7XG5cbmNvbnN0IGdldERlZmF1bHRJY29uID0gKG1ldHJpYzogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgaWYgKG1ldHJpYy5pbmNsdWRlcygndGVtcGVyYXR1cmUnKSkgcmV0dXJuIGljb25UZW1wZXJhdHVyZTtcbiAgaWYgKG1ldHJpYy5pbmNsdWRlcygncHJlY2lwaXRhdGlvbicpKSByZXR1cm4gaWNvblByZWNpcGl0YXRpb247XG4gIHJldHVybiAnbWRpOmhlbHAtY2lyY2xlLW91dGxpbmUnO1xufTtcblxuY29uc3QgYnVpbGRIb3VybHlGb3JlY2FzdFNsb3QgPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmc6IHN0cmluZyxcbiAgY3djTG9jV2luZERpcmVjdGlvbnMsXG4gIGZvcmVjYXN0OiBpSG91cmx5Rm9yZWNhc3QsXG4gIGZvcmVjYXN0VHlwZTogbnVtYmVyLFxuICBpY29uc0NvbmZpZzogaUljb25zQ29uZmlnLFxuICBzdW5TdGF0ZTogc3RyaW5nLFxuICBzbG90SWQ6IHN0cmluZyxcbikgPT4ge1xuICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGlGb3JlY2FzdERhdGFJdGVtPiA9IHt9O1xuICBjb25zdCBsb2NhbGVJbmZvID0gZ2V0TG9jYWxlSW5mbyhsYW5nKTtcblxuICBsZXQgZGF0ZXRpbWU6IERhdGU7XG5cbiAgLy8gQ29uZGl6aW9uZSBtZXRlb1xuICBpZiAoZm9yZWNhc3QuY29uZGl0aW9uICYmIGZvcmVjYXN0LmNvbmRpdGlvbltzbG90SWRdKSB7XG4gICAgcmVjb3JkWydjb25kaXRpb24nXSA9IHtcbiAgICAgIGltZzogZ2V0V2VhdGhlckljb24oZ2V0RW50aXR5UmF3VmFsdWUoaGFzcywgZm9yZWNhc3QuY29uZGl0aW9uW3Nsb3RJZF0pLCBpY29uc0NvbmZpZywgc3VuU3RhdGUpLFxuICAgIH07XG4gIH1cblxuICAvLyBXaW5kIEJlYXJpbmdcbiAgaWYgKGZvcmVjYXN0LndpbmRfYmVhcmluZyAmJiBmb3JlY2FzdC53aW5kX2JlYXJpbmdbc2xvdElkXSkge1xuICAgIHJlY29yZFsnd2luZF9iZWFyaW5nJ10gPSB7XG4gICAgICB2YWx1ZTogZ2V0V2luZERpcmVjdGlvbnMoZ2V0RW50aXR5UmF3VmFsdWUoaGFzcywgZm9yZWNhc3Qud2luZF9iZWFyaW5nW3Nsb3RJZF0pLCBjd2NMb2NXaW5kRGlyZWN0aW9ucyksXG4gICAgfTtcbiAgfVxuICAgXG4gIC8vIE1ldHJpY2hlIGRhIGdlc3RpcmVcbiAgY29uc3QgbWV0cmljcyA9IFtcbiAgICAndGVtcGVyYXR1cmUnLFxuICAgICd0ZW1wZXJhdHVyZV9mZWVsc2xpa2UnLFxuICAgICdwcmVjaXBpdGF0aW9uX2ludGVuc2l0eScsXG4gICAgJ3ByZWNpcGl0YXRpb25fcHJvYmFiaWxpdHknLFxuICAgICd3aW5kX3NwZWVkJyxcbiAgXTtcblxuICBtZXRyaWNzLmZvckVhY2goKG1ldHJpY0tleSkgPT4ge1xuICAgIGNvbnN0IG1ldHJpY1Nsb3RzID0gZm9yZWNhc3RbbWV0cmljS2V5XTtcbiAgICBjb25zdCBlbnRpdHlJZCA9IG1ldHJpY1Nsb3RzPy5bc2xvdElkXTtcbiAgICBsZXQgZGVjaW1hbHMgPSAwO1xuXG4gICAgaWYgKCFlbnRpdHlJZCkgcmV0dXJuO1xuXG4gICAgaWYgKG1ldHJpY0tleSA9PT0gJ3ByZWNpcGl0YXRpb25faW50ZW5zaXR5JykgZGVjaW1hbHMgPSAyO1xuXG4gICAgZGF0ZXRpbWUgPSBuZXcgRGF0ZShnZXRFbnRpdHlSYXdBdHRyaWJ1dGUoaGFzcywgZW50aXR5SWQsICdkYXRldGltZScpKTtcblxuICAgIHJlY29yZFttZXRyaWNLZXldID0ge1xuICAgICAgdmFsdWU6IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7XG4gICAgICAgIGVudGl0eUlkLCBoYXNzLCBsYW5nLCBkZWNpbWFscyxcbiAgICAgIH0pLFxuICAgICAgdW5pdDogZ2V0RW50aXR5VW5pdChoYXNzLCBlbnRpdHlJZCksXG4gICAgICBpbWc6IGdldEVudGl0eUljb24oaGFzcywgZW50aXR5SWQpIHx8IGdldERlZmF1bHRJY29uKG1ldHJpY0tleSksXG4gICAgfTtcbiAgfSk7XG5cbiAgaWYgKGRhdGV0aW1lICYmIE9iamVjdC5rZXlzKHJlY29yZCkubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGhvdXJUaW1lID0gZGF0ZXRpbWUudG9Mb2NhbGVUaW1lU3RyaW5nKGxvY2FsZUluZm8ubG9jYWxlLCB7XG4gICAgICBob3VyOiAnMi1kaWdpdCcsXG4gICAgICBtaW51dGU6ICcyLWRpZ2l0JyxcbiAgICAgIHRpbWVab25lOiBsb2NhbGVJbmZvLnRpbWV6b25lLFxuICAgIH0pO1xuXG4gICAgcmVjb3JkWydyZWZlcmVuY2UnXSA9IHtcbiAgICAgIHZhbHVlOiAoZm9yZWNhc3RUeXBlID09PSAwID8gaG91clRpbWUgOiBob3VyVGltZSksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiByZWNvcmQ7XG59O1xuXG5jb25zdCBidWlsZERhaWx5Rm9yZWNhc3RTbG90ID0gKFxuICBoYXNzOiBIb21lQXNzaXN0YW50LFxuICBsYW5nOiBzdHJpbmcsXG4gIGZvcmVjYXN0OiBpRGFpbHlGb3JlY2FzdCxcbiAgZm9yZWNhc3RUeXBlOiBudW1iZXIsXG4gIGljb25zQ29uZmlnOiBpSWNvbnNDb25maWcsXG4gIHN1blN0YXRlOiBzdHJpbmcsXG4gIHNsb3RJZDogc3RyaW5nLFxuKSA9PiB7XG4gIGNvbnN0IHJlY29yZDogUmVjb3JkPHN0cmluZywgaUZvcmVjYXN0RGF0YUl0ZW0+ID0ge307XG4gIGNvbnN0IGxvY2FsZUluZm8gPSBnZXRMb2NhbGVJbmZvKGxhbmcpO1xuXG4gIGxldCBkYXRldGltZTogRGF0ZTtcblxuICAvLyBHZXN0aW9uZSBjb25kaXppb25lIG1ldGVvXG4gIGlmIChmb3JlY2FzdC5jb25kaXRpb24gJiYgZm9yZWNhc3QuY29uZGl0aW9uW3Nsb3RJZF0pIHtcbiAgICByZWNvcmRbJ2NvbmRpdGlvbiddID0ge1xuICAgICAgaW1nOiBnZXRXZWF0aGVySWNvbihnZXRFbnRpdHlSYXdWYWx1ZShoYXNzLCBmb3JlY2FzdC5jb25kaXRpb25bc2xvdElkXSksIGljb25zQ29uZmlnLCBzdW5TdGF0ZSksXG4gICAgfTtcbiAgfVxuXG4gIC8vIExpc3RhIGZpc3NhIGRlbGxlIG1ldHJpY2hlIGRhIGNvbnNpZGVyYXJlXG4gIGNvbnN0IG1ldHJpY3MgPSBbXG4gICAgJ3RlbXBlcmF0dXJlX2hpZ2gnLFxuICAgICd0ZW1wZXJhdHVyZV9sb3cnLFxuICAgICdwcmVjaXBpdGF0aW9uX2ludGVuc2l0eScsXG4gICAgJ3ByZWNpcGl0YXRpb25fcHJvYmFiaWxpdHknLFxuICBdO1xuXG4gIG1ldHJpY3MuZm9yRWFjaCgobWV0cmljS2V5KSA9PiB7XG4gICAgY29uc3QgbWV0cmljU2xvdHMgPSBmb3JlY2FzdFttZXRyaWNLZXldO1xuICAgIGNvbnN0IGVudGl0eUlkID0gbWV0cmljU2xvdHM/LltzbG90SWRdO1xuICAgIGxldCBkZWNpbWFscyA9IDA7XG5cbiAgICBpZiAoIWVudGl0eUlkKSByZXR1cm47XG5cbiAgICBpZiAobWV0cmljS2V5ID09PSAncHJlY2lwaXRhdGlvbl9pbnRlbnNpdHknKSB7XG4gICAgICBkZWNpbWFscyA9IDI7XG4gICAgfVxuXG4gICAgZGF0ZXRpbWUgPSBuZXcgRGF0ZShnZXRFbnRpdHlSYXdBdHRyaWJ1dGUoaGFzcywgZW50aXR5SWQsICdkYXRldGltZScpKTtcbiAgICAvLyBjb25zb2xlLmRlYnVnKGA+Pj4gJHtlbnRpdHlJZH0gJHtsYW5nfSAke2dldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkLCBoYXNzLCBsYW5nIH0pfWApO1xuICAgIHJlY29yZFttZXRyaWNLZXldID0ge1xuICAgICAgdmFsdWU6IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7XG4gICAgICAgIGVudGl0eUlkLCBoYXNzLCBsYW5nLCBkZWNpbWFscyxcbiAgICAgIH0pLFxuICAgICAgdW5pdDogZ2V0RW50aXR5VW5pdChoYXNzLCBlbnRpdHlJZCksXG4gICAgICBpbWc6IGdldEVudGl0eUljb24oaGFzcywgZW50aXR5SWQpIHx8IGdldERlZmF1bHRJY29uKG1ldHJpY0tleSksXG4gICAgfTtcbiAgfSk7XG5cbiAgaWYgKGRhdGV0aW1lICYmIE9iamVjdC5rZXlzKHJlY29yZCkubGVuZ3RoID4gMCkge1xuICAgIC8vIEdpb3JubyBkZWxsYSBzZXR0aW1hbmEgYWJicmV2aWF0byAoZXMuIFwiTHVuXCIpXG4gICAgY29uc3Qgd2Vla2RheSA9IGRhdGV0aW1lLnRvTG9jYWxlRGF0ZVN0cmluZyhsb2NhbGVJbmZvLmxvY2FsZSwge1xuICAgICAgd2Vla2RheTogJ3Nob3J0JyxcbiAgICAgIHRpbWVab25lOiAnVVRDJywgLy8gZm9yemEgbGEgbGV0dHVyYSBzZW56YSBjb252ZXJzaW9uZSBsb2NhbGVcbiAgICB9KTtcblxuICAgIC8vIE9yYSBlIG1pbnV0aSAoZXMuIFwiMTM6NDVcIilcbiAgICBjb25zdCBob3VyZGF5ID0gZGF0ZXRpbWUudG9Mb2NhbGVUaW1lU3RyaW5nKGxvY2FsZUluZm8ubG9jYWxlLCB7XG4gICAgICBob3VyOiAnMi1kaWdpdCcsXG4gICAgICBtaW51dGU6ICcyLWRpZ2l0JyxcbiAgICAgIHRpbWVab25lOiBsb2NhbGVJbmZvLnRpbWV6b25lLFxuICAgIH0pO1xuXG4gICAgcmVjb3JkWydyZWZlcmVuY2UnXSA9IHtcbiAgICAgIHZhbHVlOiAoZm9yZWNhc3RUeXBlID09PSAwID8gd2Vla2RheS50b1VwcGVyQ2FzZSgpIDogaG91cmRheSksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiByZWNvcmQ7XG59O1xuXG5jb25zdCBidWlsZE1hcmluZURhaWx5Rm9yZWNhc3RTbG90ID0gKFxuICBoYXNzOiBIb21lQXNzaXN0YW50LFxuICBsYW5nOiBzdHJpbmcsXG4gIGN3Y0xvY1dpbmREaXJlY3Rpb25zLFxuICBmb3JlY2FzdDogaU1hcmluZURhaWx5Rm9yZWNhc3QsXG4gIGZvcmVjYXN0VHlwZTogbnVtYmVyLFxuICBpY29uc0NvbmZpZzogaUljb25zQ29uZmlnLFxuICBzdW5TdGF0ZTogc3RyaW5nLFxuICBzbG90SWQ6IHN0cmluZyxcbikgPT4ge1xuICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGlGb3JlY2FzdERhdGFJdGVtPiA9IHt9O1xuXG4gIGNvbnN0IGZpZWxkQ29sb3IgPSAoXG4gICAgd2F2ZUhlaWdodE1heDogbnVtYmVyLFxuICAgIHN3ZWxsV2F2ZUhlaWdodE1heDogbnVtYmVyLFxuICAgIHdpbmRXYXZlSGVpZ2h0TWF4OiBudW1iZXIsXG4gICkgPT4ge1xuICAgIC8vIPCfn6UgQmFuZGllcmEgcm9zc2Eg4oCTIGNvbmRpemlvbmkgcGVyaWNvbG9zZVxuICAgIGlmICh3YXZlSGVpZ2h0TWF4ID49IDEuOCkge1xuICAgICAgcmV0dXJuICdyZWQnO1xuICAgIH1cblxuICAgIGlmIChzd2VsbFdhdmVIZWlnaHRNYXggPj0gMS41ICYmIHdpbmRXYXZlSGVpZ2h0TWF4ID49IDAuOCkge1xuICAgICAgcmV0dXJuICdyZWQnO1xuICAgIH1cblxuICAgIC8vIPCfn6ggQmFuZGllcmEgZ2lhbGxhIOKAkyBjb25kaXppb25pIGRhIGF0dGVuemlvbmFyZVxuICAgIGlmICh3YXZlSGVpZ2h0TWF4ID49IDEuMCkge1xuICAgICAgcmV0dXJuICd5ZWxsb3cnO1xuICAgIH1cblxuICAgIGlmIChzd2VsbFdhdmVIZWlnaHRNYXggPj0gMC44KSB7XG4gICAgICByZXR1cm4gJ3llbGxvdyc7XG4gICAgfVxuXG4gICAgaWYgKHdpbmRXYXZlSGVpZ2h0TWF4ID49IDAuNikge1xuICAgICAgcmV0dXJuICd5ZWxsb3cnO1xuICAgIH1cblxuICAgIC8vIPCfn6kgQmFuZGllcmEgdmVyZGUg4oCTIGNvbmRpemlvbmkgc2ljdXJlXG4gICAgcmV0dXJuICdncmVlbic7XG4gIH07XG5cbiAgY29uc3QgbG9jYWxlSW5mbyA9IGdldExvY2FsZUluZm8obGFuZyk7XG5cbiAgbGV0IGRhdGV0aW1lOiBEYXRlO1xuXG4gIC8vIEdlc3Rpb25lIGNvbmRpemlvbmUgbWV0ZW9cbiAgaWYgKFxuICAgIGZvcmVjYXN0LndhdmVfaGVpZ2h0X21heCAmJlxuICAgIGZvcmVjYXN0LnN3ZWxsX3dhdmVfaGVpZ2h0X21heCAmJlxuICAgIGZvcmVjYXN0LndpbmRfd2F2ZV9oZWlnaHRfbWF4ICYmXG4gICAgZm9yZWNhc3Quc3dlbGxfd2F2ZV9oZWlnaHRfbWF4W3Nsb3RJZF0gJiZcbiAgICBmb3JlY2FzdC53aW5kX3dhdmVfaGVpZ2h0X21heFtzbG90SWRdXG4gICkge1xuICAgIHJlY29yZFsnY29uZGl0aW9uJ10gPSB7XG4gICAgICBpY29uOiAnbWRpOmZsYWctdmFyaWFudCcsXG4gICAgICBpY29uQ29sb3I6IGZpZWxkQ29sb3IoZm9yZWNhc3Qud2F2ZV9oZWlnaHRfbWF4W3Nsb3RJZF0sIGZvcmVjYXN0LnN3ZWxsX3dhdmVfaGVpZ2h0X21heFtzbG90SWRdLCBmb3JlY2FzdC53aW5kX3dhdmVfaGVpZ2h0X21heFtzbG90SWRdKSxcbiAgICB9O1xuICB9XG5cbiAgLy8gV2luZCBCZWFyaW5nXG4gIGlmIChmb3JlY2FzdC53YXZlX2RpcmVjdGlvbiAmJiBmb3JlY2FzdC53YXZlX2RpcmVjdGlvbltzbG90SWRdKSB7XG4gICAgcmVjb3JkWyd3YXZlX2RpcmVjdGlvbiddID0ge1xuICAgICAgdmFsdWU6IGdldFdpbmREaXJlY3Rpb25zKGdldEVudGl0eVJhd1ZhbHVlKGhhc3MsIGZvcmVjYXN0LndhdmVfZGlyZWN0aW9uW3Nsb3RJZF0pLCBjd2NMb2NXaW5kRGlyZWN0aW9ucyksXG4gICAgICBpY29uOiBnZXRFbnRpdHlSYXdWYWx1ZShoYXNzLCBmb3JlY2FzdC53YXZlX2RpcmVjdGlvbltzbG90SWRdKSxcbiAgICB9O1xuICB9XG5cbiAgLy8gTGlzdGEgZmlzc2EgZGVsbGUgbWV0cmljaGUgZGEgY29uc2lkZXJhcmVcbiAgY29uc3QgbWV0cmljcyA9IFtcbiAgICAnd2F2ZV9oZWlnaHRfbWF4JyxcbiAgICAnc3dlbGxfd2F2ZV9oZWlnaHRfbWF4JyxcbiAgICAnd2luZF93YXZlX2hlaWdodF9tYXgnLFxuICBdO1xuXG4gIG1ldHJpY3MuZm9yRWFjaCgobWV0cmljS2V5KSA9PiB7XG4gICAgY29uc3QgbWV0cmljU2xvdHMgPSBmb3JlY2FzdFttZXRyaWNLZXldO1xuICAgIGNvbnN0IGVudGl0eUlkID0gbWV0cmljU2xvdHM/LltzbG90SWRdO1xuICAgIGNvbnN0IGRlY2ltYWxzID0gMTtcblxuICAgIGlmICghZW50aXR5SWQpIHJldHVybjtcblxuICAgIGRhdGV0aW1lID0gbmV3IERhdGUoZ2V0RW50aXR5UmF3QXR0cmlidXRlKGhhc3MsIGVudGl0eUlkLCAnZGF0ZXRpbWUnKSk7XG4gICAgLy8gY29uc29sZS5kZWJ1ZyhgPj4+ICR7ZW50aXR5SWR9ICR7bGFuZ30gJHtnZXRFbnRpdHlOdW1lcmljVmFsdWUoeyBlbnRpdHlJZCwgaGFzcywgbGFuZyB9KX1gKTtcbiAgICByZWNvcmRbbWV0cmljS2V5XSA9IHtcbiAgICAgIHZhbHVlOiBnZXRFbnRpdHlOdW1lcmljVmFsdWUoe1xuICAgICAgICBlbnRpdHlJZCwgaGFzcywgbGFuZywgZGVjaW1hbHMsXG4gICAgICB9KSxcbiAgICAgIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgZW50aXR5SWQpLFxuICAgICAgaW1nOiBnZXRFbnRpdHlJY29uKGhhc3MsIGVudGl0eUlkKSB8fCBnZXREZWZhdWx0SWNvbihtZXRyaWNLZXkpLFxuICAgIH07XG4gIH0pO1xuXG4gIGlmIChkYXRldGltZSAmJiBPYmplY3Qua2V5cyhyZWNvcmQpLmxlbmd0aCA+IDApIHtcbiAgICAvLyBHaW9ybm8gZGVsbGEgc2V0dGltYW5hIGFiYnJldmlhdG8gKGVzLiBcIkx1blwiKVxuICAgIGNvbnN0IHdlZWtkYXkgPSBkYXRldGltZS50b0xvY2FsZURhdGVTdHJpbmcobG9jYWxlSW5mby5sb2NhbGUsIHtcbiAgICAgIHdlZWtkYXk6ICdzaG9ydCcsXG4gICAgICB0aW1lWm9uZTogJ1VUQycsIC8vIGZvcnphIGxhIGxldHR1cmEgc2VuemEgY29udmVyc2lvbmUgbG9jYWxlXG4gICAgfSk7XG5cbiAgICAvLyBPcmEgZSBtaW51dGkgKGVzLiBcIjEzOjQ1XCIpXG4gICAgY29uc3QgaG91cmRheSA9IGRhdGV0aW1lLnRvTG9jYWxlVGltZVN0cmluZyhsb2NhbGVJbmZvLmxvY2FsZSwge1xuICAgICAgaG91cjogJzItZGlnaXQnLFxuICAgICAgbWludXRlOiAnMi1kaWdpdCcsXG4gICAgICB0aW1lWm9uZTogbG9jYWxlSW5mby50aW1lem9uZSxcbiAgICB9KTtcblxuICAgIHJlY29yZFsncmVmZXJlbmNlJ10gPSB7XG4gICAgICB2YWx1ZTogKGZvcmVjYXN0VHlwZSA9PT0gMiA/IHdlZWtkYXkudG9VcHBlckNhc2UoKSA6IGhvdXJkYXkpLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4gcmVjb3JkO1xufTtcblxuY29uc3QgYnVpbGRXZWF0aGVyRm9yZWNhc3QgPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmc6IHN0cmluZyxcbiAgdGVybXM6IGlUZXJtcyxcbiAgZGFpbHlGb3JlY2FzdDogaURhaWx5Rm9yZWNhc3QsXG4gIGhvdXJseUZvcmVjYXN0OiBpSG91cmx5Rm9yZWNhc3QsXG4gIG1hcmluZURhaWx5Rm9yZWNhc3RzOiBpTWFyaW5lRGFpbHlGb3JlY2FzdCxcbiAgbWFyaW5lSG91cmx5Rm9yZWNhc3RzOiBpTWFyaW5lSG91cmx5Rm9yZWNhc3QsXG4gIGZvcmVjYXN0VHlwZTogKDAgfCAxIHwgMiB8IDMpLFxuICBpY29uc0NvbmZpZzogaUljb25zQ29uZmlnLFxuICBzdW5FbnRpdHlJZDogc3RyaW5nLFxuKSA9PiB7XG4gIGNvbnN0IHZvaWRSZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGlGb3JlY2FzdERhdGFJdGVtPltdID0gW107XG4gIFxuICBjb25zdCBzdW5TdGF0ZSA9IGdldEVudGl0eVJhd1ZhbHVlKGhhc3MsIHN1bkVudGl0eUlkKTtcblxuICBsZXQgZGFpbHlGb3JlY2FzdERhdGEgPSB2b2lkUmVjb3JkO1xuICBpZiAoZGFpbHlGb3JlY2FzdCkge1xuICAgIGNvbnN0IGRhaWx5U2xvdElkcyA9IE9iamVjdC5rZXlzKFxuICAgICAgZGFpbHlGb3JlY2FzdC5jb25kaXRpb24gfHxcbiAgICAgIGRhaWx5Rm9yZWNhc3QudGVtcGVyYXR1cmVfaGlnaCB8fCBkYWlseUZvcmVjYXN0LnRlbXBlcmF0dXJlX2xvdyB8fFxuICAgICAgZGFpbHlGb3JlY2FzdC5wcmVjaXBpdGF0aW9uX2ludGVuc2l0eSB8fCBkYWlseUZvcmVjYXN0LnByZWNpcGl0YXRpb25fcHJvYmFiaWxpdHkgfHxcbiAgICAgIHt9LFxuICAgICk7XG4gICAgZGFpbHlGb3JlY2FzdERhdGEgPSBkYWlseVNsb3RJZHMubWFwKChzbG90SWQpID0+IGJ1aWxkRGFpbHlGb3JlY2FzdFNsb3QoXG4gICAgICBoYXNzLFxuICAgICAgbGFuZyxcbiAgICAgIGRhaWx5Rm9yZWNhc3QsXG4gICAgICBmb3JlY2FzdFR5cGUsXG4gICAgICBpY29uc0NvbmZpZyxcbiAgICAgIHN1blN0YXRlLFxuICAgICAgc2xvdElkLFxuICAgICkpO1xuICB9XG5cbiAgbGV0IGhvdXJseWZvcmVjYXN0RGF0YSA9IHZvaWRSZWNvcmQ7XG4gIGlmIChob3VybHlGb3JlY2FzdCkge1xuICAgIGNvbnN0IGhvdXJseVNsb3RJZHMgPSBPYmplY3Qua2V5cyhcbiAgICAgIGhvdXJseUZvcmVjYXN0LmNvbmRpdGlvbiB8fFxuICAgICAgaG91cmx5Rm9yZWNhc3QudGVtcGVyYXR1cmUgfHwgaG91cmx5Rm9yZWNhc3QudGVtcGVyYXR1cmVfZmVlbHNsaWtlIHx8XG4gICAgICBob3VybHlGb3JlY2FzdC5wcmVjaXBpdGF0aW9uX2ludGVuc2l0eSB8fCBob3VybHlGb3JlY2FzdC5wcmVjaXBpdGF0aW9uX3Byb2JhYmlsaXR5IHx8XG4gICAgICB7fSxcbiAgICApO1xuICAgIGhvdXJseWZvcmVjYXN0RGF0YSA9IGhvdXJseVNsb3RJZHMubWFwKChzbG90SWQpID0+IGJ1aWxkSG91cmx5Rm9yZWNhc3RTbG90KFxuICAgICAgaGFzcyxcbiAgICAgIGxhbmcsXG4gICAgICB0ZXJtcy53aW5kRGlyZWN0aW9ucyxcbiAgICAgIGhvdXJseUZvcmVjYXN0LFxuICAgICAgZm9yZWNhc3RUeXBlLFxuICAgICAgaWNvbnNDb25maWcsXG4gICAgICBzdW5TdGF0ZSxcbiAgICAgIHNsb3RJZCxcbiAgICApKTtcbiAgfVxuXG4gIGxldCBtYXJpbmVEYWlseUZvcmVjYXN0RGF0YSA9IHZvaWRSZWNvcmQ7XG4gIGlmIChtYXJpbmVEYWlseUZvcmVjYXN0cykge1xuICAgIGNvbnN0IG1hcmluZURhaWx5U2xvdElkcyA9IE9iamVjdC5rZXlzKFxuICAgICAgbWFyaW5lRGFpbHlGb3JlY2FzdHMuc3dlbGxfd2F2ZV9oZWlnaHRfbWF4IHx8XG4gICAgICBtYXJpbmVEYWlseUZvcmVjYXN0cy53YXZlX2RpcmVjdGlvbiB8fCBtYXJpbmVEYWlseUZvcmVjYXN0cy53YXZlX2hlaWdodF9tYXggfHxcbiAgICAgIG1hcmluZURhaWx5Rm9yZWNhc3RzLndpbmRfd2F2ZV9oZWlnaHRfbWF4IHx8XG4gICAgICB7fSxcbiAgICApO1xuICAgIG1hcmluZURhaWx5Rm9yZWNhc3REYXRhID0gbWFyaW5lRGFpbHlTbG90SWRzLm1hcCgoc2xvdElkKSA9PiBidWlsZE1hcmluZURhaWx5Rm9yZWNhc3RTbG90KFxuICAgICAgaGFzcyxcbiAgICAgIGxhbmcsXG4gICAgICB0ZXJtcy53aW5kRGlyZWN0aW9ucyxcbiAgICAgIG1hcmluZURhaWx5Rm9yZWNhc3RzLFxuICAgICAgZm9yZWNhc3RUeXBlLFxuICAgICAgaWNvbnNDb25maWcsXG4gICAgICBzdW5TdGF0ZSxcbiAgICAgIHNsb3RJZCxcbiAgICApKTtcbiAgfVxuXG4gIHN3aXRjaCAoZm9yZWNhc3RUeXBlKSB7XG4gICAgY2FzZSAwOlxuICAgICAgcmV0dXJuIHJlbmRlcldlYXRoZXJGb3JlY2FzdChmb3JlY2FzdFR5cGUsIGRhaWx5Rm9yZWNhc3REYXRhKTtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gcmVuZGVyV2VhdGhlckZvcmVjYXN0KGZvcmVjYXN0VHlwZSwgaG91cmx5Zm9yZWNhc3REYXRhKTtcbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gcmVuZGVyV2VhdGhlckZvcmVjYXN0KGZvcmVjYXN0VHlwZSwgbWFyaW5lRGFpbHlGb3JlY2FzdERhdGEpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gcmVuZGVyV2VhdGhlckZvcmVjYXN0KGZvcmVjYXN0VHlwZSwgdm9pZFJlY29yZCk7XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IGJ1aWxkV2VhdGhlckZvcmVjYXN0O1xuIiwiaW1wb3J0IHsgSG9tZUFzc2lzdGFudCB9IGZyb20gJ2N1c3RvbS1jYXJkLWhlbHBlcnMvZGlzdCc7XG5pbXBvcnQgeyBpVGVybXMgfSBmcm9tICcuLi9iYXNlL2xvdmVsYWNlLWJhc2UnO1xuaW1wb3J0IHJlbmRlckNhbWVyYSBmcm9tICcuLi90ZW1wbGF0ZXMvdC1jYW1lcmEnO1xuXG5jb25zdCBidWlsZENhbWVyYSA9IChcbiAgaGFzczogSG9tZUFzc2lzdGFudCxcbiAgbGFuZzogc3RyaW5nLFxuICB0ZXJtczogaVRlcm1zLFxuICBoYW5kbGVQb3B1cDogKGU6IEV2ZW50LCBlbnRpdHlJZDogc3RyaW5nKSA9PiB2b2lkLFxuICBjYW1lcmFJZDogc3RyaW5nLFxuKSA9PiB7XG4gIGNvbnN0IGNhbWVyYSA9IGNhbWVyYUlkICYmIGhhc3Muc3RhdGVzW2NhbWVyYUlkXTtcblxuICBjb25zdCBlbnRpdHlQaWN0dXJlID0gY2FtZXJhPy5hdHRyaWJ1dGVzPy5lbnRpdHlfcGljdHVyZTtcbiAgY29uc3QgZnJpZW5kbHlOYW1lID0gY2FtZXJhPy5hdHRyaWJ1dGVzPy5mcmllbmRseV9uYW1lID8/IGNhbWVyYUlkO1xuXG4gIHJldHVybiByZW5kZXJDYW1lcmEoaGFuZGxlUG9wdXAsIGNhbWVyYUlkLCBlbnRpdHlQaWN0dXJlLCBmcmllbmRseU5hbWUpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgYnVpbGRDYW1lcmE7XG4iLCJpbXBvcnQgeyBodG1sIH0gZnJvbSAnbGl0JztcblxuY29uc3QgcmVuZGVyQ2FtZXJhID0gKFxuICBoYW5kbGVQb3B1cDogKGU6IEV2ZW50LCBlbnRpdHlJZDogc3RyaW5nKSA9PiB2b2lkLFxuICBjYW1lcmFJZDogc3RyaW5nLFxuICBjYW1lcmFQaWN0dXJlOiBzdHJpbmcsXG4gIGZyaWVuZGx5TmFtZTogc3RyaW5nLFxuKSA9PiB7XG4gIGlmICghY2FtZXJhUGljdHVyZSkgcmV0dXJuIGh0bWxgYDtcblxuICByZXR1cm4gaHRtbGBcbiAgICA8ZGl2IFxuICAgICAgY2xhc3M9XCJjYW1lcmEtY29udGFpbmVyXCJcbiAgICAgIEBjbGljaz0keyhlOiBFdmVudCkgPT4gaGFuZGxlUG9wdXAoZSwgY2FtZXJhSWQpfVxuICAgID5cbiAgICAgIDxkaXYgY2xhc3M9XCJjYW1lcmEtaW1hZ2VcIj5cbiAgICAgICAgPGltZyBcbiAgICAgICAgICBzcmM9XCIke2NhbWVyYVBpY3R1cmV9XCIgXG4gICAgICAgICAgYWx0PVwiJHtmcmllbmRseU5hbWV9XCJcbiAgICAgICAgICBsb2FkaW5nPVwibGF6eVwiXG4gICAgICAgIC8+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYDtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IHJlbmRlckNhbWVyYTtcbiIsIi8qIGVzbGludC1kaXNhYmxlIGNhbWVsY2FzZSAqL1xuLyogZXNsaW50LWRpc2FibGUgbm8tZWxzZS1yZXR1cm4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG9iamVjdC1jdXJseS1uZXdsaW5lICovXG5pbXBvcnQgeyBIb21lQXNzaXN0YW50IH0gZnJvbSAnY3VzdG9tLWNhcmQtaGVscGVycy9kaXN0JztcbmltcG9ydCB7IGlBaXJRdWFsaXR5IH0gZnJvbSAnLi4vdXRpbHMvY29uZmlnLXNjaGVtYSc7XG5pbXBvcnQgeyBnZXRFbnRpdHlOdW1lcmljVmFsdWUsIGdldEVudGl0eVJhd1ZhbHVlLCBnZXRFbnRpdHlVbml0IH0gZnJvbSAnLi4vdXRpbHMvaGVscGVyJztcbmltcG9ydCB7IHJlbmRlcldlYXRoZXJQcmVzZW50IH0gZnJvbSAnLi4vdGVtcGxhdGVzL3QtcHJlc2VudCc7XG5cbi8qKlxuICogUmVzdGl0dWlzY2UgdW4gY29sb3JlIChpbiBmb3JtYXRvIGhleCkgaW4gYmFzZSBhbCB2YWxvcmUgZGVsbCdpbmRpY2UgRVBBIEFRSS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBhcWkgLSBWYWxvcmUgQVFJIGNvbXByZXNvIHRyYSAwIGUgNTAwXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIENvbG9yZSBlc2FkZWNpbWFsZSBhc3NvY2lhdG8gYWxsYSBmYXNjaWEgQVFJXG4gKi9cbmZ1bmN0aW9uIGdldEFRSUNvbG9yKGFxaTogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKGFxaSA8PSA1MCkge1xuICAgIHJldHVybiAnIzAwOTk2Nic7IC8vIFZlcmRlIChCdW9uYSlcbiAgfSBlbHNlIGlmIChhcWkgPD0gMTAwKSB7XG4gICAgcmV0dXJuICcjZmZkZTMzJzsgLy8gR2lhbGxvIChNb2RlcmF0YSlcbiAgfSBlbHNlIGlmIChhcWkgPD0gMTUwKSB7XG4gICAgcmV0dXJuICcjZmY5OTMzJzsgLy8gQXJhbmNpb25lIChTZW5zaWJpbGkpXG4gIH0gZWxzZSBpZiAoYXFpIDw9IDIwMCkge1xuICAgIHJldHVybiAnI2NjMDAzMyc7IC8vIFJvc3NvIChOb24gc2FsdXRhcmUpXG4gIH0gZWxzZSBpZiAoYXFpIDw9IDMwMCkge1xuICAgIHJldHVybiAnIzY2MDA5OSc7IC8vIFZpb2xhIChNb2x0byBub24gc2FsdXRhcmUpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuICcjN2UwMDIzJzsgLy8gTWFycm9uZSBzY3VybyAoUGVyaWNvbG9zYSlcbiAgfVxufVxuXG5jb25zdCBidWlsZEFpclF1YWxpdHkgPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmd1YWdlOiBzdHJpbmcsXG4gIGFpcnF1YWxpdHk6IGlBaXJRdWFsaXR5LFxuKSA9PiB7XG4gIGNvbnN0IGxhbmcgPSBsYW5ndWFnZSB8fCBoYXNzLnNlbGVjdGVkTGFuZ3VhZ2UgfHwgaGFzcy5sYW5ndWFnZTtcblxuICBjb25zdCBwbTI1ID0gZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IGFpcnF1YWxpdHkucG0yNSwgaGFzcywgbGFuZzogbGFuZ3VhZ2UsIGRlY2ltYWxzOiAwIH0pO1xuICBjb25zdCBwbTEwID0gZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IGFpcnF1YWxpdHkucG0xMCwgaGFzcywgbGFuZzogbGFuZ3VhZ2UsIGRlY2ltYWxzOiAwIH0pO1xuICBjb25zdCBvMyA9IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBhaXJxdWFsaXR5Lm8zLCBoYXNzLCBsYW5nOiBsYW5ndWFnZSwgZGVjaW1hbHM6IDEgfSk7XG4gIGNvbnN0IG5vMiA9IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBhaXJxdWFsaXR5Lm5vMiwgaGFzcywgbGFuZzogbGFuZ3VhZ2UsIGRlY2ltYWxzOiAwIH0pO1xuICBjb25zdCBjbyA9IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBhaXJxdWFsaXR5LmNvLCBoYXNzLCBsYW5nOiBsYW5ndWFnZSwgZGVjaW1hbHM6IDEgfSk7XG4gIGNvbnN0IHNvMiA9IGdldEVudGl0eU51bWVyaWNWYWx1ZSh7IGVudGl0eUlkOiBhaXJxdWFsaXR5LnNvMiwgaGFzcywgbGFuZzogbGFuZ3VhZ2UsIGRlY2ltYWxzOiAwIH0pO1xuICBjb25zdCBlcGFfYXFpID0gZ2V0RW50aXR5TnVtZXJpY1ZhbHVlKHsgZW50aXR5SWQ6IGFpcnF1YWxpdHkuZXBhX2FxaSwgaGFzcywgbGFuZzogbGFuZ3VhZ2UsIGRlY2ltYWxzOiAwIH0pO1xuICBjb25zdCBlcGFfcHJpbWFyeV9wb2xsdXRhbnQgPSBnZXRFbnRpdHlSYXdWYWx1ZShoYXNzLCBhaXJxdWFsaXR5LmVwYV9wcmltYXJ5X3BvbGx1dGFudCk7XG5cbiAgY29uc3QgYWlyUXVhbGl0eURhdGEgPSB7XG4gICAgcG0yNToge1xuICAgICAgdmFsdWU6IChwbTI1ID8gYHBtMi41ICR7cG0yNX1gIDogcG0yNSksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIGFpcnF1YWxpdHkucG0yNSkgfHwgJ8K1Zy9twrMnLFxuICAgICAgaWNvbjogJ21kaTp3ZWF0aGVyLWhhenknLFxuICAgIH0sXG4gICAgcG0xMDoge1xuICAgICAgdmFsdWU6IChwbTEwID8gYHBtMTAgJHtwbTEwfWAgOiBwbTEwKSxcbiAgICAgIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgYWlycXVhbGl0eS5wbTEwKSB8fCAnwrVnL23CsycsXG4gICAgICBpY29uOiAnbWRpOndlYXRoZXItaGF6eScsXG4gICAgfSxcbiAgICBvMzoge1xuICAgICAgdmFsdWU6IChvMyA/IGBvMyAke28zfWAgOiBvMyksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIGFpcnF1YWxpdHkubzMpIHx8ICfCtWcvbcKzJyxcbiAgICAgIGljb246ICdtZGk6bW9sZWN1bGUnLFxuICAgIH0sXG4gICAgbm8yOiB7XG4gICAgICB2YWx1ZTogKG5vMiA/IGBubzIgJHtubzJ9YCA6IG5vMiksXG4gICAgICB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIGFpcnF1YWxpdHkubm8yKSB8fCAnwrVnL23CsycsXG4gICAgICBpY29uOiAnbWRpOm1vbGVjdWxlJyxcbiAgICB9LFxuICAgIGNvOiB7XG4gICAgICB2YWx1ZTogKGNvID8gYGNvICR7Y299YCA6IGNvKSxcbiAgICAgIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgYWlycXVhbGl0eS5jbykgfHwgJ8K1Zy9twrMnLFxuICAgICAgaWNvbjogJ21kaTptb2xlY3VsZScsXG4gICAgfSxcbiAgICBzbzI6IHtcbiAgICAgIHZhbHVlOiAoc28yID8gYHNvMiAke3NvMn1gIDogc28yKSxcbiAgICAgIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgYWlycXVhbGl0eS5zbzIpIHx8ICfCtWcvbcKzJyxcbiAgICAgIGljb246ICdtZGk6bW9sZWN1bGUnLFxuICAgIH0sXG4gICAgZXBhX2FxaToge1xuICAgICAgdmFsdWU6IChlcGFfYXFpID8gYEFpciBRdWFsaXR5IEluZGV4ICR7ZXBhX2FxaX1gIDogZXBhX2FxaSksXG4gICAgICAvLyB1bml0OiBnZXRFbnRpdHlVbml0KGhhc3MsIGFpcnF1YWxpdHkuZXBhX2FxaSkgfHwgJ8K1Zy9twrMnLFxuICAgICAgaWNvbjogJ21kaTp3ZWF0aGVyLWhhenknLFxuICAgICAgaWNvbl9jb2xvcjogZ2V0QVFJQ29sb3IoTnVtYmVyKGdldEVudGl0eVJhd1ZhbHVlKGhhc3MsIGFpcnF1YWxpdHkuZXBhX2FxaSkpKSxcbiAgICB9LFxuICAgIGVwYV9wcmltYXJ5X3BvbGx1dGFudDoge1xuICAgICAgdmFsdWU6IChlcGFfcHJpbWFyeV9wb2xsdXRhbnQgPyBgUHJpbWFyeSAke2VwYV9wcmltYXJ5X3BvbGx1dGFudH1gIDogZXBhX3ByaW1hcnlfcG9sbHV0YW50KSxcbiAgICAgIC8vIHVuaXQ6IGdldEVudGl0eVVuaXQoaGFzcywgYWlycXVhbGl0eS5lcGFfYXFpKSB8fCAnwrVnL23CsycsXG4gICAgICBpY29uOiAnbWRpOndlYXRoZXItaGF6eScsXG4gICAgfSxcbiAgfTtcblxuICByZXR1cm4gcmVuZGVyV2VhdGhlclByZXNlbnQoYWlyUXVhbGl0eURhdGEsIGxhbmcpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgYnVpbGRBaXJRdWFsaXR5O1xuIiwiLyogZXNsaW50LWRpc2FibGUgY2FtZWxjYXNlICovXG4vKiBlc2xpbnQtZGlzYWJsZSBxdW90ZS1wcm9wcyAqL1xuaW1wb3J0IHsgSG9tZUFzc2lzdGFudCB9IGZyb20gJ2N1c3RvbS1jYXJkLWhlbHBlcnMvZGlzdCc7XG5pbXBvcnQgeyBpVGVybXMgfSBmcm9tICcuLi9iYXNlL2xvdmVsYWNlLWJhc2UnO1xuaW1wb3J0IHsgaURQQ0FsZXJ0IH0gZnJvbSAnLi4vdXRpbHMvY29uZmlnLXNjaGVtYSc7XG5pbXBvcnQgcmVuZGVyTWV0ZW9EUENhbGFybSwgeyBpV2VhdGhlck1ldGVvRFBDQWxhcm1EYXRhSW50ZXJmYWNlIH0gZnJvbSAnLi4vdGVtcGxhdGVzL3QtbWV0ZW9hbGFybSc7XG5pbXBvcnQgeyBnZXRMb2NhbGVJbmZvIH0gZnJvbSAnLi4vdXRpbHMvaGVscGVyJztcblxuY29uc3QgZ2V0RWZmZWN0aXZlTGFiZWwgPSAoZWZmZWN0aXZlOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgZWZmZWN0aXZlRGF0ZXRpbWUgPSBuZXcgRGF0ZShlZmZlY3RpdmUpO1xuICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuXG4gIC8vIFJlc2V0IGRlbGwnb3JhIHBlciBjb25mcm9udG8gc29sbyBhIGxpdmVsbG8gZGkgZ2lvcm5vXG4gIGNvbnN0IHRvZGF5ID0gbmV3IERhdGUobm93LmdldEZ1bGxZZWFyKCksIG5vdy5nZXRNb250aCgpLCBub3cuZ2V0RGF0ZSgpKTtcbiAgY29uc3QgZWZmZWN0aXZlRGF0ZSA9IG5ldyBEYXRlKGVmZmVjdGl2ZURhdGV0aW1lLmdldEZ1bGxZZWFyKCksIGVmZmVjdGl2ZURhdGV0aW1lLmdldE1vbnRoKCksIGVmZmVjdGl2ZURhdGV0aW1lLmdldERhdGUoKSk7XG5cbiAgY29uc3QgbXNJbkRheSA9IDI0ICogNjAgKiA2MCAqIDEwMDA7XG4gIGNvbnN0IGRheURpZmZlcmVuY2UgPSBNYXRoLnJvdW5kKChlZmZlY3RpdmVEYXRlLmdldFRpbWUoKSAtIHRvZGF5LmdldFRpbWUoKSkgLyBtc0luRGF5KTtcblxuICBsZXQgZWZmZWN0aXZlTGFiZWw6ICdvZ2dpJyB8ICdkb21hbmknIHwgJ2RvcG9kb21hbmknIHwgdW5kZWZpbmVkO1xuXG4gIGlmIChkYXlEaWZmZXJlbmNlID09PSAwKSB7XG4gICAgZWZmZWN0aXZlTGFiZWwgPSAnb2dnaSc7XG4gIH0gZWxzZSBpZiAoZGF5RGlmZmVyZW5jZSA9PT0gMSkge1xuICAgIGVmZmVjdGl2ZUxhYmVsID0gJ2RvbWFuaSc7XG4gIH0gZWxzZSBpZiAoZGF5RGlmZmVyZW5jZSA9PT0gMikge1xuICAgIGVmZmVjdGl2ZUxhYmVsID0gJ2RvcG9kb21hbmknO1xuICB9IGVsc2Uge1xuICAgIGVmZmVjdGl2ZUxhYmVsID0gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiBlZmZlY3RpdmVMYWJlbDtcbn07XG5cbmNvbnN0IGJ1aWxkTWV0ZW9BbGFybURhdGEgPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmc6IHN0cmluZyxcbiAgdGVybXM6IGlUZXJtcyxcbiAgbWV0ZW9hbGFybUlkOiBzdHJpbmcsXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuKTogUmVjb3JkPHN0cmluZywgaVdlYXRoZXJNZXRlb0RQQ0FsYXJtRGF0YUludGVyZmFjZT4gPT4ge1xuICBjb25zdCBldmVudEljb246IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgJ3dpbmQnOiAnbWRpOndlYXRoZXItd2luZHknLFxuICAgICdzbm93LWljZSc6ICdtZGk6c25vd2ZsYWtlLWFsZXJ0JyxcbiAgICAndGh1bmRlcnN0b3JtJzogJ21kaTp3ZWF0aGVyLWxpZ2h0bmluZycsXG4gICAgJ2ZvZyc6ICdtZGk6d2VhdGhlci1mb2cnLFxuICAgICdoaWdoLXRlbXBlcmF0dXJlJzogJ21kaTp3ZWF0aGVyLXN1bm55LWFsZXJ0JyxcbiAgICAnbG93LXRlbXBlcmF0dXJlJzogJ21kaTp0aGVybW9tZXRlci1sb3cnLFxuICAgICdjb2FzdGFsLWV2ZW50JzogJ21kaTpob21lLWZsb29kJyxcbiAgICAnZm9yZXN0LWZpcmUnOiAnbWRpOnBpbmUtdHJlZS1maXJlJyxcbiAgICAnYXZhbGFuY2hlJzogJ21kaTppbWFnZS1maWx0ZXItaGRyJyxcbiAgICAncmFpbic6ICdtZGk6d2VhdGhlci1wb3VyaW5nJyxcbiAgICAnZmxvb2QnOiAnbWRpOmhvbWUtZmxvb2QnLFxuICAgICdyYWluLWZsb29kJzogJ21kaTp3ZWF0aGVyLXBvdXJpbmcnLFxuICAgICdtYXJpbmUtaGF6YXJkJzogJ21kaTp3ZWF0aGVyLWh1cnJpY2FuZScsXG4gICAgJ2Ryb3VnaHQnOiAnbWRpOndhdGVyLW9mZicsXG4gIH07XG5cbiAgY29uc3QgZXZlbnRJY29uQ29sb3I6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgZ3JlZW46ICdncmVlbicsXG4gICAgeWVsbG93OiAnI2ZmYTYwMCcsXG4gICAgb3JhbmdlOiAnb3JhbmdlJyxcbiAgICByZWQ6ICdyZWQnLFxuICB9O1xuXG4gIGNvbnN0IG1ldGVvYWxhcm0gPSBtZXRlb2FsYXJtSWQgJiYgaGFzcy5zdGF0ZXNbbWV0ZW9hbGFybUlkXTtcbiAgaWYgKCFtZXRlb2FsYXJtPy5hdHRyaWJ1dGVzKSByZXR1cm4ge307XG5cbiAgY29uc3QgZnBjRGF0YTogUmVjb3JkPHN0cmluZywgaVdlYXRoZXJNZXRlb0RQQ0FsYXJtRGF0YUludGVyZmFjZT4gPSB7fTtcblxuICBpZiAobWV0ZW9hbGFybS5zdGF0ZSA9PT0gJ29uJyAmJiBtZXRlb2FsYXJtLmF0dHJpYnV0ZXMpIHtcbiAgICBjb25zdCBsb2NhbGVJbmZvID0gZ2V0TG9jYWxlSW5mbyhsYW5nKTtcbiAgICBjb25zdCB7XG4gICAgICBldmVudCxcbiAgICAgIHNldmVyaXR5LFxuICAgICAgYXdhcmVuZXNzX3R5cGUsXG4gICAgICBhd2FyZW5lc3NfbGV2ZWwsXG4gICAgICBlZmZlY3RpdmUsXG4gICAgfSA9IG1ldGVvYWxhcm0uYXR0cmlidXRlcztcblxuICAgIGNvbnN0IGF3YXJlbmVzc1R5cGUgPSBhd2FyZW5lc3NfdHlwZT8uc3BsaXQoJzsnKVsxXT8udHJpbSgpLnRvTG93ZXJDYXNlKCkgfHwgJyc7XG4gICAgY29uc3QgYXdhcmVuZXNzTGV2ZWwgPSBhd2FyZW5lc3NfbGV2ZWw/LnNwbGl0KCc7JylbMV0/LnRyaW0oKS50b0xvd2VyQ2FzZSgpIHx8ICcnO1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGV2ZW50IHx8ICcnO1xuICAgIGNvbnN0IHNldmVyaXR5TGV2ZWwgPSBzZXZlcml0eT8uc3BsaXQoJzsnKVsxXT8udHJpbSgpIHx8ICcnO1xuICAgIGNvbnN0IGVmZmVjdGl2ZURhdGV0aW1lID0gZ2V0RWZmZWN0aXZlTGFiZWwoZWZmZWN0aXZlKTtcblxuICAgIGZwY0RhdGFbJ21ldGVvYWxhcm0nXSA9IHtcbiAgICAgIGV2ZW50OiBldmVudE5hbWUsXG4gICAgICBzZXZlcml0eTogc2V2ZXJpdHlMZXZlbCxcbiAgICAgIGljb246IGV2ZW50SWNvblthd2FyZW5lc3NUeXBlXSB8fCAnbWRpOmFsZXJ0JyxcbiAgICAgIGljb25fY29sb3I6IGV2ZW50SWNvbkNvbG9yW2F3YXJlbmVzc0xldmVsXSB8fCAnZ3JleScsXG4gICAgICBkYXRldGltZTogKG5ldyBEYXRlKGVmZmVjdGl2ZSkpLnRvTG9jYWxlRGF0ZVN0cmluZyhsb2NhbGVJbmZvLmxvY2FsZSwge1xuICAgICAgICB3ZWVrZGF5OiAnc2hvcnQnLFxuICAgICAgICB0aW1lWm9uZTogbG9jYWxlSW5mby50aW1lem9uZSxcbiAgICAgIH0pLnRvTG9jYWxlVXBwZXJDYXNlKCksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBmcGNEYXRhO1xufTtcblxuY29uc3QgYnVpbGREUENBbGFybURhdGEgPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmc6IHN0cmluZyxcbiAgdGVybXM6IGlUZXJtcyxcbiAgZHBjYWxhcm06IGlEUENBbGVydCxcbikgPT4ge1xuICBpZiAoIWRwY2FsYXJtKSByZXR1cm4ge307XG5cbiAgY29uc3QgbG9jYWxlSW5mbyA9IGdldExvY2FsZUluZm8obGFuZyk7XG4gIGNvbnN0IGV2ZW50SWNvbkNvbG9yID0ge1xuICAgIDA6ICdncmF5JyxcbiAgICAxOiAnZ3JlZW4nLFxuICAgIDI6ICcjZmZhNjAwJyxcbiAgICAzOiAnb3JhbmdlJyxcbiAgICA0OiAncmVkJyxcbiAgfTtcblxuICBjb25zdCBzb3VyY2VzID0gWyd0aHVuZGVyc3Rvcm1zJywgJ2h5ZHJhdWxpYycsICdoeWRyb2dlb2xvZ2ljYWwnXTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgY29uc3QgZnBjRGF0YTogUmVjb3JkPHN0cmluZywgaVdlYXRoZXJNZXRlb0RQQ0FsYXJtRGF0YUludGVyZmFjZT4gPSB7fTtcblxuICBzb3VyY2VzLmZvckVhY2goKGtleSkgPT4ge1xuICAgIGNvbnN0IGVudGl0eUlkID0gZHBjYWxhcm1ba2V5IGFzIGtleW9mIGlEUENBbGVydF07XG4gICAgY29uc3QgZW50aXR5ID0gZW50aXR5SWQgJiYgaGFzcy5zdGF0ZXNbZW50aXR5SWRdO1xuXG4gICAgaWYgKGVudGl0eSAmJiBlbnRpdHkuc3RhdGUgPT09ICdvbicgJiYgZW50aXR5LmF0dHJpYnV0ZXMpIHtcbiAgICAgIGNvbnN0IHsgbGV2ZWwsIGluZm8sIGljb24gfSA9IGVudGl0eS5hdHRyaWJ1dGVzO1xuICAgICAgZnBjRGF0YVtrZXldID0ge1xuICAgICAgICBldmVudDogaW5mbyxcbiAgICAgICAgc2V2ZXJpdHk6IGxldmVsLFxuICAgICAgICBpY29uLFxuICAgICAgICBpY29uX2NvbG9yOiBldmVudEljb25Db2xvcltsZXZlbF0sXG4gICAgICAgIGRhdGV0aW1lOiAobmV3IERhdGUoKSkudG9Mb2NhbGVEYXRlU3RyaW5nKGxvY2FsZUluZm8ubG9jYWxlLCB7XG4gICAgICAgICAgd2Vla2RheTogJ3Nob3J0JyxcbiAgICAgICAgICB0aW1lWm9uZTogbG9jYWxlSW5mby50aW1lem9uZSxcbiAgICAgICAgfSkudG9Mb2NhbGVVcHBlckNhc2UoKSxcbiAgICAgIH07XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGZwY0RhdGE7XG59O1xuXG5jb25zdCBidWlsZE1ldGVvRFBDYWxhcm0gPSAoXG4gIGhhc3M6IEhvbWVBc3Npc3RhbnQsXG4gIGxhbmc6IHN0cmluZyxcbiAgdGVybXM6IGlUZXJtcyxcbiAgbWV0ZW9hbGFybUlkOiBzdHJpbmcsXG4gIGRwY2FsYXJtOiBpRFBDQWxlcnQsIFxuKSA9PiB7XG4gIGNvbnN0IGFsYXJtc0RhdGEgPSB7IC4uLmJ1aWxkTWV0ZW9BbGFybURhdGEoaGFzcywgbGFuZywgdGVybXMsIG1ldGVvYWxhcm1JZCksIC4uLmJ1aWxkRFBDQWxhcm1EYXRhKGhhc3MsIGxhbmcsIHRlcm1zLCBkcGNhbGFybSkgfTtcbiAgLy8gY29uc29sZS5kZWJ1ZygnYnVpbGRNZXRlb0RQQ2FsYXJtJywgYWxhcm1zRGF0YSk7XG4gIHJldHVybiByZW5kZXJNZXRlb0RQQ2FsYXJtKGFsYXJtc0RhdGEpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgYnVpbGRNZXRlb0RQQ2FsYXJtO1xuIiwiaW1wb3J0IHsgaHRtbCB9IGZyb20gJ2xpdCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgaVdlYXRoZXJNZXRlb0RQQ0FsYXJtRGF0YUludGVyZmFjZSB7XG4gIGV2ZW50Pzogc3RyaW5nLFxuICBzZXZlcml0eT86IHN0cmluZyxcbiAgaWNvbj86IHN0cmluZyxcbiAgaWNvbl9jb2xvcj86IHN0cmluZyxcbiAgZGF0ZXRpbWU/OiBzdHJpbmcsXG59XG5cbmNvbnN0IHJlbmRlck1ldGVvRFBDYWxhcm0gPSAoXG4gIG1ldGVvRFBDYWxhcm1EYXRhOiBSZWNvcmQ8c3RyaW5nLCBpV2VhdGhlck1ldGVvRFBDQWxhcm1EYXRhSW50ZXJmYWNlPiB8IG51bGwsXG4pID0+IHtcbiAgaWYgKCFtZXRlb0RQQ2FsYXJtRGF0YSB8fCBPYmplY3Qua2V5cyhtZXRlb0RQQ2FsYXJtRGF0YSkubGVuZ3RoID09PSAwKSByZXR1cm4gaHRtbGBgO1xuXG4gIHJldHVybiBodG1sYFxuICA8ZGl2IGNsYXNzPVwibWV0ZW9kY3BhbGFybS1ncmlkLWNvbnRhaW5lclwiPlxuICAgICR7T2JqZWN0LmVudHJpZXMobWV0ZW9EUENhbGFybURhdGEpLm1hcCgoW2tleSwgZGF0YV0pID0+IGh0bWxgXG4gICAgICA8ZGl2IGNsYXNzPVwibWV0ZW9kY3BhbGFybS1ncm91cFwiPlxuICAgICAgICA8aGEtaWNvbiBpY29uPVwiJHtkYXRhLmljb259XCIgc3R5bGU9XCJjb2xvcjogJHtkYXRhLmljb25fY29sb3J9O1wiPjwvaGEtaWNvbj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1ldGVvZGNwYWxhcm0tbGFiZWxcIj4ke2RhdGEuZGF0ZXRpbWV9PC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtZXRlb2RjcGFsYXJtLWxhYmVsXCI+JHtkYXRhLmV2ZW50fTwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgYCl9XG4gIDwvZGl2PlxuICBgO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgcmVuZGVyTWV0ZW9EUENhbGFybTtcbiIsIi8qIGVzbGludC1kaXNhYmxlIG5vLXVuZGVyc2NvcmUtZGFuZ2xlICovXG5pbXBvcnQgeyBodG1sLCBUZW1wbGF0ZVJlc3VsdCB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBjdXN0b21FbGVtZW50IH0gZnJvbSAnbGl0L2RlY29yYXRvcnMuanMnO1xuXG5pbXBvcnQgeyBMb3ZlbGFjZUJhc2VFbGVtZW50LCBwcmVsb2FkUmVzb3VyY2VzIH0gZnJvbSAnLi9iYXNlL2xvdmVsYWNlLWJhc2UnO1xuXG5pbXBvcnQgYnVpbGRXZWF0aGVyU3VtbWFyeSBmcm9tICcuL2J1aWxkZXIvYi1zdW1tYXJ5JztcbmltcG9ydCBidWlsZFdlYXRoZXJQcmVzZW50IGZyb20gJy4vYnVpbGRlci9iLXByZXNlbnQnO1xuaW1wb3J0IGJ1aWxkVWx0cmF2aW9sZXQgZnJvbSAnLi9idWlsZGVyL2ItdWx0cmF2aW9sZXQnO1xuaW1wb3J0IGJ1aWxkUG9sbGVuIGZyb20gJy4vYnVpbGRlci9iLXBvbGxlbic7XG5pbXBvcnQgYnVpbGRXZWF0aGVyRm9yZWNhc3QgZnJvbSAnLi9idWlsZGVyL2Itd2VhdGhlci1mb3JlY2FzdCc7XG5pbXBvcnQgYnVpbGRDYW1lcmEgZnJvbSAnLi9idWlsZGVyL2ItY2FtZXJhJztcbmltcG9ydCBidWlsZEFpclF1YWxpdHkgZnJvbSAnLi9idWlsZGVyL2ItYWlycXVhbGl0eSc7XG5pbXBvcnQgYnVpbGRNZXRlb0RQQ2FsYXJtIGZyb20gJy4vYnVpbGRlci9iLW1ldGVvYWxhcm0nO1xuXG5jb25zdCB7IHRyYW5zbGF0aW9ucywgaW1hZ2VQYXRoIH0gPSBhd2FpdCBwcmVsb2FkUmVzb3VyY2VzKCk7IC8vIGVzZWN1emlvbmUgaW1tZWRpYXRhXG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tIERFRklOSVpJT05FIENPTVBPTkVOVEUgLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuQGN1c3RvbUVsZW1lbnQoJ2hhLWNhcmQtd2VhdGhlci1jb25kaXRpb25zJylcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvcHJlZmVyLWRlZmF1bHQtZXhwb3J0XG5leHBvcnQgY2xhc3MgSGFDYXJkV2VhdGhlckNvbmRpdGlvbnMgZXh0ZW5kcyBMb3ZlbGFjZUJhc2VFbGVtZW50IHtcbiAgX3RyYW5zbGF0aW9ucyA9IHRyYW5zbGF0aW9ucztcblxuICBfaW1hZ2VzUGF0aCA9IGltYWdlUGF0aDtcblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuICBwcm90ZWN0ZWQgX3JlbmRlcigpOiBUZW1wbGF0ZVJlc3VsdCB7XG4gICAgcmV0dXJuIGh0bWxgXG4gICAgICA8aGEtY2FyZCBjbGFzcz1cImhhLWNhcmQtd2VhdGhlci1jb25kaXRpb25zXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJuZC1jb250YWluZXJcIj5cbiAgICAgICAgICAke3RoaXMuX2J1aWxkVGVtcGxhdGUoKX1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2hhLWNhcmQ+XG4gICAgYDtcbiAgfVxuXG4gIHByaXZhdGUgX2J1aWxkVGVtcGxhdGUoKTogVGVtcGxhdGVSZXN1bHQge1xuICAgIGxldCBzdW1tYXJ5ID0gaHRtbGBgO1xuICAgIGxldCBwcmVzZW50ID0gaHRtbGBgO1xuICAgIGxldCBkYWlseVdlYXRoZXJGb3JlY2FzdCA9IGh0bWxgYDtcbiAgICBsZXQgaG91cmx5V2VhdGhlckZvcmVjYXN0ID0gaHRtbGBgO1xuICAgIGxldCBtYXJpbmVEYWlseVdlYXRoZXJGb3JlY2FzdCA9IGh0bWxgYDtcbiAgICBsZXQgbWFyaW5lSG91cmx5V2VhdGhlckZvcmVjYXN0ID0gaHRtbGBgO1xuICAgIGxldCBtZXRlb0RQQ2FsYXJtID0gaHRtbGBgO1xuICAgIGxldCB1bHRyYXZpb2xldCA9IGh0bWxgYDtcbiAgICBsZXQgcG9sbGVuID0gaHRtbGBgO1xuICAgIGxldCBhaXJRdWFsaXR5ID0gaHRtbGBgO1xuICAgIGxldCBjYW1lcmEgPSBodG1sYGA7XG5cbiAgICBjb25zdCBnZXRXZWF0aGVyRm9yZWNhc3QgPSAobW9kZTogMCB8IDEgfCAyIHwgMykgPT4gYnVpbGRXZWF0aGVyRm9yZWNhc3QoXG4gICAgICB0aGlzLmhhc3MsXG4gICAgICB0aGlzLl9sYW5ndWFnZSxcbiAgICAgIHRoaXMuX3Rlcm1zLFxuICAgICAgdGhpcy5fY29uZmlnLndlYXRoZXIuZGFpbHlfZm9yZWNhc3RzLFxuICAgICAgdGhpcy5fY29uZmlnLndlYXRoZXIuaG91cmx5X2ZvcmVjYXN0cyxcbiAgICAgIHRoaXMuX2NvbmZpZy53ZWF0aGVyLm1hcmluZV9kYWlseV9mb3JlY2FzdHMsXG4gICAgICB0aGlzLl9jb25maWcud2VhdGhlci5tYXJpbmVfaG91cmx5X2ZvcmVjYXN0cyxcbiAgICAgIG1vZGUsXG4gICAgICB0aGlzLl9pY29uc0NvbmZpZyxcbiAgICAgIHRoaXMuX2NvbmZpZy53ZWF0aGVyLnN1bixcbiAgICApO1xuXG4gICAgaWYgKHRoaXMuX2hhc1ByZXNlbnQpIHtcbiAgICAgIHN1bW1hcnkgPSBidWlsZFdlYXRoZXJTdW1tYXJ5KFxuICAgICAgICB0aGlzLmhhc3MsXG4gICAgICAgIHRoaXMuX2xhbmd1YWdlLFxuICAgICAgICB0aGlzLl90ZXJtcyxcbiAgICAgICAgdGhpcy5faWNvbnNDb25maWcsXG4gICAgICAgIHRoaXMuX2NvbmZpZy53ZWF0aGVyPy5uYW1lLFxuICAgICAgICB0aGlzLl9jb25maWc/LndlYXRoZXI/LnByZXNlbnQgfHwgbnVsbCxcbiAgICAgICAgdGhpcy5fY29uZmlnPy53ZWF0aGVyPy5zdW4sXG4gICAgICAgIHRoaXMuX2NvbmZpZz8ud2VhdGhlcj8ubW9vbnBoYXNlLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5faGFzUHJlc2VudCkge1xuICAgICAgcHJlc2VudCA9IGJ1aWxkV2VhdGhlclByZXNlbnQoXG4gICAgICAgIHRoaXMuaGFzcyxcbiAgICAgICAgdGhpcy5fbGFuZ3VhZ2UsXG4gICAgICAgIHRoaXMuX3Rlcm1zLFxuICAgICAgICB0aGlzLl9jb25maWc/LndlYXRoZXI/LnByZXNlbnQgfHwge30sXG4gICAgICAgIHRoaXMuX2NvbmZpZz8ud2VhdGhlcj8uc3VuLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5faGFzTWV0ZWFsYXJtIHx8IHRoaXMuX2hhc0RQQ2FsYXJtKSB7XG4gICAgICBtZXRlb0RQQ2FsYXJtID0gYnVpbGRNZXRlb0RQQ2FsYXJtKFxuICAgICAgICB0aGlzLmhhc3MsXG4gICAgICAgIHRoaXMuX2xhbmd1YWdlLFxuICAgICAgICB0aGlzLl90ZXJtcyxcbiAgICAgICAgdGhpcy5fY29uZmlnPy53ZWF0aGVyPy5tZXRlb2FsYXJtLFxuICAgICAgICB0aGlzLl9jb25maWc/LndlYXRoZXI/LmRwY2FsYXJtLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5faGFzRGFpbHlGb3JlY2FzdHMpIHtcbiAgICAgIGRhaWx5V2VhdGhlckZvcmVjYXN0ID0gZ2V0V2VhdGhlckZvcmVjYXN0KDApO1xuICAgIH1cbiAgICBpZiAodGhpcy5faGFzSG91cmx5Rm9yZWNhc3RzKSB7XG4gICAgICBob3VybHlXZWF0aGVyRm9yZWNhc3QgPSBnZXRXZWF0aGVyRm9yZWNhc3QoMSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9oYXNNYXJpbmVEYWlseUZvcmVjYXN0cykge1xuICAgICAgbWFyaW5lRGFpbHlXZWF0aGVyRm9yZWNhc3QgPSBnZXRXZWF0aGVyRm9yZWNhc3QoMik7XG4gICAgfVxuICAgIGlmICh0aGlzLl9oYXNNYXJpbmVIb3VybHlGb3JlY2FzdHMpIHtcbiAgICAgIG1hcmluZUhvdXJseVdlYXRoZXJGb3JlY2FzdCA9IGdldFdlYXRoZXJGb3JlY2FzdCgzKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5faGFzVWx0cmF2aW9sZXQpIHtcbiAgICAgIHVsdHJhdmlvbGV0ID0gYnVpbGRVbHRyYXZpb2xldCh0aGlzLmhhc3MsIHRoaXMuX2xhbmd1YWdlLCB0aGlzLl9jb25maWcudWx0cmF2aW9sZXQpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9oYXNQb2xsZW4pIHtcbiAgICAgIHBvbGxlbiA9IGJ1aWxkUG9sbGVuKHRoaXMuaGFzcywgdGhpcy5fbGFuZ3VhZ2UsIHRoaXMuX2NvbmZpZy5wb2xsZW4pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9oYXNBaXJRdWFsaXR5KSB7XG4gICAgICBhaXJRdWFsaXR5ID0gYnVpbGRBaXJRdWFsaXR5KHRoaXMuaGFzcywgdGhpcy5fbGFuZ3VhZ2UsIHRoaXMuX2NvbmZpZy5haXJxdWFsaXR5KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5faGFzQ2FtZXJhKSB7XG4gICAgICBjYW1lcmEgPSBidWlsZENhbWVyYSh0aGlzLmhhc3MsIHRoaXMuX2xhbmd1YWdlLCB0aGlzLl90ZXJtcywgdGhpcy5faGFuZGxlUG9wdXAuYmluZCh0aGlzKSwgdGhpcy5fY29uZmlnLmNhbWVyYSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGh0bWxgXG4gICAgJHtzdW1tYXJ5fVxuICAgICR7cHJlc2VudH1cbiAgICAke2hvdXJseVdlYXRoZXJGb3JlY2FzdH1cbiAgICAke2RhaWx5V2VhdGhlckZvcmVjYXN0fVxuICAgICR7bWFyaW5lSG91cmx5V2VhdGhlckZvcmVjYXN0fVxuICAgICR7bWFyaW5lRGFpbHlXZWF0aGVyRm9yZWNhc3R9XG4gICAgJHttZXRlb0RQQ2FsYXJtfVxuICAgICR7cG9sbGVufVxuICAgICR7dWx0cmF2aW9sZXR9XG4gICAgJHthaXJRdWFsaXR5fVxuICAgICR7Y2FtZXJhfWA7XG4gIH1cblxuICAvKipcbiAgICogQXByZSBpbCBwb3B1cCBkaSBkZXR0YWdsaW8gcGVyIGwnZW50aXTDoCBzcGVjaWZpY2F0YS5cbiAgICogQHBhcmFtIGUgTCdldmVudG8gY2xpY2sgb3JpZ2luYWxlLlxuICAgKiBAcGFyYW0gZW50aXR5SWQgTCdJRCBkZWxsJ2VudGl0w6AgSG9tZSBBc3Npc3RhbnQgZGEgbW9zdHJhcmUuXG4gICAqL1xuICBwcm90ZWN0ZWQgX2hhbmRsZVBvcHVwKGU6IEV2ZW50LCBlbnRpdHlJZDogc3RyaW5nKSB7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3QgbW9yZUluZm9FdmVudCA9IG5ldyBFdmVudCgnaGFzcy1tb3JlLWluZm8nLCB7IGNvbXBvc2VkOiB0cnVlIH0pIGFzIGFueTtcbiAgICBtb3JlSW5mb0V2ZW50LmRldGFpbCA9IHsgZW50aXR5SWQgfTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobW9yZUluZm9FdmVudCk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJfX2RlY29yYXRlIiwiZGVjb3JhdG9ycyIsInRhcmdldCIsImtleSIsImRlc2MiLCJkIiwiYyIsImFyZ3VtZW50cyIsImxlbmd0aCIsInIiLCJPYmplY3QiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJSZWZsZWN0IiwiZGVjb3JhdGUiLCJpIiwiZGVmaW5lUHJvcGVydHkiLCJTdXBwcmVzc2VkRXJyb3IiLCJ0IiwiZ2xvYmFsVGhpcyIsImUiLCJTaGFkb3dSb290IiwiU2hhZHlDU1MiLCJuYXRpdmVTaGFkb3ciLCJEb2N1bWVudCIsInByb3RvdHlwZSIsIkNTU1N0eWxlU2hlZXQiLCJzIiwiU3ltYm9sIiwibyIsIldlYWtNYXAiLCJuJDMiLCJjb25zdHJ1Y3RvciIsInRoaXMiLCJfJGNzc1Jlc3VsdCQiLCJFcnJvciIsImNzc1RleHQiLCJzdHlsZVNoZWV0IiwiZ2V0IiwicmVwbGFjZVN5bmMiLCJzZXQiLCJ0b1N0cmluZyIsInJlZHVjZSIsIm4iLCJjc3NSdWxlcyIsImlzIiwiaCIsImdldE93blByb3BlcnR5TmFtZXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJnZXRQcm90b3R5cGVPZiIsImEiLCJ0cnVzdGVkVHlwZXMiLCJsIiwiZW1wdHlTY3JpcHQiLCJwIiwicmVhY3RpdmVFbGVtZW50UG9seWZpbGxTdXBwb3J0IiwidSIsInRvQXR0cmlidXRlIiwiQm9vbGVhbiIsIkFycmF5IiwiSlNPTiIsInN0cmluZ2lmeSIsImZyb21BdHRyaWJ1dGUiLCJOdW1iZXIiLCJwYXJzZSIsImYiLCJiIiwiYXR0cmlidXRlIiwidHlwZSIsIlN0cmluZyIsImNvbnZlcnRlciIsInJlZmxlY3QiLCJ1c2VEZWZhdWx0IiwiaGFzQ2hhbmdlZCIsIm1ldGFkYXRhIiwibGl0UHJvcGVydHlNZXRhZGF0YSIsInkkMSIsIkhUTUxFbGVtZW50IiwiYWRkSW5pdGlhbGl6ZXIiLCJfJEVpIiwicHVzaCIsIm9ic2VydmVkQXR0cmlidXRlcyIsImZpbmFsaXplIiwiXyRFaCIsImtleXMiLCJjcmVhdGVQcm9wZXJ0eSIsInN0YXRlIiwiaGFzT3duUHJvcGVydHkiLCJjcmVhdGUiLCJ3cmFwcGVkIiwiZWxlbWVudFByb3BlcnRpZXMiLCJub0FjY2Vzc29yIiwiZ2V0UHJvcGVydHlEZXNjcmlwdG9yIiwiY2FsbCIsInJlcXVlc3RVcGRhdGUiLCJjb25maWd1cmFibGUiLCJlbnVtZXJhYmxlIiwiZ2V0UHJvcGVydHlPcHRpb25zIiwiTWFwIiwiZmluYWxpemVkIiwicHJvcGVydGllcyIsIl8kRXUiLCJlbGVtZW50U3R5bGVzIiwiZmluYWxpemVTdHlsZXMiLCJzdHlsZXMiLCJpc0FycmF5IiwiU2V0IiwiZmxhdCIsInJldmVyc2UiLCJ1bnNoaWZ0IiwidG9Mb3dlckNhc2UiLCJzdXBlciIsIl8kRXAiLCJpc1VwZGF0ZVBlbmRpbmciLCJoYXNVcGRhdGVkIiwiXyRFbSIsIl8kRXYiLCJfJEVTIiwiUHJvbWlzZSIsImVuYWJsZVVwZGF0aW5nIiwiXyRBTCIsIl8kRV8iLCJmb3JFYWNoIiwiYWRkQ29udHJvbGxlciIsIl8kRU8iLCJhZGQiLCJyZW5kZXJSb290IiwiaXNDb25uZWN0ZWQiLCJob3N0Q29ubmVjdGVkIiwicmVtb3ZlQ29udHJvbGxlciIsImRlbGV0ZSIsInNpemUiLCJjcmVhdGVSZW5kZXJSb290Iiwic2hhZG93Um9vdCIsImF0dGFjaFNoYWRvdyIsInNoYWRvd1Jvb3RPcHRpb25zIiwiYWRvcHRlZFN0eWxlU2hlZXRzIiwibWFwIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50IiwibGl0Tm9uY2UiLCJzZXRBdHRyaWJ1dGUiLCJ0ZXh0Q29udGVudCIsImFwcGVuZENoaWxkIiwiY29ubmVjdGVkQ2FsbGJhY2siLCJkaXNjb25uZWN0ZWRDYWxsYmFjayIsImhvc3REaXNjb25uZWN0ZWQiLCJhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2siLCJfJEFLIiwiXyRFVCIsInJlbW92ZUF0dHJpYnV0ZSIsIl8kRWoiLCJoYXNBdHRyaWJ1dGUiLCJDIiwiXyRFUCIsImhhcyIsIl8kRXEiLCJyZWplY3QiLCJzY2hlZHVsZVVwZGF0ZSIsInBlcmZvcm1VcGRhdGUiLCJzaG91bGRVcGRhdGUiLCJ3aWxsVXBkYXRlIiwiaG9zdFVwZGF0ZSIsInVwZGF0ZSIsIl8kRU0iLCJfJEFFIiwiaG9zdFVwZGF0ZWQiLCJmaXJzdFVwZGF0ZWQiLCJ1cGRhdGVkIiwidXBkYXRlQ29tcGxldGUiLCJnZXRVcGRhdGVDb21wbGV0ZSIsInkiLCJtb2RlIiwiUmVhY3RpdmVFbGVtZW50IiwicmVhY3RpdmVFbGVtZW50VmVyc2lvbnMiLCJjcmVhdGVQb2xpY3kiLCJjcmVhdGVIVE1MIiwiTWF0aCIsInJhbmRvbSIsInRvRml4ZWQiLCJzbGljZSIsImNyZWF0ZUNvbW1lbnQiLCJ2IiwiXyIsIm0iLCJSZWdFeHAiLCJnIiwiJCIsIngiLCJfJGxpdFR5cGUkIiwic3RyaW5ncyIsInZhbHVlcyIsIlQiLCJmb3IiLCJFIiwiQSIsImNyZWF0ZVRyZWVXYWxrZXIiLCJQIiwiViIsImxhc3RJbmRleCIsImV4ZWMiLCJ0ZXN0Iiwic3RhcnRzV2l0aCIsIk4iLCJwYXJ0cyIsImVsIiwiY3VycmVudE5vZGUiLCJjb250ZW50IiwiZmlyc3RDaGlsZCIsInJlcGxhY2VXaXRoIiwiY2hpbGROb2RlcyIsIm5leHROb2RlIiwibm9kZVR5cGUiLCJoYXNBdHRyaWJ1dGVzIiwiZ2V0QXR0cmlidXRlTmFtZXMiLCJlbmRzV2l0aCIsImdldEF0dHJpYnV0ZSIsInNwbGl0IiwiaW5kZXgiLCJuYW1lIiwiY3RvciIsIkgiLCJJIiwiTCIsImsiLCJ0YWdOYW1lIiwiYXBwZW5kIiwiZGF0YSIsImluZGV4T2YiLCJpbm5lckhUTUwiLCJTIiwiXyRDbyIsIl8kQ2wiLCJfJGxpdERpcmVjdGl2ZSQiLCJfJEFPIiwiXyRBVCIsIl8kQVMiLCJNIiwiXyRBViIsIl8kQU4iLCJfJEFEIiwiXyRBTSIsInBhcmVudE5vZGUiLCJfJEFVIiwiY3JlYXRpb25TY29wZSIsImltcG9ydE5vZGUiLCJSIiwibmV4dFNpYmxpbmciLCJ6IiwiXyRBSSIsIl8kQ3YiLCJfJEFIIiwiXyRBQSIsIl8kQUIiLCJvcHRpb25zIiwic3RhcnROb2RlIiwiZW5kTm9kZSIsIl8kQVIiLCJpdGVyYXRvciIsIk8iLCJpbnNlcnRCZWZvcmUiLCJjcmVhdGVUZXh0Tm9kZSIsIl8kQUMiLCJfJEFQIiwicmVtb3ZlIiwic2V0Q29ubmVjdGVkIiwiZWxlbWVudCIsImZpbGwiLCJqIiwidG9nZ2xlQXR0cmlidXRlIiwiY2FwdHVyZSIsIm9uY2UiLCJwYXNzaXZlIiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsImFkZEV2ZW50TGlzdGVuZXIiLCJoYW5kbGVFdmVudCIsImhvc3QiLCJsaXRIdG1sUG9seWZpbGxTdXBwb3J0IiwibGl0SHRtbFZlcnNpb25zIiwicmVuZGVyT3B0aW9ucyIsIl8kRG8iLCJyZW5kZXJCZWZvcmUiLCJyZW5kZXIiLCJfJGxpdFBhcnQkIiwiXyRsaXRFbGVtZW50JCIsImxpdEVsZW1lbnRIeWRyYXRlU3VwcG9ydCIsIkxpdEVsZW1lbnQiLCJsaXRFbGVtZW50UG9seWZpbGxTdXBwb3J0IiwibGl0RWxlbWVudFZlcnNpb25zIiwia2luZCIsImluaXQiLCJkZWZhdWx0Q29sb3JDc3MiLCJjc3MiLCJkZWZhdWx0RGFya0NvbG9yQ3NzIiwibG9nbyIsImhhY3NJbWFnZVBhdGgiLCJtYW5JbWFnZVBhdGgiLCJvcHRDb25zb2xlUGFyYW0xIiwib3B0Q29uc29sZVBhcmFtMiIsIm9wdENvbnNvbGVQYXJhbTMiLCJjd2NMb2NhbGUiLCJlbiIsIml0IiwibmwiLCJlcyIsImRlIiwiZnIiLCJwdCIsImRhIiwiY3MiLCJydSIsImN3Y0J1aWVucmFkYXJEYXlJY29ucyIsInNub3d5IiwicmFpbnkiLCJjbG91ZHkiLCJwYXJ0bHljbG91ZHkiLCJsaWdodG5pbmciLCJjbGVhciIsImN3Y0J1aWVucmFkYXJOaWdodEljb25zIiwiY3djQ2xpbWFjZWxsRGF5SWNvbnMiLCJmcmVlemluZ19yYWluX2hlYXZ5IiwiZnJlZXppbmdfcmFpbiIsImZyZWV6aW5nX3JhaW5fbGlnaHQiLCJmcmVlemluZ19kcml6emxlIiwiaWNlX3BlbGxldHNfaGVhdnkiLCJpY2VfcGVsbGV0cyIsImljZV9wZWxsZXRzX2xpZ2h0Iiwic25vd19oZWF2eSIsInNub3ciLCJzbm93X2xpZ2h0IiwiZmx1cnJpZXMiLCJ0c3Rvcm0iLCJyYWluX2hlYXZ5IiwicmFpbl9saWdodCIsInJhaW4iLCJkcml6emxlIiwiZm9nX2xpZ2h0IiwiZm9nIiwibW9zdGx5X2Nsb3VkeSIsInBhcnRseV9jbG91ZHkiLCJtb3N0bHlfY2xlYXIiLCJjd2NDbGltYWNlbGxOaWdodEljb25zIiwic3VubnkiLCJjd2NEYXJrc2t5RGF5SWNvbnMiLCJzbGVldCIsIndpbmQiLCJjd2NEYXJrc2t5TmlnaHRJY29ucyIsImN3Y0RlZmF1bHRIYXNzRGF5SWNvbnMiLCJleGNlcHRpb25hbCIsImhhaWwiLCJwb3VyaW5nIiwid2luZHkiLCJjd2NEZWZhdWx0SGFzc05pZ2h0SWNvbnMiLCJjd2NPcGVuV2VhdGhlck1hcERheUljb25zIiwidGh1bmRlcnN0b3JtIiwibWlzdCIsImN3Y09wZW5XZWF0aGVyTWFwTmlnaHRJY29ucyIsImN3Y0RheXRpbWVQaXJhdGVXZWF0aGVySWNvbnMiLCJjd2NOaWdodGx5UGlyYXRlV2VhdGVySWNvbnMiLCJpY29uc01vZGVscyIsInBpcmF0ZXdlYXRoZXIiLCJpY29uc0RheSIsImljb25zTmlnaHQiLCJjbGltYWNlbGwiLCJkYXJrc2t5Iiwib3BlbndlYXRoZXJtYXAiLCJidWllbnJhZGFyIiwiZGVmYXVsdGhhc3MiLCJ0cmFuc2xhdGUiLCJ0ZXJtIiwiZGljdGlvbmFyeSIsImZpbmQiLCJnZXRMb2NhbGVJbmZvIiwibGFuZyIsImxvY2FsZSIsInRpbWV6b25lIiwiamEiLCJjd2MiLCJnZXRMb2NhbGUiLCJ6aCIsInRvVXBwZXJDYXNlIiwiZm9ybWF0TnVtYmVyIiwic3RyaW5nTnVtYmVyIiwiZnJhY3Rpb25EaWdpdHMiLCJ1c2VHcm91cGluZyIsIm51bWJlciIsInBhcnNlRmxvYXQiLCJpc05hTiIsImVmZmVjdGl2ZUZvcm1hdHRlciIsImdldEZvcm1hdHRlciIsIkludGwiLCJOdW1iZXJGb3JtYXQiLCJtaW5pbXVtRnJhY3Rpb25EaWdpdHMiLCJtYXhpbXVtRnJhY3Rpb25EaWdpdHMiLCJmb3JtYXQiLCJnZXRFbnRpdHlSYXdWYWx1ZSIsImhhc3MiLCJlbnRpdHlJZCIsInN0YXRlcyIsImdldEVudGl0eVJhd0F0dHJpYnV0ZSIsImF0dHJpYnV0ZXMiLCJnZXRFbnRpdHlOdW1lcmljVmFsdWUiLCJkZWNpbWFscyIsInVuZGVmaW5lZCIsImdldEVudGl0eVVuaXQiLCJ1bml0X29mX21lYXN1cmVtZW50IiwiZ2V0RW50aXR5SWNvbiIsImljb24iLCJnZXRXaW5kRGlyZWN0aW9ucyIsIndkIiwiY3djTG9jV2luZERpcmVjdGlvbnMiLCJ3ZE51bWJlciIsImNvbnNvbGUiLCJlcnJvciIsImZsb29yIiwiaW1hZ2VFeGlzdCIsImltYWdlU3JjIiwidGltZW91dCIsInJlc29sdmUiLCJpbWciLCJJbWFnZSIsInRpbWVyIiwic2V0VGltZW91dCIsInNyYyIsIm9ubG9hZCIsImNsZWFyVGltZW91dCIsIm9uZXJyb3IiLCJsb2dJbmZvIiwibWVzc2FnZSIsImluZm8iLCJwYXJzZUxvY2FsaXplZE51bWJlciIsInZhbHVlIiwibm9ybWFsaXplZCIsInJlcGxhY2UiLCJjd2NNb29uUGhhc2VJY29ucyIsIm5ld19tb29uIiwibmV3Iiwid2F4aW5nX2NyZXNjZW50IiwiZmlyc3RfcXVhcnRlciIsIndheGluZ19naWJib3VzIiwiZnVsbCIsImZ1bGxfbW9vbiIsIndhbmluZ19naWJib3VzIiwidGhpcmRfcXVhcnRlciIsImxhc3RfcXVhcnRlciIsIndhbmluZ19jcmVzY2VudCIsImNhcmRTdHlsZSIsInN1bW1hcnlTdHlsZSIsInByZXNlbnRTdHlsZSIsInVsdHJhdmlvbGV0U3R5bGUiLCJwb2xsZW5TdHlsZSIsImNhbWVyYVN0eWxlIiwid2VhdGhlckZvcmVjYXN0U3R5bGUiLCJtZXRlb2RjcGFsYXJtU3R5bGUiLCJnZXRXZWF0aGVySWNvbiIsImNvbmRpdGlvbiIsImljb25zQ29uZmlnIiwic3VuU3RhdGUiLCJpc05pZ2h0IiwiaWNvbk5hbWUiLCJwYXRoIiwiaWNvblR5cGUiLCJpY29uc19tb2RlbCIsImNvbXB1dGVEYXJrTW9kZSIsInRoZW1lcyIsImRhcmtNb2RlIiwiYXN5bmMiLCJwcmVsb2FkUmVzb3VyY2VzIiwiaGFjc1Jlc3VsdCIsIm1hblJlc3VsdCIsImFsbCIsImltYWdlUGF0aCIsInRyYW5zbGF0aW9ucyIsInRyYW5zbFBhdGgiLCJmdWxsX3BhdGhfZmlsZSIsInJlc3BvbnNlIiwiZmV0Y2giLCJvayIsImVyciIsInN0YXR1cyIsInN0YXR1c1RleHQiLCJ0ZXh0IiwibG9hZEpTT04iLCJMb3ZlbGFjZUJhc2VFbGVtZW50IiwiaXNQYW5lbCIsImVkaXRNb2RlIiwiaW52YWxpZENvbmZpZyIsIl9oYXNQcmVzZW50IiwiX2hhc0RhaWx5Rm9yZWNhc3RzIiwiX2hhc0hvdXJseUZvcmVjYXN0cyIsIl9oYXNNYXJpbmVEYWlseUZvcmVjYXN0cyIsIl9oYXNNYXJpbmVIb3VybHlGb3JlY2FzdHMiLCJfaGFzTWV0ZWFsYXJtIiwiX2hhc0RQQ2FsYXJtIiwiX2hhc01ldGVvZ3JhbSIsIl9oYXNBaXJRdWFsaXR5IiwiX2hhc1BvbGxlbiIsIl9oYXNVbHRyYXZpb2xldCIsIl9oYXNBbGVydCIsIl9oYXNTZWEiLCJfaGFzQ2FtZXJhIiwiY2hhbmdlZFByb3BzIiwiY3VycmVudERhcmtNb2RlIiwibmV3RGFya01vZGUiLCJzdW1tYXJ5U3R5bGVzIiwic2V0Q29uZmlnIiwiY29uZmlnIiwiX3RyYW5zbGF0aW9ucyIsIl9pbWFnZXNQYXRoIiwiX25hbWUiLCJ3ZWF0aGVyIiwiX2xhbmd1YWdlIiwibGFuZ3VhZ2UiLCJfbG9hZFRyYW5zbGF0aW9ucyIsIl9kZXRlY3REYXRhU2VjdGlvbnMiLCJfc2V0dXBJY29ucyIsIl9jb25maWciLCJnZXRDYXJkU2l6ZSIsInRyYW5zbHMiLCJfdGVybXMiLCJ3aW5kRGlyZWN0aW9ucyIsIndvcmRzIiwiY3djVGVybXMiLCJmYWxsYmFjayIsInByZXNlbnQiLCJkYWlseV9mb3JlY2FzdHMiLCJob3VybHlfZm9yZWNhc3RzIiwibWFyaW5lX2RhaWx5X2ZvcmVjYXN0cyIsIm1hcmluZV9ob3VybHlfZm9yZWNhc3RzIiwibWV0ZW9hbGFybSIsImRwY2FsYXJtIiwiYWlycXVhbGl0eSIsInBvbGxlbiIsImVudGl0aWVzIiwidWx0cmF2aW9sZXQiLCJjYW1lcmEiLCJpY29uc01vZGVsIiwiX2ljb25zQ29uZmlnIiwiYW5pbWF0aW9uIiwibW9kZWxEYXRhIiwibW9kZWxOYW1lIiwid2FybiIsImdldEljb25Nb2RlbERhdGEiLCJodG1sIiwiX3JlbmRlciIsInByb3BlcnR5IiwiYnVpbGRXZWF0aGVyU3VtbWFyeSIsInRlcm1zIiwicHJlc2VudERhdGEiLCJzdW5JZCIsIm1vb25waGFzZSIsIm1vb25QaGFzZSIsIm1vb25JY29uIiwic3VuIiwiY3VycmVudENvbmRpdGlvbnMiLCJ0ZW1wZXJhdHVyZSIsInRlbXBlcmF0dXJlRmVlbHNMaWtlIiwidGVtcGVyYXR1cmVfZmVlbHNsaWtlIiwidGVtcGVyYXR1cmVGZWVsc0xpa2VJY29uIiwicmVuZGVyV2VhdGhlclN1bW1hcnkiLCJ0aXRsZSIsIm1vb25UZXh0IiwiY29uZGl0aW9uVGV4dCIsImNvbmRpdGlvbkljb24iLCJ0ZW1wZXJhdHVyZVVuaXQiLCJmZWVsc0xpa2VUZXJtIiwibm90aGluZyIsImlzVmFsaWRJbnB1dCIsInZhbCIsInByZXBhcmVXZWF0aGVyUHJlc2VudCIsImFsbEl0ZW1zIiwicGkiLCJwcmVjaXBpdGF0aW9uSW50ZW5zaXR5IiwicHAiLCJwcmVjaXBpdGF0aW9uUHJvYmFiaWxpdHkiLCJwYXJzZWRQSSIsInBhcnNlZFBQIiwidW5pdCIsInRlbXBlcmF0dXJlTG93IiwidGVtcGVyYXR1cmVIaWdoIiwiYWRkSWZWYWxpZCIsIml0ZW0iLCJ3aW5kU3BlZWQiLCJ3aW5kQmVhcmluZyIsInByZXBhcmVBaXJRdWFsaXR5IiwicmVuZGVyV2VhdGhlclByZXNlbnQiLCJidWlsZEJsb2NrUmlnaHQiLCJpY29uX2NvbG9yIiwicm93cyIsImxlZnQiLCJyaWdodCIsImJ1aWxkV2VhdGhlclByZXNlbnQiLCJzZWxlY3RlZExhbmd1YWdlIiwicHJlc2VudE9iaiIsImxvY2FsZUluZm8iLCJzdW5FbnRpdHkiLCJuZXh0X3Jpc2luZyIsIm5leHRfc2V0dGluZyIsIm5leHRSaXNpbmciLCJEYXRlIiwidG9Mb2NhbGVUaW1lU3RyaW5nIiwiaG91ciIsIm1pbnV0ZSIsInNlY29uZCIsImhvdXIxMiIsInRpbWVab25lIiwibmV4dFNldHRpbmciLCJwcmVjaXBpdGF0aW9uX2ludGVuc2l0eSIsInByZWNpcGl0YXRpb25fcHJvYmFiaWxpdHkiLCJodW1pZGl0eSIsIndpbmRfYmVhcmluZyIsIndpbmRfc3BlZWQiLCJwcmVzc3VyZSIsInZpc2liaWxpdHkiLCJ0ZW1wZXJhdHVyZV9tYXgiLCJ0ZW1wZXJhdHVyZV9taW4iLCJudW0iLCJjb2xvcnMiLCJyZW5kZXJVbHRyYXZpb2xldCIsInNraW5EYXRhIiwiY3VycmVudFVWSW5kZXgiLCJtYXhVVkluZGV4Iiwic3VtbWFyeVJvd3MiLCJza2luVHlwZXMiLCJza2luVHlwZTEiLCJza2luVHlwZTIiLCJza2luVHlwZTMiLCJza2luVHlwZTQiLCJza2luVHlwZTUiLCJza2luVHlwZTYiLCJyZW5kZXJTa2luR3JpZCIsImJnQ29sb3IiLCJ0ZXh0Q29sb3IiLCJoZXgiLCJwYXJzZUludCIsInN1YnN0ciIsImdldFRleHRDb2xvciIsImdldFRpbWUiLCJOYU4iLCJpc0Zpbml0ZSIsImhvdXJzIiwibWludXRlcyIsIndpZHRoIiwicGFkU3RhcnQiLCJwYWQiLCJzdW1tYXJ5RGF0YSIsInV2IiwicHJvdGVjdGlvbldpbmRvdyIsInByb3RlY3Rpb25fd2luZG93IiwiY3VycmVudFVWTGV2ZWwiLCJ1dl9sZXZlbCIsInV2X2luZGV4IiwibWF4X3V2X2luZGV4IiwiY3VycmVudE96b25lTGV2ZWwiLCJvem9uZV9sZXZlbCIsInNldF9za2luX3R5cGVfMSIsInNldF9za2luX3R5cGVfMiIsInNldF9za2luX3R5cGVfMyIsInNldF9za2luX3R5cGVfNCIsInNldF9za2luX3R5cGVfNSIsInNldF9za2luX3R5cGVfNiIsIkxFVkVMX05BTUVTIiwicmVuZGVyUG9sbGVuIiwibGV2ZWxNaW4iLCJsZXZlbE1heCIsIm51bUxldmVscyIsImxldmVscyIsImFjdGl2ZUluZGV4IiwiZ2V0TGV2ZWxJbmRleCIsInN0ZXAiLCJtaW4iLCJsZXZlbE5hbWUiLCJidWlsZFBvbGxlbiIsInJhd3ZhbHVlIiwiZW50aXR5Iiwic3RyaW5nMk51bWJlciIsImlucHV0IiwiZm9ybWF0VG9QYXJ0cyIsImdyb3VwIiwicGFydCIsImRlY2ltYWwiLCJtYXgiLCJyZW5kZXJXZWF0aGVyRm9yZWNhc3QiLCJmb3JlY2FzdFR5cGUiLCJkYXlEYXRhIiwiZGF5IiwicmVmZXJlbmNlIiwiaWNvbkNvbG9yIiwidGVtcExvdyIsInRlbXBlcmF0dXJlX2xvdyIsInRlbXBIaWdoIiwidGVtcGVyYXR1cmVfaGlnaCIsInRlbXBITFVuaXQiLCJwcmVjaXBQcm9iIiwicHJlY2lwSW50IiwicHJlY2lwVW5pdCIsInRlbXAiLCJ0ZW1wVW5pdCIsInRlbXBfZmVlbHNsaWtlIiwid2luZF9zcGVlZFVuaXQiLCJ3aW5kX3dhdmVfaGVpZ2h0X21heCIsInN3ZWxsX3dhdmVfaGVpZ2h0X21heCIsIndhdmVfaGVpZ2h0X21heCIsIndhdmVfZGlyZWN0aW9uIiwid2F2ZV9kaXJlY3Rpb25fZGVncmVlcyIsIndhdmVfaGVpZ2h0X21heF91bml0IiwiZ2V0RGVmYXVsdEljb24iLCJtZXRyaWMiLCJpbmNsdWRlcyIsImJ1aWxkV2VhdGhlckZvcmVjYXN0IiwiZGFpbHlGb3JlY2FzdCIsImhvdXJseUZvcmVjYXN0IiwibWFyaW5lRGFpbHlGb3JlY2FzdHMiLCJtYXJpbmVIb3VybHlGb3JlY2FzdHMiLCJzdW5FbnRpdHlJZCIsInZvaWRSZWNvcmQiLCJkYWlseUZvcmVjYXN0RGF0YSIsInNsb3RJZCIsImJ1aWxkRGFpbHlGb3JlY2FzdFNsb3QiLCJmb3JlY2FzdCIsInJlY29yZCIsImRhdGV0aW1lIiwibWV0cmljS2V5IiwibWV0cmljU2xvdHMiLCJ3ZWVrZGF5IiwidG9Mb2NhbGVEYXRlU3RyaW5nIiwiaG91cmRheSIsImhvdXJseWZvcmVjYXN0RGF0YSIsImJ1aWxkSG91cmx5Rm9yZWNhc3RTbG90IiwiaG91clRpbWUiLCJtYXJpbmVEYWlseUZvcmVjYXN0RGF0YSIsImJ1aWxkTWFyaW5lRGFpbHlGb3JlY2FzdFNsb3QiLCJmaWVsZENvbG9yIiwid2F2ZUhlaWdodE1heCIsInN3ZWxsV2F2ZUhlaWdodE1heCIsIndpbmRXYXZlSGVpZ2h0TWF4IiwiYnVpbGRDYW1lcmEiLCJoYW5kbGVQb3B1cCIsImNhbWVyYUlkIiwiZW50aXR5UGljdHVyZSIsImVudGl0eV9waWN0dXJlIiwicmVuZGVyQ2FtZXJhIiwiY2FtZXJhUGljdHVyZSIsImZyaWVuZGx5TmFtZSIsImZyaWVuZGx5X25hbWUiLCJidWlsZE1ldGVvQWxhcm1EYXRhIiwibWV0ZW9hbGFybUlkIiwiZXZlbnRJY29uIiwiYXZhbGFuY2hlIiwiZmxvb2QiLCJkcm91Z2h0IiwiZXZlbnRJY29uQ29sb3IiLCJncmVlbiIsInllbGxvdyIsIm9yYW5nZSIsInJlZCIsImZwY0RhdGEiLCJldmVudCIsInNldmVyaXR5IiwiYXdhcmVuZXNzX3R5cGUiLCJhd2FyZW5lc3NfbGV2ZWwiLCJlZmZlY3RpdmUiLCJhd2FyZW5lc3NUeXBlIiwidHJpbSIsImF3YXJlbmVzc0xldmVsIiwiZXZlbnROYW1lIiwic2V2ZXJpdHlMZXZlbCIsImVmZmVjdGl2ZURhdGV0aW1lIiwibm93IiwidG9kYXkiLCJnZXRGdWxsWWVhciIsImdldE1vbnRoIiwiZ2V0RGF0ZSIsImVmZmVjdGl2ZURhdGUiLCJkYXlEaWZmZXJlbmNlIiwicm91bmQiLCJlZmZlY3RpdmVMYWJlbCIsImdldEVmZmVjdGl2ZUxhYmVsIiwidG9Mb2NhbGVVcHBlckNhc2UiLCJidWlsZERQQ0FsYXJtRGF0YSIsImxldmVsIiwiYnVpbGRNZXRlb0RQQ2FsYXJtIiwiYWxhcm1zRGF0YSIsIm1ldGVvRFBDYWxhcm1EYXRhIiwiZW50cmllcyIsIkhhQ2FyZFdlYXRoZXJDb25kaXRpb25zIiwiX2J1aWxkVGVtcGxhdGUiLCJzdW1tYXJ5IiwiZGFpbHlXZWF0aGVyRm9yZWNhc3QiLCJob3VybHlXZWF0aGVyRm9yZWNhc3QiLCJtYXJpbmVEYWlseVdlYXRoZXJGb3JlY2FzdCIsIm1hcmluZUhvdXJseVdlYXRoZXJGb3JlY2FzdCIsIm1ldGVvRFBDYWxhcm0iLCJhaXJRdWFsaXR5IiwiZ2V0V2VhdGhlckZvcmVjYXN0IiwiYnVpbGRVbHRyYXZpb2xldCIsImJ1aWxkQWlyUXVhbGl0eSIsInBtMjUiLCJwbTEwIiwibzMiLCJubzIiLCJjbyIsInNvMiIsImVwYV9hcWkiLCJlcGFfcHJpbWFyeV9wb2xsdXRhbnQiLCJhaXJRdWFsaXR5RGF0YSIsImFxaSIsIl9oYW5kbGVQb3B1cCIsImJpbmQiLCJzdG9wUHJvcGFnYXRpb24iLCJtb3JlSW5mb0V2ZW50IiwiRXZlbnQiLCJjb21wb3NlZCIsImRldGFpbCIsImRpc3BhdGNoRXZlbnQiLCJjdXN0b21FbGVtZW50cyIsImRlZmluZSIsImN1c3RvbUVsZW1lbnQiXSwibWFwcGluZ3MiOiJBQXNETyxTQUFTQSxFQUFXQyxFQUFZQyxFQUFRQyxFQUFLQyxHQUNoRCxJQUEySEMsRUFBdkhDLEVBQUlDLFVBQVVDLE9BQVFDLEVBQUlILEVBQUksRUFBSUosRUFBa0IsT0FBVEUsRUFBZ0JBLEVBQU9NLE9BQU9DLHlCQUF5QlQsRUFBUUMsR0FBT0MsRUFDckgsR0FBdUIsaUJBQVpRLFNBQW9ELG1CQUFyQkEsUUFBUUMsU0FBeUJKLEVBQUlHLFFBQVFDLFNBQVNaLEVBQVlDLEVBQVFDLEVBQUtDLFFBQ3BILElBQUssSUFBSVUsRUFBSWIsRUFBV08sT0FBUyxFQUFHTSxHQUFLLEVBQUdBLEtBQVNULEVBQUlKLEVBQVdhLE1BQUlMLEdBQUtILEVBQUksRUFBSUQsRUFBRUksR0FBS0gsRUFBSSxFQUFJRCxFQUFFSCxFQUFRQyxFQUFLTSxHQUFLSixFQUFFSCxFQUFRQyxLQUFTTSxHQUNoSixPQUFPSCxFQUFJLEdBQUtHLEdBQUtDLE9BQU9LLGVBQWViLEVBQVFDLEVBQUtNLEdBQUlBLENBQ2hFLENBNlFrRCxtQkFBcEJPLGlCQUFpQ0E7Ozs7OztBQ25VL0QsTUFBTUMsRUFBRUMsV0FBV0MsRUFBRUYsRUFBRUcsa0JBQWEsSUFBU0gsRUFBRUksVUFBVUosRUFBRUksU0FBU0MsZUFBZSx1QkFBdUJDLFNBQVNDLFdBQVcsWUFBWUMsY0FBY0QsVUFBVUUsRUFBRUMsU0FBU0MsRUFBRSxJQUFJQyxRQUFRLElBQUFD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QUVSd1ksR0FBSSxDQUNGaFgsTUFBUWdYLEVBQUssTUFBTUEsSUFBT0EsRUFDMUI5TixLQUFNN0ssR0FBY1IsRUFBTXVJLEVBQVc0USxLQUFPLFFBQzVDeFksS0FBTSxnQkFFUnlZLElBQUssQ0FDSGpYLE1BQVFpWCxFQUFNLE9BQU9BLElBQVFBLEVBQzdCL04sS0FBTTdLLEdBQWNSLEVBQU11SSxFQUFXNlEsTUFBUSxRQUM3Q3pZLEtBQU0sZ0JBRVIwWSxHQUFJLENBQ0ZsWCxNQUFRa1gsRUFBSyxNQUFNQSxJQUFPQSxFQUMxQmhPLEtBQU03SyxHQUFjUixFQUFNdUksRUFBVzhRLEtBQU8sUUFDNUMxWSxLQUFNLGdCQUVSMlksSUFBSyxDQUNIblgsTUFBUW1YLEVBQU0sT0FBT0EsSUFBUUEsRUFDN0JqTyxLQUFNN0ssR0FBY1IsRUFBTXVJLEVBQVcrUSxNQUFRLFFBQzdDM1ksS0FBTSxnQkFFUjRZLFFBQVMsQ0FDUHBYLE1BQVFvWCxFQUFVLHFCQUFxQkEsSUFBWUEsRUFFbkQ1WSxLQUFNLG1CQUNOb0wsWUFuRWUyTixFQW1FU3Z1QixPQUFPNFUsR0FBa0JDLEVBQU11SSxFQUFXZ1IsVUFsRWxFRyxHQUFPLEdBQ0YsVUFDRUEsR0FBTyxJQUNULFVBQ0VBLEdBQU8sSUFDVCxVQUNFQSxHQUFPLElBQ1QsVUFDRUEsR0FBTyxJQUNULFVBRUEsWUF5RFBGLHNCQUF1QixDQUNyQnJYLE1BQVFxWCxFQUF3QixXQUFXQSxJQUEwQkEsRUFFckU3WSxLQUFNLHFCQXhFWixJQUFxQitZLEVBNEVuQixPQUFPN04sR0FBcUI0TixFQUFnQmhiLEVBQUssRUc2QmhDdWEsQ0FBZ0IzdkIsS0FBSzJXLEtBQU0zVyxLQUFLOGQsVUFBVzlkLEtBQUttZSxRQUFRZSxhQUduRWxmLEtBQUttZCxhQUNQbUMsRUFBU3lNLEdBQVkvckIsS0FBSzJXLEtBQU0zVyxLQUFLOGQsVUFBVzlkLEtBQUtzZSxPQUFRdGUsS0FBS3N3QixhQUFhQyxLQUFLdndCLE1BQU9BLEtBQUttZSxRQUFRbUIsU0FHbkdRLENBQUk7TUFDVG9QO01BQ0F2UTtNQUNBeVE7TUFDQUQ7TUFDQUc7TUFDQUQ7TUFDQUU7TUFDQXBRO01BQ0FFO01BQ0FtUTtNQUNBbFEsR0FDSixDQU9VZ1IsWUFBQUEsQ0FBYW54QixFQUFVeVgsR0FDL0J6WCxFQUFFcXhCLGtCQUdGLE1BQU1DLEVBQWdCLElBQUlDLE1BQU0saUJBQWtCLENBQUVDLFVBQVUsSUFDOURGLEVBQWNHLE9BQVMsQ0FBRWhhLFlBQ3pCNVcsS0FBSzZ3QixjQUFjSixFQUNyQixHQWxJV3pCLEdBQXVCaHhCLEVBQUEsQ3RDaEI1QmlCLElBQUcsQ0FBQ0UsRUFBRVMsY0FBY0EsRUFBRUEsRUFBRWlELGdCQUFnQixLQUFLaXVCLGVBQWVDLE9BQU85eEIsRUFBRUUsRUFBRyxJQUFHMnhCLGVBQWVDLE9BQU85eEIsRUFBRUUsSXNDYzFHNnhCLENBQWMsK0JBRUZoQyIsInhfZ29vZ2xlX2lnbm9yZUxpc3QiOlswLDEsMiwzLDQsNSw2XX0=
================================================
FILE: dist/transl/cs.json
================================================
{
"cwcLocWindDirections": {
"N": "S",
"NNE": "SSV",
"NE": "SV",
"ENE": "VSV",
"E": "V",
"ESE": "VJV",
"SE": "JV",
"SSE": "JJV",
"S": "J",
"SSW": "JJZ",
"SW": "JZ",
"WSW": "ZJZ",
"W": "Z",
"WNW": "ZSZ",
"NW": "SZ",
"NNW": "SSZ"
},
"cwcTerms": {
"Feels Like" : "Pocitová teplota",
"new_moon": "Nov",
"new": "Nov",
"waxing_crescent": "Dorůstající srpek",
"first_quarter": "První čtvrť",
"waxing_gibbous": "Dorůstající měsíc",
"full": "Úplněk",
"full_moon": "Úplněk",
"waning_gibbous": "Couvající měsíc",
"third_quarter": "Třetí čtvrť",
"last_quarter": "Poslední čtvrť",
"waning_crescent": "Ubývající srpek"
}
}
================================================
FILE: dist/transl/da.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNØ",
"NE": "NØ",
"ENE": "ØNØ",
"E": "Ø",
"ESE": "ØSØ",
"SE": "SØ",
"SSE": "SSØ",
"S": "S",
"SSW": "SSV",
"SW": "SV",
"WSW": "VSV",
"W": "V",
"WNW": "VNV",
"NW": "NV",
"NNW": "NNV"
},
"cwcTerms": {
"Feels Like" : "Føles som",
"new_moon": "Nymåne",
"new": "Nymåne",
"waxing_crescent": "Tiltagende halvmåne",
"first_quarter": "Første kvartal",
"waxing_gibbous": "Tiltagende måne",
"full": "Fuldmåne",
"full_moon": "Fuldmåne",
"waning_gibbous": "Aftagende måne",
"third_quarter": "Tredje kvartal",
"last_quarter": "Sidste kvartal",
"waning_crescent": "Aftagende halvmåne"
}
}
================================================
FILE: dist/transl/de.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNO",
"NE": "NO",
"ENE": "ONO",
"E": "O",
"ESE": "OSO",
"SE": "SO",
"SSE": "SSO",
"S": "S",
"SSW": "SSW",
"SW": "SW",
"WSW": "WSW",
"W": "W",
"WNW": "WNW",
"NW": "NW",
"NNW": "NNW"
},
"cwcTerms": {
"Feels Like" : "Gefühlt",
"new_moon": "Neumond",
"new": "Neumond",
"waxing_crescent": "Zunehmende Sichel",
"first_quarter": "Erstes Viertel",
"waxing_gibbous": "Zunehmender Halbmond",
"full": "Vollmond",
"full_moon": "Vollmond",
"waning_gibbous": "Abnehmender Halbmond",
"third_quarter": "Drittes Viertel",
"last_quarter": "Letztes Viertel",
"waning_crescent": "Abnehmende Sichel"
}
}
================================================
FILE: dist/transl/en.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNE",
"NE": "NE",
"ENE": "ENE",
"E": "E",
"ESE": "ESE",
"SE": "SE",
"SSE": "SSE",
"S": "S",
"SSW": "SSW",
"SW": "SW",
"WSW": "WSW",
"W": "W",
"WNW": "WNW",
"NW": "NW",
"NNW": "NNW"
},
"cwcTerms": {
"Feels Like" : "Feels Like",
"new_moon": "New moon",
"new": "New moon",
"waxing_crescent": "Waxing crescent",
"first_quarter": "First quarter",
"waxing_gibbous": "Waxing Gibbous",
"full": "Full",
"full_moon": "Full",
"waning_gibbous": "Waning Gibbous",
"third_quarter": "Third Quarter",
"last_quarter": "Last Quarter",
"waning_crescent": "Waning Crescent"
}
}
================================================
FILE: dist/transl/es.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNE",
"NE": "NE",
"ENE": "ENE",
"E": "E",
"ESE": "ESE",
"SE": "SE",
"SSE": "SSE",
"S": "S",
"SSW": "SSO",
"SW": "SO",
"WSW": "OSO",
"W": "O",
"WNW": "ONO",
"NW": "NO",
"NNW": "NNO"
},
"cwcTerms": {
"Feels Like" : "Sensación térmica",
"new_moon": "Luna nueva",
"new": "Luna nueva",
"waxing_crescent": "Luna creciente",
"first_quarter": "Cuarto creciente",
"waxing_gibbous": "Luna menguante gibosa",
"full": "Luna llena",
"full_moon": "Luna llena",
"waning_gibbous": "Luna menguante gibosa",
"third_quarter": "Media luna",
"last_quarter": "Cuarto menguante",
"waning_crescent": "Luna menguante"
}
}
================================================
FILE: dist/transl/fr.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNE",
"NE": "NE",
"ENE": "ENE",
"E": "E",
"ESE": "ESE",
"SE": "SE",
"SSE": "SSE",
"S": "S",
"SSW": "SSO",
"SW": "SO",
"WSW": "OSO",
"W": "O",
"WNW": "ONO",
"NW": "NO",
"NNW": "NNO"
},
"cwcTerms": {
"Feels Like" : "Ressentie",
"new_moon": "Nouvelle lune",
"new": "Nouvelle lune",
"waxing_crescent": "Premier croissant",
"first_quarter": "Premier quartier",
"waxing_gibbous": "Gibbeuse croissante",
"full": "Pleine lune",
"full_moon": "Pleine lune",
"waning_gibbous": "Gibbeuse décroissante",
"third_quarter": "Dernier quartier",
"last_quarter": "Dernier quartier",
"waning_crescent": "Lune décroissante"
}
}
================================================
FILE: dist/transl/it.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNE",
"NE": "NE",
"ENE": "ENE",
"E": "E",
"ESE": "ESE",
"SE": "SE",
"SSE": "SSE",
"S": "S",
"SSW": "SSO",
"SW": "SO",
"WSW": "OSO",
"W": "O",
"WNW": "ONO",
"NW": "NO",
"NNW": "NNO"
},
"cwcTerms": {
"Feels Like" : "Percepita",
"new_moon": "Novilunio",
"new": "Novilunio",
"waxing_crescent": "Luna crescente",
"first_quarter": "Primo Quarto",
"waxing_gibbous": "Gibbosa crescente",
"full": "Luna piena",
"full_moon": "Luna piena",
"waning_gibbous": "Gibbosa calante",
"third_quarter": "Ultimo quarto",
"last_quarter": "Ultimo quarto",
"waning_crescent": "Luna calante"
}
}
================================================
FILE: dist/transl/nl.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNO",
"NE": "NO",
"ENE": "ONO",
"E": "O",
"ESE": "OZO",
"SE": "ZO",
"SSE": "ZZO",
"S": "Z",
"SSW": "ZZW",
"SW": "ZW",
"WSW": "WZW",
"W": "W",
"WNW": "WNW",
"NW": "NW",
"NNW": "NNW"
},
"cwcTerms": {
"Feels Like": "Voelt Als",
"new_moon": "Nieuwe maan",
"new": "Nieuwe maan",
"waxing_crescent": "Wassende halve maan",
"first_quarter": "Eerste kwartier",
"waxing_gibbous": "Wassende maan",
"full": "Volle maan",
"full_moon": "Volle maan",
"waning_gibbous": "Afnemende maan",
"third_quarter": "Derde Kwartier",
"last_quarter": "Laatste Kwartier",
"waning_crescent": "Afnemende halve maan"
}
}
================================================
FILE: dist/transl/no-NO.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNØ",
"NE": "NØ",
"ENE": "ØNØ",
"E": "Ø",
"ESE": "ØSØ",
"SE": "SØ",
"SSE": "SSØ",
"S": "S",
"SSW": "SSV",
"SW": "SV",
"WSW": "VSV",
"W": "V",
"WNW": "VNV",
"NW": "NV",
"NNW": "NNV"
},
"cwcTerms": {
"Feels Like" : "Føles som",
"new_moon": "Nymåne",
"new": "Nymåne",
"waxing_crescent": "Tiltagende halvmåne",
"first_quarter": "Første kvartal",
"waxing_gibbous": "Tiltagende måne",
"full": "Fullmåne",
"full_moon": "Fullmåne",
"waning_gibbous": "Avtagende måne",
"third_quarter": "Tredje kvartal",
"last_quarter": "Sidste kvartal",
"waning_crescent": "Avtagende halvmåne"
}
}
================================================
FILE: dist/transl/pt.json
================================================
{
"cwcLocWindDirections": {
"N": "N",
"NNE": "NNE",
"NE": "NE",
"ENE": "ENE",
"E": "E",
"ESE": "ESE",
"SE": "SE",
"SSE": "SSE",
"S": "S",
"SSW": "SSW",
"SW": "SW",
"WSW": "WSW",
"W": "W",
"WNW": "WNW",
"NW": "NW",
"NNW": "NNW"
},
"cwcTerms": {
"Feels Like" : "Sentida",
"new_moon": "Lua Nova",
"new": "Lua nova",
"waxing_crescent": "Lua Crescente",
"first_quarter": "Quarto Crescente",
"waxing_gibbous": "Crescente Gibosa",
"full": "Lua Cheia",
"full_moon": "Lua Cheia",
"waning_gibbous": "Minguante Gibosa",
"third_quarter": "Quarto Minguante",
"last_quarter": "Quarto Minguante",
"waning_crescent": "Lua Minguante"
}
}
================================================
FILE: dist/transl/ru.json
================================================
{
"cwcLocWindDirections": {
"N": "С",
"NNE": "ССВ",
"NE": "СВ",
"ENE": "ВСВ",
"E": "В",
"ESE": "ВЮВ",
"SE": "ЮВ",
"SSE": "ЮЮВ",
"S": "Ю",
"SSW": "ЮЮЗ",
"SW": "ЮЗ",
"WSW": "ЗЮЗ",
"W": "З",
"WNW": "ЗСЗ",
"NW": "СЗ",
"NNW": "ССЗ"
},
"cwcTerms": {
"Feels Like" : "Ощущается как",
"new_moon": "Новолуние",
"new": "Новолуние",
"waxing_crescent": "Растущий серп",
"first_quarter": "Первая четверть",
"waxing_gibbous": "Растущая луна",
"full": "Полнолуние",
"full_moon": "Полнолуние",
"waning_gibbous": "Убывающая луна",
"third_quarter": "Третья четверть",
"last_quarter": "Последняя четверть",
"waning_crescent": "Убывающая луна"
}
}
================================================
FILE: dist/transl/sr-latn.json
================================================
{
"cwcLocWindDirections": {
"N": "S",
"NNE": "SSI",
"NE": "SI",
"ENE": "ISI",
"E": "I",
"ESE": "IJI",
"SE": "JI",
"SSE": "JJI",
"S": "J",
"SSW": "JJZ",
"SW": "JZ",
"WSW": "ZSZ",
"W": "Z",
"WNW": "ZSZ",
"NW": "SZ",
"NNW": "SSZ"
},
"cwcTerms": {
"Feels Like" : "Subjektivni osećaj",
"new_moon": "Mlad mesec",
"new": "Mlad mesec",
"waxing_crescent": "Prva osmina",
"first_quarter": "Prva četvrt",
"waxing_gibbous": "Treća osmina",
"full": "Pun mesec",
"full_moon": "Pun mesec",
"waning_gibbous": "Peta osmina",
"third_quarter": "Treća četvrtina",
"last_quarter": "Zadnja četvrtina",
"waning_crescent": "Sedma osmina"
}
}
================================================
FILE: hacs.json
================================================
{
"name": "HA (Lovelace) Card Weather Conditions",
"domains": ["weather"],
"render_readme": false,
"filename": "ha-card-weather-conditions.js"
}
================================================
FILE: info.md
================================================
# Weather Conditions Card
ha-card-weather-conditions is a powerful and flexible Lovelace card for Home Assistant. It integrates a variety of weather-related data sources to present a comprehensive summary and forecast.
[](https://github.com/hacs/integration)
[![License][license-shield]](LICENSE)
[](https://lgtm.com/projects/g/r-renato/ha-card-weather-conditions/alerts/)
[](https://lgtm.com/projects/g/r-renato/ha-card-weather-conditions/context:javascript)
[![BuyMeCoffee][buymecoffeebadge]][buymecoffee]
## Features
* Current and forecast weather conditions
* Marine forecast (swell, wave, wind)
* Ultraviolet radiation index and protection advice
* Pollen level display (tree, weed, grass)
* Air quality index with multiple pollutant types
* Weather alerts (fire, storm, hydrogeological, hydraulic)
* Meteogram and camera integration
* Multilingual support
* Display MeteoAlarm (Early Warnings for Europe) and Dipartimento Protezione Civile (Italy only) Alert
## **Card Configuration**
To use the ```ha-card-weather-conditions``` card, add the following configuration to your ```lovelace``` dashboard:
```yaml
resources:
# Required: Load the card if installed via HACS
- url: /hacsfiles/ha-card-weather-conditions/ha-card-weather-conditions.js
type: module
# Optional: Load Card Mod to enable advanced styling/customization
- url: /hacsfiles/lovelace-card-mod/card-mod.js
type: module
# ...
```
## **Card Schema Summary**
| **Parameter** | **Type** | **Required** | **Default** | **Description** |
| ------------- | --------- | ------------ | ----------- | ---------------------------------------------------------------------------------------------------------- |
| `type` | `string` | Yes | — | Must be set to `custom:ha-card-weather-conditions`. |
| `language` | `string` | No | `en` | Language for labels. Supported values: `en`, `it`, `nl`, `es`, `de`, `fr`, `sr-latn`, `pt`, `da`, `no-NO`, `cs`. |
| `weather` | `object` | No | — | Configuration for main weather source. See dedicated section. |
| `ultraviolet` | `object` | No | — | Configuration for UV index display. See dedicated section for details. |
| `pollen` | `object` | No | — | Configuration for pollen levels. See dedicated section. |
| `airquality` | `object` | No | — | Configuration for air quality index. See dedicated section. |
| `camera` | `string` | No | — | Entity ID of the camera to display. |
## **1 `weather` Object Schema**
The following parameters configure the weather object to display current conditions, short-term and long-term forecasts, as well as related alerts.
This card has been tested with weather data provided by `pirateweather`, `climacell`, `darksky` and `openweathermap` integrations.
| **Name** | **Type** | **Required** | **Default** | **Description** |
| ------------------------- | --------- | ------------ | --------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | No | — | Name of the location displayed in the summary section. |
| `sun` | `string` | No | — | Entity ID for the sun sensor (used to adjust visuals for daylight, sunrise, and sunset). |
| `moonphase` | `string` | No | — | Entity ID for the moon phase sensor. |
| `icons_model` | `string` | **Yes** | `pirateweather` | Icon set to use. Supported values: `pirateweather`, `climacell`, `darksky`, `openweathermap`, `buienradar`, `defaulthass`. |
| `animation` | `boolean` | No | `false` | Enables visual effects like moving clouds, rain, or waves based on weather conditions. |
| `present` | `object` | No | — | Object containing current weather data (e.g., temperature, humidity, pressure). |
| `daily_forecasts` | `object` | No | — | Object containing multi-day weather forecast data. |
| `hourly_forecasts` | `object` | No | — | Object containing hourly weather forecast data. |
| `marine_daily_forecasts` | `object` | No | — | Object with daily marine forecast data (e.g., wave height, wind, tides). |
| `marine_hourly_forecasts` | `object` | No | — | Object with hourly marine forecast data. |
| `meteoalarm` | `string` | No | — | Entity ID from [Meteoalarm](https://meteoalarm.org/) integration for regional weather warnings. |
| `dpcalarm` | `object` | No | — | Object providing DPC (Protezione Civile) alerts such as thunderstorm or flood risks. |
### **1.1 `present` Object Schema**
The present object defines the entities used to display the current weather conditions in the summary section of the card. Each property corresponds to a specific sensor or attribute providing real-time environmental data.
| **Name** | **Type** | **Required** | **Default** | **Description** |
| --------------------------- | ---------- | ------------ | ----------- | ----------------------------------------------------------------------------- |
| `condition` | `string` | No | — | Entity ID providing the current weather condition (e.g. sunny, cloudy, rain). |
| `temperature` | `string` | No | — | Entity ID providing the current temperature. |
| `temperature_feelslike` | `string` | No | — | Entity ID providing the perceived (feels-like) temperature. |
| `temperature_min` | `string` | No | — | Entity ID providing the minimum temperature of the day. |
| `temperature_max` | `string` | No | — | Entity ID providing the maximum temperature of the day. |
| `humidity` | `string` | No | — | Entity ID providing the current humidity level (%). |
| `pressure` | `string` | No | — | Entity ID providing the current atmospheric pressure. |
| `visibility` | `string` | No | — | Entity ID providing the current visibility level. |
| `wind_bearing` | `string` | No | — | Entity ID providing the wind direction in degrees. |
| `wind_speed` | `string` | No | — | Entity ID providing the wind speed. |
| `precipitation_intensity` | `string` | No | — | Entity ID providing the precipitation rate (e.g. mm/h). |
| `precipitation_probability` | `string` | No | — | Entity ID providing the probability of precipitation (%). |
### **1.2 `daily_forecasts` Object Schema**
This object defines the structure for multi-day forecast data, where each property can include multiple time slots (e.g. day_1, day_2, day_3…).
| **Name** | **Type** | **Required** | **Default** | **Description** |
| --------------------------- | ------------ | ------------ | ----------- | -------------------------------------------------------------------------- |
| `condition` | `iTimeSlots` | No | — | Object containing the weather condition icons or states for each day slot. |
| `temperature_high` | `iTimeSlots` | No | — | Object containing the daily high temperature values per slot. |
| `temperature_low` | `iTimeSlots` | No | — | Object containing the daily low temperature values per slot. |
| `precipitation_intensity` | `iTimeSlots` | No | — | Object with the forecasted precipitation amount for each slot. |
| `precipitation_probability` | `iTimeSlots` | No | — | Object with the probability of precipitation (%) per slot. |
### **1.3 `hourly_forecasts` Object Schema**
This object defines the structure for hourly weather forecast data. All fields are optional and do not have default values.
| **Name** | **Type** | **Required** | **Default** | **Description** |
| --------------------------- | ------------ | ------------ | ----------- | ----------------------------------------------------------------------------- |
| `condition` | `iTimeSlots` | No | — | Object containing the weather condition icons or states for each hourly slot. |
| `temperature` | `iTimeSlots` | No | — | Object containing the perceived ambient temperature for each hour. |
| `temperature_feelslike` | `iTimeSlots` | No | — | Object containing the "feels like" temperature values for each hour. |
| `precipitation_intensity` | `iTimeSlots` | No | — | Object with forecasted precipitation amount per hour. |
| `precipitation_probability` | `iTimeSlots` | No | — | Object with probability of precipitation (%) per hour. |
| `wind_bearing` | `iTimeSlots` | No | — | Object with wind direction (in degrees or cardinal direction) per hour. |
| `wind_speed` | `iTimeSlots` | No | — | Object with wind speed values per hour. |
### **1.3.1 `iTimeSlots` Object Schema**
This object represents a set of six time slots used to store sequential forecast data (e.g., hourly, daily, etc.).
| **Name** | **Type** | **Required** | **Description** |
| -------- | -------- | ------------ | ------------------------------------------------------------ |
| `slot1` | `string` | No | Value for the first time slot (e.g., current or first hour). |
| `slot2` | `string` | No | Value for the second time slot. |
| `slot3` | `string` | No | Value for the third time slot. |
| `slot4` | `string` | No | Value for the fourth time slot. |
| `slot5` | `string` | No | Value for the fifth time slot. |
| `slot6` | `string` | No | Value for the sixth time slot. |
### **1.4 `dpcalarm` Object Schema**
The `dpcalarm` object is used to configure weather-related alerts provided by the Italian Civil Protection Department (DPC), including thunderstorms, hydraulic, and hydrogeological risks. Each property should reference a specific sensor entity ID.
| **Name** | **Type** | **Required** | **Description** |
| ----------------- | -------- | ------------ | ---------------------------------------------------------------------------- |
| `thunderstorms` | `string` | No | Entity ID providing thunderstorm alert information from DPC. |
| `hydraulic` | `string` | No | Entity ID providing hydraulic (river/stream flooding) alert information. |
| `hydrogeological` | `string` | No | Entity ID providing hydrogeological (landslide/soil instability) alert data. |
## **2 `ultraviolet` Object Schema**
The ultraviolet object allows you to display UV-related data such as the current index, ozone level, protection window, and safe exposure times for different skin types (I–VI).
| **Name** | **Type** | **Required** | **Description** |
| ------------------- | -------- | ------------ | ------------------------------------------------------------------------------- |
| `protection_window` | `string` | No | Entity ID providing the time window during which sun protection is recommended. |
| `ozone_level` | `string` | No | Entity ID providing the current atmospheric ozone level. |
| `uv_index` | `string` | No | Entity ID providing the current UV index value. |
| `uv_level` | `string` | No | Entity ID describing the UV risk level (e.g. low, moderate, high). |
| `max_uv_index` | `string` | No | Entity ID providing the maximum forecasted UV index for the day. |
| `set_skin_type_1` | `string` | No | Entity ID providing sun exposure time recommendation for skin type I. |
| `set_skin_type_2` | `string` | No | Entity ID providing sun exposure time recommendation for skin type II. |
| `set_skin_type_3` | `string` | No | Entity ID providing sun exposure time recommendation for skin type III. |
| `set_skin_type_4` | `string` | No | Entity ID providing sun exposure time recommendation for skin type IV. |
| `set_skin_type_5` | `string` | No | Entity ID providing sun exposure time recommendation for skin type V. |
| `set_skin_type_6` | `string` | No | Entity ID providing sun exposure time recommendation for skin type VI. |
## **3 `pollen` Object Schema**
The pollen object provides information about airborne allergens. It defines the range of measured values (`min` and `max`) and includes a list of `entities` describing each pollen type.
| **Name** | **Type** | **Required** | **Description** |
| ---------- | --------------- | ------------ | ----------------------------------------------------------------------- |
| `entities` | `iPollenItem[]` | Yes | Array of pollen data objects, each representing a specific pollen type. |
| `min` | `number` | Yes | Minimum expected pollen concentration (used for scaling). |
| `max` | `number` | Yes | Maximum expected pollen concentration (used for scaling). |
## **3.1 `iPollenItem` Object Schema**
Each `iPollenItem` defines a specific pollen type to be tracked, including a name for display and the corresponding entity ID in Home Assistant.
| **Name** | **Type** | **Required** | **Description** |
| -------- | -------- | ------------ | ----------------------------------------------------------------- |
| `name` | `string` | Yes | Display name of the pollen type (e.g., “Grass”, “Birch”). |
| `entity` | `string` | Yes | Home Assistant entity ID providing the pollen concentration data. |
## **4 `airquality` Object Schema**
The `airquality` object defines the Home Assistant entity IDs used to monitor various air pollution metrics and EPA health indicators. Each field corresponds to a specific air quality parameter.
| **Name** | **Type** | **Required** | **Description** |
| ----------------------- | -------- | ------------ | ---------------------------------------------------------------------------- |
| `pm25` | `string` | No | Entity ID providing PM2.5 (fine particulate matter) concentration. |
| `pm10` | `string` | No | Entity ID providing PM10 (coarse particulate matter) concentration. |
| `o3` | `string` | No | Entity ID providing Ozone (O₃) concentration. |
| `no2` | `string` | No | Entity ID providing Nitrogen Dioxide (NO₂) concentration. |
| `co` | `string` | No | Entity ID providing Carbon Monoxide (CO) concentration. |
| `so2` | `string` | No | Entity ID providing Sulfur Dioxide (SO₂) concentration. |
| `epa_aqi` | `string` | No | Entity ID providing the EPA-computed Air Quality Index. |
| `epa_primary_pollutant` | `string` | No | Entity ID providing the EPA-designated primary pollutant. |
| `epa_health_concern` | `string` | No | Entity ID describing the EPA-assigned health concern level (e.g., moderate). |
## **Card Layers Sample**
This section showcases a complete example of the different visual layers supported by the `ha-card-weather-conditions` card.
Each layer such as summary, weather conditions, air quality, UV index, and alerts—can be configured independently, allowing full control over how and where data appears.
Use this reference as a guide when designing your Lovelace configuration to build a fully personalized weather dashboard.
### **Summary Layer**
The summary layers present a concise visual overview of current weather conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
name: "Acquafredda"
icons_model: pirateweather
moonphase: sensor.moon_phase
present:
condition: sensor.home_condition
temperature: sensor.home_temperature
temperature_feelslike: sensor.home_apparent_temperature
```
### **Present Layer**
This layer displays the current weather conditions using entity data such as temperature, humidity, wind, and more.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
sun: sun.sun
present:
temperature_min: sensor.home_temperature_min
temperature_max: sensor.home_temperature_max
humidity: sensor.home_relative_humidity
pressure: sensor.home_pressure
wind_bearing: sensor.home_wind_bearing
wind_speed: sensor.home_wind_speed
precipitation_intensity: sensor.home_precipitation
precipitation_probability: sensor.home_precipitation_probability
```
### **Daily Forecast Layer**
This layer provides a multi-day weather overview, including expected temperature highs and lows, precipitation probability, and general conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
daily_forecasts:
condition:
slot1: sensor.home_daily_forecast_condition_d1
slot2: sensor.home_daily_forecast_condition_d2
slot3: sensor.home_daily_forecast_condition_d3
slot4: sensor.home_daily_forecast_condition_d4
temperature_high:
slot1: sensor.home_daily_forecast_temperature_max_d1
slot2: sensor.home_daily_forecast_temperature_max_d2
slot3: sensor.home_daily_forecast_temperature_max_d3
slot4: sensor.home_daily_forecast_temperature_max_d4
temperature_low:
slot1: sensor.home_daily_forecast_temperature_min_d1
slot2: sensor.home_daily_forecast_temperature_min_d2
slot3: sensor.home_daily_forecast_temperature_min_d3
slot4: sensor.home_daily_forecast_temperature_min_d4
precipitation_probability:
slot1: sensor.home_daily_forecast_precipitation_probability_d1
slot2: sensor.home_daily_forecast_precipitation_probability_d2
slot3: sensor.home_daily_forecast_precipitation_probability_d3
slot4: sensor.home_daily_forecast_precipitation_probability_d4
precipitation_intensity:
slot1: sensor.home_daily_forecast_precipitation_d1
slot2: sensor.home_daily_forecast_precipitation_d2
slot3: sensor.home_daily_forecast_precipitation_d3
slot4: sensor.home_daily_forecast_precipitation_d4
```
### **Hourly Forecast Layer**
This layer displays detailed weather data for the next several hours, including temperature, precipitation, and wind conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
hourly_forecasts:
condition:
slot1: sensor.home_hourly_forecast_condition_h1
slot2: sensor.home_hourly_forecast_condition_h2
slot3: sensor.home_hourly_forecast_condition_h3
slot4: sensor.home_hourly_forecast_condition_h4
temperature:
slot1: sensor.home_hourly_forecast_temperature_h1
slot2: sensor.home_hourly_forecast_temperature_h2
slot3: sensor.home_hourly_forecast_temperature_h3
slot4: sensor.home_hourly_forecast_temperature_h4
temperature_feelslike:
slot1: sensor.home_hourly_forecast_apparent_temperature_h1
slot2: sensor.home_hourly_forecast_apparent_temperature_h2
slot3: sensor.home_hourly_forecast_apparent_temperature_h3
slot4: sensor.home_hourly_forecast_apparent_temperature_h4
precipitation_intensity:
slot1: sensor.home_hourly_forecast_precipitation_h1
slot2: sensor.home_hourly_forecast_precipitation_h2
slot3: sensor.home_hourly_forecast_precipitation_h3
slot4: sensor.home_hourly_forecast_precipitation_h4
precipitation_probability:
slot1: sensor.home_hourly_forecast_precipitation_probability_h1
slot2: sensor.home_hourly_forecast_precipitation_probability_h2
slot3: sensor.home_hourly_forecast_precipitation_probability_h3
slot4: sensor.home_hourly_forecast_precipitation_probability_h4
wind_bearing:
slot1: sensor.home_hourly_forecast_wind_bearing_h1
slot2: sensor.home_hourly_forecast_wind_bearing_h2
slot3: sensor.home_hourly_forecast_wind_bearing_h3
slot4: sensor.home_hourly_forecast_wind_bearing_h4
wind_speed:
slot1: sensor.home_hourly_forecast_wind_speed_h1
slot2: sensor.home_hourly_forecast_wind_speed_h2
slot3: sensor.home_hourly_forecast_wind_speed_h3
slot4: sensor.home_hourly_forecast_wind_speed_h4
```
### **Marine Daily Forecast Layer**
This layer provides daily marine weather forecasts, including information such as wave height, wind speed, and sea conditions.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
marine_daily_forecasts:
wave_height_max:
slot1: sensor.marine_wave_height_max_day_0
slot2: sensor.marine_wave_height_max_day_1
slot3: sensor.marine_wave_height_max_day_2
slot4: sensor.marine_wave_height_max_day_3
wave_direction:
slot1: sensor.marine_wave_direction_dominant_day_0
slot2: sensor.marine_wave_direction_dominant_day_1
slot3: sensor.marine_wave_direction_dominant_day_2
slot4: sensor.marine_wave_direction_dominant_day_3
swell_wave_height_max:
slot1: sensor.amarine_swell_wave_height_max_day_0
slot2: sensor.marine_swell_wave_height_max_day_1
slot3: sensor.marine_swell_wave_height_max_day_2
slot4: sensor.marine_swell_wave_height_max_day_3
wind_wave_height_max:
slot1: sensor.marine_wind_wave_height_max_day_0
slot2: sensor.marine_wind_wave_height_max_day_1
slot3: sensor.marine_wind_wave_height_max_day_2
slot4: sensor.marine_wind_wave_height_max_day_3
```
### **Alarms Layer**
This layer displays weather alerts and warnings from official sources such as Meteoalarm and the Italian Civil Protection Department (DPC).
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
weather:
icons_model: pirateweather
meteoalarm: binary_sensor.italy_basilicata_meteo_alarm
dpcalarm:
thunderstorms: binary_sensor.dpc_basilicata_temporali_oggi
hydraulic: binary_sensor.dpc_basilicata_idraulico_oggi
hydrogeological: binary_sensor.dpc_basilicata_idrogeologico_oggi
```
### **Ultraviolet Layer**
This layer presents real-time ultraviolet (UV) radiation data, including UV index levels, ozone concentration, and skin protection recommendations.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
ultraviolet:
protection_window: binary_sensor.openuv_protection_window
ozone_level: sensor.openuv_current_ozone_level
uv_index: sensor.openuv_current_uv_index
uv_level: sensor.openuv_current_uv_level
max_uv_index: sensor.openuv_max_uv_index
set_skin_type_1: sensor.openuv_skin_type_1_safe_exposure_time
set_skin_type_2: sensor.openuv_skin_type_2_safe_exposure_time
set_skin_type_3: sensor.openuv_skin_type_3_safe_exposure_time
set_skin_type_4: sensor.openuv_skin_type_4_safe_exposure_time
set_skin_type_5: sensor.openuv_skin_type_5_safe_exposure_time
set_skin_type_6: sensor.openuv_skin_type_6_safe_exposure_time
```
### **Pollen Layer**
This layer displays information about airborne pollen levels, helping users monitor potential allergen exposure.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
pollen:
min: 1
max: 4
entities:
- name: Alder
entity: sensor.openmeteo_pollen_alder_level
- name: Birch
entity: sensor.openmeteo_pollen_birch_level
- name: Grass
entity: sensor.openmeteo_pollen_grass_level
- name: Mugwort
entity: sensor.openmeteo_pollen_mugwort_level
- name: Olive
entity: sensor.openmeteo_pollen_olive_level
- name: Ragweed
entity: sensor.openmeteo_pollen_ragweed_level
```
### **Air Quality Layer**
This layer presents real-time data on key air quality indicators such as PM2.5, PM10, ozone, and nitrogen dioxide levels.
#### **YAML example**
```yaml
type: custom:ha-card-weather-conditions
language: it
airquality:
pm25: sensor.lazio_italy_pm2_5
pm10: sensor.lazio_italy_pm10
o3: sensor.roma_lazio_italy_ozone
co: sensor.roma_lazio_italy_carbon_monoxide
epa_aqi: sensor.lazio_italy_air_quality_index
epa_primary_pollutant: sensor.lazio_italy_dominant_pollutant
```
[license-shield]:https://img.shields.io/github/license/r-renato/ha-card-weather-conditions
[buymecoffee]: https://www.buymeacoffee.com/0D3WbkKrn
[buymecoffeebadge]: https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow?style=for-the-badge
================================================
FILE: package.json
================================================
{
"name": "ha-card-weather-conditions",
"version": "2.0.0",
"description": "Home Assistant lovelace card for display weather data.",
"keywords": [
"home-assistant",
"homeassistant",
"hass",
"automation",
"lovelace",
"custom-cards",
"weather"
],
"homepage": "https://github.com/r-renato/ha-card-weather-conditions#readme",
"module": "ha-card-weather-conditions.js",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/r-renato/ha-card-weather-conditions.git"
},
"author": "Renato Rossi",
"license": "MIT",
"dependencies": {
"@material/mwc-select": "^0.27.0",
"@material/mwc-textfield": "^0.27.0",
"color": "^4.2.3",
"custom-card-helpers": "^1.0.8",
"hammerjs": "^2.0.8",
"home-assistant-js-websocket": "^9.4.0",
"lit": "^3.2.1",
"memoize-one": "^6.0.0",
"object-hash": "^3.0.0",
"sortablejs": "^1.15.6",
"superstruct": "^2.0.2"
},
"devDependencies": {
"@babel/core": "^7.24.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.3",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.5",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.29.1",
"prettier": "^3.2.5",
"rollup": "^4.12.0",
"rollup-plugin-execute": "^1.1.1",
"typescript": "5.3.3"
},
"bugs": {
"url": "https://github.com/r-renato/ha-card-weather-conditions/issues"
},
"main": "index.js",
"scripts": {
"watch": "rollup -c --watch",
"build": "npm run lint && npm run rollup -- --config rollup.config.mjs",
"build:new": "npm run lint && npm run rollup -- --config rollup.new.config.mjs",
"lint": "eslint src/*.ts",
"rollup": "rollup --no-compact "
}
}
================================================
FILE: rollup.new.config.mjs
================================================
import resolve from '@rollup/plugin-node-resolve'; // ✅ nuovo package
import typescript from '@rollup/plugin-typescript'; // ✅ moderno
import babel from '@rollup/plugin-babel';
import terser from '@rollup/plugin-terser'; // ✅ va destrutturato
import execute from 'rollup-plugin-execute'; // ancora valido
import commonjs from '@rollup/plugin-commonjs'; // 👈 nuovo import
export default {
input: 'src/ha-weather-ecard.ts',
output: {
//dir: './dist',
file: 'dist/ha-card-weather-conditions.js', // 👈 nome file forzato
format: 'esm',
sourcemap: 'inline',
banner: false,
// comments: false
},
plugins: [
resolve({
browser: true, // 👈 molto importante per card frontend
exportConditions: ['browser']
}),
commonjs(), // 👈 serve per convertire eventuali commonjs a es6
typescript({
tsconfig: './tsconfig.json'
}),
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**',
extensions: ['.js', '.ts']
}),
terser(),
execute([
`echo "$(date '+%d/%m/%Y %H:%M:%S') rollup done." ; echo -e '\\007'`
])
]
};
================================================
FILE: src/base/lovelace-base.ts
================================================
/* eslint-disable no-underscore-dangle */
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from 'lit';
import { property } from 'lit/decorators.js';
import { HomeAssistant } from 'custom-card-helpers';
import { defaultColorCss, defaultDarkColorCss } from '../utils/colors';
import { iCardConfig, iLovelaceCardConfig } from '../utils/config-schema';
import {
cwcLocale,
hacsImagePath,
logo,
manImagePath,
optConsoleParam1,
optConsoleParam2,
optConsoleParam3,
} from '../utils/const';
import {
getIconModelData,
imageExist,
loadJSON,
logInfo,
} from '../utils/helper';
import { cwcClimacellDayIcons, cwcClimacellNightIcons } from '../iconmodels/im-climacell';
import { getCardStyles } from '../utils/helper-render';
import { cwcDaytimePirateWeatherIcons, cwcNightlyPirateWeaterIcons } from '../iconmodels/im-pirateweather';
export interface iTerms {
windDirections: string;
words: Record;
}
export interface iIconsConfig {
path: string ;
iconType: string ;
icons_model: string ;
iconsDay: { [key: string]: string; } ;
iconsNight: { [key: string]: string; } ;
}
export interface iLovelaceCard extends HTMLElement {
hass?: HomeAssistant;
isPanel?: boolean;
editMode?: boolean;
getCardSize(): number | Promise;
setConfig(config: iLovelaceCardConfig): void;
}
export function computeDarkMode(hass?: HomeAssistant): boolean {
if (!hass) return false;
return (hass.themes as any).darkMode as boolean;
}
/* -------------------- VARIABILI GLOBALI -------------------- */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// let loadedTranslations: any[] = [];
// let resolvedImagePath: string | null = null;
export async function preloadResources(): Promise<{ translations: any[]; imagePath: string | null }> {
const [hacsResult, manResult] = await Promise.all([
imageExist(`${hacsImagePath}/static/cloudy.svg`),
imageExist(`${manImagePath}/static/cloudy.svg`),
]);
let imagePath: string | null = null;
if (hacsResult) {
imagePath = hacsImagePath;
} else if (manResult) {
imagePath = manImagePath;
} else {
imagePath = null;
}
if (!imagePath) {
logInfo(`${logo} - Impossibile determinare il path immagini.`);
return { translations: [], imagePath: null };
}
const langs = ['en', 'it', 'nl', 'es', 'de', 'fr', 'sr-latn', 'pt', 'da', 'no-NO', 'cs'];
const translPath = `${imagePath}/../transl/`;
const translations = await Promise.all(langs.map((lang) => loadJSON(`${translPath}${lang}.json`)));
return { translations, imagePath };
}
export abstract class LovelaceBaseElement extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) protected _config?: iCardConfig;
public isPanel?: boolean = false;
public editMode?: boolean = false;
public invalidConfig: boolean = false;
protected _iconsConfig: iIconsConfig;
protected _imagesPath: string;
protected _name: string;
protected _language: string;
protected _translations: string[];
protected _terms: iTerms;
protected _hasPresent: boolean = false;
protected _hasDailyForecasts: boolean = false;
protected _hasHourlyForecasts: boolean = false;
protected _hasMarineDailyForecasts: boolean = false;
protected _hasMarineHourlyForecasts: boolean = false;
protected _hasMetealarm: boolean = false;
protected _hasDPCalarm: boolean = false;
protected _hasMeteogram: boolean = false;
protected _hasAirQuality: boolean = false;
protected _hasPollen: boolean = false;
protected _hasUltraviolet: boolean = false;
protected _hasAlert: boolean = false;
protected _hasSea: boolean = false;
protected _hasCamera: boolean = false;
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (changedProps.has('hass') && this.hass) {
const currentDarkMode = computeDarkMode(changedProps.get('hass'));
const newDarkMode = computeDarkMode(this.hass);
if (currentDarkMode !== newDarkMode) {
this.toggleAttribute('dark-mode', newDarkMode);
}
}
}
static get styles(): CSSResultGroup {
return [
// animations,
css`
:host {
${defaultColorCss}
}
:host([dark-mode]) {
${defaultDarkColorCss}
}
${getCardStyles()}
`,
];
}
public async setConfig(config: iCardConfig) {
if (!config) {
this.invalidConfig = true;
throw new Error('Invalid configuration');
}
// console.log({ card_config: config });
if (!this._translations?.length || !this._imagesPath) {
const { translations, imagePath } = await preloadResources();
this._translations = translations;
this._imagesPath = imagePath;
}
this._name = config?.weather?.name ?? undefined;
this._language = config.language?.toLowerCase() || 'en';
this._loadTranslations(this._language);
// this._initNumberFormatters(this._language);
// this._setupDisplaySections(config.display ?? []);
this._detectDataSections(config);
this._setupIcons(config.weather?.icons_model);
this._config = config;
logInfo(`${logo} - Config loaded.`);
}
// eslint-disable-next-line class-methods-use-this
public getCardSize(): number | Promise {
return 1;
}
private _loadTranslations(lang: string) {
try {
const transls = JSON.parse(this._translations[cwcLocale[lang]]);
this._terms = {
windDirections: transls.cwcLocWindDirections,
words: transls.cwcTerms,
};
logInfo(
`${logo}%c card "${this._name}", locale is '${lang}'.`,
optConsoleParam1,
optConsoleParam2,
optConsoleParam3,
);
} catch (e) {
const fallback = 'en';
const transls = JSON.parse(this._translations[cwcLocale[fallback]]);
this._terms = {
windDirections: transls.cwcLocWindDirections,
words: transls.cwcTerms,
};
logInfo(
`${logo}%c card "${this._name}" unable to use '${lang}' locale, set as default '${fallback}'.`,
optConsoleParam1,
optConsoleParam2,
optConsoleParam3,
);
}
}
private _detectDataSections(config: iCardConfig) {
this._hasPresent = !!config.weather?.present;
this._hasDailyForecasts = !!config.weather?.daily_forecasts;
this._hasHourlyForecasts = !!config.weather?.hourly_forecasts;
this._hasMarineDailyForecasts = !!config.weather?.marine_daily_forecasts;
this._hasMarineHourlyForecasts = !!config.weather?.marine_hourly_forecasts;
this._hasMetealarm = !!config.weather?.meteoalarm;
this._hasDPCalarm = !!config.weather?.dpcalarm;
// this._hasMeteogram = !!config.weather?.forecast?.meteogram;
this._hasAirQuality = !!config.airquality;
this._hasPollen = config.pollen && Array.isArray(config.pollen.entities) && config.pollen.entities.length > 0;
this._hasUltraviolet = !!config.ultraviolet;
this._hasCamera = !!config.camera;
// this._hasAlert = !!config.alert;
}
private _setupIcons(iconsModel?: string) {
this._iconsConfig = {
path: this._imagesPath,
iconType: this._config?.weather?.animation ? 'animated' : 'static',
icons_model: iconsModel || 'pirateweather',
iconsDay: cwcDaytimePirateWeatherIcons,
iconsNight: cwcNightlyPirateWeaterIcons,
};
if (iconsModel) {
const modelData = getIconModelData(iconsModel);
this._iconsConfig.icons_model = modelData.iconsModel;
this._iconsConfig.iconsDay = modelData.iconsDay;
this._iconsConfig.iconsNight = modelData.iconsNight;
}
}
/**
* generates the card HTML
* @return {TemplateResult}
*/
public render(): TemplateResult {
if (this.invalidConfig) {
return html`
Configuration ERROR!
`;
}
return this._render();
}
protected abstract _render(): TemplateResult;
}
================================================
FILE: src/builder/b-airquality.ts
================================================
/* eslint-disable camelcase */
/* eslint-disable no-else-return */
/* eslint-disable object-curly-newline */
import { HomeAssistant } from 'custom-card-helpers/dist';
import { iAirQuality } from '../utils/config-schema';
import { getEntityNumericValue, getEntityRawValue, getEntityUnit } from '../utils/helper';
import { renderWeatherPresent } from '../templates/t-present';
/**
* Restituisce un colore (in formato hex) in base al valore dell'indice EPA AQI.
* @param {number} aqi - Valore AQI compreso tra 0 e 500
* @returns {string} - Colore esadecimale associato alla fascia AQI
*/
function getAQIColor(aqi: number): string {
if (aqi <= 50) {
return '#009966'; // Verde (Buona)
} else if (aqi <= 100) {
return '#ffde33'; // Giallo (Moderata)
} else if (aqi <= 150) {
return '#ff9933'; // Arancione (Sensibili)
} else if (aqi <= 200) {
return '#cc0033'; // Rosso (Non salutare)
} else if (aqi <= 300) {
return '#660099'; // Viola (Molto non salutare)
} else {
return '#7e0023'; // Marrone scuro (Pericolosa)
}
}
const buildAirQuality = (
hass: HomeAssistant,
language: string,
airquality: iAirQuality,
) => {
const lang = language || hass.selectedLanguage || hass.language;
const pm25 = getEntityNumericValue({ entityId: airquality.pm25, hass, lang: language, decimals: 0 });
const pm10 = getEntityNumericValue({ entityId: airquality.pm10, hass, lang: language, decimals: 0 });
const o3 = getEntityNumericValue({ entityId: airquality.o3, hass, lang: language, decimals: 1 });
const no2 = getEntityNumericValue({ entityId: airquality.no2, hass, lang: language, decimals: 0 });
const co = getEntityNumericValue({ entityId: airquality.co, hass, lang: language, decimals: 1 });
const so2 = getEntityNumericValue({ entityId: airquality.so2, hass, lang: language, decimals: 0 });
const epa_aqi = getEntityNumericValue({ entityId: airquality.epa_aqi, hass, lang: language, decimals: 0 });
const epa_primary_pollutant = getEntityRawValue(hass, airquality.epa_primary_pollutant);
const airQualityData = {
pm25: {
value: (pm25 ? `pm2.5 ${pm25}` : pm25),
unit: getEntityUnit(hass, airquality.pm25) || 'µg/m³',
icon: 'mdi:weather-hazy',
},
pm10: {
value: (pm10 ? `pm10 ${pm10}` : pm10),
unit: getEntityUnit(hass, airquality.pm10) || 'µg/m³',
icon: 'mdi:weather-hazy',
},
o3: {
value: (o3 ? `o3 ${o3}` : o3),
unit: getEntityUnit(hass, airquality.o3) || 'µg/m³',
icon: 'mdi:molecule',
},
no2: {
value: (no2 ? `no2 ${no2}` : no2),
unit: getEntityUnit(hass, airquality.no2) || 'µg/m³',
icon: 'mdi:molecule',
},
co: {
value: (co ? `co ${co}` : co),
unit: getEntityUnit(hass, airquality.co) || 'µg/m³',
icon: 'mdi:molecule',
},
so2: {
value: (so2 ? `so2 ${so2}` : so2),
unit: getEntityUnit(hass, airquality.so2) || 'µg/m³',
icon: 'mdi:molecule',
},
epa_aqi: {
value: (epa_aqi ? `Air Quality Index ${epa_aqi}` : epa_aqi),
// unit: getEntityUnit(hass, airquality.epa_aqi) || 'µg/m³',
icon: 'mdi:weather-hazy',
icon_color: getAQIColor(Number(getEntityRawValue(hass, airquality.epa_aqi))),
},
epa_primary_pollutant: {
value: (epa_primary_pollutant ? `Primary ${epa_primary_pollutant}` : epa_primary_pollutant),
// unit: getEntityUnit(hass, airquality.epa_aqi) || 'µg/m³',
icon: 'mdi:weather-hazy',
},
};
return renderWeatherPresent(airQualityData, lang);
};
export default buildAirQuality;
================================================
FILE: src/builder/b-camera.ts
================================================
import { HomeAssistant } from 'custom-card-helpers/dist';
import { iTerms } from '../base/lovelace-base';
import renderCamera from '../templates/t-camera';
const buildCamera = (
hass: HomeAssistant,
lang: string,
terms: iTerms,
handlePopup: (e: Event, entityId: string) => void,
cameraId: string,
) => {
const camera = cameraId && hass.states[cameraId];
const entityPicture = camera?.attributes?.entity_picture;
const friendlyName = camera?.attributes?.friendly_name ?? cameraId;
return renderCamera(handlePopup, cameraId, entityPicture, friendlyName);
};
export default buildCamera;
================================================
FILE: src/builder/b-meteoalarm.ts
================================================
/* eslint-disable camelcase */
/* eslint-disable quote-props */
import { HomeAssistant } from 'custom-card-helpers/dist';
import { iTerms } from '../base/lovelace-base';
import { iDPCAlert } from '../utils/config-schema';
import renderMeteoDPCalarm, { iWeatherMeteoDPCAlarmDataInterface } from '../templates/t-meteoalarm';
import { getLocaleInfo } from '../utils/helper';
const getEffectiveLabel = (effective: string) => {
const effectiveDatetime = new Date(effective);
const now = new Date();
// Reset dell'ora per confronto solo a livello di giorno
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const effectiveDate = new Date(effectiveDatetime.getFullYear(), effectiveDatetime.getMonth(), effectiveDatetime.getDate());
const msInDay = 24 * 60 * 60 * 1000;
const dayDifference = Math.round((effectiveDate.getTime() - today.getTime()) / msInDay);
let effectiveLabel: 'oggi' | 'domani' | 'dopodomani' | undefined;
if (dayDifference === 0) {
effectiveLabel = 'oggi';
} else if (dayDifference === 1) {
effectiveLabel = 'domani';
} else if (dayDifference === 2) {
effectiveLabel = 'dopodomani';
} else {
effectiveLabel = undefined;
}
return effectiveLabel;
};
const buildMeteoAlarmData = (
hass: HomeAssistant,
lang: string,
terms: iTerms,
meteoalarmId: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Record => {
const eventIcon: Record = {
'wind': 'mdi:weather-windy',
'snow-ice': 'mdi:snowflake-alert',
'thunderstorm': 'mdi:weather-lightning',
'fog': 'mdi:weather-fog',
'high-temperature': 'mdi:weather-sunny-alert',
'low-temperature': 'mdi:thermometer-low',
'coastal-event': 'mdi:home-flood',
'forest-fire': 'mdi:pine-tree-fire',
'avalanche': 'mdi:image-filter-hdr',
'rain': 'mdi:weather-pouring',
'flood': 'mdi:home-flood',
'rain-flood': 'mdi:weather-pouring',
'marine-hazard': 'mdi:weather-hurricane',
'drought': 'mdi:water-off',
};
const eventIconColor: Record = {
green: 'green',
yellow: '#ffa600',
orange: 'orange',
red: 'red',
};
const meteoalarm = meteoalarmId && hass.states[meteoalarmId];
if (!meteoalarm?.attributes) return {};
const fpcData: Record = {};
if (meteoalarm.state === 'on' && meteoalarm.attributes) {
const localeInfo = getLocaleInfo(lang);
const {
event,
severity,
awareness_type,
awareness_level,
effective,
} = meteoalarm.attributes;
const awarenessType = awareness_type?.split(';')[1]?.trim().toLowerCase() || '';
const awarenessLevel = awareness_level?.split(';')[1]?.trim().toLowerCase() || '';
const eventName = event || '';
const severityLevel = severity?.split(';')[1]?.trim() || '';
const effectiveDatetime = getEffectiveLabel(effective);
fpcData['meteoalarm'] = {
event: eventName,
severity: severityLevel,
icon: eventIcon[awarenessType] || 'mdi:alert',
icon_color: eventIconColor[awarenessLevel] || 'grey',
datetime: (new Date(effective)).toLocaleDateString(localeInfo.locale, {
weekday: 'short',
timeZone: localeInfo.timezone,
}).toLocaleUpperCase(),
};
}
return fpcData;
};
const buildDPCAlarmData = (
hass: HomeAssistant,
lang: string,
terms: iTerms,
dpcalarm: iDPCAlert,
) => {
if (!dpcalarm) return {};
const localeInfo = getLocaleInfo(lang);
const eventIconColor = {
0: 'gray',
1: 'green',
2: '#ffa600',
3: 'orange',
4: 'red',
};
const sources = ['thunderstorms', 'hydraulic', 'hydrogeological'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const fpcData: Record = {};
sources.forEach((key) => {
const entityId = dpcalarm[key as keyof iDPCAlert];
const entity = entityId && hass.states[entityId];
if (entity && entity.state === 'on' && entity.attributes) {
const { level, info, icon } = entity.attributes;
fpcData[key] = {
event: info,
severity: level,
icon,
icon_color: eventIconColor[level],
datetime: (new Date()).toLocaleDateString(localeInfo.locale, {
weekday: 'short',
timeZone: localeInfo.timezone,
}).toLocaleUpperCase(),
};
}
});
return fpcData;
};
const buildMeteoDPCalarm = (
hass: HomeAssistant,
lang: string,
terms: iTerms,
meteoalarmId: string,
dpcalarm: iDPCAlert,
) => {
const alarmsData = { ...buildMeteoAlarmData(hass, lang, terms, meteoalarmId), ...buildDPCAlarmData(hass, lang, terms, dpcalarm) };
// console.debug('buildMeteoDPCalarm', alarmsData);
return renderMeteoDPCalarm(alarmsData);
};
export default buildMeteoDPCalarm;
================================================
FILE: src/builder/b-pollen.ts
================================================
import { HomeAssistant } from 'custom-card-helpers/dist';
import { iPollen } from '../utils/config-schema';
import { getEntityRawValue, string2Number } from '../utils/helper';
import { iPollenData, renderPollen } from '../templates/t-pollen';
const buildPollen = (hass: HomeAssistant, lang: string, pollen: iPollen) => {
const allItems: iPollenData[] = [];
if (Array.isArray(pollen.entities) && pollen.entities.length > 0) {
pollen.entities.forEach((item) => {
const rawvalue = getEntityRawValue(hass, item.entity);
if (rawvalue && rawvalue !== 'unknown' && rawvalue !== 'unavailable') {
let value: number = string2Number(getEntityRawValue(hass, item.entity));
if (Number.isNaN(value) || value < pollen.min || value > pollen.max) {
value = 0;
}
allItems.push({
name: item.name,
value,
});
}
// console.log(`Nome: ${item.name}, Entità: ${item.entity}`);
});
}
return renderPollen(allItems, pollen.min, pollen.max);
};
export default buildPollen;
================================================
FILE: src/builder/b-present.ts
================================================
/* eslint-disable camelcase */
import { HomeAssistant } from 'custom-card-helpers/dist';
import {
getEntityNumericValue,
getEntityRawValue,
getEntityUnit,
getLocaleInfo,
getWindDirections,
} from '../utils/helper';
// import { getSensorUnit } from '../utils/helper-render';
import { renderWeatherPresent } from '../templates/t-present';
import { iPresentData } from '../utils/config-schema';
import { iTerms } from '../base/lovelace-base';
const present = (hass: HomeAssistant, language: string, cwcLocWindDirections, presentData: iPresentData, sunId: string) => {
const localeInfo = getLocaleInfo(language);
const sunEntity = sunId ? hass.states[sunId] : undefined;
const { next_rising, next_setting } = sunEntity?.attributes ?? {};
const next_rising_formatted = next_rising ? new Date(next_rising).toLocaleTimeString(localeInfo.locale, {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: localeInfo.timezone,
}) : undefined;
const next_setting_formatted = next_rising ? new Date(next_setting).toLocaleTimeString(localeInfo.locale, {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: localeInfo.timezone,
}) : undefined;
return {
nextRising: { value: next_rising_formatted, icon: 'mdi:weather-sunset-up' },
nextSetting: { value: next_setting_formatted, icon: 'mdi:weather-sunset-down' },
precipitationIntensity: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.precipitation_intensity, hass, lang: language, decimals: 2 }),
unit: getEntityUnit(hass, presentData.precipitation_intensity),
icon: 'mdi:weather-rainy',
},
precipitationProbability: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.precipitation_probability, hass, lang: language, decimals: 0 }),
unit: getEntityUnit(hass, presentData.precipitation_probability),
icon: 'mdi:weather-rainy',
},
humidity: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.humidity, hass, lang: language, decimals: 0 }),
unit: getEntityUnit(hass, presentData.humidity),
icon: 'mdi:water-percent',
},
windBearing: { value: getWindDirections(getEntityRawValue(hass, presentData.wind_bearing), cwcLocWindDirections) },
windSpeed: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.wind_speed, hass, lang: language, decimals: 0 }),
unit: getEntityUnit(hass, presentData.wind_speed),
icon: 'mdi:weather-windy',
},
pressure: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.pressure, hass, lang: language, decimals: 0 }),
unit: getEntityUnit(hass, presentData.pressure),
icon: 'mdi:gauge',
},
visibility: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.visibility, hass, lang: language, decimals: 0 }),
unit: getEntityUnit(hass, presentData.visibility),
icon: 'mdi:weather-fog',
},
temperatureHigh: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.temperature_max, hass, lang: language, decimals: 0 }),
unit: getEntityUnit(hass, presentData.temperature_max),
icon: 'mdi:thermometer',
},
temperatureLow: {
// eslint-disable-next-line object-curly-newline
value: getEntityNumericValue({ entityId: presentData.temperature_min, hass, lang: language, decimals: 0 }),
unit: getEntityUnit(hass, presentData.temperature_min),
icon: 'mdi:thermometer',
},
};
};
// const presentFromForecastData = (hass: HomeAssistant, language: string, forecastCfg: Forecast) => {
// const getValue = (obj: Record) => {
// const [key, entityId] = Object.entries(obj)[0] ?? [];
// const state = entityId && hass.states[entityId]?.state;
// return state !== undefined ? formatNumber({ stringNumber: state, lang: language, fractionDigits: 0 }) : undefined;
// };
// const {
// temperature_high = {},
// temperature_low = {},
// precipitation_probability = {},
// precipitation_intensity = {},
// } = forecastCfg;
// return {
// temperatureHigh: { value: getValue(temperature_high), unit: getEntityUnit(hass, temperature_high), icon: 'mdi:thermometer' },
// temperatureLow: { value: getValue(temperature_low), unit: getEntityUnit(hass, 'temperature'), icon: 'mdi:thermometer' },
// precipitationProbability: { value: getValue(precipitation_probability), unit: '%', icon: 'mdi:weather-rainy' },
// precipitationIntensity: { value: getValue(precipitation_intensity), unit: getEntityUnit(hass, 'precipitation'), icon: 'mdi:weather-rainy' },
// };
// };
const buildWeatherPresent = (
hass: HomeAssistant,
language: string,
terms: iTerms,
presentData: iPresentData,
sunId: string,
) => {
const lang = language || hass.selectedLanguage || hass.language;
const presentObj = present(hass, lang, terms.windDirections, presentData, sunId);
// const presentFromForecastObj = presentFromForecastData(hass, language, forecastCfg);
// console.debug('buildWeatherPresent', { presentObj });
return renderWeatherPresent({ ...presentObj }, lang);
};
export default buildWeatherPresent;
================================================
FILE: src/builder/b-summary.ts
================================================
import { HomeAssistant } from 'custom-card-helpers/dist';
import renderWeatherSummary from '../templates/t-summary';
import {
getEntityNumericValue,
getEntityRawValue,
getEntityUnit,
translate,
} from '../utils/helper';
import { getMoonIcon, getWeatherIcon } from '../utils/helper-render';
import { iPresentData } from '../utils/config-schema';
import { iIconsConfig, iTerms } from '../base/lovelace-base';
const buildWeatherSummary = (
hass: HomeAssistant,
language: string,
terms: iTerms,
iconsConfig: iIconsConfig,
name: string,
presentData: iPresentData,
sunId: string,
moonphase: string,
) => {
const moonPhase = getEntityRawValue(hass, moonphase);
const moonIcon: string = moonPhase ? getMoonIcon(moonPhase) : '';
const sun = getEntityRawValue(hass, sunId);
const currentConditions = getEntityRawValue(hass, presentData.condition)?.toLowerCase() || 'na';
// eslint-disable-next-line max-len
const temperature = presentData.temperature ? getEntityNumericValue({ entityId: presentData.temperature, hass, lang: language }) ?? undefined : undefined;
// eslint-disable-next-line max-len
const temperatureFeelsLike = presentData.temperature_feelslike ? getEntityNumericValue({ entityId: presentData.temperature_feelslike, hass, lang: language }) ?? undefined : undefined;
const temperatureFeelsLikeIcon = hass.states[presentData.temperature_feelslike]?.attributes.icon ?? '';
return renderWeatherSummary({
title: name ?? undefined, // 'Verkhnenovokutlumbetyevo',
moonText: (moonphase ? translate(moonPhase, terms.words) : undefined),
moonIcon,
conditionText: currentConditions,
conditionIcon: getWeatherIcon(currentConditions, iconsConfig, sun),
temperature,
temperatureUnit: getEntityUnit(hass, presentData.temperature),
feelsLikeTerm: translate('Feels Like', terms.words),
temperatureFeelsLike,
temperatureFeelsLikeIcon,
});
};
export default buildWeatherSummary;
================================================
FILE: src/builder/b-ultraviolet.ts
================================================
import { HomeAssistant } from 'custom-card-helpers/dist';
import { getEntityNumericValue, getEntityRawValue, pad } from '../utils/helper';
import renderUltraviolet from '../templates/t-ultraviolet';
import { iUltraviolet } from '../utils/config-schema';
// const getRawValue = (hass: HomeAssistant, entityId?: string): string | undefined => entityId && hass.states[entityId]?.state;
// const getValue = (hass: HomeAssistant, entityId?: string, lang: string = 'en', decimals = 0): string | undefined => {
// const state = entityId && hass.states[entityId]?.state;
// return state !== undefined ? formatNumber(state, lang, decimals) : undefined;
// };
const getTime = (state?: string | number): string => {
const value = typeof state === 'string' && state.toLowerCase() === 'unknown'
? NaN
: Number(state);
// console.debug(state);
if (!Number.isFinite(value) || value < 0) return '--';
const hours = Math.floor(value / 60);
const minutes = value % 60;
return hours > 0
? `${hours}:${pad(minutes, 2)} h`
: `${minutes} m`;
};
const summaryData = (hass: HomeAssistant, lang: string, uv: iUltraviolet) => ({
protectionWindow: {
value: (!getEntityRawValue(hass, uv.protection_window) || getEntityRawValue(hass, uv.protection_window) === 'unknown' ? 'off' :
getEntityRawValue(hass, uv.protection_window)
),
icon: 'mdi:sunglasses',
},
currentUVLevel: { value: getEntityRawValue(hass, uv.uv_level), icon: 'mdi:weather-sunny' },
currentUVIndex: { value: getEntityNumericValue({ entityId: uv.uv_index, hass, lang }), unit: 'UV Idx', icon: 'mdi:weather-sunny' },
maxUVIndex: { value: getEntityNumericValue({ entityId: uv.max_uv_index, hass, lang }), unit: 'UV Idx', icon: 'mdi:weather-sunny' },
currentOzoneLevel: { value: getEntityNumericValue({ entityId: uv.ozone_level, hass, lang }), unit: 'DU', icon: 'mdi:vector-triangle' },
});
const skinData = (hass: HomeAssistant, lang: string, uv: iUltraviolet) => ({
skinType1: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_1, hass, lang })) },
skinType2: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_2, hass, lang })) },
skinType3: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_3, hass, lang })) },
skinType4: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_4, hass, lang })) },
skinType5: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_5, hass, lang })) },
skinType6: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_6, hass, lang })) },
});
const buildUltraviolet = (hass: HomeAssistant, lang: string, uv: iUltraviolet) =>
// eslint-disable-next-line implicit-arrow-linebreak
renderUltraviolet({ ...summaryData(hass, lang, uv) }, { ...skinData(hass, lang, uv) });
export default buildUltraviolet;
================================================
FILE: src/builder/b-weather-forecast.ts
================================================
import { HomeAssistant } from 'custom-card-helpers/dist';
import { getWeatherIcon } from '../utils/helper-render';
import { iIconsConfig, iTerms } from '../base/lovelace-base';
import {
getEntityIcon,
getEntityNumericValue,
getEntityRawAttribute,
getEntityRawValue,
getEntityUnit,
getLocaleInfo,
getWindDirections,
} from '../utils/helper';
import { iconPrecipitation, iconTemperature } from '../utils/const';
import { iForecastDataItem, renderWeatherForecast } from '../templates/t-weather-forecast';
import {
iDailyForecast,
iHourlyForecast,
iMarineDailyForecast,
iMarineHourlyForecast,
} from '../utils/config-schema';
const getDefaultIcon = (metric: string): string => {
if (metric.includes('temperature')) return iconTemperature;
if (metric.includes('precipitation')) return iconPrecipitation;
return 'mdi:help-circle-outline';
};
const buildHourlyForecastSlot = (
hass: HomeAssistant,
lang: string,
cwcLocWindDirections,
forecast: iHourlyForecast,
forecastType: number,
iconsConfig: iIconsConfig,
sunState: string,
slotId: string,
) => {
const record: Record = {};
const localeInfo = getLocaleInfo(lang);
let datetime: Date;
// Condizione meteo
if (forecast.condition && forecast.condition[slotId]) {
record['condition'] = {
img: getWeatherIcon(getEntityRawValue(hass, forecast.condition[slotId]), iconsConfig, sunState),
};
}
// Wind Bearing
if (forecast.wind_bearing && forecast.wind_bearing[slotId]) {
record['wind_bearing'] = {
value: getWindDirections(getEntityRawValue(hass, forecast.wind_bearing[slotId]), cwcLocWindDirections),
};
}
// Metriche da gestire
const metrics = [
'temperature',
'temperature_feelslike',
'precipitation_intensity',
'precipitation_probability',
'wind_speed',
];
metrics.forEach((metricKey) => {
const metricSlots = forecast[metricKey];
const entityId = metricSlots?.[slotId];
let decimals = 0;
if (!entityId) return;
if (metricKey === 'precipitation_intensity') decimals = 2;
datetime = new Date(getEntityRawAttribute(hass, entityId, 'datetime'));
record[metricKey] = {
value: getEntityNumericValue({
entityId, hass, lang, decimals,
}),
unit: getEntityUnit(hass, entityId),
img: getEntityIcon(hass, entityId) || getDefaultIcon(metricKey),
};
});
if (datetime && Object.keys(record).length > 0) {
const hourTime = datetime.toLocaleTimeString(localeInfo.locale, {
hour: '2-digit',
minute: '2-digit',
timeZone: localeInfo.timezone,
});
record['reference'] = {
value: (forecastType === 0 ? hourTime : hourTime),
};
}
return record;
};
const buildDailyForecastSlot = (
hass: HomeAssistant,
lang: string,
forecast: iDailyForecast,
forecastType: number,
iconsConfig: iIconsConfig,
sunState: string,
slotId: string,
) => {
const record: Record = {};
const localeInfo = getLocaleInfo(lang);
let datetime: Date;
// Gestione condizione meteo
if (forecast.condition && forecast.condition[slotId]) {
record['condition'] = {
img: getWeatherIcon(getEntityRawValue(hass, forecast.condition[slotId]), iconsConfig, sunState),
};
}
// Lista fissa delle metriche da considerare
const metrics = [
'temperature_high',
'temperature_low',
'precipitation_intensity',
'precipitation_probability',
];
metrics.forEach((metricKey) => {
const metricSlots = forecast[metricKey];
const entityId = metricSlots?.[slotId];
let decimals = 0;
if (!entityId) return;
if (metricKey === 'precipitation_intensity') {
decimals = 2;
}
datetime = new Date(getEntityRawAttribute(hass, entityId, 'datetime'));
// console.debug(`>>> ${entityId} ${lang} ${getEntityNumericValue({ entityId, hass, lang })}`);
record[metricKey] = {
value: getEntityNumericValue({
entityId, hass, lang, decimals,
}),
unit: getEntityUnit(hass, entityId),
img: getEntityIcon(hass, entityId) || getDefaultIcon(metricKey),
};
});
if (datetime && Object.keys(record).length > 0) {
// Giorno della settimana abbreviato (es. "Lun")
const weekday = datetime.toLocaleDateString(localeInfo.locale, {
weekday: 'short',
timeZone: 'UTC', // forza la lettura senza conversione locale
});
// Ora e minuti (es. "13:45")
const hourday = datetime.toLocaleTimeString(localeInfo.locale, {
hour: '2-digit',
minute: '2-digit',
timeZone: localeInfo.timezone,
});
record['reference'] = {
value: (forecastType === 0 ? weekday.toUpperCase() : hourday),
};
}
return record;
};
const buildMarineDailyForecastSlot = (
hass: HomeAssistant,
lang: string,
cwcLocWindDirections,
forecast: iMarineDailyForecast,
forecastType: number,
iconsConfig: iIconsConfig,
sunState: string,
slotId: string,
) => {
const record: Record = {};
const fieldColor = (
waveHeightMax: number,
swellWaveHeightMax: number,
windWaveHeightMax: number,
) => {
// 🟥 Bandiera rossa – condizioni pericolose
if (waveHeightMax >= 1.8) {
return 'red';
}
if (swellWaveHeightMax >= 1.5 && windWaveHeightMax >= 0.8) {
return 'red';
}
// 🟨 Bandiera gialla – condizioni da attenzionare
if (waveHeightMax >= 1.0) {
return 'yellow';
}
if (swellWaveHeightMax >= 0.8) {
return 'yellow';
}
if (windWaveHeightMax >= 0.6) {
return 'yellow';
}
// 🟩 Bandiera verde – condizioni sicure
return 'green';
};
const localeInfo = getLocaleInfo(lang);
let datetime: Date;
// Gestione condizione meteo
if (
forecast.wave_height_max &&
forecast.swell_wave_height_max &&
forecast.wind_wave_height_max &&
forecast.swell_wave_height_max[slotId] &&
forecast.wind_wave_height_max[slotId]
) {
record['condition'] = {
icon: 'mdi:flag-variant',
iconColor: fieldColor(forecast.wave_height_max[slotId], forecast.swell_wave_height_max[slotId], forecast.wind_wave_height_max[slotId]),
};
}
// Wind Bearing
if (forecast.wave_direction && forecast.wave_direction[slotId]) {
record['wave_direction'] = {
value: getWindDirections(getEntityRawValue(hass, forecast.wave_direction[slotId]), cwcLocWindDirections),
icon: getEntityRawValue(hass, forecast.wave_direction[slotId]),
};
}
// Lista fissa delle metriche da considerare
const metrics = [
'wave_height_max',
'swell_wave_height_max',
'wind_wave_height_max',
];
metrics.forEach((metricKey) => {
const metricSlots = forecast[metricKey];
const entityId = metricSlots?.[slotId];
const decimals = 1;
if (!entityId) return;
datetime = new Date(getEntityRawAttribute(hass, entityId, 'datetime'));
// console.debug(`>>> ${entityId} ${lang} ${getEntityNumericValue({ entityId, hass, lang })}`);
record[metricKey] = {
value: getEntityNumericValue({
entityId, hass, lang, decimals,
}),
unit: getEntityUnit(hass, entityId),
img: getEntityIcon(hass, entityId) || getDefaultIcon(metricKey),
};
});
if (datetime && Object.keys(record).length > 0) {
// Giorno della settimana abbreviato (es. "Lun")
const weekday = datetime.toLocaleDateString(localeInfo.locale, {
weekday: 'short',
timeZone: 'UTC', // forza la lettura senza conversione locale
});
// Ora e minuti (es. "13:45")
const hourday = datetime.toLocaleTimeString(localeInfo.locale, {
hour: '2-digit',
minute: '2-digit',
timeZone: localeInfo.timezone,
});
record['reference'] = {
value: (forecastType === 2 ? weekday.toUpperCase() : hourday),
};
}
return record;
};
const buildWeatherForecast = (
hass: HomeAssistant,
lang: string,
terms: iTerms,
dailyForecast: iDailyForecast,
hourlyForecast: iHourlyForecast,
marineDailyForecasts: iMarineDailyForecast,
marineHourlyForecasts: iMarineHourlyForecast,
forecastType: (0 | 1 | 2 | 3),
iconsConfig: iIconsConfig,
sunEntityId: string,
) => {
const voidRecord: Record[] = [];
const sunState = getEntityRawValue(hass, sunEntityId);
let dailyForecastData = voidRecord;
if (dailyForecast) {
const dailySlotIds = Object.keys(
dailyForecast.condition ||
dailyForecast.temperature_high || dailyForecast.temperature_low ||
dailyForecast.precipitation_intensity || dailyForecast.precipitation_probability ||
{},
);
dailyForecastData = dailySlotIds.map((slotId) => buildDailyForecastSlot(
hass,
lang,
dailyForecast,
forecastType,
iconsConfig,
sunState,
slotId,
));
}
let hourlyforecastData = voidRecord;
if (hourlyForecast) {
const hourlySlotIds = Object.keys(
hourlyForecast.condition ||
hourlyForecast.temperature || hourlyForecast.temperature_feelslike ||
hourlyForecast.precipitation_intensity || hourlyForecast.precipitation_probability ||
{},
);
hourlyforecastData = hourlySlotIds.map((slotId) => buildHourlyForecastSlot(
hass,
lang,
terms.windDirections,
hourlyForecast,
forecastType,
iconsConfig,
sunState,
slotId,
));
}
let marineDailyForecastData = voidRecord;
if (marineDailyForecasts) {
const marineDailySlotIds = Object.keys(
marineDailyForecasts.swell_wave_height_max ||
marineDailyForecasts.wave_direction || marineDailyForecasts.wave_height_max ||
marineDailyForecasts.wind_wave_height_max ||
{},
);
marineDailyForecastData = marineDailySlotIds.map((slotId) => buildMarineDailyForecastSlot(
hass,
lang,
terms.windDirections,
marineDailyForecasts,
forecastType,
iconsConfig,
sunState,
slotId,
));
}
switch (forecastType) {
case 0:
return renderWeatherForecast(forecastType, dailyForecastData);
case 1:
return renderWeatherForecast(forecastType, hourlyforecastData);
case 2:
return renderWeatherForecast(forecastType, marineDailyForecastData);
default:
return renderWeatherForecast(forecastType, voidRecord);
}
};
export default buildWeatherForecast;
================================================
FILE: src/css/css-base-card.ts
================================================
import { css } from 'lit';
const cardStyle = css`
ha-card {
cursor: pointer;
position: relative;
width: 100%;
}
.ha-card-weather-conditions {
width: 100%;
box-sizing: border-box;
background-color: var(--card-background-color, #1c1c1c);
color: var(--primary-text-color, #ffffff);
border-radius: var(--ha-card-border-radius, 12px);
box-shadow: var(--ha-card-box-shadow, 0 2px 6px rgba(0, 0, 0, 0.2));
overflow: hidden;
padding: 0;
display: flex;
flex-direction: column;
}
.nd-container {
width: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
padding: 16px 20px; /* ← padding orizzontale più ampio */
gap: 12px;
background-size: cover;
background-position: center;
transition: background-image 0.3s ease-in-out;
}
/* Esempio di stile dinamico aggiuntivo se habgImage è una classe */
.nd-container.sunny {
background-image: url('/local/images/sunny-bg.jpg');
}
.nd-container.rainy {
background-image: url('/local/images/rainy-bg.jpg');
}
/* -------------- */
`;
export default cardStyle;
================================================
FILE: src/css/css-camera.ts
================================================
import { css } from 'lit';
const cameraStyle = css`
.camera-container {
margin-top: 10px;
width: 100%;
display: flex;
align-items: stretch;
}
.camera-image {
aspect-ratio: 16 / 9;
width: 100%;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.camera-image > img {
width: 100%;
height: 100%;
object-fit: cover;
}
`;
export default cameraStyle;
================================================
FILE: src/css/css-meteoalarm.ts
================================================
import { css } from 'lit';
const meteodcpalarmStyle = css`
.meteodcpalarm-grid-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 16px;
padding: 12px;
}
.meteodcpalarm-group {
display: flex;
flex-direction: column;
align-items: center;
flex: 1 1 72px; /* 👈 cresce, ma non scende sotto i 72px */
max-width: 220px; /* 👈 opzionale: previene allargamento eccessivo */
text-align: center;
}
.meteodcpalarm-group ha-icon {
--mdc-icon-size: 36px;
}
.meteodcpalarm-label {
margin-top: 6px;
font-size: 0.85em;
color: var(--primary-text-color);
}
`;
export default meteodcpalarmStyle;
================================================
FILE: src/css/css-pollen.ts
================================================
import { css } from 'lit';
const pollenStyle = css`
.pollen-grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
gap: 8px 12px;
width: 100%;
justify-items: center;
align-items: end;
padding: 8px 4px;
box-sizing: border-box;
}
.pollen-stack {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
min-width: 48px;
}
.levels {
display: flex;
flex-direction: column-reverse;
gap: clamp(1px, 0.2vw, 2px);
}
.level {
width: clamp(16px, 3.5vw, 24px);
height: clamp(5px, 0.7vw, 8px); /* 👈 anche in altezza */
border-radius: 3px;
opacity: 0.3;
transition: opacity 0.2s ease;
}
.level.active {
opacity: 1;
outline: 1px solid #333;
}
.molto-alto {
background-color: #f44336;
}
.alto {
background-color: #ff9800;
}
.moderato {
background-color: #ffeb3b;
}
.basso {
background-color: #4caf50;
}
.pollen-name {
font-size: clamp(0.55em, 1.3vw, 0.85em); /* 👈 stringe di più */
// font-weight: 500;
text-align: center;
// color: #333;
white-space: nowrap;
}
.label {
width: 100%;
text-align: center;
font-size: clamp(0.55em, 1.3vw, 0.85em);
// font-weight: 500;
margin-top: clamp(4px, 0.5vw, 8px);
}
`;
export default pollenStyle;
================================================
FILE: src/css/css-present.ts
================================================
import { css } from 'lit';
const presentStyle = css`
.present-grid-container {
display: flex;
flex-direction: column;
gap: 4px;
}
.present-row {
display: flex;
justify-content: space-between;
gap: 16px;
}
.present-left,
.present-right {
flex: 1;
}
.present-left {
display: flex;
justify-content: flex-start;
}
.present-right {
display: flex;
justify-content: flex-end;
}
.present-value-block {
display: flex;
align-items: center;
gap: 4px;
}
.present-unit {
font-size: 0.9em;
opacity: 0.8;
}
`;
export default presentStyle;
================================================
FILE: src/css/css-summary.ts
================================================
import { css } from 'lit';
const summaryStyle = css`
.summary-grid-container {
position: relative;
z-index: 1;
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* <-- 3 colonne reali */
grid-template-rows: auto auto;
width: 100%;
max-width: 600px;
// background: #1c1c1c;
// color: white;
gap: 4px;
padding: 0px;
box-sizing: border-box;
// border: 1px solid #444; /* debug */
}
.summary-col-left {
grid-column: 1;
grid-row: 1 / span 2;
// background: #2c2c2c;
padding-top: 0px;
padding-right: 0px;
padding-bottom: 0px;
padding-left: 0px;
display: flex; /* Attiva Flexbox */
justify-content: center; /* Centra orizzontalmente */
align-items: center; /* Centra verticalmente */
width: 100%;
max-width: 100%;
aspect-ratio: 1 / 1; /* opzionale: mantiene forma quadrata */
overflow: hidden;
}
.summary-top-right {
grid-column: 2 / span 2; /* occupa colonne 2 e 3 */
grid-row: 1;
// background: #3c3c3c;
padding-top: 0px;
padding-right: 8px;
padding-bottom: 0px;
padding-left: 8px;
display: flex; /* aggiunto */
align-items: center; /* centra verticalmente */
justify-content: flex-start; /* allinea a sinistra */
}
.summary-bottom-right-left {
grid-column: 2;
grid-row: 2;
// background: #4c4c4c;
padding-top: 0px;
padding-right: 8px;
padding-bottom: 0px;
padding-left: 8px;
display: flex; /* Attiva Flexbox */
justify-content: center; /* Centra orizzontalmente */
align-items: center; /* Centra verticalmente */
}
.summary-bottom-right-right {
grid-column: 3;
grid-row: 2;
// background: #5c5c5c;
padding-top: 0px;
padding-right: 8px;
padding-bottom: 0px;
padding-left: 8px;
}
.weather-condition-icon {
width: 100%;
height: auto;
max-width: 100%;
max-height: 100%;
object-fit: contain;
// max-width: 100%;
// max-height: 100%;
// width: 72px;
// height: 72px;
// object-fit: contain;
transition: transform 0.2s ease;
}
.summary-col-left:hover .weather-condition-icon {
transform: scale(1.05);
}
.weather-city-name {
font-size: clamp(1em, 2vw, 1.2em);
text-align: left;
}
.moon-row {
display: flex;
align-items: center;
gap: 6px;
// font-size: 0.95em;
// color: #eeeeee;
}
.summary-moon-icon {
font-size: 1.8em;
display: inline-block;
}
.temperature-block {
display: flex;
flex-direction: column;
align-items: flex-end;
text-align: right;
}
.temperature {
font-size: 1.6em;
font-weight: bold;
}
.temp-unit {
font-size: 0.95em;
vertical-align: super;
margin-left: 2px;
}
.feels-like {
font-size: 0.85em;
// color: #aaaaaa;
}
.summary-wrapper {
position: relative;
width: 100%;
height: 100%;
min-height: 100px; /* oppure clamp() dinamico */
overflow: visible;
}
.lightning-background {
position: absolute;
inset: 0; /* top: 0; right: 0; bottom: 0; left: 0 */
pointer-events: none;
z-index: 0;
}
.lightning-flash {
position: absolute;
width: 2px;
background: white;
opacity: 0.7;
transform: translate(-50%, -50%);
animation-name: flash-blink;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
border-radius: 1px;
filter: blur(0.5px);
box-shadow: 0 0 4px rgba(255,255,255,0.6);
z-index: 0;
}
@keyframes flash-blink {
0%, 100% {
opacity: 0.1;
}
50% {
opacity: 0.9;
}
}
.lightning-flash-zigzag {
position: absolute;
width: 2px;
height: 0;
background: linear-gradient(to bottom, yellow, white);
clip-path: polygon(var(--points));
animation: flash-zigzag linear forwards;
z-index: 3;
}
@keyframes flash-zigzag {
0% {
opacity: 1;
transform: scaleY(1);
}
100% {
opacity: 0;
transform: scaleY(1.2);
}
}
.lightning-svg {
position: absolute;
transform: translate(-50%, 0);
opacity: 0;
filter: drop-shadow(0 0 4px rgba(98, 61, 173, 0.6));
animation-name: flash-zigzag-svg;
animation-timing-function: ease-in-out;
animation-iteration-count: 1;
z-index: 3;
}
@keyframes flash-zigzag-svg {
0%, 100% {
opacity: 0;
}
40% {
opacity: 1;
}
60% {
opacity: 0.5;
}
}
`;
export default summaryStyle;
================================================
FILE: src/css/css-ultraviolet.ts
================================================
import { css } from 'lit';
const ultravioletStyle = css`
.ultraviolet-grid-container {
display: flex;
flex-direction: column;
gap: 4px;
}
.ultraviolet-row {
display: flex;
justify-content: space-between;
gap: 16px;
}
.ultraviolet-left,
.present-right {
flex: 1;
}
.ultraviolet-left {
display: flex;
justify-content: flex-start;
}
.ultraviolet-right {
display: flex;
justify-content: flex-end;
}
.ultraviolet-value-block {
display: flex;
align-items: center;
gap: 4px;
}
.ultraviolet-unit {
font-size: 0.9em;
opacity: 0.8;
}
------------------------------------------------------------------
// .ultraviolet-grid-container {
// display: flex;
// flex-direction: column;
// gap: 12px;
// }
// .ultraviolet-row {
// display: flex;
// justify-content: space-between;
// padding: 4px 0;
// }
// .ultraviolet-value-block {
// display: flex;
// align-items: center;
// gap: 4px;
// }
// .ultraviolet-unit {
// font-size: 0.9em;
// opacity: 0.7;
// }
.ultraviolet-skin-type-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
gap: 8px;
margin-top: 8px;
}
.ultraviolet-skin-type-cell {
flex: 1;
min-width: 48px;
height: 48px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 6px;
font-family: 'Segoe UI', sans-serif;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
color: black;
}
.ultraviolet-skin-type-label {
font-weight: bold;
font-size: 0.95em;
line-height: 1em;
}
.ultraviolet-exposure-time {
font-size: 0.75em;
margin-top: 2px;
color: #222;
opacity: 0.85;
}
`;
export default ultravioletStyle;
================================================
FILE: src/css/css-weather-forecast.ts
================================================
import { css } from 'lit';
const weatherForecastStyle = css`
.weather-forecast-grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
column-gap: 2px; /* spazio orizzontale tra i giorni */
row-gap: 6px; /* spazio verticale tra righe, se ci sono */
align-items: stretch;
font-family: 'Segoe UI', sans-serif;
width: 100%;
}
.weather-forecast-grid-wrapper {
display: flex;
flex-direction: column;
align-items: center; /* centrare il titolo orizzontalmente */
}
.weather-forecast-title {
font-size: clamp(0.85em, 1vw, 0.95em);
font-weight: bold;
// margin-bottom: 0.5em;
text-align: center;
}
.weather-forecast-slot {
text-align: center;
padding: 8px 4px;
min-width: 0;
overflow: hidden;
}
.weather-forecast-slot:last-child {
border-right: none;
}
.weather-forecast-label-slot {
font-size: 0.9em;
font-weight: bold;
margin-bottom: 6px; /* ridotto */
}
.weather-forecast-icon {
font-size: 1.6rem; /* ridotto */
/* margin: 6px 0; ridotto */
height: 32px;
}
.weather-forecast-temperature {
font-size: clamp(0.8em, 1vw, 0.9em); /* leggermente più piccolo */
margin: 4px 0; /* meno margine */
}
.weather-forecast-temperature .high {
font-weight: bold;
}
.weather-forecast-precipitation {
font-size: clamp(0.65em, 1vw, 0.75em);
line-height: 1.2; /* compatta verticalmente */
}
.weather-forecast-precipitation .mm {
font-weight: bold;
}
`;
export default weatherForecastStyle;
================================================
FILE: src/ha-weather-ecard.ts
================================================
/* eslint-disable no-underscore-dangle */
import { html, TemplateResult } from 'lit';
import { customElement } from 'lit/decorators.js';
import { LovelaceBaseElement, preloadResources } from './base/lovelace-base';
import buildWeatherSummary from './builder/b-summary';
import buildWeatherPresent from './builder/b-present';
import buildUltraviolet from './builder/b-ultraviolet';
import buildPollen from './builder/b-pollen';
import buildWeatherForecast from './builder/b-weather-forecast';
import buildCamera from './builder/b-camera';
import buildAirQuality from './builder/b-airquality';
import buildMeteoDPCalarm from './builder/b-meteoalarm';
const { translations, imagePath } = await preloadResources(); // esecuzione immediata
/* -------------------- DEFINIZIONE COMPONENTE -------------------- */
@customElement('ha-card-weather-conditions')
// eslint-disable-next-line import/prefer-default-export
export class HaCardWeatherConditions extends LovelaceBaseElement {
_translations = translations;
_imagesPath = imagePath;
// eslint-disable-next-line class-methods-use-this
protected _render(): TemplateResult {
return html`
${this._buildTemplate()}
`;
}
private _buildTemplate(): TemplateResult {
let summary = html``;
let present = html``;
let dailyWeatherForecast = html``;
let hourlyWeatherForecast = html``;
let marineDailyWeatherForecast = html``;
let marineHourlyWeatherForecast = html``;
let meteoDPCalarm = html``;
let ultraviolet = html``;
let pollen = html``;
let airQuality = html``;
let camera = html``;
const getWeatherForecast = (mode: 0 | 1 | 2 | 3) => buildWeatherForecast(
this.hass,
this._language,
this._terms,
this._config.weather.daily_forecasts,
this._config.weather.hourly_forecasts,
this._config.weather.marine_daily_forecasts,
this._config.weather.marine_hourly_forecasts,
mode,
this._iconsConfig,
this._config.weather.sun,
);
if (this._hasPresent) {
summary = buildWeatherSummary(
this.hass,
this._language,
this._terms,
this._iconsConfig,
this._config.weather?.name,
this._config?.weather?.present || null,
this._config?.weather?.sun,
this._config?.weather?.moonphase,
);
}
if (this._hasPresent) {
present = buildWeatherPresent(
this.hass,
this._language,
this._terms,
this._config?.weather?.present || {},
this._config?.weather?.sun,
);
}
if (this._hasMetealarm || this._hasDPCalarm) {
meteoDPCalarm = buildMeteoDPCalarm(
this.hass,
this._language,
this._terms,
this._config?.weather?.meteoalarm,
this._config?.weather?.dpcalarm,
);
}
if (this._hasDailyForecasts) {
dailyWeatherForecast = getWeatherForecast(0);
}
if (this._hasHourlyForecasts) {
hourlyWeatherForecast = getWeatherForecast(1);
}
if (this._hasMarineDailyForecasts) {
marineDailyWeatherForecast = getWeatherForecast(2);
}
if (this._hasMarineHourlyForecasts) {
marineHourlyWeatherForecast = getWeatherForecast(3);
}
if (this._hasUltraviolet) {
ultraviolet = buildUltraviolet(this.hass, this._language, this._config.ultraviolet);
}
if (this._hasPollen) {
pollen = buildPollen(this.hass, this._language, this._config.pollen);
}
if (this._hasAirQuality) {
airQuality = buildAirQuality(this.hass, this._language, this._config.airquality);
}
if (this._hasCamera) {
camera = buildCamera(this.hass, this._language, this._terms, this._handlePopup.bind(this), this._config.camera);
}
return html`
${summary}
${present}
${hourlyWeatherForecast}
${dailyWeatherForecast}
${marineHourlyWeatherForecast}
${marineDailyWeatherForecast}
${meteoDPCalarm}
${pollen}
${ultraviolet}
${airQuality}
${camera}`;
}
/**
* Apre il popup di dettaglio per l'entità specificata.
* @param e L'evento click originale.
* @param entityId L'ID dell'entità Home Assistant da mostrare.
*/
protected _handlePopup(e: Event, entityId: string) {
e.stopPropagation();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const moreInfoEvent = new Event('hass-more-info', { composed: true }) as any;
moreInfoEvent.detail = { entityId };
this.dispatchEvent(moreInfoEvent);
}
}
================================================
FILE: src/iconmodels/im-buienradar.ts
================================================
// clear=ok, partlycloudy=ok, cloudy=ok, partlycloudy-fog=ok, partlycloudy-light-rain=ok, partlycloudy-rain=ok,
// light-rain=ok, rainy=ok, snowy-rainy=ok, partlycloudy-light-snow=ok, partlycloudy-snow=ok, light-snow=ok, snowy=ok,
// partlycloudy-lightning=ok or lightning
export const cwcBuienradarDayIcons: { [key: string]: string; } = {
// freezing_rain_heavy: 'rainy-3',
// freezing_rain: 'rainy-2',
// freezing_rain_light: 'rainy-1',
// freezing_drizzle: 'rain-and-sleet-mix',
// ice_pellets_heavy: 'rain-and-snow-mix',
// ice_pellets: 'rain-and-snow-mix',
// ice_pellets_light: 'rain-and-snow-mix',
snowy: 'snowy-3',
'light-snow': 'snowy-2',
'snowy-rainy': 'snowy-1',
'partlycloudy-light-snow': 'snowy-1',
'partlycloudy-snow': 'snowy-1',
// flurries: 'wind',
// tstorm: 'tropical-storm',
// rain_heavy: 'rainy-3',
'partlycloudy-light-rain': 'rainy-1',
'light-rain': 'rainy-1',
rainy: 'rainy-2',
'partlycloudy-rain': 'rainy-1',
// fog_light: 'haze',
'partlycloudy-fog': 'fog',
cloudy: 'cloudy-original',
// mostly_cloudy: 'cloudy-day-3',
partlycloudy: 'cloudy-day-2',
'partlycloudy-lightning': 'cloudy-day-1',
lightning: 'cloudy-day-1',
// mostly_clear: 'cloudy-day-1',
clear: 'day',
};
export const cwcBuienradarNightIcons: { [key: string]: string; } = {
...cwcBuienradarDayIcons,
// freezing_rain_heavy: 'rainy-6',
// freezing_rain: 'rainy-5',
// freezing_rain_light: 'rainy-4',
// freezing_drizzle: 'rain-and-sleet-mix',
// ice_pellets_heavy: 'rain-and-snow-mix',
// ice_pellets: 'rain-and-snow-mix',
// ice_pellets_light: 'rain-and-snow-mix',
// snow_heavy: 'snowy-6',
// snow: 'nowy-5',
// snow_light: 'nowy-4',
// flurries: 'wind',
// tstorm: 'tropical-storm',
// rain_heavy: 'rainy-6',
// rain_light: 'rainy-4',
// rain: 'rainy-5',
// drizzle: 'rainy-4',
// fog_light: 'haze',
// fog: 'fog',
// cloudy: 'cloudy',
// mostly_cloudy: 'cloudy-night-3',
// partly_cloudy: 'cloudy-night-2',
// mostly_clear: 'cloudy-night-1',
// clear: 'night'
};
================================================
FILE: src/iconmodels/im-climacell.ts
================================================
export const cwcClimacellDayIcons: { [key: string]: string; } = {
freezing_rain_heavy: 'rainy-3',
'heavy freezing rain': 'rainy-3',
freezing_rain: 'rainy-2',
'freezing rain': 'rainy-2',
freezing_rain_light: 'rainy-1',
'light freezing rain': 'rainy-1',
freezing_drizzle: 'rain-and-sleet-mix',
'freezing drizzle': 'rain-and-sleet-mix',
ice_pellets_heavy: 'rain-and-snow-mix',
'heavy ice pellets': 'rain-and-snow-mix',
ice_pellets: 'rain-and-snow-mix',
'ice pellets': 'rain-and-snow-mix',
ice_pellets_light: 'rain-and-snow-mix',
'light ice pellets': 'rain-and-snow-mix',
snow_heavy: 'snowy-3',
'heavy snow': 'snowy-3',
snow: 'snowy-2',
snow_light: 'snowy-1',
'light snow': 'snowy-1',
flurries: 'wind',
tstorm: 'tropical-storm',
rain_heavy: 'rainy-3',
'heavy rain': 'rainy-3',
rain_light: 'rainy-1',
'light rain': 'rainy-1',
rain: 'rainy-2',
drizzle: 'rainy-1',
fog_light: 'haze',
'light fog': 'haze',
fog: 'fog',
cloudy: 'cloudy-original',
mostly_cloudy: 'cloudy-day-3',
'mostly cloudy': 'cloudy-day-3',
partly_cloudy: 'cloudy-day-2',
'partly cloudy': 'cloudy-day-2',
mostly_clear: 'cloudy-day-1',
'mostly clear': 'cloudy-day-1',
clear: 'day',
};
export const cwcClimacellNightIcons: { [key: string]: string; } = {
...cwcClimacellDayIcons,
freezing_rain_heavy: 'rainy-6',
'heavy freezing rain': 'rainy-6',
freezing_rain: 'rainy-5',
'freezing rain': 'rainy-5',
freezing_rain_light: 'rainy-4',
'light freezing rain': 'rainy-4',
// freezing_drizzle: 'rain-and-sleet-mix',
// ice_pellets_heavy: 'rain-and-snow-mix',
// ice_pellets: 'rain-and-snow-mix',
// ice_pellets_light: 'rain-and-snow-mix',
snow_heavy: 'snowy-6',
'heavy snow': 'snowy-6',
snow: 'snowy-5',
snow_light: 'snowy-4',
'light snow': 'snowy-4',
// flurries: 'wind',
// tstorm: 'tropical-storm',
rain_heavy: 'rainy-6',
'heavy rain': 'rainy-6',
rain_light: 'rainy-4',
'light rain': 'rainy-4',
rain: 'rainy-5',
drizzle: 'rainy-4',
// fog_light: 'haze',
// fog: 'fog',
// cloudy: 'cloudy',
mostly_cloudy: 'cloudy-night-3',
'mostly cloudy': 'cloudy-night-3',
partly_cloudy: 'cloudy-night-2',
'partly cloudy': 'cloudy-night-2',
mostly_clear: 'cloudy-night-1',
'mostly clear': 'cloudy-night-1',
clear: 'night',
sunny: 'night',
};
export const cwcClimacellDayBg: { [key: string]: string; } = {
freezing_rain_heavy: 'rainy-3',
freezing_rain: 'rainy-2',
freezing_rain_light: 'rainy-1',
freezing_drizzle: 'rain-and-sleet-mix',
ice_pellets_heavy: 'rain-and-snow-mix',
ice_pellets: 'rain-and-snow-mix',
ice_pellets_light: 'rain-and-snow-mix',
snow_heavy: 'snowy-3',
snow: 'snowy-2',
snow_light: 'snowy-1',
flurries: 'wind',
tstorm: 'tropical-storm',
rain_heavy: 'rainy-3',
rain_light: 'rainy-1',
rain: 'rainy-2',
drizzle: 'rainy-1',
fog_light: 'haze',
fog: 'fog',
cloudy: 'cloudy-original',
mostly_cloudy: 'day-cloud-3.jpg',
partly_cloudy: 'day-cloud-2.jpg',
mostly_clear: 'day-cloud-1.jpg',
clear: 'day-clear.jpg',
};
================================================
FILE: src/iconmodels/im-darksky.ts
================================================
export const cwcDarkskyDayIcons: { [key: string]: string; } = {
clear: 'day',
'clear-day': 'day',
rain: 'rainy-2',
snow: 'snowy-2',
sleet: 'rain-and-sleet-mix',
wind: 'cloudy-day-1',
fog: 'fog',
cloudy: 'cloudy-original',
'partly-cloudy-day': 'cloudy-day-2',
};
export const cwcDarkskyNightIcons: { [key: string]: string; } = {
...cwcDarkskyDayIcons,
clear: 'night',
'clear-night': 'night',
wind: 'cloudy-night-1',
'partly-cloudy-day': 'cloudy-night-2',
'partly-cloudy-night': 'cloudy-night-2',
};
================================================
FILE: src/iconmodels/im-hass.ts
================================================
export const cwcDefaultHassDayIcons: { [key: string]: string } = {
cloudy: 'cloudy-day-3',
exceptional: 'severe-thunderstorm',
fog: 'fog',
hail: 'snow-and-sleet-mix',
lightning: 'severe-thunderstorm',
'lightning-rainy': 'scattered-thunderstorms',
partlycloudy: 'cloudy-day-3',
pouring: 'rainy-6',
rainy: 'rainy-5',
snowy: 'snowy-6',
'snowy-rainy': 'snow-and-sleet-mix',
sunny: 'clear-day',
windy: 'wind',
'windy-variant': 'wind',
};
export const cwcDefaultHassNightIcons: { [key: string]: string } = {
...cwcDefaultHassDayIcons,
'clear-night': 'clear-night',
};
================================================
FILE: src/iconmodels/im-openweathermap.ts
================================================
export const cwcOpenWeatherMapDayIcons: { [key: string]: string; } = {
'clear sky': 'day',
'few clouds': 'cloudy-day-1',
'scattered clouds': 'cloudy-day-2',
'broken clouds': 'cloudy-day-3',
'shower rain': 'rainy-3',
rain: 'rainy-2',
thunderstorm: 'tropical-storm',
snow: 'snowy-2',
mist: 'fog',
};
export const cwcOpenWeatherMapNightIcons: { [key: string]: string; } = {
...cwcOpenWeatherMapDayIcons,
'clear sky': 'day-night',
'few clouds': 'cloudy-night-1',
'scattered clouds': 'cloudy-night-2',
'broken clouds': 'cloudy-night-3',
};
================================================
FILE: src/iconmodels/im-pirateweather.ts
================================================
// Pirate Weather Icons
// clear-day, clear-night, rain, snow, sleet, wind, fog, cloudy, partly-cloudy-day and partly-cloudy-night
// mostly-clear-day, mostly-clear-night, mostly-cloudy-day, mostly-cloudy-night, possible-rain-day, possible-rain-night
// possible-snow-day, possible-snow-night, possible-sleet-day, possible-sleet-night, possible-precipitation-day
// possible-precipitation-night, precipitation, drizzle, light-rain, heavy-rain, flurries, light-snow, heavy-snow
// very-light-sleet, light-sleet, heavy-sleet, breezy, dangerous-wind
export const cwcDaytimePirateWeatherIcons: { [key: string]: string; } = {
freezing_rain_heavy: 'rainy-3',
'heavy freezing rain': 'rainy-3',
freezing_rain: 'rainy-2',
'freezing rain': 'rainy-2',
freezing_rain_light: 'rainy-1',
'light freezing rain': 'rainy-1',
freezing_drizzle: 'rain-and-sleet-mix',
sleet: 'rain-and-sleet-mix',
'freezing drizzle': 'rain-and-sleet-mix',
ice_pellets_heavy: 'rain-and-snow-mix',
'heavy ice pellets': 'rain-and-snow-mix',
ice_pellets: 'rain-and-snow-mix',
'ice pellets': 'rain-and-snow-mix',
ice_pellets_light: 'rain-and-snow-mix',
'light ice pellets': 'rain-and-snow-mix',
snow_heavy: 'snowy-3',
'heavy snow': 'snowy-3',
snow: 'snowy-2',
snow_light: 'snowy-1',
'light snow': 'snowy-1',
flurries: 'wind',
tstorm: 'tropical-storm',
rain_heavy: 'rainy-3',
'heavy rain': 'rainy-3',
rain_light: 'rainy-1',
rainy: 'rainy-1',
'light rain': 'rainy-1',
rain: 'rainy-2',
drizzle: 'rainy-1',
fog_light: 'haze',
'light fog': 'haze',
fog: 'fog',
cloudy: 'cloudy-original',
mostly_cloudy: 'cloudy-day-3',
'mostly cloudy': 'cloudy-day-3',
partly_cloudy: 'cloudy-day-2',
partlycloudy: 'cloudy-day-2',
'partly-cloudy-day': 'cloudy-day-2',
'partly cloudy': 'cloudy-day-2',
mostly_clear: 'cloudy-day-1',
'mostly clear': 'cloudy-day-1',
clear: 'day',
'clear-day': 'day',
wind: 'wind',
windy: 'wind',
sunny: 'day',
'clear-night': 'day',
};
export const cwcNightlyPirateWeaterIcons: { [key: string]: string; } = {
...cwcDaytimePirateWeatherIcons,
freezing_rain_heavy: 'rainy-6',
'heavy freezing rain': 'rainy-6',
freezing_rain: 'rainy-5',
'freezing rain': 'rainy-5',
freezing_rain_light: 'rainy-4',
'light freezing rain': 'rainy-4',
// freezing_drizzle: 'rain-and-sleet-mix',
// ice_pellets_heavy: 'rain-and-snow-mix',
// ice_pellets: 'rain-and-snow-mix',
// ice_pellets_light: 'rain-and-snow-mix',
snow_heavy: 'snowy-6',
'heavy snow': 'snowy-6',
snow: 'snowy-5',
snow_light: 'snowy-4',
'light snow': 'snowy-4',
// flurries: 'wind',
// tstorm: 'tropical-storm',
rain_heavy: 'rainy-6',
'heavy rain': 'rainy-6',
rain_light: 'rainy-4',
'light rain': 'rainy-4',
rain: 'rainy-5',
drizzle: 'rainy-4',
// fog_light: 'haze',
// fog: 'fog',
// cloudy: 'cloudy',
mostly_cloudy: 'cloudy-night-3',
'mostly cloudy': 'cloudy-night-3',
partly_cloudy: 'cloudy-night-2',
partlycloudy: 'cloudy-night-2',
'partly-cloudy-night': 'cloudy-night-2',
'partly cloudy': 'cloudy-night-2',
mostly_clear: 'cloudy-night-1',
'mostly clear': 'cloudy-night-1',
clear: 'night',
'clear-night': 'night',
sunny: 'night',
};
================================================
FILE: src/templates/t-camera.ts
================================================
import { html } from 'lit';
const renderCamera = (
handlePopup: (e: Event, entityId: string) => void,
cameraId: string,
cameraPicture: string,
friendlyName: string,
) => {
if (!cameraPicture) return html``;
return html`
handlePopup(e, cameraId)}
>
`;
};
export default renderCamera;
================================================
FILE: src/templates/t-meteoalarm.ts
================================================
import { html } from 'lit';
export interface iWeatherMeteoDPCAlarmDataInterface {
event?: string,
severity?: string,
icon?: string,
icon_color?: string,
datetime?: string,
}
const renderMeteoDPCalarm = (
meteoDPCalarmData: Record | null,
) => {
if (!meteoDPCalarmData || Object.keys(meteoDPCalarmData).length === 0) return html``;
return html`
${Object.entries(meteoDPCalarmData).map(([key, data]) => html`
${data.datetime}
${data.event}
`)}
`;
};
export default renderMeteoDPCalarm;
================================================
FILE: src/templates/t-pollen.ts
================================================
import { html } from 'lit';
export interface iPollenData {
name: string;
value: number;
}
const LEVEL_NAMES = ['basso', 'moderato', 'alto', 'molto-alto', 'estremo'];
const getLevelIndex = (value: number, levelMin: number, levelMax: number): number => {
const range = levelMax - levelMin + 1;
const step = range / LEVEL_NAMES.length;
const index = Math.floor((value - levelMin) / step);
return Math.min(index, LEVEL_NAMES.length - 1);
};
export const renderPollen = (data: iPollenData[], levelMin: number, levelMax: number) => {
const numLevels = levelMax - levelMin + 1;
const levels = LEVEL_NAMES.slice(0, numLevels);
if (data.length === 0) {
return html``;
}
return html`
${data.map((item) => {
const activeIndex = getLevelIndex(item.value, levelMin, levelMax);
return html`
${levels.map((levelName, index) => html`
`)}
${item.name}
`;
})}
`;
};
================================================
FILE: src/templates/t-present.ts
================================================
import { html } from 'lit';
import { getLocale, parseLocalizedNumber } from '../utils/helper';
export interface iRenderDataItem {
value?: number | string | Date;
unit?: string;
icon?: string;
icon_color?: string;
}
export interface WeatherData {
temperatureHigh?: iRenderDataItem;
temperatureLow?: iRenderDataItem;
precipitationProbability?: iRenderDataItem;
precipitationIntensity?: iRenderDataItem;
nextRising?: iRenderDataItem;
nextSetting?: iRenderDataItem;
// precipitation?: iRenderDataItem;
humidity?: iRenderDataItem;
windBearing?: iRenderDataItem;
windSpeed?: iRenderDataItem;
pressure?: iRenderDataItem;
visibility?: iRenderDataItem;
}
export interface iAirQualityData {
pm25: iRenderDataItem,
pm10:iRenderDataItem,
o3: iRenderDataItem,
no2: iRenderDataItem,
co: iRenderDataItem,
so2: iRenderDataItem,
epa_aqi: iRenderDataItem,
epa_primary_pollutant: iRenderDataItem,
}
const isValidInput = (val: unknown): val is string | number => typeof val === 'string' || typeof val === 'number';
const prepareWeatherPresent = (data: WeatherData, language: string) => {
const allItems: iRenderDataItem[] = [];
const addIfValid = (key: keyof WeatherData, item?: iRenderDataItem) => {
if (item?.value === undefined) return;
allItems.push(item);
};
const pi = data.precipitationIntensity?.value;
const pp = data.precipitationProbability?.value;
if (isValidInput(pi) && isValidInput(pp)) {
const locale = getLocale(language);
const parsedPI = parseLocalizedNumber(pi, locale);
const parsedPP = parseLocalizedNumber(pp, locale);
if (!Number.isNaN(Number(parsedPI)) && !Number.isNaN(Number(parsedPP)) && parsedPI > 0 && parsedPP > 0) {
allItems.push({
icon:
data.precipitationIntensity.icon ||
data.precipitationProbability.icon ||
'mdi:weather-rainy',
// eslint-disable-next-line max-len
value: `${data.precipitationIntensity.value} ${data.precipitationIntensity.unit} / ${data.precipitationProbability.value} ${data.precipitationProbability.unit}`,
});
}
}
// Temperatura min/max combinata
if (
data.temperatureLow?.value !== undefined &&
data.temperatureHigh?.value !== undefined
) {
allItems.push({
icon: data.temperatureLow.icon || data.temperatureHigh.icon || 'mdi:thermometer',
value: `${data.temperatureLow.value} / ${data.temperatureHigh.value}`,
unit: data.temperatureLow.unit || data.temperatureHigh.unit,
});
}
const keys: (keyof WeatherData)[] = [
'humidity',
'pressure',
'visibility',
];
keys.forEach((k) => addIfValid(k, data[k]));
// Wind (bearing + speed)
// eslint-disable-next-line max-len
if (data.windSpeed?.value !== undefined || data.windBearing?.value !== undefined) {
allItems.push({
icon: data.windSpeed?.icon || 'mdi:weather-windy',
value: `${data.windBearing?.value ? `${data.windBearing.value} ` : ''}${data.windSpeed?.value ?? ''}`,
unit: data.windSpeed?.unit ? `${data.windSpeed.unit}` : '',
});
}
// Sun times
['nextRising', 'nextSetting'].forEach((k) => {
const item = data[k as keyof WeatherData];
if (item?.value) {
allItems.push({
icon: item.icon,
value: item.value,
unit: '',
});
}
});
return allItems;
};
const prepareAirQuality = (data: iAirQualityData, language: string) => {
const allItems: iRenderDataItem[] = [];
const addIfValid = (key: keyof iAirQualityData, item?: iRenderDataItem) => {
if (item?.value === undefined) return;
allItems.push(item);
};
const keys: (keyof iAirQualityData)[] = [
'epa_aqi',
'epa_primary_pollutant',
'pm25',
'pm10',
'o3',
'no2',
'co',
'so2',
];
keys.forEach((k) => addIfValid(k, data[k]));
return allItems;
};
export const renderWeatherPresent = (data, language: string) => {
const allItems: iRenderDataItem[] = [];
const buildBlockLeft = (item: iRenderDataItem) => html`
${item.value}${item.unit ? html`${item.unit} ` : ''}
`;
const buildBlockRight = (item: iRenderDataItem) => html`
${item.value}${item.unit ? html`${item.unit} ` : ''}
`;
allItems.push(...prepareWeatherPresent(data, language), ...prepareAirQuality(data, language));
const rows = [];
for (let i = 0; i < allItems.length; i += 2) {
const left = allItems[i];
const right = allItems[i + 1];
if ((left && left.value) || (right && right.value)) {
rows.push(html`
${left ? buildBlockLeft(left) : html``}
${right ? buildBlockRight(right) : html``}
`);
}
}
return rows.length > 0 ? html`
${rows}
` : html``;
};
================================================
FILE: src/templates/t-summary.ts
================================================
import { html, nothing } from 'lit';
export interface WeatherSummaryInterface {
title?: string;
moonText?: string | undefined;
moonIcon?: string;
conditionText: string;
conditionIcon: string;
temperature?: string;
temperatureUnit?: string;
feelsLikeTerm?: string;
temperatureFeelsLike?: string;
temperatureFeelsLikeIcon?: string;
}
const renderLightningFlashZigzag = (xPercent: number, yPercent: number, segments: number = 7) => {
const width = 10; // larghezza in pixel della viewport SVG
const height = 20 + Math.random() * 50;
const points = [];
let x = width / 2;
let y = 0;
for (let i = 0; i < segments; i += 1) {
// x += (Math.random() * width - width / 2);
// y += height / segments;
x += (Math.random() * width * 1.5 - width * 0.75); // maggiore zigzag
y += (height / segments) * (0.7 + Math.random() * 0.6); // lunghezza variabile
points.push(`${x},${y}`);
}
const pathD = `M${width / 2},0 ${points.map((p) => `L${p}`).join(' ')}`;
const delay = Math.random() * 15.5;
const duration = 0.2 + Math.random() * 0.3 * 33;
return html`
`;
};
const renderLightningFlashes = (azimuth: number, distance: number, strikes: number) => {
const flashes = [];
for (let i = 0; i < strikes; i += 1) {
const x = Math.random() * 100;
const y = Math.random() * 20;
flashes.push(renderLightningFlashZigzag(x, y));
}
return flashes;
};
const renderWeatherSummary = ({
title,
moonText,
moonIcon,
conditionText,
conditionIcon,
temperature,
temperatureUnit,
feelsLikeTerm,
temperatureFeelsLike,
temperatureFeelsLikeIcon,
}: WeatherSummaryInterface) => {
const lightningAzimuth = 0; // Replace with actual data
const lightningDistanceKm = 0; // Replace with actual data
const lightningStrikes = 0; // Replace with actual data
const showLightning =
lightningStrikes > 0 &&
typeof lightningAzimuth === 'number' &&
typeof lightningDistanceKm === 'number';
if (conditionIcon || moonText || temperature) {
return html`
${showLightning ? html`
${renderLightningFlashes(lightningAzimuth!, lightningDistanceKm!, lightningStrikes)}
` : nothing}
${conditionIcon ? html`
` : nothing}
${title ? html`
${title}
` : nothing}
${moonText ? html`
` : nothing}
${temperature ? html`
${temperature}
${temperatureUnit}
${temperatureFeelsLike && html`
${feelsLikeTerm}
${temperatureFeelsLike} ${temperatureUnit}
`}
` : nothing}
`;
}
return html``;
};
export default renderWeatherSummary;
================================================
FILE: src/templates/t-ultraviolet.ts
================================================
import { html } from 'lit';
export interface RenderDataItem {
value?: number | string | Date;
unit?: string;
icon?: string;
}
export interface RenderData {
protectionWindow?: RenderDataItem,
currentUVLevel?: RenderDataItem,
currentUVIndex?: RenderDataItem,
maxUVIndex?: RenderDataItem,
currentOzoneLevel?: RenderDataItem,
}
export interface RenderSkinData {
skinType1: RenderDataItem,
skinType2: RenderDataItem,
skinType3: RenderDataItem,
skinType4: RenderDataItem,
skinType5: RenderDataItem,
skinType6: RenderDataItem,
}
const num = ['I', 'II', 'III', 'IV', 'V', 'VI'];
const colors = ['#F1D1B1', '#E4B590', '#CF9F7D', '#B67851', '#A15E2D', '#513938'];
const getTextColor = (hex: string): string => {
const c = hex.replace('#', '');
const r = parseInt(c.substr(0, 2), 16);
const g = parseInt(c.substr(2, 2), 16);
const b = parseInt(c.substr(4, 2), 16);
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
return brightness > 125 ? '#000' : '#fff';
};
const renderUltraviolet = (data: RenderData, skinData: RenderSkinData) => {
const allItems: RenderDataItem[] = [];
const buildBlockLeft = (item: RenderDataItem) => html`
${item.value}${item.unit ? html`${item.unit} ` : ''}
`;
const buildBlockRight = (item: RenderDataItem) => html`
${item.value}${item.unit ? html`${item.unit} ` : ''}
`;
const addIfValid = (key: keyof RenderData, item?: RenderDataItem) => {
if (item?.value === undefined) return;
allItems.push(item);
};
let keys: (keyof RenderData)[] = [
'protectionWindow',
'currentUVLevel',
];
keys.forEach((k) => addIfValid(k, data[k]));
// UV Level current/max combinata
if (
data.currentUVIndex?.value !== undefined &&
data.maxUVIndex?.value !== undefined
) {
allItems.push({
icon: data.currentUVIndex.icon || data.maxUVIndex.icon || 'mdi:weather-sunny',
value: `${data.currentUVIndex.value} / ${data.maxUVIndex.value}`,
unit: data.currentUVIndex.unit || data.maxUVIndex.unit,
});
}
keys = [
'currentOzoneLevel',
];
keys.forEach((k) => addIfValid(k, data[k]));
const summaryRows = [];
for (let i = 0; i < allItems.length; i += 2) {
const left = allItems[i];
const right = allItems[i + 1];
summaryRows.push(html`
${left ? buildBlockLeft(left) : html``}
${right ? buildBlockRight(right) : html``}
`);
}
const skinTypes = [
skinData.skinType1,
skinData.skinType2,
skinData.skinType3,
skinData.skinType4,
skinData.skinType5,
skinData.skinType6,
];
const renderSkinGrid = html`
${skinTypes.map((item, i) => {
const bgColor = colors[i];
const textColor = getTextColor(bgColor);
return html`
${num[i]}
${item.value || '--'}
`;
})}
`;
return html`
${summaryRows}
${renderSkinGrid}
`;
};
export default renderUltraviolet;
================================================
FILE: src/templates/t-weather-forecast.ts
================================================
/* eslint-disable max-len */
/* eslint-disable camelcase */
import { html } from 'lit';
export interface iForecastDataItem {
value?: number | string | Date;
unit?: string;
img?: string;
icon?: string;
iconColor?: string;
}
export const renderWeatherForecast = (forecastType: number, data: Record[]) => {
const rows = data.map((dayData) => {
const day = dayData.reference?.value;
const img = dayData.condition?.img;
const icon = dayData.condition?.icon;
const iconColor = dayData.condition?.iconColor;
const tempLow = dayData.temperature_low?.value;
const tempHigh = dayData.temperature_high?.value;
const tempHLUnit = dayData.temperature_high?.unit || dayData.temperature_low?.unit;
const precipProb: number = Number(dayData.precipitation_probability?.value ?? 0);
const precipInt = dayData.precipitation_intensity?.value;
const precipUnit = dayData.precipitation_intensity?.unit;
const temp = dayData.temperature?.value;
const tempUnit = dayData.temperature?.unit || dayData.temperature_feelslike?.unit;
const temp_feelslike = dayData.temperature_feelslike?.value;
const wind_speed = dayData.wind_speed?.value;
const wind_speedUnit = dayData.wind_speed?.unit;
const wind_bearing = dayData.wind_bearing?.value;
const wind_wave_height_max = dayData.wind_wave_height_max?.value;
const swell_wave_height_max = dayData.swell_wave_height_max?.value;
const wave_height_max = dayData.wave_height_max?.value;
const wave_direction = dayData.wave_direction?.value;
const wave_direction_degrees = dayData.wave_direction?.icon;
const wave_height_max_unit = dayData.wave_height_max?.unit;
return html`
${day ? html`
${day}
` : ''}
${img ? html`
` : ''}
${icon ? html`
` : ''}
${
tempLow !== undefined && tempHigh !== undefined
? html`
${tempLow} / ${tempHigh}${tempHLUnit ? ` ${tempHLUnit}` : ''}
`
: ''
}
${
temp !== undefined && temp_feelslike !== undefined
? html`
${temp} / ${temp_feelslike}${tempUnit ? ` ${tempUnit}` : ''}
`
: ''
}
${
wind_speed !== undefined && wind_bearing !== undefined
? html`
${wind_speed} ${wind_speedUnit} ${wind_bearing}
`
: ''
}
${
wave_height_max !== undefined
? html`
${wave_height_max} ${wave_height_max_unit ? ` ${wave_height_max_unit}` : ''}
`
: ''
}
${
wave_direction !== undefined
? html`
${wave_direction_degrees ? html` ` : ''} ${wave_direction}
`
: ''
}
${
wind_wave_height_max !== undefined && swell_wave_height_max !== undefined
? html`
${swell_wave_height_max} / ${wind_wave_height_max} ${wave_height_max_unit ? ` ${wave_height_max_unit}` : ''}
`
: ''
}
${
precipProb !== undefined && precipInt !== undefined && precipProb !== 0
? html`
${precipProb} % / ${precipInt}${precipUnit ? ` ${precipUnit}` : ''}
`
: ''
}
`;
});
let title = 'Daily';
if (forecastType === 1) {
title = 'Hourly';
} else if (forecastType === 2) {
title = 'Marine daily';
} else if (forecastType === 3) {
title = 'Marine hourly';
}
return html`
${title} forecast
${rows}
`;
};
================================================
FILE: src/utils/colors.ts
================================================
import { css } from 'lit';
import * as Color from 'color';
export const COLORS = [
'primary',
'accent',
'red',
'pink',
'purple',
'deep-purple',
'indigo',
'blue',
'light-blue',
'cyan',
'teal',
'green',
'light-green',
'lime',
'yellow',
'amber',
'orange',
'deep-orange',
'brown',
'light-grey',
'grey',
'dark-grey',
'blue-grey',
'black',
'white',
'disabled',
];
export function computeRgbColor(color: string): string {
if (color === 'primary' || color === 'accent') {
return `var(--rgb-${color}-color)`;
}
if (COLORS.includes(color)) {
return `var(--rgb-${color})`;
// eslint-disable-next-line no-else-return
} else if (color.startsWith('#')) {
try {
return Color.rgb(color).rgb().array().join(', ');
} catch (err) {
return '';
}
}
return color;
}
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
export function computeColorName(color: string): string {
return color
.split('-')
.map((s) => capitalizeFirstLetter(s))
.join(' ');
}
export const defaultColorCss = css`
--default-red: 244, 67, 54;
--default-pink: 233, 30, 99;
--default-purple: 146, 107, 199;
--default-deep-purple: 110, 65, 171;
--default-indigo: 63, 81, 181;
--default-blue: 33, 150, 243;
--default-light-blue: 3, 169, 244;
--default-cyan: 0, 188, 212;
--default-teal: 0, 150, 136;
--default-green: 76, 175, 80;
--default-light-green: 139, 195, 74;
--default-lime: 205, 220, 57;
--default-yellow: 255, 235, 59;
--default-amber: 255, 193, 7;
--default-orange: 255, 152, 0;
--default-deep-orange: 255, 111, 34;
--default-brown: 121, 85, 72;
--default-light-grey: 189, 189, 189;
--default-grey: 158, 158, 158;
--default-dark-grey: 96, 96, 96;
--default-blue-grey: 96, 125, 139;
--default-black: 0, 0, 0;
--default-white: 255, 255, 255;
--default-disabled: 189, 189, 189;
`;
export const defaultDarkColorCss = css`
--default-disabled: 111, 111, 111;
`;
================================================
FILE: src/utils/config-schema.ts
================================================
export interface iLovelaceCardConfig {
index?: number; // Indice della card all'interno della vista (opzionale).
view_index?: number; // Indice della vista in cui si trova la card (opzionale).
view_layout?: unknown; // Informazioni di layout (griglia, posizione, ecc.) per l'editor UI.
type: string; // Obbligatorio. Indica il tipo di card
[key: string]: unknown; // Permette di aggiungere parametri arbitrari, cioè supporta proprietà dinamiche definite dall’utente.
}
export interface iPresentData {
// sun?: string;
// moonphase?: string;
condition?: string;
temperature?: string;
temperature_feelslike?: string;
temperature_min?: string;
temperature_max?: string;
humidity?: string;
pressure?: string;
visibility?: string;
wind_bearing?: string;
wind_speed?: string;
precipitation_intensity?: string;
precipitation_probability?: string;
}
export interface iTimeSlots {
slot1: string;
slot2: string;
slot3: string;
slot4: string;
slot5: string;
slot6: string;
}
export interface iDailyForecast {
condition?: iTimeSlots;
temperature_high?: iTimeSlots;
temperature_low?: iTimeSlots;
precipitation_intensity?: iTimeSlots;
precipitation_probability?: iTimeSlots;
meteogram?: string ;
}
export interface iHourlyForecast {
condition?: iTimeSlots;
temperature?: iTimeSlots;
temperature_feelslike?: iTimeSlots;
precipitation_intensity?: iTimeSlots;
precipitation_probability?: iTimeSlots;
wind_bearing?: iTimeSlots;
wind_speed?: iTimeSlots;
}
export interface iMarineHourlyForecast {
swell_direction?: iTimeSlots ;
swell_height?: iTimeSlots ;
swell_period?: iTimeSlots ;
wind_direction: iTimeSlots ;
wind_speed: iTimeSlots ;
air_temperature: iTimeSlots ;
water_temperature: iTimeSlots ;
}
export interface iMarineDailyForecast {
wave_height_max?: iTimeSlots ;
wave_direction?: iTimeSlots ;
swell_wave_height_max?: iTimeSlots ;
wind_wave_height_max?: iTimeSlots ;
}
export interface iDPCAlert {
thunderstorms?: string;
hydraulic?: string;
hydrogeological?: string;
}
export interface iWeather {
name?: string; // location name, in summary
sun?: string;
moonphase?: string;
icons_model: string;
animation?: boolean;
present?: iPresentData ;
daily_forecasts?: iDailyForecast;
hourly_forecasts?: iHourlyForecast;
marine_daily_forecasts?: iMarineDailyForecast;
marine_hourly_forecasts?: iMarineHourlyForecast;
meteoalarm?: string; // Meteoalarm alert
dpcalarm?: iDPCAlert; // DPC alert
}
export interface iUltraviolet {
protection_window?: string ;
ozone_level?: string ;
uv_index?: string ;
uv_level?: string ;
max_uv_index?: string ;
set_skin_type_1?: string ;
set_skin_type_2?: string ;
set_skin_type_3?: string ;
set_skin_type_4?: string ;
set_skin_type_5?: string ;
set_skin_type_6?: string ;
}
export interface iPollenItem {
name: string;
entity: string;
}
export interface iPollen {
entities: iPollenItem[];
min: number;
max: number;
}
export interface iAirQuality {
pm25?: string ;
pm10?: string ;
o3?: string ;
no2?: string ;
co?: string ;
so2?: string ;
epa_aqi?: string ;
epa_primary_pollutant?: string ;
epa_health_concern?: string ;
}
export interface iCardConfig {
type: string; // ha-card-weather-conditions
language?: string ; // Card language
weather: iWeather;
ultraviolet?: iUltraviolet;
pollen?: iPollen;
airquality?: iAirQuality ;
camera?: string;
// display: string[]
// alert: Alert ;
// sea: Sea ;
}
================================================
FILE: src/utils/const.ts
================================================
export const logo: string = '%c WEATHER-CONDITION-CARD %c 2.0.0';
export const hacsImagePath: string = '/local/community/ha-card-weather-conditions/icons';
export const manImagePath: string = '/local/ha-card-weather-conditions/icons';
export const optConsoleParam1: string = 'color: white; background: green; font-weight: 700;';
export const optConsoleParam2: string = 'color: green; background: white; font-weight: 700;';
export const optConsoleParam3: string = 'color: black; background: white; font-weight: 700;';
export const iconTemperature: string = 'mdi:thermometer';
export const iconPrecipitation: string = 'mdi:weather-rainy';
export const cwcLocale = {
en: 0,
it: 1,
nl: 2,
es: 3,
de: 4,
fr: 5,
'sr-latn': 6,
pt: 7,
da: 8,
'no-no': 9,
cs: 10,
ru: 11,
};
// 🌑 🌒 🌓 🌔 🌕 🌖 🌗 🌘 🌑
export const cwcMoonPhaseIcons = {
new_moon: '🌑',
new: '🌑',
waxing_crescent: '🌒',
first_quarter: '🌓',
waxing_gibbous: '🌔',
full: '🌕',
full_moon: '🌕',
waning_gibbous: '🌖',
third_quarter: '🌗',
last_quarter: '🌗',
waning_crescent: '🌘',
};
================================================
FILE: src/utils/helper-render.ts
================================================
import { css } from 'lit';
// import { HomeAssistant } from 'custom-card-helpers/dist';
import { cwcMoonPhaseIcons } from '../../backup/ha-cwc-consts';
import cardStyle from '../css/css-base-card';
import summaryStyles from '../css/css-summary';
import presentStyle from '../css/css-present';
import ultravioletStyle from '../css/css-ultraviolet';
import pollenStyle from '../css/css-pollen';
import cameraStyle from '../css/css-camera';
import { iIconsConfig } from '../base/lovelace-base';
import weatherForecastStyle from '../css/css-weather-forecast';
import meteodcpalarmStyle from '../css/css-meteoalarm';
export const getMoonIcon = (phase: string): string => cwcMoonPhaseIcons[phase.toLowerCase()];
export const getWeatherIcon = (
condition: string,
iconsConfig: iIconsConfig,
sunState: string,
): string => {
const isNight = sunState === 'below_horizon';
const iconMap = isNight ? iconsConfig.iconsNight : iconsConfig.iconsDay;
const iconName = iconMap[condition];
if (!iconsConfig.path) {
console.info('Image path not found.');
}
if (!iconName) {
console.info(
`Icons issue. Model=${iconsConfig.icons_model}, Time=${isNight ? 'night' : 'day'}, Condition=${condition}`,
);
return '';
}
return `${iconsConfig.path}/${iconsConfig.iconType}/${iconName}.svg`;
};
// export const getSensorUnit = (hass: HomeAssistant, measure: string): string => {
// const lengthUnit = hass.config.unit_system.length;
// const unitOverrides: Record = {
// air_pressure: lengthUnit === 'km' ? 'hPa' : 'inHg',
// precipitation: lengthUnit === 'km' ? 'mm' : 'in',
// length: lengthUnit,
// };
// if (measure in unitOverrides) {
// return unitOverrides[measure];
// }
// const unit = (hass.config.unit_system as Record)[measure];
// if (unit !== undefined) {
// return unit;
// }
// console.warn(`Unit for '${measure}' not found in hass.config.unit_system.`);
// return '';
// };
export const getCardStyles = () => css`
${cardStyle}
${summaryStyles}
${presentStyle}
${weatherForecastStyle}
${ultravioletStyle}
${pollenStyle}
${cameraStyle}
${meteodcpalarmStyle}
`;
================================================
FILE: src/utils/helper.ts
================================================
/* eslint-disable camelcase */
import { HomeAssistant } from 'custom-card-helpers/dist';
import { iconsModels } from '../../backup/types';
export interface IconsConfigResult {
iconsModel: string;
iconsDay: Record;
iconsNight: Record;
}
// export const getEntityState = (hass: HomeAssistant, entityId?: string) => (
// entityId ? hass.states[entityId]?.state : undefined
// );
/**
* Restituisce la traduzione di un termine usando un dizionario, in modo case-insensitive.
* Se il termine non è trovato, restituisce l'originale.
*/
export const translate = (term: string, dictionary: Record): string => {
const key = Object.keys(dictionary).find((k) => k.toLowerCase() === term.toLowerCase());
return key ? dictionary[key] : term;
};
type LocaleInfo = {
locale: string;
timezone: string;
cwc?: number;
};
export const getLocaleInfo = (lang: string): LocaleInfo => {
const localeMap: Record = {
en: 'en-US',
it: 'it-IT',
nl: 'nl-NL',
es: 'es-ES',
de: 'de-DE',
fr: 'fr-FR',
'sr-latn': 'sr-Latn',
pt: 'pt-PT',
da: 'da-DK',
'no-no': 'nb-NO',
cs: 'cs-CZ',
ru: 'ru-RU',
};
const timezoneMap: Record = {
en: 'America/New_York',
it: 'Europe/Rome',
nl: 'Europe/Amsterdam',
es: 'Europe/Madrid',
de: 'Europe/Berlin',
fr: 'Europe/Paris',
'sr-latn': 'Europe/Belgrade',
ja: 'Asia/Tokyo',
pt: 'Europe/Lisbon',
da: 'Europe/Copenhagen',
'no-no': 'Europe/Oslo',
cs: 'Europe/Prague',
ru: 'Europe/Moscow',
};
const cwcLocale: Record = {
en: 0,
it: 1,
nl: 2,
es: 3,
de: 4,
fr: 5,
'sr-latn': 6,
pt: 7,
da: 8,
'no-no': 9,
cs: 10,
ru: 11,
};
return {
locale: localeMap[lang] || lang,
timezone: timezoneMap[lang] || 'UTC',
...(lang in cwcLocale && { cwc: cwcLocale[lang] }),
};
};
export const getLocale = (lang: string) => {
const map = {
it: 'it-IT',
en: 'en-US',
fr: 'fr-FR',
de: 'de-DE',
es: 'es-ES',
ja: 'ja-JP',
zh: 'zh-CN',
// Aggiungi altri se servono
};
return map[lang] || `${lang}-${lang.toUpperCase()}`; // fallback generico
};
export const getFormatter = (
locale: string = 'en-US',
fractionDigits: number = 1,
useGrouping: boolean = false,
): Intl.NumberFormat => new Intl.NumberFormat(locale, {
minimumFractionDigits: fractionDigits,
maximumFractionDigits: fractionDigits,
useGrouping,
});
export const formatNumber = (
{
stringNumber,
lang = 'en',
fractionDigits = 1,
useGrouping = false,
}: {
stringNumber: string;
lang?: string;
fractionDigits?: number;
useGrouping?: boolean;
},
): string => {
const number = parseFloat(stringNumber);
if (Number.isNaN(number)) return '';
const effectiveFormatter = getFormatter(getLocale(lang), fractionDigits, useGrouping);
// console.debug(`>>>|| ${number} ${effectiveFormatter.format(number)}`);
return effectiveFormatter.format(number);
};
export const getIconModelData = (iconsModel: string): IconsConfigResult => {
const modelName = iconsModel.toLowerCase() ?? 'climacell';
if (modelName in iconsModels) {
const { iconsDay, iconsNight } = iconsModels[modelName];
return {
iconsModel: modelName,
iconsDay,
iconsNight,
};
}
console.warn(`Unknown icons model: ${modelName}. Falling back to 'climacell'.`);
const fallback = iconsModels['climacell'];
return {
iconsModel: 'climacell',
iconsDay: fallback.iconsDay,
iconsNight: fallback.iconsNight,
};
};
export function pad(n: number | string, width: number, z = '0'): string {
return n.toString().padStart(width, z);
}
/**
* Converte una stringa numerica localizzata in un numero.
* Esempio: '1.234,56' (it-IT) → 1234.56
* @param input - La stringa o numero da convertire.
* @param locale - Il locale da utilizzare per determinare i separatori.
* @returns Il numero convertito o NaN se la conversione fallisce.
*/
export const string2Number = (input: string | number, locale: string = 'en-US'): number => {
if (typeof input === 'number') return input;
const formatter = new Intl.NumberFormat(locale);
const parts = formatter.formatToParts(1234567.89);
const group = parts.find((part) => part.type === 'group')?.value || '';
const decimal = parts.find((part) => part.type === 'decimal')?.value || '.';
// Rimuove i separatori delle migliaia e sostituisce il separatore decimale con '.'
const normalized = input
.replace(new RegExp(`\\${group}`, 'g'), '')
.replace(new RegExp(`\\${decimal}`), '.');
return Number(normalized);
};
export const getEntityRawValue = (hass: HomeAssistant, entityId?: string): string | undefined => (
entityId && hass.states[entityId]?.state
);
export const getEntityRawAttribute = (hass: HomeAssistant, entityId: string, attribute: string): string | undefined => (
entityId && hass.states[entityId]?.attributes[attribute]
);
export const getEntityNumericValue = (
{
entityId,
hass,
lang = 'en',
decimals = 0,
}: {
entityId?: string;
hass?: HomeAssistant;
lang?: string;
decimals?: number;
} = {},
): string | undefined => {
const state = hass && entityId && hass.states[entityId]?.state;
return state !== undefined ? formatNumber({ stringNumber: state, fractionDigits: decimals, lang }) : undefined;
};
export const getEntityUnit = (hass: HomeAssistant, entityId?: string): string | undefined => (
entityId && hass.states[entityId]?.attributes?.unit_of_measurement
);
export const getEntityIcon = (hass: HomeAssistant, entityId?: string): string | undefined => (
entityId && hass.states[entityId]?.attributes?.icon
);
export const getWindDirections = (
wd: number | string,
cwcLocWindDirections,
): string | null => {
const wdNumber = typeof wd === 'number' ? wd : parseFloat(wd);
if (Number.isNaN(wdNumber)) {
return cwcLocWindDirections[wd] ?? null;
}
if (wdNumber < 0 || wdNumber > 360) {
console.error(`Invalid wind direction: '${wd}'. Valid values are between 0 and 360 degrees.`);
return null;
}
const directions = [
'N', 'NNE', 'NE', 'ENE', 'E', 'ESE',
'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW',
'W', 'WNW', 'NW', 'NNW',
];
const index = Math.floor(((wdNumber + 11.25) % 360) / 22.5);
const dirKey = directions[index];
return cwcLocWindDirections[dirKey] ?? null;
};
export function imageExist(imageSrc: string, timeout = 5000): Promise {
return new Promise((resolve) => {
const img = new Image();
const timer = setTimeout(() => {
img.src = ''; // forza stop
resolve(false);
}, timeout);
img.onload = () => {
clearTimeout(timer);
resolve(true);
};
img.onerror = () => {
clearTimeout(timer);
resolve(false);
};
img.src = imageSrc;
});
}
export async function loadJSON(full_path_file: string): Promise {
try {
const response = await fetch(full_path_file);
if (!response.ok) {
const err = `ERROR retrieving JSON file: '${full_path_file}', status: ${response.status} ${response.statusText}`;
console.info(err);
throw new Error(err);
}
console.info(`Locale '${full_path_file}' loaded`);
return await response.text();
} catch (error) {
console.info(`Fetch failed for '${full_path_file}':`, error);
throw error;
}
}
export function logInfo(message: string, ...styles: unknown[]) {
console.info(message, ...(styles.length ? styles : []));
}
export function parseLocalizedNumber(value: string | number, locale = 'en-US'): number {
if (typeof value === 'number') return value;
// Semplificazione solo per 'it-IT': usa virgola come separatore decimale
const normalized = value.replace(/\./g, '').replace(',', '.');
return Number(normalized);
}
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"target": "es2020",
"module": "esnext",
"moduleResolution": "node",
"lib": ["es2020", "dom", "dom.iterable"],
"noEmit": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"strict": true,
"noImplicitAny": false,
"skipLibCheck": true,
"resolveJsonModule": true,
"experimentalDecorators": true,
"strictNullChecks": false
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"],
"scripts": {
"start": "rollup -c --watch",
"build": "npm run lint && npm run rollup",
"lint": "eslint src/*.ts",
"rollup": "rollup -c"
}
}