{"version":3,"file":"index.cjs","sources":["../../src/constants.ts","../../src/radioBrowser.ts"],"sourcesContent":["/**\n */\nexport const StationSearchOrder = {\n  name: 'name',\n  url: 'url',\n  homepage: 'homepage',\n  favicon: 'favicon',\n  tags: 'tags',\n  country: 'country',\n  state: 'state',\n  language: 'language',\n  votes: 'votes',\n  codec: 'codec',\n  bitrate: 'bitrate',\n  lastCheckOK: 'lastCheckOK',\n  lastCheckTime: 'lastCheckTime',\n  clickTimeStamp: 'clickTimeStamp',\n  clickCount: 'clickCount',\n  clickTrend: 'clickTrend',\n  random: 'random'\n} as const\n\n/**\n */\nexport const StationSearchType = {\n  byUuid: 'byUuid',\n  byName: 'byName',\n  byNameExact: 'byNameExact',\n  byCodec: 'byCodec',\n  byCodexExact: 'byCodecExact',\n  byCountry: 'byCountry',\n  byCountryExact: 'byCountryExact',\n  byCountryCodeExact: 'byCountryCodeExact',\n  byState: 'byState',\n  byStateExact: 'byStateExact',\n  byLanguage: 'byLanguage',\n  byLanguageExact: 'byLanguageExact',\n  byTag: 'byTag',\n  byTagExact: 'byTagExact'\n} as const\n\n/**\n */\nexport type StationResponse = {\n  changeuuid: string\n  stationuuid: string\n  name: string\n  url: string\n  url_resolved: string\n  homepage: string\n  favicon: string\n  tags: string\n  country: string\n  countrycode: string\n  state: string\n  language: string\n  votes: number\n  lastchangetime: string\n  codec: string\n  bitrate: number\n  hls: number\n  lastcheckok: number\n  lastchecktime: string\n  lastlocalchecktime: string\n  lastcheckoktime: string\n  clicktimestamp: string\n  clickcount: number\n  clicktrend: number\n  geo_lat?: number | null\n  geo_long?: number | null\n}\n\n/**\n */\nexport type Station = {\n  changeId: string\n  id: string\n  name: string\n  url: string\n  urlResolved: string\n  homepage: string\n  favicon: string\n  tags: string[]\n  country: string\n  countryCode: string\n  state: string\n  language: string[]\n  votes: number\n  lastChangeTime: Date\n  codec: string\n  bitrate: number\n  hls: boolean\n  lastCheckOk: boolean\n  lastCheckTime: Date\n  lastCheckOkTime: Date\n  lastLocalCheckTime: Date\n  clickTimestamp: Date\n  clickCount: number\n  clickTrend: number\n  geoLat?: number | null\n  geoLong?: number | null\n}\n\n/**\n */\nexport type StationQuery = {\n  offset?: number\n  limit?: number\n  reverse?: boolean\n  order?: keyof typeof StationSearchOrder\n  hideBroken?: boolean\n  removeDuplicates?: boolean\n}\n\n/**\n */\nexport type AdvancedStationQuery = {\n  name?: string\n  nameExact?: boolean\n  country?: string\n  countryExact?: boolean\n  countryCode?: string\n  state?: string\n  stateExact?: boolean\n  language?: string\n  languageExact?: boolean\n  tag?: string\n  tagExact?: boolean\n  tagList?: string[]\n  codec?: string\n  bitrateMin?: string\n  bitrateMax?: string\n  hasGeoInfo?: boolean\n} & StationQuery\n\n/**\n */\nexport type Query = {\n  order?: 'name' | 'stationcount'\n  reverse?: boolean\n  hideBroken?: boolean\n} & Record<string, any>\n\n// valid for country codes also\n/**\n */\nexport type CountryResult = {\n  name: string\n  stationcount: number\n}\n\n/**\n */\nexport type TagResult = CountryResult\n/**\n */\nexport type CountryStateResult = CountryResult & {\n  country: string\n}\n","import {\n  AdvancedStationQuery,\n  CountryResult,\n  CountryStateResult,\n  Query,\n  Station,\n  StationQuery,\n  StationResponse,\n  StationSearchType,\n  TagResult\n} from './constants'\n\n/**\n * Query the radio browser api.\n */\nexport class RadioBrowserApi {\n  static version = __VERSION__\n\n  protected baseUrl: string | undefined\n\n  protected fetchConfig: RequestInit = {\n    method: 'GET',\n    redirect: 'follow'\n  }\n\n  /**\n   * Creates an instance of radio browser api.\n   * @param appName - App name to be used as user agent header to indentify the calls to the API\n   * @param hideBroken - Hide broken stations for all future API calls\n   */\n  constructor(protected appName: string, protected hideBroken = true) {\n    if (!appName) {\n      throw new Error('appName is required')\n    }\n    this.fetchConfig.headers = { 'user-agent': this.appName }\n  }\n\n  /**\n   * Resolves API base url this will be the default for all class instances.\n   * @param config -  Fetch configuration\n   * @returns Array of objects with the ip and name of the api server\n   */\n  async resolveBaseUrl(\n    config: RequestInit = {}\n  ): Promise<{ ip: string; name: string }[]> {\n    let result: { ip: string; name: string }[]\n    const response = await fetch(\n      'https://all.api.radio-browser.info/json/servers',\n      config\n    )\n    if (response.ok) {\n      result = await response.json()\n\n      return result\n    } else {\n      throw response\n    }\n  }\n\n  /**\n   * Sets base url for all api calls\n   * @param url - Url to the api server\n   */\n  setBaseUrl(url: string): void {\n    this.baseUrl = url\n  }\n\n  /**\n   * Get current  base url\n   * @returns Base url\n   */\n  getBaseUrl(): string | undefined {\n    return this.baseUrl\n  }\n\n  /**\n   * Gets available countries\n   * @param search - Search for country\n   * @param query - Query params\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of country results with the name of the station and station count\n   */\n  async getCountries(\n    search?: string,\n    query?: Query,\n    fetchConfig?: RequestInit\n  ): Promise<CountryResult[]> {\n    return this.runRequest(\n      this.buildRequest('countries', search, query),\n      fetchConfig\n    )\n  }\n\n  /**\n   * Gets countries by country code\n   * @param search - Country code\n   * @param query  - Query\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of country results with the name of the station and station count\n   */\n  async getCountryCodes(\n    search?: string,\n    query?: Query,\n    fetchConfig?: RequestInit\n  ): Promise<CountryResult[]> {\n    search = search ? `${search.toUpperCase()}` : ''\n\n    return this.runRequest(\n      this.buildRequest('countrycodes', search, query),\n      fetchConfig\n    )\n  }\n\n  /**\n   * Gets available codes\n   * @param query - Query\n   * @param fetchConfig -  Fetch configuration\n   * @returns List of available codes\n   */\n  async getCodecs(\n    query?: Query,\n    fetchConfig?: RequestInit\n  ): Promise<CountryResult[]> {\n    return this.runRequest(this.buildRequest('codecs', '', query), fetchConfig)\n  }\n\n  /**\n   * Gets country states. States **should** be regions inside a country.\n   * @param country - Limit state to particular country\n   * @param query - Query\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of country states\n   */\n  async getCountryStates(\n    country?: string,\n    query?: Query,\n    fetchConfig?: RequestInit\n  ): Promise<CountryStateResult[]> {\n    return this.runRequest(\n      this.buildRequest('states', country, query),\n      fetchConfig\n    )\n  }\n\n  /**\n   * Gets all available languages\n   * @param language - Limit results to particular language\n   * @param query -  Query\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of language results\n   */\n  async getLanguages(\n    language?: string,\n    query?: Query,\n    fetchConfig?: RequestInit\n  ): Promise<CountryResult[]> {\n    return this.runRequest(\n      this.buildRequest('languages', language, query),\n      fetchConfig\n    )\n  }\n\n  /**\n   * Gets all available tags\n   * @param tag - Limit results to particular tag\n   * @param query - Query\n   * @param fetchConfig - Fetch configuration\n   * @returns List of tag results\n   */\n  async getTags(\n    tag?: string,\n    query?: Query,\n    fetchConfig?: RequestInit\n  ): Promise<TagResult[]> {\n    tag = tag ? tag.toLowerCase() : '' // empty string returns all tags\n\n    return this.runRequest(this.buildRequest('tags', tag, query), fetchConfig)\n  }\n\n  /**\n   * Gets stations by various available parameters\n   * @param searchType - Parameter for the search\n   * @param search - Search value for the parameter\n   * @param query - Query\n   * @param fetchConfig - Fetch configuration\n   * @param removeDuplicates - remove duplicate stations\n   * @returns Array of station results\n   */\n  async getStationsBy(\n    searchType: keyof typeof StationSearchType,\n    search?: string,\n    query?: StationQuery,\n    fetchConfig?: RequestInit,\n    removeDuplicates = false\n  ): Promise<Station[]> {\n    if (!StationSearchType[searchType]) {\n      throw new Error(`search type does not exist: ${searchType}`)\n    }\n\n    search = search ? search.toLowerCase() : ''\n\n    // http://fr1.api.radio-browser.info/{format}/stations/byuuid/{searchterm}\n    const stations = await this.runRequest<StationResponse[]>(\n      this.buildRequest(`stations/${searchType.toLowerCase()}`, search, query),\n      fetchConfig\n    )\n\n    return this.normalizeStations(stations, removeDuplicates)\n  }\n\n  /**\n   * Normalizes stations from the API response\n   * @param stations - Array of station responses\n   * @param removeDuplicates - remove duplicate stations\n   * @returns Array of normalized stations\n   */\n  protected normalizeStations(\n    stations: StationResponse[],\n    removeDuplicates = false\n  ): Station[] {\n    const result = []\n    const duplicates: { [key: string]: boolean } = {}\n\n    for (const response of stations) {\n      if (removeDuplicates) {\n        const nameAndUrl = `${response.name.toLowerCase().trim()}${response.url\n          .toLowerCase()\n          .trim()}`\n\n        // guard against results having the same stations under different id's\n        if (duplicates[nameAndUrl]) continue\n\n        duplicates[nameAndUrl] = true\n      }\n\n      const station: Station = {\n        changeId: response.changeuuid,\n        id: response.stationuuid,\n        name: response.name,\n        url: response.url,\n        urlResolved: response.url_resolved,\n        homepage: response.homepage,\n        favicon: response.favicon,\n        country: response.country,\n        countryCode: response.countrycode,\n        state: response.state,\n        votes: response.votes,\n        codec: response.codec,\n        bitrate: response.bitrate,\n        clickCount: response.clickcount,\n        clickTrend: response.clicktrend,\n        hls: Boolean(response.hls),\n        lastCheckOk: Boolean(response.lastcheckok),\n        lastChangeTime: new Date(response.lastchangetime),\n        lastCheckOkTime: new Date(response.lastcheckoktime),\n        clickTimestamp: new Date(response.clicktimestamp),\n        lastLocalCheckTime: new Date(response.lastlocalchecktime),\n        language: response.language.split(','),\n        lastCheckTime: new Date(response.lastchecktime),\n        geoLat: response.geo_lat,\n        geoLong: response.geo_long,\n        tags: Array.from(new Set(response.tags.split(','))).filter(\n          (tag) => tag.length > 0 && tag.length < 10\n        ) // drop duplicates and tags over 10 characters\n      }\n\n      result.push(station)\n    }\n\n    return result\n  }\n\n  /**\n   * Gets all available stations. Please note that if results\n   * are not limited somehow, they can be huge (size in MB)\n   * @param query - Query\n   * @param fetchConfig - Fetch configuration\n   * @param removeDuplicates - remove duplicate stations\n   * @returns Array of all available stations\n   */\n  async getAllStations(\n    query?: Omit<StationQuery, 'hidebroken'>,\n    fetchConfig?: RequestInit,\n    removeDuplicates = false\n  ): Promise<Station[]> {\n    const stations = await this.runRequest<StationResponse[]>(\n      this.buildRequest('stations', '', query),\n      fetchConfig\n    )\n\n    return this.normalizeStations(stations, removeDuplicates)\n  }\n\n  /**\n   * Searches stations by particular params\n   * @param query - Query\n   * @param fetchConfig - Fetch configuration\n   * @param removeDuplicates - remove duplicate stations\n   * @returns Array of station results\n   */\n  async searchStations(\n    query: AdvancedStationQuery,\n    fetchConfig?: RequestInit,\n    removeDuplicates = false\n  ): Promise<Station[]> {\n    const stations = await this.runRequest<StationResponse[]>(\n      this.buildRequest('stations/search', undefined, query),\n      fetchConfig\n    )\n\n    return this.normalizeStations(stations, removeDuplicates)\n  }\n\n  /**\n   * Gets stations by clicks. Stations with the highest number of clicks are most popular\n   * @param limit - Limit the number of returned stations\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of stations\n   */\n  async getStationsByClicks(\n    limit?: number,\n    fetchConfig?: RequestInit\n  ): Promise<Station[]> {\n    return this.resolveGetStations('topclick', limit, fetchConfig)\n  }\n\n  /**\n   * Gets stations by votes. Returns most voted stations\n   * @param limit - Limit the number of returned stations\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of stations\n   */\n  async getStationsByVotes(\n    limit?: number,\n    fetchConfig?: RequestInit\n  ): Promise<Station[]> {\n    return this.resolveGetStations('topvote', limit, fetchConfig)\n  }\n\n  /**\n   * Gets stations by recent clicks. They are basically most recently listened stations.\n   * @param limit - Limit the number of returned stations\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of stations\n   */\n  async getStationsByRecentClicks(\n    limit?: number,\n    fetchConfig?: RequestInit\n  ): Promise<Station[]> {\n    return this.resolveGetStations('lastclick', limit, fetchConfig)\n  }\n\n  /**\n   * Sends click for the station. This method should be used when user starts to listen to the station.\n   * @param id - Station id\n   * @param fetchConfig  - Fetch configuration\n   * @returns Station click object\n   */\n  async sendStationClick(\n    id: string,\n    fetchConfig?: RequestInit\n  ): Promise<{\n    ok: boolean\n    message: string\n    stationuuid: string\n    name: string\n    url: string\n  }> {\n    return this.runRequest(\n      this.buildRequest('url', id, undefined, false),\n      fetchConfig\n    )\n  }\n\n  /**\n   * Votes for station. This method should be used when user adds the station to favourites etc..\n   * @param id - Station id\n   * @param fetchConfig - Fetch configuration\n   * @returns Station vote object\n   */\n  async voteForStation(\n    id: string,\n    fetchConfig?: RequestInit\n  ): Promise<{\n    ok: boolean\n    message: string\n    stationuuid: string\n    name: string\n    url: string\n  }> {\n    return this.runRequest(this.buildRequest('vote', id), fetchConfig)\n  }\n\n  /**\n   * Gets stations by station id\n   * @param ids - Array of station id's\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of stations\n   */\n  async getStationsById(\n    ids: string[],\n    fetchConfig?: RequestInit\n  ): Promise<Station[]> {\n    const stationsIds = ids.join(',')\n    const stations = await this.runRequest<StationResponse[]>(\n      this.buildRequest(\n        `stations/byuuid?uuids=${stationsIds}`,\n        undefined,\n        undefined,\n        false\n      ),\n      fetchConfig\n    )\n\n    return this.normalizeStations(stations)\n  }\n\n  /**\n   * Gets station by station url\n   * @param url - Station url\n   * @param fetchConfig - Fetch configuration\n   * @returns Array of stations\n   */\n  async getStationByUrl(\n    url: string,\n    fetchConfig?: RequestInit\n  ): Promise<Station[]> {\n    const stations = await this.runRequest<StationResponse[]>(\n      this.buildRequest(\n        `stations/byurl?url=${url}`,\n        undefined,\n        undefined,\n        false\n      ),\n      fetchConfig\n    )\n\n    return this.normalizeStations(stations)\n  }\n\n  protected async resolveGetStations(\n    endPoint: string,\n    limit?: number,\n    fetchConfig?: RequestInit\n  ): Promise<Station[]> {\n    const limitStations = limit ? `/${limit}` : ''\n    const stations = await this.runRequest<StationResponse[]>(\n      this.buildRequest(\n        `stations/${endPoint}${limitStations}`,\n        undefined,\n        undefined,\n        false\n      ),\n      fetchConfig\n    )\n\n    return this.normalizeStations(stations)\n  }\n\n  /**\n   * Builds request to the API\n   * @param endPoint - API endpoint\n   * @param search - Search term\n   * @param query - Query\n   * @param addHideBrokenParam - Hide broken stations from the results\n   * @returns Built request string\n   */\n  protected buildRequest(\n    endPoint: string,\n    search?: string,\n    query?: Query | AdvancedStationQuery | StationQuery,\n    addHideBrokenParam = true\n  ): string {\n    search = search ? `/${encodeURIComponent(search)}` : ''\n\n    let queryCopy\n    if (query) {\n      queryCopy = { ...query }\n      if ('tagList' in queryCopy && Array.isArray(queryCopy.tagList)) {\n        queryCopy.tagList = [...queryCopy.tagList]\n      }\n      if (addHideBrokenParam && queryCopy.hideBroken === undefined) {\n        queryCopy.hideBroken = this.hideBroken\n      }\n    }\n\n    const queryParams = queryCopy ? this.createQueryParams(queryCopy) : ''\n\n    return `${endPoint}${search}${queryParams}`\n  }\n\n  /**\n   * Fires of the request to the API\n   * @param url - Request url\n   * @param fetchConfig - Fetch configuration\n   * @returns Fetch response\n   */\n  protected async runRequest<T>(\n    url: string,\n    fetchConfig: RequestInit = {}\n  ): Promise<T> {\n    const finalConfig = {\n      ...this.fetchConfig,\n      ...fetchConfig,\n      headers: {\n        ...this.fetchConfig.headers,\n        ...fetchConfig.headers\n      }\n    }\n\n    if (!this.baseUrl) {\n      const results = await this.resolveBaseUrl()\n      const random = Math.floor(Math.random() * results.length)\n      this.baseUrl = `https://${results[random].name}`\n    }\n\n    const response = await fetch(`${this.baseUrl}/json/${url}`, finalConfig)\n\n    if (response.ok) {\n      return response.json()\n    } else {\n      throw response\n    }\n  }\n\n  /**\n   * Encodes query parameters\n   * @param params - Object that represents paramters as key value pairs\n   * @returns  String of encoded query parameters\n   */\n  protected createQueryParams(params?: object): string {\n    let result = ''\n    if (params) {\n      for (const [key, value] of Object.entries(params)) {\n        let finalKey = key.toLowerCase()\n\n        switch (finalKey) {\n          case 'hasgeoinfo':\n            finalKey = 'has_geo_info'\n            break\n          case 'hidebroken':\n            finalKey = 'hidebroken'\n            break\n\n          case 'taglist':\n            // github.com/segler-alex/radiobrowser-api-rust/issues/80\n            finalKey = 'tagList' // tagList is the only one that is not lowercased\n        }\n\n        result += `&${finalKey}=${encodeURIComponent(value)}`\n      }\n    }\n\n    return result.length ? `?${result.slice(1)}` : ''\n  }\n}\n"],"names":["StationSearchType","byUuid","byName","byNameExact","byCodec","byCodexExact","byCountry","byCountryExact","byCountryCodeExact","byState","byStateExact","byLanguage","byLanguageExact","byTag","byTagExact","RadioBrowserApi","appName","hideBroken","baseUrl","fetchConfig","method","redirect","this","Error","headers","_proto","prototype","resolveBaseUrl","config","Promise","resolve","fetch","then","response","ok","json","_response$json","e","reject","setBaseUrl","url","getBaseUrl","getCountries","search","query","runRequest","buildRequest","getCountryCodes","toUpperCase","getCodecs","getCountryStates","country","getLanguages","language","getTags","tag","toLowerCase","getStationsBy","searchType","removeDuplicates","_this7","stations","normalizeStations","_step","result","duplicates","_iterator","_createForOfIteratorHelperLoose","done","value","nameAndUrl","name","trim","station","changeId","changeuuid","id","stationuuid","urlResolved","url_resolved","homepage","favicon","countryCode","countrycode","state","votes","codec","bitrate","clickCount","clickcount","clickTrend","clicktrend","hls","Boolean","lastCheckOk","lastcheckok","lastChangeTime","Date","lastchangetime","lastCheckOkTime","lastcheckoktime","clickTimestamp","clicktimestamp","lastLocalCheckTime","lastlocalchecktime","split","lastCheckTime","lastchecktime","geoLat","geo_lat","geoLong","geo_long","tags","Array","from","Set","filter","length","push","getAllStations","_this8","searchStations","_this9","undefined","getStationsByClicks","limit","resolveGetStations","getStationsByVotes","getStationsByRecentClicks","sendStationClick","voteForStation","getStationsById","ids","_this15","stationsIds","join","getStationByUrl","_this16","endPoint","_this17","addHideBrokenParam","queryCopy","encodeURIComponent","_extends","isArray","tagList","concat","createQueryParams","_temp2","_this18","finalConfig","_temp","results","random","Math","floor","params","_i","_Object$entries","Object","entries","_Object$entries$_i","finalKey","slice","version","lastCheckOK","clickTimeStamp"],"mappings":"8TAEa,IAsBAA,EAAoB,CAC/BC,OAAQ,SACRC,OAAQ,SACRC,YAAa,cACbC,QAAS,UACTC,aAAc,eACdC,UAAW,YACXC,eAAgB,iBAChBC,mBAAoB,qBACpBC,QAAS,UACTC,aAAc,eACdC,WAAY,aACZC,gBAAiB,kBACjBC,MAAO,QACPC,WAAY,cCvBDC,eAeX,WAAA,SAAAA,EAAsBC,EAA2BC,GAC/C,QAD+CA,IAAAA,IAAAA,GAAa,GAAxCD,KAAAA,aAA2BC,EAAAA,KAAAA,gBAZvCC,EAAAA,KAAAA,aAEAC,EAAAA,KAAAA,YAA2B,CACnCC,OAAQ,MACRC,SAAU,UAQUC,KAAON,QAAPA,EAA2BM,KAAUL,WAAVA,GAC1CD,EACH,MAAU,IAAAO,MAAM,uBAElBD,KAAKH,YAAYK,QAAU,CAAE,aAAcF,KAAKN,QAClD,CAAC,IAAAS,EAAAV,EAAAW,UAugBA,OAvgBAD,EAOKE,eAAA,SACJC,QAAAA,IAAAA,IAAAA,EAAsB,CAAA,GAAE,IAEkB,OAAAC,QAAAC,QACnBC,MACrB,kDACAH,IACDI,KAHKC,SAAAA,MAIFA,EAASC,GAAE,OAAAL,QAAAC,QACEG,EAASE,QAAMH,KAAAI,SAAAA,GAE9B,OAFMA,CAEO,GAEb,MAAMH,GAEV,CAAC,MAAAI,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EAMDc,WAAA,SAAWC,GACTlB,KAAKJ,QAAUsB,CACjB,EAACf,EAMDgB,WAAA,WACE,OAAWnB,KAACJ,OACd,EAACO,EASKiB,aAAA,SACJC,EACAC,EACAzB,GAAyB,IAEzB,OAAAU,QAAAC,QAAOR,KAAKuB,WAALvB,KACAwB,aAAa,YAAaH,EAAQC,GACvCzB,GAEJ,CAAC,MAAAkB,GAAAR,OAAAA,QAAAS,OAAAD,KAAAZ,EASKsB,gBAAe,SACnBJ,EACAC,EACAzB,GAAyB,IAIzB,OAFAwB,EAASA,EAAYA,GAAAA,EAAOK,cAAkB,GAE9CnB,QAAAC,QAAOR,KAAKuB,WAALvB,KACAwB,aAAa,eAAgBH,EAAQC,GAC1CzB,GAEJ,CAAC,MAAAkB,GAAAR,OAAAA,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EAQKwB,UAAS,SACbL,EACAzB,GAAyB,IAEzB,OAAAU,QAAAC,QAAOR,KAAKuB,WAALvB,KAAqBwB,aAAa,SAAU,GAAIF,GAAQzB,GACjE,CAAC,MAAAkB,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EASKyB,iBAAgB,SACpBC,EACAP,EACAzB,GAAyB,IAEzB,OAAAU,QAAAC,QAAOR,KAAKuB,WAALvB,KACAwB,aAAa,SAAUK,EAASP,GACrCzB,GAEJ,CAAC,MAAAkB,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EASK2B,aAAY,SAChBC,EACAT,EACAzB,GAAyB,IAEzB,OAAAU,QAAAC,QAAOR,KAAKuB,WAALvB,KACAwB,aAAa,YAAaO,EAAUT,GACzCzB,GAEJ,CAAC,MAAAkB,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EASK6B,QAAA,SACJC,EACAX,EACAzB,GAAyB,IAIzB,OAFAoC,EAAMA,EAAMA,EAAIC,cAAgB,GAEhC3B,QAAAC,QAAOR,KAAKuB,WAALvB,KAAqBwB,aAAa,OAAQS,EAAKX,GAAQzB,GAChE,CAAC,MAAAkB,GAAA,OAAAR,QAAAS,OAAAD,EAAAZ,CAAAA,EAAAA,EAWKgC,cAAA,SACJC,EACAf,EACAC,EACAzB,EACAwC,QAAgB,IAAhBA,IAAAA,GAAmB,GAAK,IAAAC,IAAAA,EASDtC,KAPvB,IAAKtB,EAAkB0D,GACrB,MAAM,IAAInC,MAAqCmC,+BAAAA,GAGN,OAA3Cf,EAASA,EAASA,EAAOa,cAAgB,GAAE3B,QAAAC,QAGpB8B,EAAKf,WAC1Be,EAAKd,aAAY,YAAaY,EAAWF,cAAiBb,EAAQC,GAClEzB,IACDa,KAAA,SAHK6B,GAKN,OAAOD,EAAKE,kBAAkBD,EAAUF,EAAiB,EAC3D,CAAC,MAAAtB,GAAA,OAAAR,QAAAS,OAAAD,EAAAZ,CAAAA,EAAAA,EAQSqC,kBAAA,SACRD,EACAF,YAAAA,IAAAA,GAAmB,GAKnB,IAHA,IAG+BI,EAHzBC,EAAS,GACTC,EAAyC,CAAE,EAEjDC,2pBAAAC,CAAuBN,KAAQE,EAAAG,KAAAE,MAAE,CAAA,IAAtBnC,EAAQ8B,EAAAM,MACjB,GAAIV,EAAkB,CACpB,IAAMW,EAAgBrC,GAAAA,EAASsC,KAAKf,cAAcgB,OAASvC,EAASO,IACjEgB,cACAgB,OAGH,GAAIP,EAAWK,GAAa,SAE5BL,EAAWK,IAAc,CAC1B,CAED,IAAMG,EAAmB,CACvBC,SAAUzC,EAAS0C,WACnBC,GAAI3C,EAAS4C,YACbN,KAAMtC,EAASsC,KACf/B,IAAKP,EAASO,IACdsC,YAAa7C,EAAS8C,aACtBC,SAAU/C,EAAS+C,SACnBC,QAAShD,EAASgD,QAClB9B,QAASlB,EAASkB,QAClB+B,YAAajD,EAASkD,YACtBC,MAAOnD,EAASmD,MAChBC,MAAOpD,EAASoD,MAChBC,MAAOrD,EAASqD,MAChBC,QAAStD,EAASsD,QAClBC,WAAYvD,EAASwD,WACrBC,WAAYzD,EAAS0D,WACrBC,IAAKC,QAAQ5D,EAAS2D,KACtBE,YAAaD,QAAQ5D,EAAS8D,aAC9BC,eAAgB,IAAIC,KAAKhE,EAASiE,gBAClCC,gBAAiB,IAAIF,KAAKhE,EAASmE,iBACnCC,eAAgB,IAAIJ,KAAKhE,EAASqE,gBAClCC,mBAAoB,IAAIN,KAAKhE,EAASuE,oBACtCnD,SAAUpB,EAASoB,SAASoD,MAAM,KAClCC,cAAe,IAAIT,KAAKhE,EAAS0E,eACjCC,OAAQ3E,EAAS4E,QACjBC,QAAS7E,EAAS8E,SAClBC,KAAMC,MAAMC,KAAK,IAAIC,IAAIlF,EAAS+E,KAAKP,MAAM,OAAOW,OAClD,SAAC7D,GAAQ,OAAAA,EAAI8D,OAAS,GAAK9D,EAAI8D,OAAS,EAAE,IAI9CrD,EAAOsD,KAAK7C,EACb,CAED,OAAOT,CACT,EAACvC,EAUK8F,eAAA,SACJ3E,EACAzB,EACAwC,QAAAA,IAAAA,IAAAA,GAAmB,GAAK,IAAA,IAAA6D,EAEDlG,KAAI,OAAAO,QAAAC,QAAJ0F,EAAK3E,WAC1B2E,EAAK1E,aAAa,WAAY,GAAIF,GAClCzB,IACDa,KAAA,SAHK6B,GAKN,OAAO2D,EAAK1D,kBAAkBD,EAAUF,EAAiB,EAC3D,CAAC,MAAAtB,GAAAR,OAAAA,QAAAS,OAAAD,KAAAZ,EASKgG,eAAc,SAClB7E,EACAzB,EACAwC,QAAAA,IAAAA,IAAAA,GAAmB,GAAK,IAAA,IAAA+D,EAEDpG,KAAI,OAAAO,QAAAC,QAAJ4F,EAAK7E,WAC1B6E,EAAK5E,aAAa,uBAAmB6E,EAAW/E,GAChDzB,IACDa,KAHK6B,SAAAA,GAKN,OAAO6D,EAAK5D,kBAAkBD,EAAUF,EAAiB,EAC3D,CAAC,MAAAtB,GAAAR,OAAAA,QAAAS,OAAAD,EAAAZ,CAAAA,EAAAA,EAQKmG,oBAAA,SACJC,EACA1G,GAAyB,IAEzB,OAAAU,QAAAC,QAAOR,KAAKwG,mBAAmB,WAAYD,EAAO1G,GACpD,CAAC,MAAAkB,GAAAR,OAAAA,QAAAS,OAAAD,EAAAZ,CAAAA,EAAAA,EAQKsG,mBAAA,SACJF,EACA1G,GAAyB,IAEzB,OAAAU,QAAAC,QAAOR,KAAKwG,mBAAmB,UAAWD,EAAO1G,GACnD,CAAC,MAAAkB,GAAA,OAAAR,QAAAS,OAAAD,EAAAZ,CAAAA,EAAAA,EAQKuG,0BAAA,SACJH,EACA1G,GAAyB,IAEzB,OAAAU,QAAAC,QAAOR,KAAKwG,mBAAmB,YAAaD,EAAO1G,GACrD,CAAC,MAAAkB,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EAQKwG,iBAAA,SACJrD,EACAzD,GAAyB,IAQzB,OAAAU,QAAAC,QAAOR,KAAKuB,WAALvB,KACAwB,aAAa,MAAO8B,OAAI+C,GAAW,GACxCxG,GAEJ,CAAC,MAAAkB,GAAAR,OAAAA,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EAQKyG,eAAc,SAClBtD,EACAzD,GAAyB,IAQzB,OAAAU,QAAAC,QAAOR,KAAKuB,WAALvB,KAAqBwB,aAAa,OAAQ8B,GAAKzD,GACxD,CAAC,MAAAkB,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EAQK0G,gBAAe,SACnBC,EACAjH,GAAyB,IAAA,IAAAkH,EAGF/G,KADjBgH,EAAcF,EAAIG,KAAK,KAAI,OAAA1G,QAAAC,QACVuG,EAAKxF,WAC1BwF,EAAKvF,aACsBwF,yBAAAA,OACzBX,OACAA,GACA,GAEFxG,IACDa,KAAA,SARK6B,GAUN,OAAOwE,EAAKvE,kBAAkBD,EAAS,EACzC,CAAC,MAAAxB,GAAAR,OAAAA,QAAAS,OAAAD,KAAAZ,EAQK+G,gBAAe,SACnBhG,EACArB,GAAyB,IAAA,IAAAsH,EAEFnH,KAAI,OAAAO,QAAAC,QAAJ2G,EAAK5F,WAC1B4F,EAAK3F,aAAY,sBACON,OACtBmF,OACAA,GACA,GAEFxG,IACDa,KARK6B,SAAAA,GAUN,OAAO4E,EAAK3E,kBAAkBD,EAAS,EACzC,CAAC,MAAAxB,GAAA,OAAAR,QAAAS,OAAAD,EAAAZ,CAAAA,EAAAA,EAEeqG,mBAAA,SACdY,EACAb,EACA1G,GAAyB,QAAAwH,EAGFrH,KADuB,OAAAO,QAAAC,QACvB6G,EAAK9F,WAC1B8F,EAAK7F,aAAY,YACH4F,GAHMb,EAAK,IAAOA,EAAU,SAIxCF,OACAA,GACA,GAEFxG,IACDa,KAAA,SARK6B,GAUN,OAAO8E,EAAK7E,kBAAkBD,EAAS,EACzC,CAAC,MAAAxB,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EAUSqB,aAAA,SACR4F,EACA/F,EACAC,EACAgG,GAIA,IAAIC,EAaJ,YAjBAD,IAAAA,IAAAA,GAAqB,GAErBjG,EAASA,EAAamG,IAAAA,mBAAmBnG,GAAY,GAGjDC,IAEE,YADJiG,EAASE,EAAQnG,CAAAA,EAAAA,KACaqE,MAAM+B,QAAQH,EAAUI,WACpDJ,EAAUI,QAAOC,GAAAA,OAAOL,EAAUI,UAEhCL,QAA+CjB,IAAzBkB,EAAU5H,aAClC4H,EAAU5H,WAAaK,KAAKL,aAMtByH,GAAAA,EAAW/F,GAFDkG,EAAYvH,KAAK6H,kBAAkBN,GAAa,GAGtE,EAACpH,EAQeoB,WAAU,SACxBL,EACArB,QAAAA,IAAAA,IAAAA,EAA2B,CAAA,GAAE,QAAAiI,EAAA,WAAA,OAAAvH,QAAAC,QAiBNC,MAASsH,EAAKnI,QAAO,SAASsB,EAAO8G,IAAYtH,KAAlEC,SAAAA,GAEFA,GAAAA,EAASC,GACX,OAAOD,EAASE,OAEhB,MAAMF,CAAQ,EAAA,EAAAoH,EAnBX/H,KADCgI,EAAWP,EACZM,CAAAA,EAAAA,EAAKlI,YACLA,EACHK,CAAAA,QAAOuH,EACFM,CAAAA,EAAAA,EAAKlI,YAAYK,QACjBL,EAAYK,WAElB+H,EAEG,WAAA,IAACF,EAAKnI,QAAO,OAAAW,QAAAC,QACOuH,EAAK1H,kBAAgBK,KAAA,SAArCwH,GACN,IAAMC,EAASC,KAAKC,MAAMD,KAAKD,SAAWD,EAAQnC,QAClDgC,EAAKnI,QAAO,WAAcsI,EAAQC,GAAQlF,IAAM,GAH9C,UAG8C1C,QAAAC,QAAAyH,GAAAA,EAAAvH,KAAAuH,EAAAvH,KAAAoH,GAAAA,IAUpD,CAAC,MAAA/G,GAAA,OAAAR,QAAAS,OAAAD,EAAA,CAAA,EAAAZ,EAOS0H,kBAAA,SAAkBS,GAC1B,IAAI5F,EAAS,GACb,GAAI4F,EACF,IAAA,IAAAC,EAAA,EAAAC,EAA2BC,OAAOC,QAAQJ,GAAOC,EAAAC,EAAAzC,OAAAwC,IAAE,CAA9C,IAAAI,EAAAH,EAAAD,GAAYxF,EAAK4F,EAAA,GAChBC,EADSD,EAAA,GACMzG,cAEnB,OAAQ0G,GACN,IAAK,aACHA,EAAW,eACX,MACF,IAAK,aACHA,EAAW,aACX,MAEF,IAAK,UAEHA,EAAW,UAGflG,OAAckG,EAAQ,IAAIpB,mBAAmBzE,EAC9C,CAGH,OAAOL,EAAOqD,OAAM,IAAOrD,EAAOmG,MAAM,GAAO,EACjD,EAACpJ,CAAA,CA5gBD,GAfWA,EACJqJ,QAAO,6DDdkB,CAChC7F,KAAM,OACN/B,IAAK,MACLwC,SAAU,WACVC,QAAS,UACT+B,KAAM,OACN7D,QAAS,UACTiC,MAAO,QACP/B,SAAU,WACVgC,MAAO,QACPC,MAAO,QACPC,QAAS,UACT8E,YAAa,cACb3D,cAAe,gBACf4D,eAAgB,iBAChB9E,WAAY,aACZE,WAAY,aACZ+D,OAAQ"}