// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/js/wpbc_vars.js?ver=9.8.12 
/**
 * @version 1.0
 * @package Booking Calendar 
 * @subpackage JS Variables
 * @category Scripts
 * 
 * @author wpdevelop
 * @link https://wpbookingcalendar.com/
 * @email info@wpbookingcalendar.com
 *
 * @modified 2014.05.20
 */

////////////////////////////////////////////////////////////////////////////////
// Eval specific variable value (integer, bool, arrays, etc...)
////////////////////////////////////////////////////////////////////////////////

function wpbc_define_var( wpbc_global_var ) {
    if (wpbc_global_var === undefined) { return null; }
    else { return JSON.parse(wpbc_global_var); }                          //FixIn:6.1       //FixIn: 8.7.11.12
}

////////////////////////////////////////////////////////////////////////////////
// Define global Booking Calendar Varibales based on Localization
////////////////////////////////////////////////////////////////////////////////
var wpbc_ajaxurl                        = wpbc_global1.wpbc_ajaxurl; 
var wpdev_bk_plugin_url                 = wpbc_global1.wpdev_bk_plugin_url;
var wpbc_today                          = wpbc_define_var( wpbc_global1.wpbc_today );
var visible_booking_id_on_page          = wpbc_define_var( wpbc_global1.visible_booking_id_on_page );
var booking_max_monthes_in_calendar     = wpbc_global1.booking_max_monthes_in_calendar;
var user_unavilable_days                = wpbc_define_var( wpbc_global1.user_unavilable_days );
var wpdev_bk_edit_id_hash               = wpbc_global1.wpdev_bk_edit_id_hash;
var wpdev_bk_plugin_filename            = wpbc_global1.wpdev_bk_plugin_filename;
var bk_days_selection_mode              = wpbc_global1.bk_days_selection_mode; 
var wpdev_bk_personal                   = parseInt( wpbc_global1.wpdev_bk_personal );
var block_some_dates_from_today         = parseInt( wpbc_global1.block_some_dates_from_today );
var message_verif_requred               = wpbc_global1.message_verif_requred;
var message_verif_requred_for_check_box = wpbc_global1.message_verif_requred_for_check_box;
var message_verif_requred_for_radio_box = wpbc_global1.message_verif_requred_for_radio_box;
var message_verif_emeil                 = wpbc_global1.message_verif_emeil;
var message_verif_same_emeil            = wpbc_global1.message_verif_same_emeil;
var message_verif_selectdts             = wpbc_global1.message_verif_selectdts;
var new_booking_title                   = wpbc_global1.new_booking_title;

var type_of_thank_you_message           = wpbc_global1.type_of_thank_you_message;
var thank_you_page_URL                  = wpbc_global1.thank_you_page_URL;
var is_am_pm_inside_time                = ( wpbc_global1.is_am_pm_inside_time == "true" );
var is_booking_used_check_in_out_time   = ( wpbc_global1.is_booking_used_check_in_out_time == "true" );
var wpbc_active_locale                  = wpbc_global1.wpbc_active_locale;
var wpbc_message_processing             = wpbc_global1.wpbc_message_processing;
var wpbc_message_deleting               = wpbc_global1.wpbc_message_deleting;
var wpbc_message_updating               = wpbc_global1.wpbc_message_updating;
var wpbc_message_saving                 = wpbc_global1.wpbc_message_saving;

//FixIn: 8.2.1.99
var message_checkinouttime_error    = wpbc_global1.message_checkinouttime_error;                                        //FixIn:6.1.1.1
var message_starttime_error         = wpbc_global1.message_starttime_error;
var message_endtime_error           = wpbc_global1.message_endtime_error;
var message_rangetime_error         = wpbc_global1.message_rangetime_error;
var message_durationtime_error      = wpbc_global1.message_durationtime_error;
var bk_highlight_timeslot_word      = wpbc_global1.bk_highlight_timeslot_word;

if (typeof wpbc_global2 !== 'undefined') {
    var message_time_error              = wpbc_global2.message_time_error;
}
if (typeof wpbc_global3 !== 'undefined') {    
    var bk_1click_mode_days_num         = parseInt( wpbc_global3.bk_1click_mode_days_num ); 
    var bk_1click_mode_days_start       = wpbc_define_var( wpbc_global3.bk_1click_mode_days_start ); 
    var bk_2clicks_mode_days_min        = parseInt( wpbc_global3.bk_2clicks_mode_days_min ); 
    var bk_2clicks_mode_days_max        = parseInt( wpbc_global3.bk_2clicks_mode_days_max ); 
    var bk_2clicks_mode_days_specific   = wpbc_define_var( wpbc_global3.bk_2clicks_mode_days_specific ); 
    var bk_2clicks_mode_days_start      = wpbc_define_var( wpbc_global3.bk_2clicks_mode_days_start );
    // bk_highlight_timeslot_word          = wpbc_global3.bk_highlight_timeslot_word;                                   //FixIn: 9.4.3.1 //FixIn: 8.2.1.99
    var is_booking_recurrent_time       = ( wpbc_global3.is_booking_recurrent_time  == "true" );
        is_booking_used_check_in_out_time = ( wpbc_global3.is_booking_used_check_in_out_time == "true" );

}
if (typeof wpbc_global4 !== 'undefined') {
    var wpbc_available_days_num_from_today = parseInt( wpbc_global4.wpbc_available_days_num_from_today );
}
if (typeof wpbc_global5 !== 'undefined') {

};
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/assets/libs/popper/popper.js?ver=9.8.12 
/**
 * @popperjs/core v2.11.2 - MIT License
 */

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.wpbc_Popper = {}));
}(this, (function (exports) { 'use strict';

  function getWindow(node) {
    if (node == null) {
      return window;
    }

    if (node.toString() !== '[object Window]') {
      var ownerDocument = node.ownerDocument;
      return ownerDocument ? ownerDocument.defaultView || window : window;
    }

    return node;
  }

  function isElement(node) {
    var OwnElement = getWindow(node).Element;
    return node instanceof OwnElement || node instanceof Element;
  }

  function isHTMLElement(node) {
    var OwnElement = getWindow(node).HTMLElement;
    return node instanceof OwnElement || node instanceof HTMLElement;
  }

  function isShadowRoot(node) {
    // IE 11 has no ShadowRoot
    if (typeof ShadowRoot === 'undefined') {
      return false;
    }

    var OwnElement = getWindow(node).ShadowRoot;
    return node instanceof OwnElement || node instanceof ShadowRoot;
  }

  var max = Math.max;
  var min = Math.min;
  var round = Math.round;

  function getBoundingClientRect(element, includeScale) {
    if (includeScale === void 0) {
      includeScale = false;
    }

    var rect = element.getBoundingClientRect();
    var scaleX = 1;
    var scaleY = 1;

    if (isHTMLElement(element) && includeScale) {
      var offsetHeight = element.offsetHeight;
      var offsetWidth = element.offsetWidth; // Do not attempt to divide by 0, otherwise we get `Infinity` as scale
      // Fallback to 1 in case both values are `0`

      if (offsetWidth > 0) {
        scaleX = round(rect.width) / offsetWidth || 1;
      }

      if (offsetHeight > 0) {
        scaleY = round(rect.height) / offsetHeight || 1;
      }
    }

    return {
      width: rect.width / scaleX,
      height: rect.height / scaleY,
      top: rect.top / scaleY,
      right: rect.right / scaleX,
      bottom: rect.bottom / scaleY,
      left: rect.left / scaleX,
      x: rect.left / scaleX,
      y: rect.top / scaleY
    };
  }

  function getWindowScroll(node) {
    var win = getWindow(node);
    var scrollLeft = win.pageXOffset;
    var scrollTop = win.pageYOffset;
    return {
      scrollLeft: scrollLeft,
      scrollTop: scrollTop
    };
  }

  function getHTMLElementScroll(element) {
    return {
      scrollLeft: element.scrollLeft,
      scrollTop: element.scrollTop
    };
  }

  function getNodeScroll(node) {
    if (node === getWindow(node) || !isHTMLElement(node)) {
      return getWindowScroll(node);
    } else {
      return getHTMLElementScroll(node);
    }
  }

  function getNodeName(element) {
    return element ? (element.nodeName || '').toLowerCase() : null;
  }

  function getDocumentElement(element) {
    // $FlowFixMe[incompatible-return]: assume body is always available
    return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]
    element.document) || window.document).documentElement;
  }

  function getWindowScrollBarX(element) {
    // If <html> has a CSS width greater than the viewport, then this will be
    // incorrect for RTL.
    // Popper 1 is broken in this case and never had a bug report so let's assume
    // it's not an issue. I don't think anyone ever specifies width on <html>
    // anyway.
    // Browsers where the left scrollbar doesn't cause an issue report `0` for
    // this (e.g. Edge 2019, IE11, Safari)
    return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
  }

  function getComputedStyle(element) {
    return getWindow(element).getComputedStyle(element);
  }

  function isScrollParent(element) {
    // Firefox wants us to check `-x` and `-y` variations as well
    var _getComputedStyle = getComputedStyle(element),
        overflow = _getComputedStyle.overflow,
        overflowX = _getComputedStyle.overflowX,
        overflowY = _getComputedStyle.overflowY;

    return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
  }

  function isElementScaled(element) {
    var rect = element.getBoundingClientRect();
    var scaleX = round(rect.width) / element.offsetWidth || 1;
    var scaleY = round(rect.height) / element.offsetHeight || 1;
    return scaleX !== 1 || scaleY !== 1;
  } // Returns the composite rect of an element relative to its offsetParent.
  // Composite means it takes into account transforms as well as layout.


  function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
    if (isFixed === void 0) {
      isFixed = false;
    }

    var isOffsetParentAnElement = isHTMLElement(offsetParent);
    var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);
    var documentElement = getDocumentElement(offsetParent);
    var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled);
    var scroll = {
      scrollLeft: 0,
      scrollTop: 0
    };
    var offsets = {
      x: 0,
      y: 0
    };

    if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
      if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
      isScrollParent(documentElement)) {
        scroll = getNodeScroll(offsetParent);
      }

      if (isHTMLElement(offsetParent)) {
        offsets = getBoundingClientRect(offsetParent, true);
        offsets.x += offsetParent.clientLeft;
        offsets.y += offsetParent.clientTop;
      } else if (documentElement) {
        offsets.x = getWindowScrollBarX(documentElement);
      }
    }

    return {
      x: rect.left + scroll.scrollLeft - offsets.x,
      y: rect.top + scroll.scrollTop - offsets.y,
      width: rect.width,
      height: rect.height
    };
  }

  // means it doesn't take into account transforms.

  function getLayoutRect(element) {
    var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.
    // Fixes https://github.com/popperjs/popper-core/issues/1223

    var width = element.offsetWidth;
    var height = element.offsetHeight;

    if (Math.abs(clientRect.width - width) <= 1) {
      width = clientRect.width;
    }

    if (Math.abs(clientRect.height - height) <= 1) {
      height = clientRect.height;
    }

    return {
      x: element.offsetLeft,
      y: element.offsetTop,
      width: width,
      height: height
    };
  }

  function getParentNode(element) {
    if (getNodeName(element) === 'html') {
      return element;
    }

    return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle
      // $FlowFixMe[incompatible-return]
      // $FlowFixMe[prop-missing]
      element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
      element.parentNode || ( // DOM Element detected
      isShadowRoot(element) ? element.host : null) || // ShadowRoot detected
      // $FlowFixMe[incompatible-call]: HTMLElement is a Node
      getDocumentElement(element) // fallback

    );
  }

  function getScrollParent(node) {
    if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
      // $FlowFixMe[incompatible-return]: assume body is always available
      return node.ownerDocument.body;
    }

    if (isHTMLElement(node) && isScrollParent(node)) {
      return node;
    }

    return getScrollParent(getParentNode(node));
  }

  /*
  given a DOM element, return the list of all scroll parents, up the list of ancesors
  until we get to the top window object. This list is what we attach scroll listeners
  to, because if any of these parent elements scroll, we'll need to re-calculate the
  reference element's position.
  */

  function listScrollParents(element, list) {
    var _element$ownerDocumen;

    if (list === void 0) {
      list = [];
    }

    var scrollParent = getScrollParent(element);
    var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);
    var win = getWindow(scrollParent);
    var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
    var updatedList = list.concat(target);
    return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
    updatedList.concat(listScrollParents(getParentNode(target)));
  }

  function isTableElement(element) {
    return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
  }

  function getTrueOffsetParent(element) {
    if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
    getComputedStyle(element).position === 'fixed') {
      return null;
    }

    return element.offsetParent;
  } // `.offsetParent` reports `null` for fixed elements, while absolute elements
  // return the containing block


  function getContainingBlock(element) {
    var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') !== -1;
    var isIE = navigator.userAgent.indexOf('Trident') !== -1;

    if (isIE && isHTMLElement(element)) {
      // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
      var elementCss = getComputedStyle(element);

      if (elementCss.position === 'fixed') {
        return null;
      }
    }

    var currentNode = getParentNode(element);

    while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
      var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
      // create a containing block.
      // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block

      if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {
        return currentNode;
      } else {
        currentNode = currentNode.parentNode;
      }
    }

    return null;
  } // Gets the closest ancestor positioned element. Handles some edge cases,
  // such as table ancestors and cross browser bugs.


  function getOffsetParent(element) {
    var window = getWindow(element);
    var offsetParent = getTrueOffsetParent(element);

    while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
      offsetParent = getTrueOffsetParent(offsetParent);
    }

    if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {
      return window;
    }

    return offsetParent || getContainingBlock(element) || window;
  }

  var top = 'top';
  var bottom = 'bottom';
  var right = 'right';
  var left = 'left';
  var auto = 'auto';
  var basePlacements = [top, bottom, right, left];
  var start = 'start';
  var end = 'end';
  var clippingParents = 'clippingParents';
  var viewport = 'viewport';
  var popper = 'popper';
  var reference = 'reference';
  var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {
    return acc.concat([placement + "-" + start, placement + "-" + end]);
  }, []);
  var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {
    return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
  }, []); // modifiers that need to read the DOM

  var beforeRead = 'beforeRead';
  var read = 'read';
  var afterRead = 'afterRead'; // pure-logic modifiers

  var beforeMain = 'beforeMain';
  var main = 'main';
  var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)

  var beforeWrite = 'beforeWrite';
  var write = 'write';
  var afterWrite = 'afterWrite';
  var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];

  function order(modifiers) {
    var map = new Map();
    var visited = new Set();
    var result = [];
    modifiers.forEach(function (modifier) {
      map.set(modifier.name, modifier);
    }); // On visiting object, check for its dependencies and visit them recursively

    function sort(modifier) {
      visited.add(modifier.name);
      var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
      requires.forEach(function (dep) {
        if (!visited.has(dep)) {
          var depModifier = map.get(dep);

          if (depModifier) {
            sort(depModifier);
          }
        }
      });
      result.push(modifier);
    }

    modifiers.forEach(function (modifier) {
      if (!visited.has(modifier.name)) {
        // check for visited object
        sort(modifier);
      }
    });
    return result;
  }

  function orderModifiers(modifiers) {
    // order based on dependencies
    var orderedModifiers = order(modifiers); // order based on phase

    return modifierPhases.reduce(function (acc, phase) {
      return acc.concat(orderedModifiers.filter(function (modifier) {
        return modifier.phase === phase;
      }));
    }, []);
  }

  function debounce(fn) {
    var pending;
    return function () {
      if (!pending) {
        pending = new Promise(function (resolve) {
          Promise.resolve().then(function () {
            pending = undefined;
            resolve(fn());
          });
        });
      }

      return pending;
    };
  }

  function format(str) {
    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }

    return [].concat(args).reduce(function (p, c) {
      return p.replace(/%s/, c);
    }, str);
  }

  var INVALID_MODIFIER_ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s';
  var MISSING_DEPENDENCY_ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available';
  var VALID_PROPERTIES = ['name', 'enabled', 'phase', 'fn', 'effect', 'requires', 'options'];
  function validateModifiers(modifiers) {
    modifiers.forEach(function (modifier) {
      [].concat(Object.keys(modifier), VALID_PROPERTIES) // IE11-compatible replacement for `new Set(iterable)`
      .filter(function (value, index, self) {
        return self.indexOf(value) === index;
      }).forEach(function (key) {
        switch (key) {
          case 'name':
            if (typeof modifier.name !== 'string') {
              console.error(format(INVALID_MODIFIER_ERROR, String(modifier.name), '"name"', '"string"', "\"" + String(modifier.name) + "\""));
            }

            break;

          case 'enabled':
            if (typeof modifier.enabled !== 'boolean') {
              console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"enabled"', '"boolean"', "\"" + String(modifier.enabled) + "\""));
            }

            break;

          case 'phase':
            if (modifierPhases.indexOf(modifier.phase) < 0) {
              console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"phase"', "either " + modifierPhases.join(', '), "\"" + String(modifier.phase) + "\""));
            }

            break;

          case 'fn':
            if (typeof modifier.fn !== 'function') {
              console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"fn"', '"function"', "\"" + String(modifier.fn) + "\""));
            }

            break;

          case 'effect':
            if (modifier.effect != null && typeof modifier.effect !== 'function') {
              console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"effect"', '"function"', "\"" + String(modifier.fn) + "\""));
            }

            break;

          case 'requires':
            if (modifier.requires != null && !Array.isArray(modifier.requires)) {
              console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requires"', '"array"', "\"" + String(modifier.requires) + "\""));
            }

            break;

          case 'requiresIfExists':
            if (!Array.isArray(modifier.requiresIfExists)) {
              console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requiresIfExists"', '"array"', "\"" + String(modifier.requiresIfExists) + "\""));
            }

            break;

          case 'options':
          case 'data':
            break;

          default:
            console.error("PopperJS: an invalid property has been provided to the \"" + modifier.name + "\" modifier, valid properties are " + VALID_PROPERTIES.map(function (s) {
              return "\"" + s + "\"";
            }).join(', ') + "; but \"" + key + "\" was provided.");
        }

        modifier.requires && modifier.requires.forEach(function (requirement) {
          if (modifiers.find(function (mod) {
            return mod.name === requirement;
          }) == null) {
            console.error(format(MISSING_DEPENDENCY_ERROR, String(modifier.name), requirement, requirement));
          }
        });
      });
    });
  }

  function uniqueBy(arr, fn) {
    var identifiers = new Set();
    return arr.filter(function (item) {
      var identifier = fn(item);

      if (!identifiers.has(identifier)) {
        identifiers.add(identifier);
        return true;
      }
    });
  }

  function getBasePlacement(placement) {
    return placement.split('-')[0];
  }

  function mergeByName(modifiers) {
    var merged = modifiers.reduce(function (merged, current) {
      var existing = merged[current.name];
      merged[current.name] = existing ? Object.assign({}, existing, current, {
        options: Object.assign({}, existing.options, current.options),
        data: Object.assign({}, existing.data, current.data)
      }) : current;
      return merged;
    }, {}); // IE11 does not support Object.values

    return Object.keys(merged).map(function (key) {
      return merged[key];
    });
  }

  function getViewportRect(element) {
    var win = getWindow(element);
    var html = getDocumentElement(element);
    var visualViewport = win.visualViewport;
    var width = html.clientWidth;
    var height = html.clientHeight;
    var x = 0;
    var y = 0; // NB: This isn't supported on iOS <= 12. If the keyboard is open, the popper
    // can be obscured underneath it.
    // Also, `html.clientHeight` adds the bottom bar height in Safari iOS, even
    // if it isn't open, so if this isn't available, the popper will be detected
    // to overflow the bottom of the screen too early.

    if (visualViewport) {
      width = visualViewport.width;
      height = visualViewport.height; // Uses Layout Viewport (like Chrome; Safari does not currently)
      // In Chrome, it returns a value very close to 0 (+/-) but contains rounding
      // errors due to floating point numbers, so we need to check precision.
      // Safari returns a number <= 0, usually < -1 when pinch-zoomed
      // Feature detection fails in mobile emulation mode in Chrome.
      // Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) <
      // 0.001
      // Fallback here: "Not Safari" userAgent

      if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
        x = visualViewport.offsetLeft;
        y = visualViewport.offsetTop;
      }
    }

    return {
      width: width,
      height: height,
      x: x + getWindowScrollBarX(element),
      y: y
    };
  }

  // of the `<html>` and `<body>` rect bounds if horizontally scrollable

  function getDocumentRect(element) {
    var _element$ownerDocumen;

    var html = getDocumentElement(element);
    var winScroll = getWindowScroll(element);
    var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
    var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
    var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
    var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
    var y = -winScroll.scrollTop;

    if (getComputedStyle(body || html).direction === 'rtl') {
      x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
    }

    return {
      width: width,
      height: height,
      x: x,
      y: y
    };
  }

  function contains(parent, child) {
    var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method

    if (parent.contains(child)) {
      return true;
    } // then fallback to custom implementation with Shadow DOM support
    else if (rootNode && isShadowRoot(rootNode)) {
        var next = child;

        do {
          if (next && parent.isSameNode(next)) {
            return true;
          } // $FlowFixMe[prop-missing]: need a better way to handle this...


          next = next.parentNode || next.host;
        } while (next);
      } // Give up, the result is false


    return false;
  }

  function rectToClientRect(rect) {
    return Object.assign({}, rect, {
      left: rect.x,
      top: rect.y,
      right: rect.x + rect.width,
      bottom: rect.y + rect.height
    });
  }

  function getInnerBoundingClientRect(element) {
    var rect = getBoundingClientRect(element);
    rect.top = rect.top + element.clientTop;
    rect.left = rect.left + element.clientLeft;
    rect.bottom = rect.top + element.clientHeight;
    rect.right = rect.left + element.clientWidth;
    rect.width = element.clientWidth;
    rect.height = element.clientHeight;
    rect.x = rect.left;
    rect.y = rect.top;
    return rect;
  }

  function getClientRectFromMixedType(element, clippingParent) {
    return clippingParent === viewport ? rectToClientRect(getViewportRect(element)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
  } // A "clipping parent" is an overflowable container with the characteristic of
  // clipping (or hiding) overflowing elements with a position different from
  // `initial`


  function getClippingParents(element) {
    var clippingParents = listScrollParents(getParentNode(element));
    var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;
    var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;

    if (!isElement(clipperElement)) {
      return [];
    } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414


    return clippingParents.filter(function (clippingParent) {
      return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';
    });
  } // Gets the maximum area that the element is visible in due to any number of
  // clipping parents


  function getClippingRect(element, boundary, rootBoundary) {
    var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
    var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
    var firstClippingParent = clippingParents[0];
    var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
      var rect = getClientRectFromMixedType(element, clippingParent);
      accRect.top = max(rect.top, accRect.top);
      accRect.right = min(rect.right, accRect.right);
      accRect.bottom = min(rect.bottom, accRect.bottom);
      accRect.left = max(rect.left, accRect.left);
      return accRect;
    }, getClientRectFromMixedType(element, firstClippingParent));
    clippingRect.width = clippingRect.right - clippingRect.left;
    clippingRect.height = clippingRect.bottom - clippingRect.top;
    clippingRect.x = clippingRect.left;
    clippingRect.y = clippingRect.top;
    return clippingRect;
  }

  function getVariation(placement) {
    return placement.split('-')[1];
  }

  function getMainAxisFromPlacement(placement) {
    return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
  }

  function computeOffsets(_ref) {
    var reference = _ref.reference,
        element = _ref.element,
        placement = _ref.placement;
    var basePlacement = placement ? getBasePlacement(placement) : null;
    var variation = placement ? getVariation(placement) : null;
    var commonX = reference.x + reference.width / 2 - element.width / 2;
    var commonY = reference.y + reference.height / 2 - element.height / 2;
    var offsets;

    switch (basePlacement) {
      case top:
        offsets = {
          x: commonX,
          y: reference.y - element.height
        };
        break;

      case bottom:
        offsets = {
          x: commonX,
          y: reference.y + reference.height
        };
        break;

      case right:
        offsets = {
          x: reference.x + reference.width,
          y: commonY
        };
        break;

      case left:
        offsets = {
          x: reference.x - element.width,
          y: commonY
        };
        break;

      default:
        offsets = {
          x: reference.x,
          y: reference.y
        };
    }

    var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;

    if (mainAxis != null) {
      var len = mainAxis === 'y' ? 'height' : 'width';

      switch (variation) {
        case start:
          offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);
          break;

        case end:
          offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);
          break;
      }
    }

    return offsets;
  }

  function getFreshSideObject() {
    return {
      top: 0,
      right: 0,
      bottom: 0,
      left: 0
    };
  }

  function mergePaddingObject(paddingObject) {
    return Object.assign({}, getFreshSideObject(), paddingObject);
  }

  function expandToHashMap(value, keys) {
    return keys.reduce(function (hashMap, key) {
      hashMap[key] = value;
      return hashMap;
    }, {});
  }

  function detectOverflow(state, options) {
    if (options === void 0) {
      options = {};
    }

    var _options = options,
        _options$placement = _options.placement,
        placement = _options$placement === void 0 ? state.placement : _options$placement,
        _options$boundary = _options.boundary,
        boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,
        _options$rootBoundary = _options.rootBoundary,
        rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,
        _options$elementConte = _options.elementContext,
        elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,
        _options$altBoundary = _options.altBoundary,
        altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,
        _options$padding = _options.padding,
        padding = _options$padding === void 0 ? 0 : _options$padding;
    var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
    var altContext = elementContext === popper ? reference : popper;
    var popperRect = state.rects.popper;
    var element = state.elements[altBoundary ? altContext : elementContext];
    var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary);
    var referenceClientRect = getBoundingClientRect(state.elements.reference);
    var popperOffsets = computeOffsets({
      reference: referenceClientRect,
      element: popperRect,
      strategy: 'absolute',
      placement: placement
    });
    var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));
    var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect
    // 0 or negative = within the clipping rect

    var overflowOffsets = {
      top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
      bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
      left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
      right: elementClientRect.right - clippingClientRect.right + paddingObject.right
    };
    var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element

    if (elementContext === popper && offsetData) {
      var offset = offsetData[placement];
      Object.keys(overflowOffsets).forEach(function (key) {
        var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
        var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
        overflowOffsets[key] += offset[axis] * multiply;
      });
    }

    return overflowOffsets;
  }

  var INVALID_ELEMENT_ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.';
  var INFINITE_LOOP_ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.';
  var DEFAULT_OPTIONS = {
    placement: 'bottom',
    modifiers: [],
    strategy: 'absolute'
  };

  function areValidElements() {
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return !args.some(function (element) {
      return !(element && typeof element.getBoundingClientRect === 'function');
    });
  }

  function popperGenerator(generatorOptions) {
    if (generatorOptions === void 0) {
      generatorOptions = {};
    }

    var _generatorOptions = generatorOptions,
        _generatorOptions$def = _generatorOptions.defaultModifiers,
        defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
        _generatorOptions$def2 = _generatorOptions.defaultOptions,
        defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
    return function createPopper(reference, popper, options) {
      if (options === void 0) {
        options = defaultOptions;
      }

      var state = {
        placement: 'bottom',
        orderedModifiers: [],
        options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),
        modifiersData: {},
        elements: {
          reference: reference,
          popper: popper
        },
        attributes: {},
        styles: {}
      };
      var effectCleanupFns = [];
      var isDestroyed = false;
      var instance = {
        state: state,
        setOptions: function setOptions(setOptionsAction) {
          var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;
          cleanupModifierEffects();
          state.options = Object.assign({}, defaultOptions, state.options, options);
          state.scrollParents = {
            reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
            popper: listScrollParents(popper)
          }; // Orders the modifiers based on their dependencies and `phase`
          // properties

          var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers

          state.orderedModifiers = orderedModifiers.filter(function (m) {
            return m.enabled;
          }); // Validate the provided modifiers so that the consumer will get warned
          // if one of the modifiers is invalid for any reason

          {
            var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function (_ref) {
              var name = _ref.name;
              return name;
            });
            validateModifiers(modifiers);

            if (getBasePlacement(state.options.placement) === auto) {
              var flipModifier = state.orderedModifiers.find(function (_ref2) {
                var name = _ref2.name;
                return name === 'flip';
              });

              if (!flipModifier) {
                console.error(['Popper: "auto" placements require the "flip" modifier be', 'present and enabled to work.'].join(' '));
              }
            }

            var _getComputedStyle = getComputedStyle(popper),
                marginTop = _getComputedStyle.marginTop,
                marginRight = _getComputedStyle.marginRight,
                marginBottom = _getComputedStyle.marginBottom,
                marginLeft = _getComputedStyle.marginLeft; // We no longer take into account `margins` on the popper, and it can
            // cause bugs with positioning, so we'll warn the consumer


            if ([marginTop, marginRight, marginBottom, marginLeft].some(function (margin) {
              return parseFloat(margin);
            })) {
              console.warn(['Popper: CSS "margin" styles cannot be used to apply padding', 'between the popper and its reference element or boundary.', 'To replicate margin, use the `offset` modifier, as well as', 'the `padding` option in the `preventOverflow` and `flip`', 'modifiers.'].join(' '));
            }
          }

          runModifierEffects();
          return instance.update();
        },
        // Sync update – it will always be executed, even if not necessary. This
        // is useful for low frequency updates where sync behavior simplifies the
        // logic.
        // For high frequency updates (e.g. `resize` and `scroll` events), always
        // prefer the async Popper#update method
        forceUpdate: function forceUpdate() {
          if (isDestroyed) {
            return;
          }

          var _state$elements = state.elements,
              reference = _state$elements.reference,
              popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
          // anymore

          if (!areValidElements(reference, popper)) {
            {
              console.error(INVALID_ELEMENT_ERROR);
            }

            return;
          } // Store the reference and popper rects to be read by modifiers


          state.rects = {
            reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
            popper: getLayoutRect(popper)
          }; // Modifiers have the ability to reset the current update cycle. The
          // most common use case for this is the `flip` modifier changing the
          // placement, which then needs to re-run all the modifiers, because the
          // logic was previously ran for the previous placement and is therefore
          // stale/incorrect

          state.reset = false;
          state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
          // is filled with the initial data specified by the modifier. This means
          // it doesn't persist and is fresh on each update.
          // To ensure persistent data, use `${name}#persistent`

          state.orderedModifiers.forEach(function (modifier) {
            return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
          });
          var __debug_loops__ = 0;

          for (var index = 0; index < state.orderedModifiers.length; index++) {
            {
              __debug_loops__ += 1;

              if (__debug_loops__ > 100) {
                console.error(INFINITE_LOOP_ERROR);
                break;
              }
            }

            if (state.reset === true) {
              state.reset = false;
              index = -1;
              continue;
            }

            var _state$orderedModifie = state.orderedModifiers[index],
                fn = _state$orderedModifie.fn,
                _state$orderedModifie2 = _state$orderedModifie.options,
                _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
                name = _state$orderedModifie.name;

            if (typeof fn === 'function') {
              state = fn({
                state: state,
                options: _options,
                name: name,
                instance: instance
              }) || state;
            }
          }
        },
        // Async and optimistically optimized update – it will not be executed if
        // not necessary (debounced to run at most once-per-tick)
        update: debounce(function () {
          return new Promise(function (resolve) {
            instance.forceUpdate();
            resolve(state);
          });
        }),
        destroy: function destroy() {
          cleanupModifierEffects();
          isDestroyed = true;
        }
      };

      if (!areValidElements(reference, popper)) {
        {
          console.error(INVALID_ELEMENT_ERROR);
        }

        return instance;
      }

      instance.setOptions(options).then(function (state) {
        if (!isDestroyed && options.onFirstUpdate) {
          options.onFirstUpdate(state);
        }
      }); // Modifiers have the ability to execute arbitrary code before the first
      // update cycle runs. They will be executed in the same order as the update
      // cycle. This is useful when a modifier adds some persistent data that
      // other modifiers need to use, but the modifier is run after the dependent
      // one.

      function runModifierEffects() {
        state.orderedModifiers.forEach(function (_ref3) {
          var name = _ref3.name,
              _ref3$options = _ref3.options,
              options = _ref3$options === void 0 ? {} : _ref3$options,
              effect = _ref3.effect;

          if (typeof effect === 'function') {
            var cleanupFn = effect({
              state: state,
              name: name,
              instance: instance,
              options: options
            });

            var noopFn = function noopFn() {};

            effectCleanupFns.push(cleanupFn || noopFn);
          }
        });
      }

      function cleanupModifierEffects() {
        effectCleanupFns.forEach(function (fn) {
          return fn();
        });
        effectCleanupFns = [];
      }

      return instance;
    };
  }

  var passive = {
    passive: true
  };

  function effect$2(_ref) {
    var state = _ref.state,
        instance = _ref.instance,
        options = _ref.options;
    var _options$scroll = options.scroll,
        scroll = _options$scroll === void 0 ? true : _options$scroll,
        _options$resize = options.resize,
        resize = _options$resize === void 0 ? true : _options$resize;
    var window = getWindow(state.elements.popper);
    var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);

    if (scroll) {
      scrollParents.forEach(function (scrollParent) {
        scrollParent.addEventListener('scroll', instance.update, passive);
      });
    }

    if (resize) {
      window.addEventListener('resize', instance.update, passive);
    }

    return function () {
      if (scroll) {
        scrollParents.forEach(function (scrollParent) {
          scrollParent.removeEventListener('scroll', instance.update, passive);
        });
      }

      if (resize) {
        window.removeEventListener('resize', instance.update, passive);
      }
    };
  } // eslint-disable-next-line import/no-unused-modules


  var eventListeners = {
    name: 'eventListeners',
    enabled: true,
    phase: 'write',
    fn: function fn() {},
    effect: effect$2,
    data: {}
  };

  function popperOffsets(_ref) {
    var state = _ref.state,
        name = _ref.name;
    // Offsets are the actual position the popper needs to have to be
    // properly positioned near its reference element
    // This is the most basic placement, and will be adjusted by
    // the modifiers in the next step
    state.modifiersData[name] = computeOffsets({
      reference: state.rects.reference,
      element: state.rects.popper,
      strategy: 'absolute',
      placement: state.placement
    });
  } // eslint-disable-next-line import/no-unused-modules


  var popperOffsets$1 = {
    name: 'popperOffsets',
    enabled: true,
    phase: 'read',
    fn: popperOffsets,
    data: {}
  };

  var unsetSides = {
    top: 'auto',
    right: 'auto',
    bottom: 'auto',
    left: 'auto'
  }; // Round the offsets to the nearest suitable subpixel based on the DPR.
  // Zooming can change the DPR, but it seems to report a value that will
  // cleanly divide the values into the appropriate subpixels.

  function roundOffsetsByDPR(_ref) {
    var x = _ref.x,
        y = _ref.y;
    var win = window;
    var dpr = win.devicePixelRatio || 1;
    return {
      x: round(x * dpr) / dpr || 0,
      y: round(y * dpr) / dpr || 0
    };
  }

  function mapToStyles(_ref2) {
    var _Object$assign2;

    var popper = _ref2.popper,
        popperRect = _ref2.popperRect,
        placement = _ref2.placement,
        variation = _ref2.variation,
        offsets = _ref2.offsets,
        position = _ref2.position,
        gpuAcceleration = _ref2.gpuAcceleration,
        adaptive = _ref2.adaptive,
        roundOffsets = _ref2.roundOffsets,
        isFixed = _ref2.isFixed;
    var _offsets$x = offsets.x,
        x = _offsets$x === void 0 ? 0 : _offsets$x,
        _offsets$y = offsets.y,
        y = _offsets$y === void 0 ? 0 : _offsets$y;

    var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({
      x: x,
      y: y
    }) : {
      x: x,
      y: y
    };

    x = _ref3.x;
    y = _ref3.y;
    var hasX = offsets.hasOwnProperty('x');
    var hasY = offsets.hasOwnProperty('y');
    var sideX = left;
    var sideY = top;
    var win = window;

    if (adaptive) {
      var offsetParent = getOffsetParent(popper);
      var heightProp = 'clientHeight';
      var widthProp = 'clientWidth';

      if (offsetParent === getWindow(popper)) {
        offsetParent = getDocumentElement(popper);

        if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {
          heightProp = 'scrollHeight';
          widthProp = 'scrollWidth';
        }
      } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it


      offsetParent = offsetParent;

      if (placement === top || (placement === left || placement === right) && variation === end) {
        sideY = bottom;
        var offsetY = isFixed && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
        offsetParent[heightProp];
        y -= offsetY - popperRect.height;
        y *= gpuAcceleration ? 1 : -1;
      }

      if (placement === left || (placement === top || placement === bottom) && variation === end) {
        sideX = right;
        var offsetX = isFixed && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
        offsetParent[widthProp];
        x -= offsetX - popperRect.width;
        x *= gpuAcceleration ? 1 : -1;
      }
    }

    var commonStyles = Object.assign({
      position: position
    }, adaptive && unsetSides);

    var _ref4 = roundOffsets === true ? roundOffsetsByDPR({
      x: x,
      y: y
    }) : {
      x: x,
      y: y
    };

    x = _ref4.x;
    y = _ref4.y;

    if (gpuAcceleration) {
      var _Object$assign;

      return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign));
    }

    return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2));
  }

  function computeStyles(_ref5) {
    var state = _ref5.state,
        options = _ref5.options;
    var _options$gpuAccelerat = options.gpuAcceleration,
        gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,
        _options$adaptive = options.adaptive,
        adaptive = _options$adaptive === void 0 ? true : _options$adaptive,
        _options$roundOffsets = options.roundOffsets,
        roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;

    {
      var transitionProperty = getComputedStyle(state.elements.popper).transitionProperty || '';

      if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) {
        return transitionProperty.indexOf(property) >= 0;
      })) {
        console.warn(['Popper: Detected CSS transitions on at least one of the following', 'CSS properties: "transform", "top", "right", "bottom", "left".', '\n\n', 'Disable the "computeStyles" modifier\'s `adaptive` option to allow', 'for smooth transitions, or remove these properties from the CSS', 'transition declaration on the popper element if only transitioning', 'opacity or background-color for example.', '\n\n', 'We recommend using the popper element as a wrapper around an inner', 'element that can have any CSS property transitioned for animations.'].join(' '));
      }
    }

    var commonStyles = {
      placement: getBasePlacement(state.placement),
      variation: getVariation(state.placement),
      popper: state.elements.popper,
      popperRect: state.rects.popper,
      gpuAcceleration: gpuAcceleration,
      isFixed: state.options.strategy === 'fixed'
    };

    if (state.modifiersData.popperOffsets != null) {
      state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {
        offsets: state.modifiersData.popperOffsets,
        position: state.options.strategy,
        adaptive: adaptive,
        roundOffsets: roundOffsets
      })));
    }

    if (state.modifiersData.arrow != null) {
      state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {
        offsets: state.modifiersData.arrow,
        position: 'absolute',
        adaptive: false,
        roundOffsets: roundOffsets
      })));
    }

    state.attributes.popper = Object.assign({}, state.attributes.popper, {
      'data-popper-placement': state.placement
    });
  } // eslint-disable-next-line import/no-unused-modules


  var computeStyles$1 = {
    name: 'computeStyles',
    enabled: true,
    phase: 'beforeWrite',
    fn: computeStyles,
    data: {}
  };

  // and applies them to the HTMLElements such as popper and arrow

  function applyStyles(_ref) {
    var state = _ref.state;
    Object.keys(state.elements).forEach(function (name) {
      var style = state.styles[name] || {};
      var attributes = state.attributes[name] || {};
      var element = state.elements[name]; // arrow is optional + virtual elements

      if (!isHTMLElement(element) || !getNodeName(element)) {
        return;
      } // Flow doesn't support to extend this property, but it's the most
      // effective way to apply styles to an HTMLElement
      // $FlowFixMe[cannot-write]


      Object.assign(element.style, style);
      Object.keys(attributes).forEach(function (name) {
        var value = attributes[name];

        if (value === false) {
          element.removeAttribute(name);
        } else {
          element.setAttribute(name, value === true ? '' : value);
        }
      });
    });
  }

  function effect$1(_ref2) {
    var state = _ref2.state;
    var initialStyles = {
      popper: {
        position: state.options.strategy,
        left: '0',
        top: '0',
        margin: '0'
      },
      arrow: {
        position: 'absolute'
      },
      reference: {}
    };
    Object.assign(state.elements.popper.style, initialStyles.popper);
    state.styles = initialStyles;

    if (state.elements.arrow) {
      Object.assign(state.elements.arrow.style, initialStyles.arrow);
    }

    return function () {
      Object.keys(state.elements).forEach(function (name) {
        var element = state.elements[name];
        var attributes = state.attributes[name] || {};
        var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them

        var style = styleProperties.reduce(function (style, property) {
          style[property] = '';
          return style;
        }, {}); // arrow is optional + virtual elements

        if (!isHTMLElement(element) || !getNodeName(element)) {
          return;
        }

        Object.assign(element.style, style);
        Object.keys(attributes).forEach(function (attribute) {
          element.removeAttribute(attribute);
        });
      });
    };
  } // eslint-disable-next-line import/no-unused-modules


  var applyStyles$1 = {
    name: 'applyStyles',
    enabled: true,
    phase: 'write',
    fn: applyStyles,
    effect: effect$1,
    requires: ['computeStyles']
  };

  function distanceAndSkiddingToXY(placement, rects, offset) {
    var basePlacement = getBasePlacement(placement);
    var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;

    var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, {
      placement: placement
    })) : offset,
        skidding = _ref[0],
        distance = _ref[1];

    skidding = skidding || 0;
    distance = (distance || 0) * invertDistance;
    return [left, right].indexOf(basePlacement) >= 0 ? {
      x: distance,
      y: skidding
    } : {
      x: skidding,
      y: distance
    };
  }

  function offset(_ref2) {
    var state = _ref2.state,
        options = _ref2.options,
        name = _ref2.name;
    var _options$offset = options.offset,
        offset = _options$offset === void 0 ? [0, 0] : _options$offset;
    var data = placements.reduce(function (acc, placement) {
      acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);
      return acc;
    }, {});
    var _data$state$placement = data[state.placement],
        x = _data$state$placement.x,
        y = _data$state$placement.y;

    if (state.modifiersData.popperOffsets != null) {
      state.modifiersData.popperOffsets.x += x;
      state.modifiersData.popperOffsets.y += y;
    }

    state.modifiersData[name] = data;
  } // eslint-disable-next-line import/no-unused-modules


  var offset$1 = {
    name: 'offset',
    enabled: true,
    phase: 'main',
    requires: ['popperOffsets'],
    fn: offset
  };

  var hash$1 = {
    left: 'right',
    right: 'left',
    bottom: 'top',
    top: 'bottom'
  };
  function getOppositePlacement(placement) {
    return placement.replace(/left|right|bottom|top/g, function (matched) {
      return hash$1[matched];
    });
  }

  var hash = {
    start: 'end',
    end: 'start'
  };
  function getOppositeVariationPlacement(placement) {
    return placement.replace(/start|end/g, function (matched) {
      return hash[matched];
    });
  }

  function computeAutoPlacement(state, options) {
    if (options === void 0) {
      options = {};
    }

    var _options = options,
        placement = _options.placement,
        boundary = _options.boundary,
        rootBoundary = _options.rootBoundary,
        padding = _options.padding,
        flipVariations = _options.flipVariations,
        _options$allowedAutoP = _options.allowedAutoPlacements,
        allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
    var variation = getVariation(placement);
    var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {
      return getVariation(placement) === variation;
    }) : basePlacements;
    var allowedPlacements = placements$1.filter(function (placement) {
      return allowedAutoPlacements.indexOf(placement) >= 0;
    });

    if (allowedPlacements.length === 0) {
      allowedPlacements = placements$1;

      {
        console.error(['Popper: The `allowedAutoPlacements` option did not allow any', 'placements. Ensure the `placement` option matches the variation', 'of the allowed placements.', 'For example, "auto" cannot be used to allow "bottom-start".', 'Use "auto-start" instead.'].join(' '));
      }
    } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...


    var overflows = allowedPlacements.reduce(function (acc, placement) {
      acc[placement] = detectOverflow(state, {
        placement: placement,
        boundary: boundary,
        rootBoundary: rootBoundary,
        padding: padding
      })[getBasePlacement(placement)];
      return acc;
    }, {});
    return Object.keys(overflows).sort(function (a, b) {
      return overflows[a] - overflows[b];
    });
  }

  function getExpandedFallbackPlacements(placement) {
    if (getBasePlacement(placement) === auto) {
      return [];
    }

    var oppositePlacement = getOppositePlacement(placement);
    return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
  }

  function flip(_ref) {
    var state = _ref.state,
        options = _ref.options,
        name = _ref.name;

    if (state.modifiersData[name]._skip) {
      return;
    }

    var _options$mainAxis = options.mainAxis,
        checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
        _options$altAxis = options.altAxis,
        checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,
        specifiedFallbackPlacements = options.fallbackPlacements,
        padding = options.padding,
        boundary = options.boundary,
        rootBoundary = options.rootBoundary,
        altBoundary = options.altBoundary,
        _options$flipVariatio = options.flipVariations,
        flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,
        allowedAutoPlacements = options.allowedAutoPlacements;
    var preferredPlacement = state.options.placement;
    var basePlacement = getBasePlacement(preferredPlacement);
    var isBasePlacement = basePlacement === preferredPlacement;
    var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
    var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {
      return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {
        placement: placement,
        boundary: boundary,
        rootBoundary: rootBoundary,
        padding: padding,
        flipVariations: flipVariations,
        allowedAutoPlacements: allowedAutoPlacements
      }) : placement);
    }, []);
    var referenceRect = state.rects.reference;
    var popperRect = state.rects.popper;
    var checksMap = new Map();
    var makeFallbackChecks = true;
    var firstFittingPlacement = placements[0];

    for (var i = 0; i < placements.length; i++) {
      var placement = placements[i];

      var _basePlacement = getBasePlacement(placement);

      var isStartVariation = getVariation(placement) === start;
      var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
      var len = isVertical ? 'width' : 'height';
      var overflow = detectOverflow(state, {
        placement: placement,
        boundary: boundary,
        rootBoundary: rootBoundary,
        altBoundary: altBoundary,
        padding: padding
      });
      var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;

      if (referenceRect[len] > popperRect[len]) {
        mainVariationSide = getOppositePlacement(mainVariationSide);
      }

      var altVariationSide = getOppositePlacement(mainVariationSide);
      var checks = [];

      if (checkMainAxis) {
        checks.push(overflow[_basePlacement] <= 0);
      }

      if (checkAltAxis) {
        checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
      }

      if (checks.every(function (check) {
        return check;
      })) {
        firstFittingPlacement = placement;
        makeFallbackChecks = false;
        break;
      }

      checksMap.set(placement, checks);
    }

    if (makeFallbackChecks) {
      // `2` may be desired in some cases – research later
      var numberOfChecks = flipVariations ? 3 : 1;

      var _loop = function _loop(_i) {
        var fittingPlacement = placements.find(function (placement) {
          var checks = checksMap.get(placement);

          if (checks) {
            return checks.slice(0, _i).every(function (check) {
              return check;
            });
          }
        });

        if (fittingPlacement) {
          firstFittingPlacement = fittingPlacement;
          return "break";
        }
      };

      for (var _i = numberOfChecks; _i > 0; _i--) {
        var _ret = _loop(_i);

        if (_ret === "break") break;
      }
    }

    if (state.placement !== firstFittingPlacement) {
      state.modifiersData[name]._skip = true;
      state.placement = firstFittingPlacement;
      state.reset = true;
    }
  } // eslint-disable-next-line import/no-unused-modules


  var flip$1 = {
    name: 'flip',
    enabled: true,
    phase: 'main',
    fn: flip,
    requiresIfExists: ['offset'],
    data: {
      _skip: false
    }
  };

  function getAltAxis(axis) {
    return axis === 'x' ? 'y' : 'x';
  }

  function within(min$1, value, max$1) {
    return max(min$1, min(value, max$1));
  }
  function withinMaxClamp(min, value, max) {
    var v = within(min, value, max);
    return v > max ? max : v;
  }

  function preventOverflow(_ref) {
    var state = _ref.state,
        options = _ref.options,
        name = _ref.name;
    var _options$mainAxis = options.mainAxis,
        checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
        _options$altAxis = options.altAxis,
        checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,
        boundary = options.boundary,
        rootBoundary = options.rootBoundary,
        altBoundary = options.altBoundary,
        padding = options.padding,
        _options$tether = options.tether,
        tether = _options$tether === void 0 ? true : _options$tether,
        _options$tetherOffset = options.tetherOffset,
        tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
    var overflow = detectOverflow(state, {
      boundary: boundary,
      rootBoundary: rootBoundary,
      padding: padding,
      altBoundary: altBoundary
    });
    var basePlacement = getBasePlacement(state.placement);
    var variation = getVariation(state.placement);
    var isBasePlacement = !variation;
    var mainAxis = getMainAxisFromPlacement(basePlacement);
    var altAxis = getAltAxis(mainAxis);
    var popperOffsets = state.modifiersData.popperOffsets;
    var referenceRect = state.rects.reference;
    var popperRect = state.rects.popper;
    var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {
      placement: state.placement
    })) : tetherOffset;
    var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {
      mainAxis: tetherOffsetValue,
      altAxis: tetherOffsetValue
    } : Object.assign({
      mainAxis: 0,
      altAxis: 0
    }, tetherOffsetValue);
    var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;
    var data = {
      x: 0,
      y: 0
    };

    if (!popperOffsets) {
      return;
    }

    if (checkMainAxis) {
      var _offsetModifierState$;

      var mainSide = mainAxis === 'y' ? top : left;
      var altSide = mainAxis === 'y' ? bottom : right;
      var len = mainAxis === 'y' ? 'height' : 'width';
      var offset = popperOffsets[mainAxis];
      var min$1 = offset + overflow[mainSide];
      var max$1 = offset - overflow[altSide];
      var additive = tether ? -popperRect[len] / 2 : 0;
      var minLen = variation === start ? referenceRect[len] : popperRect[len];
      var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go
      // outside the reference bounds

      var arrowElement = state.elements.arrow;
      var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
        width: 0,
        height: 0
      };
      var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();
      var arrowPaddingMin = arrowPaddingObject[mainSide];
      var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want
      // to include its full size in the calculation. If the reference is small
      // and near the edge of a boundary, the popper can overflow even if the
      // reference is not overflowing as well (e.g. virtual elements with no
      // width or height)

      var arrowLen = within(0, referenceRect[len], arrowRect[len]);
      var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;
      var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;
      var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
      var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
      var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;
      var tetherMin = offset + minOffset - offsetModifierValue - clientOffset;
      var tetherMax = offset + maxOffset - offsetModifierValue;
      var preventedOffset = within(tether ? min(min$1, tetherMin) : min$1, offset, tether ? max(max$1, tetherMax) : max$1);
      popperOffsets[mainAxis] = preventedOffset;
      data[mainAxis] = preventedOffset - offset;
    }

    if (checkAltAxis) {
      var _offsetModifierState$2;

      var _mainSide = mainAxis === 'x' ? top : left;

      var _altSide = mainAxis === 'x' ? bottom : right;

      var _offset = popperOffsets[altAxis];

      var _len = altAxis === 'y' ? 'height' : 'width';

      var _min = _offset + overflow[_mainSide];

      var _max = _offset - overflow[_altSide];

      var isOriginSide = [top, left].indexOf(basePlacement) !== -1;

      var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;

      var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;

      var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;

      var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);

      popperOffsets[altAxis] = _preventedOffset;
      data[altAxis] = _preventedOffset - _offset;
    }

    state.modifiersData[name] = data;
  } // eslint-disable-next-line import/no-unused-modules


  var preventOverflow$1 = {
    name: 'preventOverflow',
    enabled: true,
    phase: 'main',
    fn: preventOverflow,
    requiresIfExists: ['offset']
  };

  var toPaddingObject = function toPaddingObject(padding, state) {
    padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {
      placement: state.placement
    })) : padding;
    return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
  };

  function arrow(_ref) {
    var _state$modifiersData$;

    var state = _ref.state,
        name = _ref.name,
        options = _ref.options;
    var arrowElement = state.elements.arrow;
    var popperOffsets = state.modifiersData.popperOffsets;
    var basePlacement = getBasePlacement(state.placement);
    var axis = getMainAxisFromPlacement(basePlacement);
    var isVertical = [left, right].indexOf(basePlacement) >= 0;
    var len = isVertical ? 'height' : 'width';

    if (!arrowElement || !popperOffsets) {
      return;
    }

    var paddingObject = toPaddingObject(options.padding, state);
    var arrowRect = getLayoutRect(arrowElement);
    var minProp = axis === 'y' ? top : left;
    var maxProp = axis === 'y' ? bottom : right;
    var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
    var startDiff = popperOffsets[axis] - state.rects.reference[axis];
    var arrowOffsetParent = getOffsetParent(arrowElement);
    var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
    var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is
    // outside of the popper bounds

    var min = paddingObject[minProp];
    var max = clientSize - arrowRect[len] - paddingObject[maxProp];
    var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
    var offset = within(min, center, max); // Prevents breaking syntax highlighting...

    var axisProp = axis;
    state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
  }

  function effect(_ref2) {
    var state = _ref2.state,
        options = _ref2.options;
    var _options$element = options.element,
        arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;

    if (arrowElement == null) {
      return;
    } // CSS selector


    if (typeof arrowElement === 'string') {
      arrowElement = state.elements.popper.querySelector(arrowElement);

      if (!arrowElement) {
        return;
      }
    }

    {
      if (!isHTMLElement(arrowElement)) {
        console.error(['Popper: "arrow" element must be an HTMLElement (not an SVGElement).', 'To use an SVG arrow, wrap it in an HTMLElement that will be used as', 'the arrow.'].join(' '));
      }
    }

    if (!contains(state.elements.popper, arrowElement)) {
      {
        console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', 'element.'].join(' '));
      }

      return;
    }

    state.elements.arrow = arrowElement;
  } // eslint-disable-next-line import/no-unused-modules


  var arrow$1 = {
    name: 'arrow',
    enabled: true,
    phase: 'main',
    fn: arrow,
    effect: effect,
    requires: ['popperOffsets'],
    requiresIfExists: ['preventOverflow']
  };

  function getSideOffsets(overflow, rect, preventedOffsets) {
    if (preventedOffsets === void 0) {
      preventedOffsets = {
        x: 0,
        y: 0
      };
    }

    return {
      top: overflow.top - rect.height - preventedOffsets.y,
      right: overflow.right - rect.width + preventedOffsets.x,
      bottom: overflow.bottom - rect.height + preventedOffsets.y,
      left: overflow.left - rect.width - preventedOffsets.x
    };
  }

  function isAnySideFullyClipped(overflow) {
    return [top, right, bottom, left].some(function (side) {
      return overflow[side] >= 0;
    });
  }

  function hide(_ref) {
    var state = _ref.state,
        name = _ref.name;
    var referenceRect = state.rects.reference;
    var popperRect = state.rects.popper;
    var preventedOffsets = state.modifiersData.preventOverflow;
    var referenceOverflow = detectOverflow(state, {
      elementContext: 'reference'
    });
    var popperAltOverflow = detectOverflow(state, {
      altBoundary: true
    });
    var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
    var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
    var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
    var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
    state.modifiersData[name] = {
      referenceClippingOffsets: referenceClippingOffsets,
      popperEscapeOffsets: popperEscapeOffsets,
      isReferenceHidden: isReferenceHidden,
      hasPopperEscaped: hasPopperEscaped
    };
    state.attributes.popper = Object.assign({}, state.attributes.popper, {
      'data-popper-reference-hidden': isReferenceHidden,
      'data-popper-escaped': hasPopperEscaped
    });
  } // eslint-disable-next-line import/no-unused-modules


  var hide$1 = {
    name: 'hide',
    enabled: true,
    phase: 'main',
    requiresIfExists: ['preventOverflow'],
    fn: hide
  };

  var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1];
  var createPopper$1 = /*#__PURE__*/popperGenerator({
    defaultModifiers: defaultModifiers$1
  }); // eslint-disable-next-line import/no-unused-modules

  var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1];
  var createPopper = /*#__PURE__*/popperGenerator({
    defaultModifiers: defaultModifiers
  }); // eslint-disable-next-line import/no-unused-modules

  exports.applyStyles = applyStyles$1;
  exports.arrow = arrow$1;
  exports.computeStyles = computeStyles$1;
  exports.createPopper = createPopper;
  exports.createPopperLite = createPopper$1;
  exports.defaultModifiers = defaultModifiers;
  exports.detectOverflow = detectOverflow;
  exports.eventListeners = eventListeners;
  exports.flip = flip$1;
  exports.hide = hide$1;
  exports.offset = offset$1;
  exports.popperGenerator = popperGenerator;
  exports.popperOffsets = popperOffsets$1;
  exports.preventOverflow = preventOverflow$1;

  Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=popper.js.map;
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/assets/libs/tippy.js/dist/tippy-bundle.umd.js?ver=9.8.12 
/**!
* tippy.js v6.3.7
* (c) 2017-2021 atomiks
* MIT License
*
* Docs: https://atomiks.github.io/tippyjs/v6/all-props/
*/
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core')) :
  typeof define === 'function' && define.amd ? define(['@popperjs/core'], factory) :
  (global = global || self, global.wpbc_tippy = factory(global.wpbc_Popper));
}(this, (function (core) { 'use strict';

  var css = ".tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:\"\";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}";

  function injectCSS(css) {
    var style = document.createElement('style');
    style.textContent = css;
    style.setAttribute('data-tippy-stylesheet', '');
    var head = document.head;
    var firstStyleOrLinkTag = document.querySelector('head>style,head>link');

    if (firstStyleOrLinkTag) {
      head.insertBefore(style, firstStyleOrLinkTag);
    } else {
      head.appendChild(style);
    }
  }

  var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
  var isIE11 = isBrowser ? // @ts-ignore
  !!window.msCrypto : false;

  var ROUND_ARROW = '<svg width="16" height="6" xmlns="http://www.w3.org/2000/svg"><path d="M0 6s1.796-.013 4.67-3.615C5.851.9 6.93.006 8 0c1.07-.006 2.148.887 3.343 2.385C14.233 6.005 16 6 16 6H0z"></svg>';
  var BOX_CLASS = "tippy-box";
  var CONTENT_CLASS = "tippy-content";
  var BACKDROP_CLASS = "tippy-backdrop";
  var ARROW_CLASS = "tippy-arrow";
  var SVG_ARROW_CLASS = "tippy-svg-arrow";
  var TOUCH_OPTIONS = {
    passive: true,
    capture: true
  };
  var TIPPY_DEFAULT_APPEND_TO = function TIPPY_DEFAULT_APPEND_TO() {
    return document.body;
  };

  function hasOwnProperty(obj, key) {
    return {}.hasOwnProperty.call(obj, key);
  }
  function getValueAtIndexOrReturn(value, index, defaultValue) {
    if (Array.isArray(value)) {
      var v = value[index];
      return v == null ? Array.isArray(defaultValue) ? defaultValue[index] : defaultValue : v;
    }

    return value;
  }
  function isType(value, type) {
    var str = {}.toString.call(value);
    return str.indexOf('[object') === 0 && str.indexOf(type + "]") > -1;
  }
  function invokeWithArgsOrReturn(value, args) {
    return typeof value === 'function' ? value.apply(void 0, args) : value;
  }
  function debounce(fn, ms) {
    // Avoid wrapping in `setTimeout` if ms is 0 anyway
    if (ms === 0) {
      return fn;
    }

    var timeout;
    return function (arg) {
      clearTimeout(timeout);
      timeout = setTimeout(function () {
        fn(arg);
      }, ms);
    };
  }
  function removeProperties(obj, keys) {
    var clone = Object.assign({}, obj);
    keys.forEach(function (key) {
      delete clone[key];
    });
    return clone;
  }
  function splitBySpaces(value) {
    return value.split(/\s+/).filter(Boolean);
  }
  function normalizeToArray(value) {
    return [].concat(value);
  }
  function pushIfUnique(arr, value) {
    if (arr.indexOf(value) === -1) {
      arr.push(value);
    }
  }
  function unique(arr) {
    return arr.filter(function (item, index) {
      return arr.indexOf(item) === index;
    });
  }
  function getBasePlacement(placement) {
    return placement.split('-')[0];
  }
  function arrayFrom(value) {
    return [].slice.call(value);
  }
  function removeUndefinedProps(obj) {
    return Object.keys(obj).reduce(function (acc, key) {
      if (obj[key] !== undefined) {
        acc[key] = obj[key];
      }

      return acc;
    }, {});
  }

  function div() {
    return document.createElement('div');
  }
  function isElement(value) {
    return ['Element', 'Fragment'].some(function (type) {
      return isType(value, type);
    });
  }
  function isNodeList(value) {
    return isType(value, 'NodeList');
  }
  function isMouseEvent(value) {
    return isType(value, 'MouseEvent');
  }
  function isReferenceElement(value) {
    return !!(value && value._tippy && value._tippy.reference === value);
  }
  function getArrayOfElements(value) {
    if (isElement(value)) {
      return [value];
    }

    if (isNodeList(value)) {
      return arrayFrom(value);
    }

    if (Array.isArray(value)) {
      return value;
    }

    return arrayFrom(document.querySelectorAll(value));
  }
  function setTransitionDuration(els, value) {
    els.forEach(function (el) {
      if (el) {
        el.style.transitionDuration = value + "ms";
      }
    });
  }
  function setVisibilityState(els, state) {
    els.forEach(function (el) {
      if (el) {
        el.setAttribute('data-state', state);
      }
    });
  }
  function getOwnerDocument(elementOrElements) {
    var _element$ownerDocumen;

    var _normalizeToArray = normalizeToArray(elementOrElements),
        element = _normalizeToArray[0]; // Elements created via a <template> have an ownerDocument with no reference to the body


    return element != null && (_element$ownerDocumen = element.ownerDocument) != null && _element$ownerDocumen.body ? element.ownerDocument : document;
  }
  function isCursorOutsideInteractiveBorder(popperTreeData, event) {
    var clientX = event.clientX,
        clientY = event.clientY;
    return popperTreeData.every(function (_ref) {
      var popperRect = _ref.popperRect,
          popperState = _ref.popperState,
          props = _ref.props;
      var interactiveBorder = props.interactiveBorder;
      var basePlacement = getBasePlacement(popperState.placement);
      var offsetData = popperState.modifiersData.offset;

      if (!offsetData) {
        return true;
      }

      var topDistance = basePlacement === 'bottom' ? offsetData.top.y : 0;
      var bottomDistance = basePlacement === 'top' ? offsetData.bottom.y : 0;
      var leftDistance = basePlacement === 'right' ? offsetData.left.x : 0;
      var rightDistance = basePlacement === 'left' ? offsetData.right.x : 0;
      var exceedsTop = popperRect.top - clientY + topDistance > interactiveBorder;
      var exceedsBottom = clientY - popperRect.bottom - bottomDistance > interactiveBorder;
      var exceedsLeft = popperRect.left - clientX + leftDistance > interactiveBorder;
      var exceedsRight = clientX - popperRect.right - rightDistance > interactiveBorder;
      return exceedsTop || exceedsBottom || exceedsLeft || exceedsRight;
    });
  }
  function updateTransitionEndListener(box, action, listener) {
    var method = action + "EventListener"; // some browsers apparently support `transition` (unprefixed) but only fire
    // `webkitTransitionEnd`...

    ['transitionend', 'webkitTransitionEnd'].forEach(function (event) {
      box[method](event, listener);
    });
  }
  /**
   * Compared to xxx.contains, this function works for dom structures with shadow
   * dom
   */

  function actualContains(parent, child) {
    var target = child;

    while (target) {
      var _target$getRootNode;

      if (parent.contains(target)) {
        return true;
      }

      target = target.getRootNode == null ? void 0 : (_target$getRootNode = target.getRootNode()) == null ? void 0 : _target$getRootNode.host;
    }

    return false;
  }

  var currentInput = {
    isTouch: false
  };
  var lastMouseMoveTime = 0;
  /**
   * When a `touchstart` event is fired, it's assumed the user is using touch
   * input. We'll bind a `mousemove` event listener to listen for mouse input in
   * the future. This way, the `isTouch` property is fully dynamic and will handle
   * hybrid devices that use a mix of touch + mouse input.
   */

  function onDocumentTouchStart() {
    if (currentInput.isTouch) {
      return;
    }

    currentInput.isTouch = true;

    if (window.performance) {
      document.addEventListener('mousemove', onDocumentMouseMove);
    }
  }
  /**
   * When two `mousemove` event are fired consecutively within 20ms, it's assumed
   * the user is using mouse input again. `mousemove` can fire on touch devices as
   * well, but very rarely that quickly.
   */

  function onDocumentMouseMove() {
    var now = performance.now();

    if (now - lastMouseMoveTime < 20) {
      currentInput.isTouch = false;
      document.removeEventListener('mousemove', onDocumentMouseMove);
    }

    lastMouseMoveTime = now;
  }
  /**
   * When an element is in focus and has a tippy, leaving the tab/window and
   * returning causes it to show again. For mouse users this is unexpected, but
   * for keyboard use it makes sense.
   * TODO: find a better technique to solve this problem
   */

  function onWindowBlur() {
    var activeElement = document.activeElement;

    if (isReferenceElement(activeElement)) {
      var instance = activeElement._tippy;

      if (activeElement.blur && !instance.state.isVisible) {
        activeElement.blur();
      }
    }
  }
  function bindGlobalEventListeners() {
    document.addEventListener('touchstart', onDocumentTouchStart, TOUCH_OPTIONS);
    window.addEventListener('blur', onWindowBlur);
  }

  function createMemoryLeakWarning(method) {
    var txt = method === 'destroy' ? 'n already-' : ' ';
    return [method + "() was called on a" + txt + "destroyed instance. This is a no-op but", 'indicates a potential memory leak.'].join(' ');
  }
  function clean(value) {
    var spacesAndTabs = /[ \t]{2,}/g;
    var lineStartWithSpaces = /^[ \t]*/gm;
    return value.replace(spacesAndTabs, ' ').replace(lineStartWithSpaces, '').trim();
  }

  function getDevMessage(message) {
    return clean("\n  %ctippy.js\n\n  %c" + clean(message) + "\n\n  %c\uD83D\uDC77\u200D This is a development-only message. It will be removed in production.\n  ");
  }

  function getFormattedMessage(message) {
    return [getDevMessage(message), // title
    'color: #00C584; font-size: 1.3em; font-weight: bold;', // message
    'line-height: 1.5', // footer
    'color: #a6a095;'];
  } // Assume warnings and errors never have the same message

  var visitedMessages;

  {
    resetVisitedMessages();
  }

  function resetVisitedMessages() {
    visitedMessages = new Set();
  }
  function warnWhen(condition, message) {
    if (condition && !visitedMessages.has(message)) {
      var _console;

      visitedMessages.add(message);

      (_console = console).warn.apply(_console, getFormattedMessage(message));
    }
  }
  function errorWhen(condition, message) {
    if (condition && !visitedMessages.has(message)) {
      var _console2;

      visitedMessages.add(message);

      (_console2 = console).error.apply(_console2, getFormattedMessage(message));
    }
  }
  function validateTargets(targets) {
    var didPassFalsyValue = !targets;
    var didPassPlainObject = Object.prototype.toString.call(targets) === '[object Object]' && !targets.addEventListener;
    errorWhen(didPassFalsyValue, ['tippy() was passed', '`' + String(targets) + '`', 'as its targets (first) argument. Valid types are: String, Element,', 'Element[], or NodeList.'].join(' '));
    errorWhen(didPassPlainObject, ['tippy() was passed a plain object which is not supported as an argument', 'for virtual positioning. Use props.getReferenceClientRect instead.'].join(' '));
  }

  var pluginProps = {
    animateFill: false,
    followCursor: false,
    inlinePositioning: false,
    sticky: false
  };
  var renderProps = {
    allowHTML: false,
    animation: 'fade',
    arrow: true,
    content: '',
    inertia: false,
    maxWidth: 350,
    role: 'tooltip',
    theme: '',
    zIndex: 9999
  };
  var defaultProps = Object.assign({
    appendTo: TIPPY_DEFAULT_APPEND_TO,
    aria: {
      content: 'auto',
      expanded: 'auto'
    },
    delay: 0,
    duration: [300, 250],
    getReferenceClientRect: null,
    hideOnClick: true,
    ignoreAttributes: false,
    interactive: false,
    interactiveBorder: 2,
    interactiveDebounce: 0,
    moveTransition: '',
    offset: [0, 10],
    onAfterUpdate: function onAfterUpdate() {},
    onBeforeUpdate: function onBeforeUpdate() {},
    onCreate: function onCreate() {},
    onDestroy: function onDestroy() {},
    onHidden: function onHidden() {},
    onHide: function onHide() {},
    onMount: function onMount() {},
    onShow: function onShow() {},
    onShown: function onShown() {},
    onTrigger: function onTrigger() {},
    onUntrigger: function onUntrigger() {},
    onClickOutside: function onClickOutside() {},
    placement: 'top',
    plugins: [],
    popperOptions: {},
    render: null,
    showOnCreate: false,
    touch: true,
    trigger: 'mouseenter focus',
    triggerTarget: null
  }, pluginProps, renderProps);
  var defaultKeys = Object.keys(defaultProps);
  var setDefaultProps = function setDefaultProps(partialProps) {
    /* istanbul ignore else */
    {
      validateProps(partialProps, []);
    }

    var keys = Object.keys(partialProps);
    keys.forEach(function (key) {
      defaultProps[key] = partialProps[key];
    });
  };
  function getExtendedPassedProps(passedProps) {
    var plugins = passedProps.plugins || [];
    var pluginProps = plugins.reduce(function (acc, plugin) {
      var name = plugin.name,
          defaultValue = plugin.defaultValue;

      if (name) {
        var _name;

        acc[name] = passedProps[name] !== undefined ? passedProps[name] : (_name = defaultProps[name]) != null ? _name : defaultValue;
      }

      return acc;
    }, {});
    return Object.assign({}, passedProps, pluginProps);
  }
  function getDataAttributeProps(reference, plugins) {
    var propKeys = plugins ? Object.keys(getExtendedPassedProps(Object.assign({}, defaultProps, {
      plugins: plugins
    }))) : defaultKeys;
    var props = propKeys.reduce(function (acc, key) {
      var valueAsString = (reference.getAttribute("data-tippy-" + key) || '').trim();

      if (!valueAsString) {
        return acc;
      }

      if (key === 'content') {
        acc[key] = valueAsString;
      } else {
        try {
          acc[key] = JSON.parse(valueAsString);
        } catch (e) {
          acc[key] = valueAsString;
        }
      }

      return acc;
    }, {});
    return props;
  }
  function evaluateProps(reference, props) {
    var out = Object.assign({}, props, {
      content: invokeWithArgsOrReturn(props.content, [reference])
    }, props.ignoreAttributes ? {} : getDataAttributeProps(reference, props.plugins));
    out.aria = Object.assign({}, defaultProps.aria, out.aria);
    out.aria = {
      expanded: out.aria.expanded === 'auto' ? props.interactive : out.aria.expanded,
      content: out.aria.content === 'auto' ? props.interactive ? null : 'describedby' : out.aria.content
    };
    return out;
  }
  function validateProps(partialProps, plugins) {
    if (partialProps === void 0) {
      partialProps = {};
    }

    if (plugins === void 0) {
      plugins = [];
    }

    var keys = Object.keys(partialProps);
    keys.forEach(function (prop) {
      var nonPluginProps = removeProperties(defaultProps, Object.keys(pluginProps));
      var didPassUnknownProp = !hasOwnProperty(nonPluginProps, prop); // Check if the prop exists in `plugins`

      if (didPassUnknownProp) {
        didPassUnknownProp = plugins.filter(function (plugin) {
          return plugin.name === prop;
        }).length === 0;
      }

      warnWhen(didPassUnknownProp, ["`" + prop + "`", "is not a valid prop. You may have spelled it incorrectly, or if it's", 'a plugin, forgot to pass it in an array as props.plugins.', '\n\n', 'All props: https://atomiks.github.io/tippyjs/v6/all-props/\n', 'Plugins: https://atomiks.github.io/tippyjs/v6/plugins/'].join(' '));
    });
  }

  var innerHTML = function innerHTML() {
    return 'innerHTML';
  };

  function dangerouslySetInnerHTML(element, html) {
    element[innerHTML()] = html;
  }

  function createArrowElement(value) {
    var arrow = div();

    if (value === true) {
      arrow.className = ARROW_CLASS;
    } else {
      arrow.className = SVG_ARROW_CLASS;

      if (isElement(value)) {
        arrow.appendChild(value);
      } else {
        dangerouslySetInnerHTML(arrow, value);
      }
    }

    return arrow;
  }

  function setContent(content, props) {
    if (isElement(props.content)) {
      dangerouslySetInnerHTML(content, '');
      content.appendChild(props.content);
    } else if (typeof props.content !== 'function') {
      if (props.allowHTML) {
        dangerouslySetInnerHTML(content, props.content);
      } else {
        content.textContent = props.content;
      }
    }
  }
  function getChildren(popper) {
    var box = popper.firstElementChild;
    var boxChildren = arrayFrom(box.children);
    return {
      box: box,
      content: boxChildren.find(function (node) {
        return node.classList.contains(CONTENT_CLASS);
      }),
      arrow: boxChildren.find(function (node) {
        return node.classList.contains(ARROW_CLASS) || node.classList.contains(SVG_ARROW_CLASS);
      }),
      backdrop: boxChildren.find(function (node) {
        return node.classList.contains(BACKDROP_CLASS);
      })
    };
  }
  function render(instance) {
    var popper = div();
    var box = div();
    box.className = BOX_CLASS;
    box.setAttribute('data-state', 'hidden');
    box.setAttribute('tabindex', '-1');
    var content = div();
    content.className = CONTENT_CLASS;
    content.setAttribute('data-state', 'hidden');
    setContent(content, instance.props);
    popper.appendChild(box);
    box.appendChild(content);
    onUpdate(instance.props, instance.props);

    function onUpdate(prevProps, nextProps) {
      var _getChildren = getChildren(popper),
          box = _getChildren.box,
          content = _getChildren.content,
          arrow = _getChildren.arrow;

      if (nextProps.theme) {
        box.setAttribute('data-theme', nextProps.theme);
      } else {
        box.removeAttribute('data-theme');
      }

      if (typeof nextProps.animation === 'string') {
        box.setAttribute('data-animation', nextProps.animation);
      } else {
        box.removeAttribute('data-animation');
      }

      if (nextProps.inertia) {
        box.setAttribute('data-inertia', '');
      } else {
        box.removeAttribute('data-inertia');
      }

      box.style.maxWidth = typeof nextProps.maxWidth === 'number' ? nextProps.maxWidth + "px" : nextProps.maxWidth;

      if (nextProps.role) {
        box.setAttribute('role', nextProps.role);
      } else {
        box.removeAttribute('role');
      }

      if (prevProps.content !== nextProps.content || prevProps.allowHTML !== nextProps.allowHTML) {
        setContent(content, instance.props);
      }

      if (nextProps.arrow) {
        if (!arrow) {
          box.appendChild(createArrowElement(nextProps.arrow));
        } else if (prevProps.arrow !== nextProps.arrow) {
          box.removeChild(arrow);
          box.appendChild(createArrowElement(nextProps.arrow));
        }
      } else if (arrow) {
        box.removeChild(arrow);
      }
    }

    return {
      popper: popper,
      onUpdate: onUpdate
    };
  } // Runtime check to identify if the render function is the default one; this
  // way we can apply default CSS transitions logic and it can be tree-shaken away

  render.$$tippy = true;

  var idCounter = 1;
  var mouseMoveListeners = []; // Used by `hideAll()`

  var mountedInstances = [];
  function createTippy(reference, passedProps) {
    var props = evaluateProps(reference, Object.assign({}, defaultProps, getExtendedPassedProps(removeUndefinedProps(passedProps)))); // ===========================================================================
    // 🔒 Private members
    // ===========================================================================

    var showTimeout;
    var hideTimeout;
    var scheduleHideAnimationFrame;
    var isVisibleFromClick = false;
    var didHideDueToDocumentMouseDown = false;
    var didTouchMove = false;
    var ignoreOnFirstUpdate = false;
    var lastTriggerEvent;
    var currentTransitionEndListener;
    var onFirstUpdate;
    var listeners = [];
    var debouncedOnMouseMove = debounce(onMouseMove, props.interactiveDebounce);
    var currentTarget; // ===========================================================================
    // 🔑 Public members
    // ===========================================================================

    var id = idCounter++;
    var popperInstance = null;
    var plugins = unique(props.plugins);
    var state = {
      // Is the instance currently enabled?
      isEnabled: true,
      // Is the tippy currently showing and not transitioning out?
      isVisible: false,
      // Has the instance been destroyed?
      isDestroyed: false,
      // Is the tippy currently mounted to the DOM?
      isMounted: false,
      // Has the tippy finished transitioning in?
      isShown: false
    };
    var instance = {
      // properties
      id: id,
      reference: reference,
      popper: div(),
      popperInstance: popperInstance,
      props: props,
      state: state,
      plugins: plugins,
      // methods
      clearDelayTimeouts: clearDelayTimeouts,
      setProps: setProps,
      setContent: setContent,
      show: show,
      hide: hide,
      hideWithInteractivity: hideWithInteractivity,
      enable: enable,
      disable: disable,
      unmount: unmount,
      destroy: destroy
    }; // TODO: Investigate why this early return causes a TDZ error in the tests —
    // it doesn't seem to happen in the browser

    /* istanbul ignore if */

    if (!props.render) {
      {
        errorWhen(true, 'render() function has not been supplied.');
      }

      return instance;
    } // ===========================================================================
    // Initial mutations
    // ===========================================================================


    var _props$render = props.render(instance),
        popper = _props$render.popper,
        onUpdate = _props$render.onUpdate;

    popper.setAttribute('data-tippy-root', '');
    popper.id = "tippy-" + instance.id;
    instance.popper = popper;
    reference._tippy = instance;
    popper._tippy = instance;
    var pluginsHooks = plugins.map(function (plugin) {
      return plugin.fn(instance);
    });
    var hasAriaExpanded = reference.hasAttribute('aria-expanded');
    addListeners();
    handleAriaExpandedAttribute();
    handleStyles();
    invokeHook('onCreate', [instance]);

    if (props.showOnCreate) {
      scheduleShow();
    } // Prevent a tippy with a delay from hiding if the cursor left then returned
    // before it started hiding


    popper.addEventListener('mouseenter', function () {
      if (instance.props.interactive && instance.state.isVisible) {
        instance.clearDelayTimeouts();
      }
    });
    popper.addEventListener('mouseleave', function () {
      if (instance.props.interactive && instance.props.trigger.indexOf('mouseenter') >= 0) {
        getDocument().addEventListener('mousemove', debouncedOnMouseMove);
      }
    });
    return instance; // ===========================================================================
    // 🔒 Private methods
    // ===========================================================================

    function getNormalizedTouchSettings() {
      var touch = instance.props.touch;
      return Array.isArray(touch) ? touch : [touch, 0];
    }

    function getIsCustomTouchBehavior() {
      return getNormalizedTouchSettings()[0] === 'hold';
    }

    function getIsDefaultRenderFn() {
      var _instance$props$rende;

      // @ts-ignore
      return !!((_instance$props$rende = instance.props.render) != null && _instance$props$rende.$$tippy);
    }

    function getCurrentTarget() {
      return currentTarget || reference;
    }

    function getDocument() {
      var parent = getCurrentTarget().parentNode;
      return parent ? getOwnerDocument(parent) : document;
    }

    function getDefaultTemplateChildren() {
      return getChildren(popper);
    }

    function getDelay(isShow) {
      // For touch or keyboard input, force `0` delay for UX reasons
      // Also if the instance is mounted but not visible (transitioning out),
      // ignore delay
      if (instance.state.isMounted && !instance.state.isVisible || currentInput.isTouch || lastTriggerEvent && lastTriggerEvent.type === 'focus') {
        return 0;
      }

      return getValueAtIndexOrReturn(instance.props.delay, isShow ? 0 : 1, defaultProps.delay);
    }

    function handleStyles(fromHide) {
      if (fromHide === void 0) {
        fromHide = false;
      }

      popper.style.pointerEvents = instance.props.interactive && !fromHide ? '' : 'none';
      popper.style.zIndex = "" + instance.props.zIndex;
    }

    function invokeHook(hook, args, shouldInvokePropsHook) {
      if (shouldInvokePropsHook === void 0) {
        shouldInvokePropsHook = true;
      }

      pluginsHooks.forEach(function (pluginHooks) {
        if (pluginHooks[hook]) {
          pluginHooks[hook].apply(pluginHooks, args);
        }
      });

      if (shouldInvokePropsHook) {
        var _instance$props;

        (_instance$props = instance.props)[hook].apply(_instance$props, args);
      }
    }

    function handleAriaContentAttribute() {
      var aria = instance.props.aria;

      if (!aria.content) {
        return;
      }

      var attr = "aria-" + aria.content;
      var id = popper.id;
      var nodes = normalizeToArray(instance.props.triggerTarget || reference);
      nodes.forEach(function (node) {
        var currentValue = node.getAttribute(attr);

        if (instance.state.isVisible) {
          node.setAttribute(attr, currentValue ? currentValue + " " + id : id);
        } else {
          var nextValue = currentValue && currentValue.replace(id, '').trim();

          if (nextValue) {
            node.setAttribute(attr, nextValue);
          } else {
            node.removeAttribute(attr);
          }
        }
      });
    }

    function handleAriaExpandedAttribute() {
      if (hasAriaExpanded || !instance.props.aria.expanded) {
        return;
      }

      var nodes = normalizeToArray(instance.props.triggerTarget || reference);
      nodes.forEach(function (node) {
        if (instance.props.interactive) {
          node.setAttribute('aria-expanded', instance.state.isVisible && node === getCurrentTarget() ? 'true' : 'false');
        } else {
          node.removeAttribute('aria-expanded');
        }
      });
    }

    function cleanupInteractiveMouseListeners() {
      getDocument().removeEventListener('mousemove', debouncedOnMouseMove);
      mouseMoveListeners = mouseMoveListeners.filter(function (listener) {
        return listener !== debouncedOnMouseMove;
      });
    }

    function onDocumentPress(event) {
      // Moved finger to scroll instead of an intentional tap outside
      if (currentInput.isTouch) {
        if (didTouchMove || event.type === 'mousedown') {
          return;
        }
      }

      var actualTarget = event.composedPath && event.composedPath()[0] || event.target; // Clicked on interactive popper

      if (instance.props.interactive && actualContains(popper, actualTarget)) {
        return;
      } // Clicked on the event listeners target


      if (normalizeToArray(instance.props.triggerTarget || reference).some(function (el) {
        return actualContains(el, actualTarget);
      })) {
        if (currentInput.isTouch) {
          return;
        }

        if (instance.state.isVisible && instance.props.trigger.indexOf('click') >= 0) {
          return;
        }
      } else {
        invokeHook('onClickOutside', [instance, event]);
      }

      if (instance.props.hideOnClick === true) {
        instance.clearDelayTimeouts();
        instance.hide(); // `mousedown` event is fired right before `focus` if pressing the
        // currentTarget. This lets a tippy with `focus` trigger know that it
        // should not show

        didHideDueToDocumentMouseDown = true;
        setTimeout(function () {
          didHideDueToDocumentMouseDown = false;
        }); // The listener gets added in `scheduleShow()`, but this may be hiding it
        // before it shows, and hide()'s early bail-out behavior can prevent it
        // from being cleaned up

        if (!instance.state.isMounted) {
          removeDocumentPress();
        }
      }
    }

    function onTouchMove() {
      didTouchMove = true;
    }

    function onTouchStart() {
      didTouchMove = false;
    }

    function addDocumentPress() {
      var doc = getDocument();
      doc.addEventListener('mousedown', onDocumentPress, true);
      doc.addEventListener('touchend', onDocumentPress, TOUCH_OPTIONS);
      doc.addEventListener('touchstart', onTouchStart, TOUCH_OPTIONS);
      doc.addEventListener('touchmove', onTouchMove, TOUCH_OPTIONS);
    }

    function removeDocumentPress() {
      var doc = getDocument();
      doc.removeEventListener('mousedown', onDocumentPress, true);
      doc.removeEventListener('touchend', onDocumentPress, TOUCH_OPTIONS);
      doc.removeEventListener('touchstart', onTouchStart, TOUCH_OPTIONS);
      doc.removeEventListener('touchmove', onTouchMove, TOUCH_OPTIONS);
    }

    function onTransitionedOut(duration, callback) {
      onTransitionEnd(duration, function () {
        if (!instance.state.isVisible && popper.parentNode && popper.parentNode.contains(popper)) {
          callback();
        }
      });
    }

    function onTransitionedIn(duration, callback) {
      onTransitionEnd(duration, callback);
    }

    function onTransitionEnd(duration, callback) {
      var box = getDefaultTemplateChildren().box;

      function listener(event) {
        if (event.target === box) {
          updateTransitionEndListener(box, 'remove', listener);
          callback();
        }
      } // Make callback synchronous if duration is 0
      // `transitionend` won't fire otherwise


      if (duration === 0) {
        return callback();
      }

      updateTransitionEndListener(box, 'remove', currentTransitionEndListener);
      updateTransitionEndListener(box, 'add', listener);
      currentTransitionEndListener = listener;
    }

    function on(eventType, handler, options) {
      if (options === void 0) {
        options = false;
      }

      var nodes = normalizeToArray(instance.props.triggerTarget || reference);
      nodes.forEach(function (node) {
        node.addEventListener(eventType, handler, options);
        listeners.push({
          node: node,
          eventType: eventType,
          handler: handler,
          options: options
        });
      });
    }

    function addListeners() {
      if (getIsCustomTouchBehavior()) {
        on('touchstart', onTrigger, {
          passive: true
        });
        on('touchend', onMouseLeave, {
          passive: true
        });
      }

      splitBySpaces(instance.props.trigger).forEach(function (eventType) {
        if (eventType === 'manual') {
          return;
        }

        on(eventType, onTrigger);

        switch (eventType) {
          case 'mouseenter':
            on('mouseleave', onMouseLeave);
            break;

          case 'focus':
            on(isIE11 ? 'focusout' : 'blur', onBlurOrFocusOut);
            break;

          case 'focusin':
            on('focusout', onBlurOrFocusOut);
            break;
        }
      });
    }

    function removeListeners() {
      listeners.forEach(function (_ref) {
        var node = _ref.node,
            eventType = _ref.eventType,
            handler = _ref.handler,
            options = _ref.options;
        node.removeEventListener(eventType, handler, options);
      });
      listeners = [];
    }

    function onTrigger(event) {
      var _lastTriggerEvent;

      var shouldScheduleClickHide = false;

      if (!instance.state.isEnabled || isEventListenerStopped(event) || didHideDueToDocumentMouseDown) {
        return;
      }

      var wasFocused = ((_lastTriggerEvent = lastTriggerEvent) == null ? void 0 : _lastTriggerEvent.type) === 'focus';
      lastTriggerEvent = event;
      currentTarget = event.currentTarget;
      handleAriaExpandedAttribute();

      if (!instance.state.isVisible && isMouseEvent(event)) {
        // If scrolling, `mouseenter` events can be fired if the cursor lands
        // over a new target, but `mousemove` events don't get fired. This
        // causes interactive tooltips to get stuck open until the cursor is
        // moved
        mouseMoveListeners.forEach(function (listener) {
          return listener(event);
        });
      } // Toggle show/hide when clicking click-triggered tooltips


      if (event.type === 'click' && (instance.props.trigger.indexOf('mouseenter') < 0 || isVisibleFromClick) && instance.props.hideOnClick !== false && instance.state.isVisible) {
        shouldScheduleClickHide = true;
      } else {
        scheduleShow(event);
      }

      if (event.type === 'click') {
        isVisibleFromClick = !shouldScheduleClickHide;
      }

      if (shouldScheduleClickHide && !wasFocused) {
        scheduleHide(event);
      }
    }

    function onMouseMove(event) {
      var target = event.target;
      var isCursorOverReferenceOrPopper = getCurrentTarget().contains(target) || popper.contains(target);

      if (event.type === 'mousemove' && isCursorOverReferenceOrPopper) {
        return;
      }

      var popperTreeData = getNestedPopperTree().concat(popper).map(function (popper) {
        var _instance$popperInsta;

        var instance = popper._tippy;
        var state = (_instance$popperInsta = instance.popperInstance) == null ? void 0 : _instance$popperInsta.state;

        if (state) {
          return {
            popperRect: popper.getBoundingClientRect(),
            popperState: state,
            props: props
          };
        }

        return null;
      }).filter(Boolean);

      if (isCursorOutsideInteractiveBorder(popperTreeData, event)) {
        cleanupInteractiveMouseListeners();
        scheduleHide(event);
      }
    }

    function onMouseLeave(event) {
      var shouldBail = isEventListenerStopped(event) || instance.props.trigger.indexOf('click') >= 0 && isVisibleFromClick;

      if (shouldBail) {
        return;
      }

      if (instance.props.interactive) {
        instance.hideWithInteractivity(event);
        return;
      }

      scheduleHide(event);
    }

    function onBlurOrFocusOut(event) {
      if (instance.props.trigger.indexOf('focusin') < 0 && event.target !== getCurrentTarget()) {
        return;
      } // If focus was moved to within the popper


      if (instance.props.interactive && event.relatedTarget && popper.contains(event.relatedTarget)) {
        return;
      }

      scheduleHide(event);
    }

    function isEventListenerStopped(event) {
      return currentInput.isTouch ? getIsCustomTouchBehavior() !== event.type.indexOf('touch') >= 0 : false;
    }

    function createPopperInstance() {
      destroyPopperInstance();
      var _instance$props2 = instance.props,
          popperOptions = _instance$props2.popperOptions,
          placement = _instance$props2.placement,
          offset = _instance$props2.offset,
          getReferenceClientRect = _instance$props2.getReferenceClientRect,
          moveTransition = _instance$props2.moveTransition;
      var arrow = getIsDefaultRenderFn() ? getChildren(popper).arrow : null;
      var computedReference = getReferenceClientRect ? {
        getBoundingClientRect: getReferenceClientRect,
        contextElement: getReferenceClientRect.contextElement || getCurrentTarget()
      } : reference;
      var tippyModifier = {
        name: '$$tippy',
        enabled: true,
        phase: 'beforeWrite',
        requires: ['computeStyles'],
        fn: function fn(_ref2) {
          var state = _ref2.state;

          if (getIsDefaultRenderFn()) {
            var _getDefaultTemplateCh = getDefaultTemplateChildren(),
                box = _getDefaultTemplateCh.box;

            ['placement', 'reference-hidden', 'escaped'].forEach(function (attr) {
              if (attr === 'placement') {
                box.setAttribute('data-placement', state.placement);
              } else {
                if (state.attributes.popper["data-popper-" + attr]) {
                  box.setAttribute("data-" + attr, '');
                } else {
                  box.removeAttribute("data-" + attr);
                }
              }
            });
            state.attributes.popper = {};
          }
        }
      };
      var modifiers = [{
        name: 'offset',
        options: {
          offset: offset
        }
      }, {
        name: 'preventOverflow',
        options: {
          padding: {
            top: 2,
            bottom: 2,
            left: 5,
            right: 5
          }
        }
      }, {
        name: 'flip',
        options: {
          padding: 5
        }
      }, {
        name: 'computeStyles',
        options: {
          adaptive: !moveTransition
        }
      }, tippyModifier];

      if (getIsDefaultRenderFn() && arrow) {
        modifiers.push({
          name: 'arrow',
          options: {
            element: arrow,
            padding: 3
          }
        });
      }

      modifiers.push.apply(modifiers, (popperOptions == null ? void 0 : popperOptions.modifiers) || []);
      instance.popperInstance = core.createPopper(computedReference, popper, Object.assign({}, popperOptions, {
        placement: placement,
        onFirstUpdate: onFirstUpdate,
        modifiers: modifiers
      }));
    }

    function destroyPopperInstance() {
      if (instance.popperInstance) {
        instance.popperInstance.destroy();
        instance.popperInstance = null;
      }
    }

    function mount() {
      var appendTo = instance.props.appendTo;
      var parentNode; // By default, we'll append the popper to the triggerTargets's parentNode so
      // it's directly after the reference element so the elements inside the
      // tippy can be tabbed to
      // If there are clipping issues, the user can specify a different appendTo
      // and ensure focus management is handled correctly manually

      var node = getCurrentTarget();

      if (instance.props.interactive && appendTo === TIPPY_DEFAULT_APPEND_TO || appendTo === 'parent') {
        parentNode = node.parentNode;
      } else {
        parentNode = invokeWithArgsOrReturn(appendTo, [node]);
      } // The popper element needs to exist on the DOM before its position can be
      // updated as Popper needs to read its dimensions


      if (!parentNode.contains(popper)) {
        parentNode.appendChild(popper);
      }

      instance.state.isMounted = true;
      createPopperInstance();
      /* istanbul ignore else */

      {
        // Accessibility check
        warnWhen(instance.props.interactive && appendTo === defaultProps.appendTo && node.nextElementSibling !== popper, ['Interactive tippy element may not be accessible via keyboard', 'navigation because it is not directly after the reference element', 'in the DOM source order.', '\n\n', 'Using a wrapper <div> or <span> tag around the reference element', 'solves this by creating a new parentNode context.', '\n\n', 'Specifying `appendTo: document.body` silences this warning, but it', 'assumes you are using a focus management solution to handle', 'keyboard navigation.', '\n\n', 'See: https://atomiks.github.io/tippyjs/v6/accessibility/#interactivity'].join(' '));
      }
    }

    function getNestedPopperTree() {
      return arrayFrom(popper.querySelectorAll('[data-tippy-root]'));
    }

    function scheduleShow(event) {
      instance.clearDelayTimeouts();

      if (event) {
        invokeHook('onTrigger', [instance, event]);
      }

      addDocumentPress();
      var delay = getDelay(true);

      var _getNormalizedTouchSe = getNormalizedTouchSettings(),
          touchValue = _getNormalizedTouchSe[0],
          touchDelay = _getNormalizedTouchSe[1];

      if (currentInput.isTouch && touchValue === 'hold' && touchDelay) {
        delay = touchDelay;
      }

      if (delay) {
        showTimeout = setTimeout(function () {
          instance.show();
        }, delay);
      } else {
        instance.show();
      }
    }

    function scheduleHide(event) {
      instance.clearDelayTimeouts();
      invokeHook('onUntrigger', [instance, event]);

      if (!instance.state.isVisible) {
        removeDocumentPress();
        return;
      } // For interactive tippies, scheduleHide is added to a document.body handler
      // from onMouseLeave so must intercept scheduled hides from mousemove/leave
      // events when trigger contains mouseenter and click, and the tip is
      // currently shown as a result of a click.


      if (instance.props.trigger.indexOf('mouseenter') >= 0 && instance.props.trigger.indexOf('click') >= 0 && ['mouseleave', 'mousemove'].indexOf(event.type) >= 0 && isVisibleFromClick) {
        return;
      }

      var delay = getDelay(false);

      if (delay) {
        hideTimeout = setTimeout(function () {
          if (instance.state.isVisible) {
            instance.hide();
          }
        }, delay);
      } else {
        // Fixes a `transitionend` problem when it fires 1 frame too
        // late sometimes, we don't want hide() to be called.
        scheduleHideAnimationFrame = requestAnimationFrame(function () {
          instance.hide();
        });
      }
    } // ===========================================================================
    // 🔑 Public methods
    // ===========================================================================


    function enable() {
      instance.state.isEnabled = true;
    }

    function disable() {
      // Disabling the instance should also hide it
      // https://github.com/atomiks/tippy.js-react/issues/106
      instance.hide();
      instance.state.isEnabled = false;
    }

    function clearDelayTimeouts() {
      clearTimeout(showTimeout);
      clearTimeout(hideTimeout);
      cancelAnimationFrame(scheduleHideAnimationFrame);
    }

    function setProps(partialProps) {
      /* istanbul ignore else */
      {
        warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('setProps'));
      }

      if (instance.state.isDestroyed) {
        return;
      }

      invokeHook('onBeforeUpdate', [instance, partialProps]);
      removeListeners();
      var prevProps = instance.props;
      var nextProps = evaluateProps(reference, Object.assign({}, prevProps, removeUndefinedProps(partialProps), {
        ignoreAttributes: true
      }));
      instance.props = nextProps;
      addListeners();

      if (prevProps.interactiveDebounce !== nextProps.interactiveDebounce) {
        cleanupInteractiveMouseListeners();
        debouncedOnMouseMove = debounce(onMouseMove, nextProps.interactiveDebounce);
      } // Ensure stale aria-expanded attributes are removed


      if (prevProps.triggerTarget && !nextProps.triggerTarget) {
        normalizeToArray(prevProps.triggerTarget).forEach(function (node) {
          node.removeAttribute('aria-expanded');
        });
      } else if (nextProps.triggerTarget) {
        reference.removeAttribute('aria-expanded');
      }

      handleAriaExpandedAttribute();
      handleStyles();

      if (onUpdate) {
        onUpdate(prevProps, nextProps);
      }

      if (instance.popperInstance) {
        createPopperInstance(); // Fixes an issue with nested tippies if they are all getting re-rendered,
        // and the nested ones get re-rendered first.
        // https://github.com/atomiks/tippyjs-react/issues/177
        // TODO: find a cleaner / more efficient solution(!)

        getNestedPopperTree().forEach(function (nestedPopper) {
          // React (and other UI libs likely) requires a rAF wrapper as it flushes
          // its work in one
          requestAnimationFrame(nestedPopper._tippy.popperInstance.forceUpdate);
        });
      }

      invokeHook('onAfterUpdate', [instance, partialProps]);
    }

    function setContent(content) {
      instance.setProps({
        content: content
      });
    }

    function show() {
      /* istanbul ignore else */
      {
        warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('show'));
      } // Early bail-out


      var isAlreadyVisible = instance.state.isVisible;
      var isDestroyed = instance.state.isDestroyed;
      var isDisabled = !instance.state.isEnabled;
      var isTouchAndTouchDisabled = currentInput.isTouch && !instance.props.touch;
      var duration = getValueAtIndexOrReturn(instance.props.duration, 0, defaultProps.duration);

      if (isAlreadyVisible || isDestroyed || isDisabled || isTouchAndTouchDisabled) {
        return;
      } // Normalize `disabled` behavior across browsers.
      // Firefox allows events on disabled elements, but Chrome doesn't.
      // Using a wrapper element (i.e. <span>) is recommended.


      if (getCurrentTarget().hasAttribute('disabled')) {
        return;
      }

      invokeHook('onShow', [instance], false);

      if (instance.props.onShow(instance) === false) {
        return;
      }

      instance.state.isVisible = true;

      if (getIsDefaultRenderFn()) {
        popper.style.visibility = 'visible';
      }

      handleStyles();
      addDocumentPress();

      if (!instance.state.isMounted) {
        popper.style.transition = 'none';
      } // If flipping to the opposite side after hiding at least once, the
      // animation will use the wrong placement without resetting the duration


      if (getIsDefaultRenderFn()) {
        var _getDefaultTemplateCh2 = getDefaultTemplateChildren(),
            box = _getDefaultTemplateCh2.box,
            content = _getDefaultTemplateCh2.content;

        setTransitionDuration([box, content], 0);
      }

      onFirstUpdate = function onFirstUpdate() {
        var _instance$popperInsta2;

        if (!instance.state.isVisible || ignoreOnFirstUpdate) {
          return;
        }

        ignoreOnFirstUpdate = true; // reflow

        void popper.offsetHeight;
        popper.style.transition = instance.props.moveTransition;

        if (getIsDefaultRenderFn() && instance.props.animation) {
          var _getDefaultTemplateCh3 = getDefaultTemplateChildren(),
              _box = _getDefaultTemplateCh3.box,
              _content = _getDefaultTemplateCh3.content;

          setTransitionDuration([_box, _content], duration);
          setVisibilityState([_box, _content], 'visible');
        }

        handleAriaContentAttribute();
        handleAriaExpandedAttribute();
        pushIfUnique(mountedInstances, instance); // certain modifiers (e.g. `maxSize`) require a second update after the
        // popper has been positioned for the first time

        (_instance$popperInsta2 = instance.popperInstance) == null ? void 0 : _instance$popperInsta2.forceUpdate();
        invokeHook('onMount', [instance]);

        if (instance.props.animation && getIsDefaultRenderFn()) {
          onTransitionedIn(duration, function () {
            instance.state.isShown = true;
            invokeHook('onShown', [instance]);
          });
        }
      };

      mount();
    }

    function hide() {
      /* istanbul ignore else */
      {
        warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('hide'));
      } // Early bail-out


      var isAlreadyHidden = !instance.state.isVisible;
      var isDestroyed = instance.state.isDestroyed;
      var isDisabled = !instance.state.isEnabled;
      var duration = getValueAtIndexOrReturn(instance.props.duration, 1, defaultProps.duration);

      if (isAlreadyHidden || isDestroyed || isDisabled) {
        return;
      }

      invokeHook('onHide', [instance], false);

      if (instance.props.onHide(instance) === false) {
        return;
      }

      instance.state.isVisible = false;
      instance.state.isShown = false;
      ignoreOnFirstUpdate = false;
      isVisibleFromClick = false;

      if (getIsDefaultRenderFn()) {
        popper.style.visibility = 'hidden';
      }

      cleanupInteractiveMouseListeners();
      removeDocumentPress();
      handleStyles(true);

      if (getIsDefaultRenderFn()) {
        var _getDefaultTemplateCh4 = getDefaultTemplateChildren(),
            box = _getDefaultTemplateCh4.box,
            content = _getDefaultTemplateCh4.content;

        if (instance.props.animation) {
          setTransitionDuration([box, content], duration);
          setVisibilityState([box, content], 'hidden');
        }
      }

      handleAriaContentAttribute();
      handleAriaExpandedAttribute();

      if (instance.props.animation) {
        if (getIsDefaultRenderFn()) {
          onTransitionedOut(duration, instance.unmount);
        }
      } else {
        instance.unmount();
      }
    }

    function hideWithInteractivity(event) {
      /* istanbul ignore else */
      {
        warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('hideWithInteractivity'));
      }

      getDocument().addEventListener('mousemove', debouncedOnMouseMove);
      pushIfUnique(mouseMoveListeners, debouncedOnMouseMove);
      debouncedOnMouseMove(event);
    }

    function unmount() {
      /* istanbul ignore else */
      {
        warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('unmount'));
      }

      if (instance.state.isVisible) {
        instance.hide();
      }

      if (!instance.state.isMounted) {
        return;
      }

      destroyPopperInstance(); // If a popper is not interactive, it will be appended outside the popper
      // tree by default. This seems mainly for interactive tippies, but we should
      // find a workaround if possible

      getNestedPopperTree().forEach(function (nestedPopper) {
        nestedPopper._tippy.unmount();
      });

      if (popper.parentNode) {
        popper.parentNode.removeChild(popper);
      }

      mountedInstances = mountedInstances.filter(function (i) {
        return i !== instance;
      });
      instance.state.isMounted = false;
      invokeHook('onHidden', [instance]);
    }

    function destroy() {
      /* istanbul ignore else */
      {
        warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('destroy'));
      }

      if (instance.state.isDestroyed) {
        return;
      }

      instance.clearDelayTimeouts();
      instance.unmount();
      removeListeners();
      delete reference._tippy;
      instance.state.isDestroyed = true;
      invokeHook('onDestroy', [instance]);
    }
  }

  function tippy(targets, optionalProps) {
    if (optionalProps === void 0) {
      optionalProps = {};
    }

    var plugins = defaultProps.plugins.concat(optionalProps.plugins || []);
    /* istanbul ignore else */

    {
      validateTargets(targets);
      validateProps(optionalProps, plugins);
    }

    bindGlobalEventListeners();
    var passedProps = Object.assign({}, optionalProps, {
      plugins: plugins
    });
    var elements = getArrayOfElements(targets);
    /* istanbul ignore else */

    {
      var isSingleContentElement = isElement(passedProps.content);
      var isMoreThanOneReferenceElement = elements.length > 1;
      warnWhen(isSingleContentElement && isMoreThanOneReferenceElement, ['tippy() was passed an Element as the `content` prop, but more than', 'one tippy instance was created by this invocation. This means the', 'content element will only be appended to the last tippy instance.', '\n\n', 'Instead, pass the .innerHTML of the element, or use a function that', 'returns a cloned version of the element instead.', '\n\n', '1) content: element.innerHTML\n', '2) content: () => element.cloneNode(true)'].join(' '));
    }

    var instances = elements.reduce(function (acc, reference) {
      var instance = reference && createTippy(reference, passedProps);

      if (instance) {
        acc.push(instance);
      }

      return acc;
    }, []);
    return isElement(targets) ? instances[0] : instances;
  }

  tippy.defaultProps = defaultProps;
  tippy.setDefaultProps = setDefaultProps;
  tippy.currentInput = currentInput;
  var hideAll = function hideAll(_temp) {
    var _ref = _temp === void 0 ? {} : _temp,
        excludedReferenceOrInstance = _ref.exclude,
        duration = _ref.duration;

    mountedInstances.forEach(function (instance) {
      var isExcluded = false;

      if (excludedReferenceOrInstance) {
        isExcluded = isReferenceElement(excludedReferenceOrInstance) ? instance.reference === excludedReferenceOrInstance : instance.popper === excludedReferenceOrInstance.popper;
      }

      if (!isExcluded) {
        var originalDuration = instance.props.duration;
        instance.setProps({
          duration: duration
        });
        instance.hide();

        if (!instance.state.isDestroyed) {
          instance.setProps({
            duration: originalDuration
          });
        }
      }
    });
  };

  // every time the popper is destroyed (i.e. a new target), removing the styles
  // and causing transitions to break for singletons when the console is open, but
  // most notably for non-transform styles being used, `gpuAcceleration: false`.

  var applyStylesModifier = Object.assign({}, core.applyStyles, {
    effect: function effect(_ref) {
      var state = _ref.state;
      var initialStyles = {
        popper: {
          position: state.options.strategy,
          left: '0',
          top: '0',
          margin: '0'
        },
        arrow: {
          position: 'absolute'
        },
        reference: {}
      };
      Object.assign(state.elements.popper.style, initialStyles.popper);
      state.styles = initialStyles;

      if (state.elements.arrow) {
        Object.assign(state.elements.arrow.style, initialStyles.arrow);
      } // intentionally return no cleanup function
      // return () => { ... }

    }
  });

  var createSingleton = function createSingleton(tippyInstances, optionalProps) {
    var _optionalProps$popper;

    if (optionalProps === void 0) {
      optionalProps = {};
    }

    /* istanbul ignore else */
    {
      errorWhen(!Array.isArray(tippyInstances), ['The first argument passed to createSingleton() must be an array of', 'tippy instances. The passed value was', String(tippyInstances)].join(' '));
    }

    var individualInstances = tippyInstances;
    var references = [];
    var triggerTargets = [];
    var currentTarget;
    var overrides = optionalProps.overrides;
    var interceptSetPropsCleanups = [];
    var shownOnCreate = false;

    function setTriggerTargets() {
      triggerTargets = individualInstances.map(function (instance) {
        return normalizeToArray(instance.props.triggerTarget || instance.reference);
      }).reduce(function (acc, item) {
        return acc.concat(item);
      }, []);
    }

    function setReferences() {
      references = individualInstances.map(function (instance) {
        return instance.reference;
      });
    }

    function enableInstances(isEnabled) {
      individualInstances.forEach(function (instance) {
        if (isEnabled) {
          instance.enable();
        } else {
          instance.disable();
        }
      });
    }

    function interceptSetProps(singleton) {
      return individualInstances.map(function (instance) {
        var originalSetProps = instance.setProps;

        instance.setProps = function (props) {
          originalSetProps(props);

          if (instance.reference === currentTarget) {
            singleton.setProps(props);
          }
        };

        return function () {
          instance.setProps = originalSetProps;
        };
      });
    } // have to pass singleton, as it maybe undefined on first call


    function prepareInstance(singleton, target) {
      var index = triggerTargets.indexOf(target); // bail-out

      if (target === currentTarget) {
        return;
      }

      currentTarget = target;
      var overrideProps = (overrides || []).concat('content').reduce(function (acc, prop) {
        acc[prop] = individualInstances[index].props[prop];
        return acc;
      }, {});
      singleton.setProps(Object.assign({}, overrideProps, {
        getReferenceClientRect: typeof overrideProps.getReferenceClientRect === 'function' ? overrideProps.getReferenceClientRect : function () {
          var _references$index;

          return (_references$index = references[index]) == null ? void 0 : _references$index.getBoundingClientRect();
        }
      }));
    }

    enableInstances(false);
    setReferences();
    setTriggerTargets();
    var plugin = {
      fn: function fn() {
        return {
          onDestroy: function onDestroy() {
            enableInstances(true);
          },
          onHidden: function onHidden() {
            currentTarget = null;
          },
          onClickOutside: function onClickOutside(instance) {
            if (instance.props.showOnCreate && !shownOnCreate) {
              shownOnCreate = true;
              currentTarget = null;
            }
          },
          onShow: function onShow(instance) {
            if (instance.props.showOnCreate && !shownOnCreate) {
              shownOnCreate = true;
              prepareInstance(instance, references[0]);
            }
          },
          onTrigger: function onTrigger(instance, event) {
            prepareInstance(instance, event.currentTarget);
          }
        };
      }
    };
    var singleton = tippy(div(), Object.assign({}, removeProperties(optionalProps, ['overrides']), {
      plugins: [plugin].concat(optionalProps.plugins || []),
      triggerTarget: triggerTargets,
      popperOptions: Object.assign({}, optionalProps.popperOptions, {
        modifiers: [].concat(((_optionalProps$popper = optionalProps.popperOptions) == null ? void 0 : _optionalProps$popper.modifiers) || [], [applyStylesModifier])
      })
    }));
    var originalShow = singleton.show;

    singleton.show = function (target) {
      originalShow(); // first time, showOnCreate or programmatic call with no params
      // default to showing first instance

      if (!currentTarget && target == null) {
        return prepareInstance(singleton, references[0]);
      } // triggered from event (do nothing as prepareInstance already called by onTrigger)
      // programmatic call with no params when already visible (do nothing again)


      if (currentTarget && target == null) {
        return;
      } // target is index of instance


      if (typeof target === 'number') {
        return references[target] && prepareInstance(singleton, references[target]);
      } // target is a child tippy instance


      if (individualInstances.indexOf(target) >= 0) {
        var ref = target.reference;
        return prepareInstance(singleton, ref);
      } // target is a ReferenceElement


      if (references.indexOf(target) >= 0) {
        return prepareInstance(singleton, target);
      }
    };

    singleton.showNext = function () {
      var first = references[0];

      if (!currentTarget) {
        return singleton.show(0);
      }

      var index = references.indexOf(currentTarget);
      singleton.show(references[index + 1] || first);
    };

    singleton.showPrevious = function () {
      var last = references[references.length - 1];

      if (!currentTarget) {
        return singleton.show(last);
      }

      var index = references.indexOf(currentTarget);
      var target = references[index - 1] || last;
      singleton.show(target);
    };

    var originalSetProps = singleton.setProps;

    singleton.setProps = function (props) {
      overrides = props.overrides || overrides;
      originalSetProps(props);
    };

    singleton.setInstances = function (nextInstances) {
      enableInstances(true);
      interceptSetPropsCleanups.forEach(function (fn) {
        return fn();
      });
      individualInstances = nextInstances;
      enableInstances(false);
      setReferences();
      setTriggerTargets();
      interceptSetPropsCleanups = interceptSetProps(singleton);
      singleton.setProps({
        triggerTarget: triggerTargets
      });
    };

    interceptSetPropsCleanups = interceptSetProps(singleton);
    return singleton;
  };

  var BUBBLING_EVENTS_MAP = {
    mouseover: 'mouseenter',
    focusin: 'focus',
    click: 'click'
  };
  /**
   * Creates a delegate instance that controls the creation of tippy instances
   * for child elements (`target` CSS selector).
   */

  function delegate(targets, props) {
    /* istanbul ignore else */
    {
      errorWhen(!(props && props.target), ['You must specity a `target` prop indicating a CSS selector string matching', 'the target elements that should receive a tippy.'].join(' '));
    }

    var listeners = [];
    var childTippyInstances = [];
    var disabled = false;
    var target = props.target;
    var nativeProps = removeProperties(props, ['target']);
    var parentProps = Object.assign({}, nativeProps, {
      trigger: 'manual',
      touch: false
    });
    var childProps = Object.assign({
      touch: defaultProps.touch
    }, nativeProps, {
      showOnCreate: true
    });
    var returnValue = tippy(targets, parentProps);
    var normalizedReturnValue = normalizeToArray(returnValue);

    function onTrigger(event) {
      if (!event.target || disabled) {
        return;
      }

      var targetNode = event.target.closest(target);

      if (!targetNode) {
        return;
      } // Get relevant trigger with fallbacks:
      // 1. Check `data-tippy-trigger` attribute on target node
      // 2. Fallback to `trigger` passed to `delegate()`
      // 3. Fallback to `defaultProps.trigger`


      var trigger = targetNode.getAttribute('data-tippy-trigger') || props.trigger || defaultProps.trigger; // @ts-ignore

      if (targetNode._tippy) {
        return;
      }

      if (event.type === 'touchstart' && typeof childProps.touch === 'boolean') {
        return;
      }

      if (event.type !== 'touchstart' && trigger.indexOf(BUBBLING_EVENTS_MAP[event.type]) < 0) {
        return;
      }

      var instance = tippy(targetNode, childProps);

      if (instance) {
        childTippyInstances = childTippyInstances.concat(instance);
      }
    }

    function on(node, eventType, handler, options) {
      if (options === void 0) {
        options = false;
      }

      node.addEventListener(eventType, handler, options);
      listeners.push({
        node: node,
        eventType: eventType,
        handler: handler,
        options: options
      });
    }

    function addEventListeners(instance) {
      var reference = instance.reference;
      on(reference, 'touchstart', onTrigger, TOUCH_OPTIONS);
      on(reference, 'mouseover', onTrigger);
      on(reference, 'focusin', onTrigger);
      on(reference, 'click', onTrigger);
    }

    function removeEventListeners() {
      listeners.forEach(function (_ref) {
        var node = _ref.node,
            eventType = _ref.eventType,
            handler = _ref.handler,
            options = _ref.options;
        node.removeEventListener(eventType, handler, options);
      });
      listeners = [];
    }

    function applyMutations(instance) {
      var originalDestroy = instance.destroy;
      var originalEnable = instance.enable;
      var originalDisable = instance.disable;

      instance.destroy = function (shouldDestroyChildInstances) {
        if (shouldDestroyChildInstances === void 0) {
          shouldDestroyChildInstances = true;
        }

        if (shouldDestroyChildInstances) {
          childTippyInstances.forEach(function (instance) {
            instance.destroy();
          });
        }

        childTippyInstances = [];
        removeEventListeners();
        originalDestroy();
      };

      instance.enable = function () {
        originalEnable();
        childTippyInstances.forEach(function (instance) {
          return instance.enable();
        });
        disabled = false;
      };

      instance.disable = function () {
        originalDisable();
        childTippyInstances.forEach(function (instance) {
          return instance.disable();
        });
        disabled = true;
      };

      addEventListeners(instance);
    }

    normalizedReturnValue.forEach(applyMutations);
    return returnValue;
  }

  var animateFill = {
    name: 'animateFill',
    defaultValue: false,
    fn: function fn(instance) {
      var _instance$props$rende;

      // @ts-ignore
      if (!((_instance$props$rende = instance.props.render) != null && _instance$props$rende.$$tippy)) {
        {
          errorWhen(instance.props.animateFill, 'The `animateFill` plugin requires the default render function.');
        }

        return {};
      }

      var _getChildren = getChildren(instance.popper),
          box = _getChildren.box,
          content = _getChildren.content;

      var backdrop = instance.props.animateFill ? createBackdropElement() : null;
      return {
        onCreate: function onCreate() {
          if (backdrop) {
            box.insertBefore(backdrop, box.firstElementChild);
            box.setAttribute('data-animatefill', '');
            box.style.overflow = 'hidden';
            instance.setProps({
              arrow: false,
              animation: 'shift-away'
            });
          }
        },
        onMount: function onMount() {
          if (backdrop) {
            var transitionDuration = box.style.transitionDuration;
            var duration = Number(transitionDuration.replace('ms', '')); // The content should fade in after the backdrop has mostly filled the
            // tooltip element. `clip-path` is the other alternative but is not
            // well-supported and is buggy on some devices.

            content.style.transitionDelay = Math.round(duration / 10) + "ms";
            backdrop.style.transitionDuration = transitionDuration;
            setVisibilityState([backdrop], 'visible');
          }
        },
        onShow: function onShow() {
          if (backdrop) {
            backdrop.style.transitionDuration = '0ms';
          }
        },
        onHide: function onHide() {
          if (backdrop) {
            setVisibilityState([backdrop], 'hidden');
          }
        }
      };
    }
  };

  function createBackdropElement() {
    var backdrop = div();
    backdrop.className = BACKDROP_CLASS;
    setVisibilityState([backdrop], 'hidden');
    return backdrop;
  }

  var mouseCoords = {
    clientX: 0,
    clientY: 0
  };
  var activeInstances = [];

  function storeMouseCoords(_ref) {
    var clientX = _ref.clientX,
        clientY = _ref.clientY;
    mouseCoords = {
      clientX: clientX,
      clientY: clientY
    };
  }

  function addMouseCoordsListener(doc) {
    doc.addEventListener('mousemove', storeMouseCoords);
  }

  function removeMouseCoordsListener(doc) {
    doc.removeEventListener('mousemove', storeMouseCoords);
  }

  var followCursor = {
    name: 'followCursor',
    defaultValue: false,
    fn: function fn(instance) {
      var reference = instance.reference;
      var doc = getOwnerDocument(instance.props.triggerTarget || reference);
      var isInternalUpdate = false;
      var wasFocusEvent = false;
      var isUnmounted = true;
      var prevProps = instance.props;

      function getIsInitialBehavior() {
        return instance.props.followCursor === 'initial' && instance.state.isVisible;
      }

      function addListener() {
        doc.addEventListener('mousemove', onMouseMove);
      }

      function removeListener() {
        doc.removeEventListener('mousemove', onMouseMove);
      }

      function unsetGetReferenceClientRect() {
        isInternalUpdate = true;
        instance.setProps({
          getReferenceClientRect: null
        });
        isInternalUpdate = false;
      }

      function onMouseMove(event) {
        // If the instance is interactive, avoid updating the position unless it's
        // over the reference element
        var isCursorOverReference = event.target ? reference.contains(event.target) : true;
        var followCursor = instance.props.followCursor;
        var clientX = event.clientX,
            clientY = event.clientY;
        var rect = reference.getBoundingClientRect();
        var relativeX = clientX - rect.left;
        var relativeY = clientY - rect.top;

        if (isCursorOverReference || !instance.props.interactive) {
          instance.setProps({
            // @ts-ignore - unneeded DOMRect properties
            getReferenceClientRect: function getReferenceClientRect() {
              var rect = reference.getBoundingClientRect();
              var x = clientX;
              var y = clientY;

              if (followCursor === 'initial') {
                x = rect.left + relativeX;
                y = rect.top + relativeY;
              }

              var top = followCursor === 'horizontal' ? rect.top : y;
              var right = followCursor === 'vertical' ? rect.right : x;
              var bottom = followCursor === 'horizontal' ? rect.bottom : y;
              var left = followCursor === 'vertical' ? rect.left : x;
              return {
                width: right - left,
                height: bottom - top,
                top: top,
                right: right,
                bottom: bottom,
                left: left
              };
            }
          });
        }
      }

      function create() {
        if (instance.props.followCursor) {
          activeInstances.push({
            instance: instance,
            doc: doc
          });
          addMouseCoordsListener(doc);
        }
      }

      function destroy() {
        activeInstances = activeInstances.filter(function (data) {
          return data.instance !== instance;
        });

        if (activeInstances.filter(function (data) {
          return data.doc === doc;
        }).length === 0) {
          removeMouseCoordsListener(doc);
        }
      }

      return {
        onCreate: create,
        onDestroy: destroy,
        onBeforeUpdate: function onBeforeUpdate() {
          prevProps = instance.props;
        },
        onAfterUpdate: function onAfterUpdate(_, _ref2) {
          var followCursor = _ref2.followCursor;

          if (isInternalUpdate) {
            return;
          }

          if (followCursor !== undefined && prevProps.followCursor !== followCursor) {
            destroy();

            if (followCursor) {
              create();

              if (instance.state.isMounted && !wasFocusEvent && !getIsInitialBehavior()) {
                addListener();
              }
            } else {
              removeListener();
              unsetGetReferenceClientRect();
            }
          }
        },
        onMount: function onMount() {
          if (instance.props.followCursor && !wasFocusEvent) {
            if (isUnmounted) {
              onMouseMove(mouseCoords);
              isUnmounted = false;
            }

            if (!getIsInitialBehavior()) {
              addListener();
            }
          }
        },
        onTrigger: function onTrigger(_, event) {
          if (isMouseEvent(event)) {
            mouseCoords = {
              clientX: event.clientX,
              clientY: event.clientY
            };
          }

          wasFocusEvent = event.type === 'focus';
        },
        onHidden: function onHidden() {
          if (instance.props.followCursor) {
            unsetGetReferenceClientRect();
            removeListener();
            isUnmounted = true;
          }
        }
      };
    }
  };

  function getProps(props, modifier) {
    var _props$popperOptions;

    return {
      popperOptions: Object.assign({}, props.popperOptions, {
        modifiers: [].concat((((_props$popperOptions = props.popperOptions) == null ? void 0 : _props$popperOptions.modifiers) || []).filter(function (_ref) {
          var name = _ref.name;
          return name !== modifier.name;
        }), [modifier])
      })
    };
  }

  var inlinePositioning = {
    name: 'inlinePositioning',
    defaultValue: false,
    fn: function fn(instance) {
      var reference = instance.reference;

      function isEnabled() {
        return !!instance.props.inlinePositioning;
      }

      var placement;
      var cursorRectIndex = -1;
      var isInternalUpdate = false;
      var triedPlacements = [];
      var modifier = {
        name: 'tippyInlinePositioning',
        enabled: true,
        phase: 'afterWrite',
        fn: function fn(_ref2) {
          var state = _ref2.state;

          if (isEnabled()) {
            if (triedPlacements.indexOf(state.placement) !== -1) {
              triedPlacements = [];
            }

            if (placement !== state.placement && triedPlacements.indexOf(state.placement) === -1) {
              triedPlacements.push(state.placement);
              instance.setProps({
                // @ts-ignore - unneeded DOMRect properties
                getReferenceClientRect: function getReferenceClientRect() {
                  return _getReferenceClientRect(state.placement);
                }
              });
            }

            placement = state.placement;
          }
        }
      };

      function _getReferenceClientRect(placement) {
        return getInlineBoundingClientRect(getBasePlacement(placement), reference.getBoundingClientRect(), arrayFrom(reference.getClientRects()), cursorRectIndex);
      }

      function setInternalProps(partialProps) {
        isInternalUpdate = true;
        instance.setProps(partialProps);
        isInternalUpdate = false;
      }

      function addModifier() {
        if (!isInternalUpdate) {
          setInternalProps(getProps(instance.props, modifier));
        }
      }

      return {
        onCreate: addModifier,
        onAfterUpdate: addModifier,
        onTrigger: function onTrigger(_, event) {
          if (isMouseEvent(event)) {
            var rects = arrayFrom(instance.reference.getClientRects());
            var cursorRect = rects.find(function (rect) {
              return rect.left - 2 <= event.clientX && rect.right + 2 >= event.clientX && rect.top - 2 <= event.clientY && rect.bottom + 2 >= event.clientY;
            });
            var index = rects.indexOf(cursorRect);
            cursorRectIndex = index > -1 ? index : cursorRectIndex;
          }
        },
        onHidden: function onHidden() {
          cursorRectIndex = -1;
        }
      };
    }
  };
  function getInlineBoundingClientRect(currentBasePlacement, boundingRect, clientRects, cursorRectIndex) {
    // Not an inline element, or placement is not yet known
    if (clientRects.length < 2 || currentBasePlacement === null) {
      return boundingRect;
    } // There are two rects and they are disjoined


    if (clientRects.length === 2 && cursorRectIndex >= 0 && clientRects[0].left > clientRects[1].right) {
      return clientRects[cursorRectIndex] || boundingRect;
    }

    switch (currentBasePlacement) {
      case 'top':
      case 'bottom':
        {
          var firstRect = clientRects[0];
          var lastRect = clientRects[clientRects.length - 1];
          var isTop = currentBasePlacement === 'top';
          var top = firstRect.top;
          var bottom = lastRect.bottom;
          var left = isTop ? firstRect.left : lastRect.left;
          var right = isTop ? firstRect.right : lastRect.right;
          var width = right - left;
          var height = bottom - top;
          return {
            top: top,
            bottom: bottom,
            left: left,
            right: right,
            width: width,
            height: height
          };
        }

      case 'left':
      case 'right':
        {
          var minLeft = Math.min.apply(Math, clientRects.map(function (rects) {
            return rects.left;
          }));
          var maxRight = Math.max.apply(Math, clientRects.map(function (rects) {
            return rects.right;
          }));
          var measureRects = clientRects.filter(function (rect) {
            return currentBasePlacement === 'left' ? rect.left === minLeft : rect.right === maxRight;
          });
          var _top = measureRects[0].top;
          var _bottom = measureRects[measureRects.length - 1].bottom;
          var _left = minLeft;
          var _right = maxRight;

          var _width = _right - _left;

          var _height = _bottom - _top;

          return {
            top: _top,
            bottom: _bottom,
            left: _left,
            right: _right,
            width: _width,
            height: _height
          };
        }

      default:
        {
          return boundingRect;
        }
    }
  }

  var sticky = {
    name: 'sticky',
    defaultValue: false,
    fn: function fn(instance) {
      var reference = instance.reference,
          popper = instance.popper;

      function getReference() {
        return instance.popperInstance ? instance.popperInstance.state.elements.reference : reference;
      }

      function shouldCheck(value) {
        return instance.props.sticky === true || instance.props.sticky === value;
      }

      var prevRefRect = null;
      var prevPopRect = null;

      function updatePosition() {
        var currentRefRect = shouldCheck('reference') ? getReference().getBoundingClientRect() : null;
        var currentPopRect = shouldCheck('popper') ? popper.getBoundingClientRect() : null;

        if (currentRefRect && areRectsDifferent(prevRefRect, currentRefRect) || currentPopRect && areRectsDifferent(prevPopRect, currentPopRect)) {
          if (instance.popperInstance) {
            instance.popperInstance.update();
          }
        }

        prevRefRect = currentRefRect;
        prevPopRect = currentPopRect;

        if (instance.state.isMounted) {
          requestAnimationFrame(updatePosition);
        }
      }

      return {
        onMount: function onMount() {
          if (instance.props.sticky) {
            updatePosition();
          }
        }
      };
    }
  };

  function areRectsDifferent(rectA, rectB) {
    if (rectA && rectB) {
      return rectA.top !== rectB.top || rectA.right !== rectB.right || rectA.bottom !== rectB.bottom || rectA.left !== rectB.left;
    }

    return true;
  }

  if (isBrowser) {
    injectCSS(css);
  }

  tippy.setDefaultProps({
    plugins: [animateFill, followCursor, inlinePositioning, sticky],
    render: render
  });
  tippy.createSingleton = createSingleton;
  tippy.delegate = delegate;
  tippy.hideAll = hideAll;
  tippy.roundArrow = ROUND_ARROW;

  return tippy;

})));
//# sourceMappingURL=tippy-bundle.umd.js.map;
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/js/datepick/jquery.datepick.wpbc.9.0.js?ver=9.8.12 
/* http://keith-wood.name/datepick.html
   Datepicker for jQuery 3.7.1.
   Written by Marc Grabanski (m@marcgrabanski.com) and
              Keith Wood (kbwood{at}iinet.com.au).
   Dual licensed under the GPL (http://dev.jQuery.com/browser/trunk/jQuery/GPL-LICENSE.txt) and
   MIT (http://dev.jQuery.com/browser/trunk/jQuery/MIT-LICENSE.txt) licenses.
   Please attribute the authors if you use it. */

/**
 * TODO: for fixing conflicts with  any other datepickers, we will be need to make fix like this here,  and then  in all  other places in plugin.
 * Replaced items (2023-07-01 )
 *
 * 	.datepick > .wpbc_calendar
		$.datepick 			> 	$.wpbc_calendar
		jQuery.datepick		>	jQuery.wpbc_calendar
	Datepick			>	WPBC_Calendar

	browser_is_supported_datepick 	> 	browser_is_supported_wpbc_calendar
	isArray							>	wpbc_is_array
	extendRemove					>	wpbc_extend_remove

	var PROP_NAME = 'datepick';		>	var PROP_NAME = 'wpbc_calendar';
	_tableClass: ['datepick', 		>	_tableClass: ['datepick wpbc_calendar',
 */

(function($) { // Hide the namespace

var PROP_NAME = 'datepick';


    // https://github.com/jquery/jquery-migrate/blob/master/src/core.js#L50
	//FixIn: 8.7.10.1
    if (!$.browser_is_supported_datepick) {
        var uaMatch = function(ua) {
            ua = ua.toLowerCase();

            var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];

            return match[2] || '0';
        };

        $.browser_is_supported_datepick = {
            mozilla: /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase()),
            webkit: /webkit/.test(navigator.userAgent.toLowerCase()),
            opera: /opera/.test(navigator.userAgent.toLowerCase()),
            msie: /msie/.test(navigator.userAgent.toLowerCase()),
            android: (navigator.userAgent.toLowerCase().indexOf('mozilla/5.0') > -1 && navigator.userAgent.toLowerCase().indexOf('android ') > -1 && navigator.userAgent.toLowerCase().indexOf('applewebkit') > -1),
            version: uaMatch(navigator.userAgent)
        };
    }

/* Date picker manager.
   Use the singleton instance of this class, $.datepick, to interact with the date picker.
   Settings for (groups of) date pickers are maintained in an instance object,
   allowing multiple different settings on the same page. */

function Datepick() {
	this._uuid = new Date().getTime(); // Unique identifier seed
	this._curInst = null; // The current instance in use
	this._keyEvent = false; // If the last event was a key event
	this._disabledInputs = []; // List of date picker inputs that have been disabled
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
	this._inDialog = false; // True if showing within a "dialog", false if not
	this.regional = []; // Available regional settings, indexed by language code
	this.regional[''] = { // Default regional settings
		clearText: 'Clear', // Display text for clear link
		clearStatus: 'Erase the current date', // Status text for clear link
		closeText: 'Close', // Display text for close link
		closeStatus: 'Close without change', // Status text for close link
		prevText: '&#x3c;Prev', // Display text for previous month link
		prevStatus: 'Show the previous month', // Status text for previous month link
		prevBigText: '&#x3c;&#x3c;', // Display text for previous year link
		prevBigStatus: 'Show the previous year', // Status text for previous year link
		nextText: 'Next&#x3e;', // Display text for next month link
		nextStatus: 'Show the next month', // Status text for next month link
		nextBigText: '&#x3e;&#x3e;', // Display text for next year link
		nextBigStatus: 'Show the next year', // Status text for next year link
		currentText: 'Today', // Display text for current month link
		currentStatus: 'Show the current month', // Status text for current month link
		monthNames: ['January','February','March','April','May','June',
			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
		monthStatus: 'Show a different month', // Status text for selecting a month
		yearStatus: 'Show a different year', // Status text for selecting a year
		weekHeader: 'Wk', // Header for the week of the year column
		weekStatus: 'Week of the year', // Status text for the week of the year column
		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
		dayStatus: 'Set DD as first week day', // Status text for the day of the week selection
		dateStatus: 'Select DD, M d', // Status text for the date selection
		dateFormat: 'mm/dd/yy', // See format options on parseDate
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
		initStatus: 'Select a date', // Initial Status text on opening
		isRTL: false, // True if right-to-left language, false if left-to-right
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
		yearSuffix: '' // Additional text to append to the year in the month headers
	};
	this._defaults = { // Global defaults for all the date picker instances
		wpbc_resource_id: 0, // ID of booking resource - customization	//FixIn: 9.4.4.13
		useThemeRoller: false, // True to apply ThemeRoller styling, false for default styling
		showOn: 'focus', // 'focus' for popup on focus,
			// 'button' for trigger button, or 'both' for either
		showAnim: 'show', // Name of jQuery animation for popup
		showOptions: {}, // Options for enhanced animations
		duration: 'normal', // Duration of display/closure
		buttonText: '...', // Text for trigger button
		buttonImage: '', // URL for trigger button image
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
		alignment: 'bottom', // Alignment of popup - with nominated corner of input:
			// 'top' or 'bottom' aligns depending on language direction,
			// 'topLeft', 'topRight', 'bottomLeft', 'bottomRight'
		autoSize: false, // True to size the input for the date format, false to leave as is
		defaultDate: null, // Used when field is blank: actual date,
			// +/-number for offset from today, null for today
		showDefault: false, // True to populate field with the default date
		appendText: '', // Display text following the input box, e.g. showing the format
		closeAtTop: true, // True to have the clear/close at the top,
			// false to have them at the bottom
		mandatory: false, // True to hide the Clear link, false to include it
		hideIfNoPrevNext: false, // True to hide next/previous month links
			// if not applicable, false to just disable them
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
		showBigPrevNext: false, // True to show big prev/next links
		stepMonths: 1, // Number of months to step back/forward
		stepBigMonths: 12, // Number of months to step back/forward for the big links
		gotoCurrent: false, // True if today link goes back to current selection instead
		changeMonth: true, // True if month can be selected directly, false if only prev/next
		changeYear: true, // True if year can be selected directly, false if only prev/next
		yearRange: '-10:+10', // Range of years to display in drop-down,
			// either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
		changeFirstDay: false, // True to click on day name to change, false to remain as set
		showOtherMonths: false, // True to show dates in other months, false to leave blank
		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
		highlightWeek: false, // True to highlight the selected week
		showWeeks: false, // True to show week of the year, false to omit
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
			// takes a Date and returns the number of the week for it
		shortYearCutoff: '+10', // Short year values < this are in the current century,
			// > this are in the previous century, string value starting with '+'
			// for current year + value, -1 for no change
		showStatus: false, // True to show status bar at bottom, false to not show it
		statusForDate: this.dateStatus, // Function to provide status text for a date -
			// takes date and instance as parameters, returns display text
		minDate: null, // The earliest selectable date, or null for no limit
		maxDate: null, // The latest selectable date, or null for no limit
		numberOfMonths: 1, // Number of months to show at a time
		showCurrentAtPos: 0, // The position in multiple months at which to show the current month (starting at 0)
		rangeSelect: false, // Allows for selecting a date range on one date picker
		rangeSeparator: ' - ', // Text between two dates in a range
		multiSelect: 0, // Maximum number of selectable dates
		multiSeparator: ',', // Text between multiple dates
		beforeShow: null, // Function that takes an input field and
			// returns a set of custom settings for the date picker
		beforeShowDay: null, // Function that takes a date and returns an array with
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
			// [2] = cell title (optional), e.g. $.datepick.noWeekends
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
		onHover: null, // Define a callback function when hovering over a day
		onSelect: null, // Define a callback function when a date is selected
		onClose: null, // Define a callback function when the datepicker is closed
		altField: '', // Selector for an alternate field to store selected dates into
		altFormat: '', // The date format to use for the alternate field
		constrainInput: true // The input is constrained by the current date format
	};
	$.extend(this._defaults, this.regional['']);
	this.dpDiv = $('<div style="display: none;"></div>');
}

$.extend(Datepick.prototype, {
	version: '3.7.0', // Current version

	/* Class name added to elements to indicate already configured with a date picker. */
	markerClassName: 'hasDatepick', // Responsive Skin

	// Class/id names for default and ThemeRoller stylings
	_mainDivId: ['datepick-div', 'ui-datepicker-div'], // The main datepicker division
	_mainDivClass: ['', 'ui-datepicker ' +
		'ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'], // Popup class
	_inlineClass: ['datepick-inline', 'ui-datepicker-inline ui-datepicker ' +
		'ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'], // Inline class
	_multiClass: ['datepick-multi', 'ui-datepicker-multi'], // Multi-month class
	_rtlClass: ['datepick-rtl', 'ui-datepicker-rtl'], // Right-to-left class
	_appendClass: ['datepick-append', 'ui-datepicker-append'], // Append text class
	_triggerClass: ['datepick-trigger', 'ui-datepicker-trigger'], // Trigger class
	_dialogClass: ['datepick-dialog', 'ui-datepicker-dialog'], // Dialog class
	_promptClass: ['datepick-prompt', 'ui-datepicker-prompt'], // Dialog prompt class
	_disableClass: ['datepick-disabled', 'ui-datepicker-disabled'], // Disabled covering class
	_controlClass: ['datepick-control', 'ui-datepicker-header ' +
		'ui-widget-header ui-helper-clearfix ui-corner-all'], // Control bar class
	_clearClass: ['datepick-clear', 'ui-datepicker-clear'], // Clear class
	_closeClass: ['datepick-close', 'ui-datepicker-close'], // Close class
	_linksClass: ['datepick-links', 'ui-datepicker-header ' +
		'ui-widget-header ui-helper-clearfix ui-corner-all'], // Links bar class
	_prevClass: ['datepick-prev', 'ui-datepicker-prev'], // Previous class
	_nextClass: ['datepick-next', 'ui-datepicker-next'], // Next class
	_currentClass: ['datepick-current', 'ui-datepicker-current'], // Current class
	_oneMonthClass: ['datepick-one-month', 'ui-datepicker-group'], // Single month class
	_newRowClass: ['datepick-new-row', 'ui-datepicker-row-break'], // New month row class
	_monthYearClass: ['datepick-header', 'ui-datepicker-header ' +
		'ui-widget-header ui-helper-clearfix ui-corner-all'], // Month/year header class
	_monthSelectClass: ['datepick-new-month', 'ui-datepicker-month'], // Month select class
	_monthClass: ['', 'ui-datepicker-month'], // Month text class
	_yearSelectClass: ['datepick-new-year', 'ui-datepicker-year'], // Year select class
	_yearClass: ['', 'ui-datepicker-year'], // Year text class
	_tableClass: ['datepick wpbc_calendar', 'ui-datepicker-calendar'], // Month table class		// FixIn: 9.7.3.7
	_tableHeaderClass: ['datepick-title-row', ''], // Week header class
	_weekColClass: ['datepick-week-col', 'ui-datepicker-week-col'], // Week number column class
	_weekRowClass: ['datepick-days-row', ''], // Week row class
	_weekendClass: ['datepick-week-end-cell', 'ui-datepicker-week-end'], // Weekend class
	_dayClass: ['datepick-days-cell', ''], // Single day class
	_otherMonthClass: ['datepick-other-month', 'ui-datepicker-other-month'], // Other month class
	_todayClass: ['datepick-today', 'ui-state-highlight'], // Today class
	_selectableClass: ['', 'ui-state-default'], // Selectable cell class
	_unselectableClass: ['datepick-unselectable',
		'ui-datepicker-unselectable ui-state-disabled'], // Unselectable cell class
	_selectedClass: ['datepick-current-day', 'ui-state-active'], // Selected day class
	_dayOverClass: ['datepick-days-cell-over', 'ui-state-hover'], // Day hover class
	_weekOverClass: ['datepick-week-over', 'ui-state-hover'], // Week hover class
	_statusClass: ['datepick-status', 'ui-datepicker-status'], // Status bar class
	_statusId: ['datepick-status-', 'ui-datepicker-status-'], // Status bar ID prefix
	_coverClass: ['datepick-cover', 'ui-datepicker-cover'], // IE6- iframe class

	/* Override the default settings for all instances of the date picker.
	   @param  settings  (object) the new settings to use as defaults (anonymous object)
	   @return  (Datepick) the manager object */
	setDefaults: function(settings) {
		extendRemove(this._defaults, settings || {});
		return this;
	},

	/* Attach the date picker to a jQuery selection.
	   @param  target    (element) the target input field or division or span
	   @param  settings  (object) the new settings to use for this date picker instance */
	_attachDatepick: function(target, settings) {
		if (!target.id)
			target.id = 'dp' + (++this._uuid);
		var nodeName = target.nodeName.toLowerCase();
		var inst = this._newInst($(target), (nodeName == 'div' || nodeName == 'span'));
		// Check for settings on the control itself
		var inlineSettings = ($.fn.metadata ? $(target).metadata() : {});
		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
		if (inst.inline) {
			inst.dpDiv.addClass(this._inlineClass[
				this._get(inst, 'useThemeRoller') ? 1 : 0]);
			this._inlineDatepick(target, inst);
		}
		else
			this._connectDatepick(target, inst);
	},

	/* Create a new instance object.
	   @param  target  (jQuery) the target input field or division or span
	   @param  inline  (boolean) true if this datepicker appears inline */
	_newInst: function(target, inline) {
		var id = target[0].id.replace(/([:\[\]\.\$])/g, '\\\\$1'); // Escape jQuery meta chars
		return {id: id, input: target, // Associated target
			cursorDate: this._daylightSavingAdjust(new Date()), // Current position
			drawMonth: 0, drawYear: 0, // Month being drawn
			dates: [], // Selected dates
			inline: inline, // Is datepicker inline or not
			dpDiv: (!inline ? this.dpDiv : $('<div></div>')), // presentation div
			siblings: $([])}; // Created siblings (trigger/append)
	},

	/* Attach the date picker to an input field.
	   @param  target  (element) the target input field or division or span
	   @param  inst    (object) the instance settings for this datepicker */
	_connectDatepick: function(target, inst) {
		var input = $(target);
		if (input.hasClass(this.markerClassName))
			return;
		var appendText = this._get(inst, 'appendText');
		var isRTL = this._get(inst, 'isRTL');
		var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0;
		if (appendText) {
			var append = $('<span class="' + this._appendClass[useTR] + '">' + appendText + '</span>');
			input[isRTL ? 'before' : 'after'](append);
			inst.siblings = inst.siblings.add(append);
		}
		var showOn = this._get(inst, 'showOn');
		if (showOn == 'focus' || showOn == 'both') // Pop-up date picker when in the marked field
			input.on('focus', this._showDatepick);
		if (showOn == 'button' || showOn == 'both') { // Pop-up date picker when button clicked
			var buttonText = this._get(inst, 'buttonText');
			var buttonImage = this._get(inst, 'buttonImage');
			var trigger = $(this._get(inst, 'buttonImageOnly') ?
				$('<img/>').addClass(this._triggerClass[useTR]).
					attr({src: buttonImage, alt: buttonText, title: buttonText}) :
				$('<button type="button"></button>').addClass(this._triggerClass[useTR]).
					html(buttonImage == '' ? buttonText : $('<img/>').attr(
					{src: buttonImage, alt: buttonText, title: buttonText})));
			input[isRTL ? 'before' : 'after'](trigger);
			inst.siblings = inst.siblings.add(trigger);
			//FixIn: 8.7.11.12
			trigger.on( 'click', function (){
				if ($.datepick._datepickerShowing && $.datepick._lastInput == target)
					$.datepick._hideDatepick();
				else
					$.datepick._showDatepick(target);
				return false;
			});
		}
		input.addClass(this.markerClassName).on( 'keydown', this._doKeyDown).on( 'keypress', this._doKeyPress).on( 'keyup', this._doKeyUp);	//FixIn: 8.7.11.12
		if (this._get(inst, 'showDefault') && !inst.input.val()) {
			inst.dates = [this._getDefaultDate(inst)];
			this._showDate(inst);
		}
		this._autoSize(inst);
		$.data(target, PROP_NAME, inst);
	},

	/* Apply the maximum length for the date format.
	   @param  inst  (object) the instance settings for this datepicker */
	_autoSize: function(inst) {
		if (this._get(inst, 'autoSize') && !inst.inline) {
			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
			var dateFormat = this._get(inst, 'dateFormat');
			if (dateFormat.match(/[DM]/)) {
				var findMax = function(names) {
					var max = 0;
					var maxI = 0;
					for (var i = 0; i < names.length; i++) {
						if (names[i].length > max) {
							max = names[i].length;
							maxI = i;
						}
					}
					return maxI;
				};
				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
					'monthNames' : 'monthNamesShort'))));
				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
			}
			inst.input.attr('size', this._formatDate(inst, date).length);
		}
	},

	/* Attach an inline date picker to a div.
	   @param  target  (element) the target input field or division or span
	   @param  inst    (object) the instance settings for this datepicker */
	_inlineDatepick: function(target, inst) {
		var divSpan = $(target);
		if (divSpan.hasClass(this.markerClassName))
			return;
		divSpan.addClass(this.markerClassName);
		$.data(target, PROP_NAME, inst);
		inst.drawMonth = inst.cursorDate.getMonth();
		inst.drawYear = inst.cursorDate.getFullYear();
		$('body').append(inst.dpDiv);
		this._updateDatepick(inst);
		// Fix width for dynamic number of date pickers
		/* // FixIn: 9.7.3.4
		   // Commented below 3 lines to  not include width into <div class="datepick-inline datepick-multi" style="width: 4428px;">
		 inst.dpDiv.width(this._getNumberOfMonths(inst)[1] *
		 		$('.' + this._oneMonthClass[this._get(inst, 'useThemeRoller') ? 1 : 0],
		 		inst.dpDiv)[0].offsetWidth);
		 */
		divSpan.append(inst.dpDiv);
		this._updateAlternate(inst);

		//FixIn: 9.4.4.13
		var resource_id = parseInt( divSpan.get( 0 ).getAttribute( 'id' ).replace( 'calendar_booking', '' ) );
		inst.settings.wpbc_resource_id = resource_id;  		// To get this property use: 	this._get(inst, 'wpbc_resource_id')

		//FixIn: 9.4.4.12
		$( 'body' ).trigger(
							  'wpbc_datepick_inline_calendar_loaded'													// event name
							, [
								  divSpan.get( 0 ).getAttribute( 'id' ).replace( 'calendar_booking', '' )				// Resource ID	-	'1'
								, divSpan																				// jQuery( '#calendar_booking1' )
								, inst 																					// datepick Obj
							  ]
							);
		// To catch this event: jQuery( 'body' ).on('wpbc_datepick_inline_calendar_loaded', function( event, resource_id, jCalContainer, inst ) { ... } );
		//FixIn End: 9.4.4.12
	},

	/* Pop-up the date picker in a "dialog" box.
	   @param  input     (element) ignored
	   @param  date      (string or Date) the initial date to display
	   @param  onSelect  (function) the function to call when a date is selected
	   @param  settings  (object) update the dialog date picker instance's settings
	   @param  pos       (int[2]) coordinates for the dialog's position within the screen or
	                     (event) with x/y coordinates or
	                     leave empty for default (screen centre) */
	_dialogDatepick: function(input, date, onSelect, settings, pos) {
		var inst = this._dialogInst; // Internal instance
		if (!inst) {
			var id = 'dp' + (++this._uuid);
			this._dialogInput = $('<input type="text" id="' + id +
				'" style="position: absolute; width: 1px; z-index: -1"/>');
			this._dialogInput.on( 'keydown', this._doKeyDown);
			$('body').append(this._dialogInput);
			inst = this._dialogInst = this._newInst(this._dialogInput, false);
			inst.settings = {};
			$.data(this._dialogInput[0], PROP_NAME, inst);
		}
		extendRemove(inst.settings, settings || {});
		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
		this._dialogInput.val(date);
		this._pos = (pos ? (isArray(pos) ? pos : [pos.pageX, pos.pageY]) : null);
		if (!this._pos) {
			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
			this._pos = // Should use actual width/height below
				[(document.documentElement.clientWidth / 2) - 100 + scrollX,
				(document.documentElement.clientHeight / 2) - 150 + scrollY];
		}

		// Move input on screen for focus, but hidden behind dialog
		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
		inst.settings.onSelect = onSelect;
		this._inDialog = true;
		this.dpDiv.addClass(this._dialogClass[this._get(inst, 'useThemeRoller') ? 1 : 0]);
		this._showDatepick(this._dialogInput[0]);
		if ($.blockUI)
			$.blockUI(this.dpDiv);
		$.data(this._dialogInput[0], PROP_NAME, inst);
	},

	/* Detach a datepicker from its control.
	   @param  target  (element) the target input field or division or span */
	_destroyDatepick: function(target) {
		var $target = $(target);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		var inst = $.data(target, PROP_NAME);
		$.removeData(target, PROP_NAME);
		if (inst.inline)
			$target.removeClass(this.markerClassName).empty();
		else {
			$(inst.siblings).remove();
			$target.removeClass(this.markerClassName).
				unbind('focus', this._showDatepick).unbind('keydown', this._doKeyDown).
				unbind('keypress', this._doKeyPress).unbind('keyup', this._doKeyUp);
		}
	},

	/* Enable the date picker to a jQuery selection.
	   @param  target  (element) the target input field or division or span */
	_enableDatepick: function(target) {
		var $target = $(target);
		if (!$target.hasClass(this.markerClassName))
			return;
		var inst = $.data(target, PROP_NAME);
		var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0;
		if (inst.inline)
			$target.children('.' + this._disableClass[useTR]).remove().end().
				find('select').attr('disabled', '');
		else {
			target.disabled = false;
			inst.siblings.filter('button.' + this._triggerClass[useTR]).
				each(function() { this.disabled = false; }).end().
				filter('img.' + this._triggerClass[useTR]).
				css({opacity: '1.0', cursor: ''});
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value == target ? null : value); }); // Delete entry
	},

	/* Disable the date picker to a jQuery selection.
	   @param  target  (element) the target input field or division or span */
	_disableDatepick: function(target) {
		var $target = $(target);
		if (!$target.hasClass(this.markerClassName))
			return;
		var inst = $.data(target, PROP_NAME);
		var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0;
		if (inst.inline) {
			var inline = $target.children('.' + this._inlineClass[useTR]);
			var offset = inline.offset();
			var relOffset = {left: 0, top: 0};
			inline.parents().each(function() {
				if ($(this).css('position') == 'relative') {
					relOffset = $(this).offset();
					return false;
				}
			});
			$target.prepend('<div class="' + this._disableClass[useTR] + '" style="' +
				'width: ' + inline.width() + 'px; height: ' + inline.height() +
				'px; left: ' + (offset.left - relOffset.left) +
				'px; top: ' + (offset.top - relOffset.top) + 'px;"></div>').
				find('select').attr('disabled', 'disabled');
		}
		else {
			target.disabled = true;
			inst.siblings.filter('button.' + this._triggerClass[useTR]).
				each(function() { this.disabled = true; }).end().
				filter('img.' + this._triggerClass[useTR]).
				css({opacity: '0.5', cursor: 'default'});
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value == target ? null : value); }); // Delete entry
		this._disabledInputs.push(target);
	},

	/* Is the first field in a jQuery collection disabled as a datepicker?
	   @param  target  (element) the target input field or division or span
	   @return  (boolean) true if disabled, false if enabled */
	_isDisabledDatepick: function(target) {
		return (!target ? false : $.inArray(target, this._disabledInputs) > -1);
	},

	/* Retrieve the instance data for the target control.
	   @param  target  (element) the target input field or division or span
	   @return  (object) the associated instance data
	   @throws  error if a jQuery problem getting data */
	_getInst: function(target) {//alert(target.id);
		try {
			return $.data(target, PROP_NAME);
		}
		catch (err) {
			throw 'Missing instance data for this datepicker';
		}
	},

	/* Update or retrieve the settings for a date picker attached to an input field or division.
	   @param  target  (element) the target input field or division or span
	   @param  name    (object) the new settings to update or
	                   (string) the name of the setting to change or retrieve,
	                   when retrieving also 'all' for all instance settings or
	                   'defaults' for all global defaults
	   @param  value   (any) the new value for the setting
	                   (omit if above is an object or to retrieve value) */
	_optionDatepick: function(target, name, value) {
		var inst = this._getInst(target);
		if (arguments.length == 2 && typeof name == 'string') {
			return (name == 'defaults' ? $.extend({}, $.datepick._defaults) :
				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
				this._get(inst, name)) : null));
		}
		var settings = name || {};
		if (typeof name == 'string') {
			settings = {};
			settings[name] = value;
		}
		if (inst) {
			if (this._curInst == inst) {
				this._hideDatepick(null);
			}
			var dates = this._getDateDatepick(target);
			extendRemove(inst.settings, settings);
			this._autoSize(inst);
			extendRemove(inst, {dates: []});
			var blank = (!dates || isArray(dates));
			if (isArray(dates))
				for (var i = 0; i < dates.length; i++)
					if (dates[i]) {
						blank = false;
						break;
					}
			if (!blank)
				this._setDateDatepick(target, dates);
			if (inst.inline)
				$(target).children('div').removeClass(this._inlineClass.join(' ')).
					addClass(this._inlineClass[this._get(inst, 'useThemeRoller') ? 1 : 0]);
			this._updateDatepick(inst);
		}
	},

	// Change method deprecated
	_changeDatepick: function(target, name, value) {
		this._optionDatepick(target, name, value);
	},

	/* Redraw the date picker attached to an input field or division.
	   @param  target  (element) the target input field or division or span */
	_refreshDatepick: function(target) {
		var inst = this._getInst(target);
		if (inst) {
			this._updateDatepick(inst);
		}
	},

	/* Set the dates for a jQuery selection.
	   @param  target   (element) the target input field or division or span
	   @param  date     (Date) the new date
	   @param  endDate  (Date) the new end date for a range (optional) */
	_setDateDatepick: function(target, date, endDate) {
		var inst = this._getInst(target);
		if (inst) {
			this._setDate(inst, date, endDate);
			this._updateDatepick(inst);
			this._updateAlternate(inst);
		}
	},

	/* Get the date(s) for the first entry in a jQuery selection.
	   @param  target  (element) the target input field or division or span
	   @return (Date) the current date or
	           (Date[2]) the current dates for a range */
	_getDateDatepick: function(target) {
		var inst = this._getInst(target);
		if (inst && !inst.inline)
			this._setDateFromField(inst);
		return (inst ? this._getDate(inst) : null);
	},

	/* Handle keystrokes.
	   @param  event  (KeyEvent) the keystroke details
	   @return  (boolean) true to continue, false to discard */
	_doKeyDown: function(event) {
		var inst = $.datepick._getInst(event.target);
		inst.keyEvent = true;
		var handled = true;
		var isRTL = $.datepick._get(inst, 'isRTL');
		var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0;
		if ($.datepick._datepickerShowing)
			switch (event.keyCode) {
				case 9:  $.datepick._hideDatepick(null, '');
						break; // Hide on tab out
				case 13: var sel = $('td.' + $.datepick._dayOverClass[useTR], inst.dpDiv);
						if (sel.length == 0)
							sel = $('td.' + $.datepick._selectedClass[useTR] + ':first', inst.dpDiv);
						if (sel[0])
							$.datepick._selectDay(sel[0], event.target, inst.cursorDate.getTime());
						else
							$.datepick._hideDatepick(null, $.datepick._get(inst, 'duration'));
						break; // Select the value on enter
				case 27: $.datepick._hideDatepick(null, $.datepick._get(inst, 'duration'));
						break; // Hide on escape
				case 33: $.datepick._adjustDate(event.target, (event.ctrlKey ?
							-$.datepick._get(inst, 'stepBigMonths') :
							-$.datepick._get(inst, 'stepMonths')), 'M');
						break; // Previous month/year on page up/+ ctrl
				case 34: $.datepick._adjustDate(event.target, (event.ctrlKey ?
							+$.datepick._get(inst, 'stepBigMonths') :
							+$.datepick._get(inst, 'stepMonths')), 'M');
						break; // Next month/year on page down/+ ctrl
				case 35: if (event.ctrlKey || event.metaKey)
							$.datepick._clearDate(event.target);
						handled = event.ctrlKey || event.metaKey;
						break; // Clear on ctrl or command + end
				case 36: if (event.ctrlKey || event.metaKey)
							$.datepick._gotoToday(event.target);
						handled = event.ctrlKey || event.metaKey;
						break; // Current on ctrl or command + home
				case 37: if (event.ctrlKey || event.metaKey)
							$.datepick._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
						handled = event.ctrlKey || event.metaKey;
						// -1 day on ctrl or command + left
						if (event.originalEvent.altKey)
							$.datepick._adjustDate(event.target,
								(event.ctrlKey ? -$.datepick._get(inst, 'stepBigMonths') :
								-$.datepick._get(inst, 'stepMonths')), 'M');
						// Next month/year on alt + left/+ ctrl
						break;
				case 38: if (event.ctrlKey || event.metaKey)
							$.datepick._adjustDate(event.target, -7, 'D');
						handled = event.ctrlKey || event.metaKey;
						break; // -1 week on ctrl or command + up
				case 39: if (event.ctrlKey || event.metaKey)
							$.datepick._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
						handled = event.ctrlKey || event.metaKey;
						// +1 day on ctrl or command + right
						if (event.originalEvent.altKey)
							$.datepick._adjustDate(event.target,
								(event.ctrlKey ? +$.datepick._get(inst, 'stepBigMonths') :
								+$.datepick._get(inst, 'stepMonths')), 'M');
						// Next month/year on alt + right/+ ctrl
						break;
				case 40: if (event.ctrlKey || event.metaKey)
							$.datepick._adjustDate(event.target, +7, 'D');
						handled = event.ctrlKey || event.metaKey;
						break; // +1 week on ctrl or command + down
				default: handled = false;
			}
		else if (event.keyCode == 36 && event.ctrlKey) // Display the date picker on ctrl+home
			$.datepick._showDatepick(this);
		else
			handled = false;
		if (handled) {
			event.preventDefault();
			event.stopPropagation();
		}
		inst.ctrlKey = (event.keyCode < 48);
		return !handled;
	},

	/* Filter entered characters - based on date format.
	   @param  event  (KeyEvent) the keystroke details
	   @return  (boolean) true to continue, false to discard */
	_doKeyPress: function(event) {
		var inst = $.datepick._getInst(event.target);
		if ($.datepick._get(inst, 'constrainInput')) {
			var chars = $.datepick._possibleChars(inst);
			var chr = String.fromCharCode(event.keyCode || event.charCode);
			return inst.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
		}
	},

	/* Synchronise manual entry and field/alternate field.
	   @param  event  (KeyEvent) the keystroke details
	   @return  (boolean) true to continue */
	_doKeyUp: function(event) {
		var inst = $.datepick._getInst(event.target);
		if (inst.input.val() != inst.lastVal) {
			try {
				var separator = ($.datepick._get(inst, 'rangeSelect') ?
					$.datepick._get(inst, 'rangeSeparator') :
					($.datepick._get(inst, 'multiSelect') ?
					$.datepick._get(inst, 'multiSeparator') : ''));
				var dates = (inst.input ? inst.input.val() : '');
				dates = (separator ? dates.split(separator) : [dates]);
				var ok = true;
				for (var i = 0; i < dates.length; i++) {
					if (!$.datepick.parseDate($.datepick._get(inst, 'dateFormat'),
							dates[i], $.datepick._getFormatConfig(inst))) {
						ok = false;
						break;
					}
				}
				if (ok) { // Only if valid
					$.datepick._setDateFromField(inst);
					$.datepick._updateAlternate(inst);
					$.datepick._updateDatepick(inst);
				}
			}
			catch (event) {
				// Ignore
			}
		}
		return true;
	},

	/* Extract all possible characters from the date format.
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (string) the set of characters allowed by this format */
	_possibleChars: function (inst) {
		var dateFormat = $.datepick._get(inst, 'dateFormat');
		var chars = ($.datepick._get(inst, 'rangeSelect') ?
			$.datepick._get(inst, 'rangeSeparator') :
			($.datepick._get(inst, 'multiSelect') ?
			$.datepick._get(inst, 'multiSeparator') : ''));
		var literal = false;
		for (var iFormat = 0; iFormat < dateFormat.length; iFormat++)
			if (literal)
				if (dateFormat.charAt(iFormat) == "'" && !lookAhead("'"))
					literal = false;
				else
					chars += dateFormat.charAt(iFormat);
			else
				switch (dateFormat.charAt(iFormat)) {
					case 'd': case 'm': case 'y': case '@':
						chars += '0123456789';
						break;
					case 'D': case 'M':
						return null; // Accept anything
					case "'":
						if (lookAhead("'"))
							chars += "'";
						else
							literal = true;
						break;
					default:
						chars += dateFormat.charAt(iFormat);
				}
		return chars;
	},

	/* Update the datepicker when hovering over a date.
	   @param  td         (element) the current cell
	   @param  id         (string) the ID of the datepicker instance
	   @param  timestamp  (number) the timestamp for this date */
	_doMouseOver: function(td, id, timestamp) {
		var inst = $.datepick._getInst($('#' + id)[0]);
		var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0;
		if ( $( td ).find( 'a' ).length )																				//FixIn: 2023-08-06
			$(td).parents('tbody').find('td').
				removeClass($.datepick._dayOverClass[useTR]).end().end().
				addClass($.datepick._dayOverClass[useTR]);
		if ($.datepick._get(inst, 'highlightWeek'))
			$(td).parent().parent().find('tr').
				removeClass($.datepick._weekOverClass[useTR]).end().end().
				addClass($.datepick._weekOverClass[useTR]);
		if ($(td).text()) {
			var date = new Date(timestamp);
			if ($.datepick._get(inst, 'showStatus')) {
				var status = ($.datepick._get(inst, 'statusForDate').apply(
					(inst.input ? inst.input[0] : null), [date, inst]) ||
					$.datepick._get(inst, 'initStatus'));
				$('#' + $.datepick._statusId[useTR] + id).html(status);
			}
			if ($.datepick._get(inst, 'onHover'))
				$.datepick._doHover(td, '#' + id, date.getFullYear(), date.getMonth());
		}
	},

	/* Update the datepicker when no longer hovering over a date.
	   @param  td  (element) the current cell
	   @param  id  (string) the ID of the datepicker instance */
	_doMouseOut: function(td, id) {
		var inst = $.datepick._getInst($('#' + id)[0]);
		var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0;
		$(td).removeClass($.datepick._dayOverClass[useTR]).
			removeClass($.datepick._weekOverClass[useTR]);
		if ($.datepick._get(inst, 'showStatus'))
			$('#' + $.datepick._statusId[useTR] + id).html($.datepick._get(inst, 'initStatus'));
		if ($.datepick._get(inst, 'onHover'))
			$.datepick._doHover(td, '#' + id);
	},

	/* Hover over a particular day.
	   @param  td     (element) the table cell containing the selection
	   @param  id     (string) the ID of the target field
	   @param  year   (number) the year for this day
	   @param  month  (number) the month for this day */
	_doHover: function(td, id, year, month) {
		var inst = this._getInst($(id)[0]);
		var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0;
		//if ($(td).hasClass(this._unselectableClass[useTR]))
		//	return;
		var onHover = this._get(inst, 'onHover');
		//FixIn: 2023-08-06
		var temp_daylight_day = ( $( td ).find( 'a' ).length) ? new Date( year, month, $( td ).find( 'a' ).text() ) : null;
		temp_daylight_day = ( ( null === temp_daylight_day ) && ( $( td ).find( 'span' ).length ) ) ? new Date( year, month, $( td ).find( 'span' ).text() ) : temp_daylight_day;

		var date = (year ?
//			this._daylightSavingAdjust(new Date(year, month, $(td).find('a').text())) : null);							//FixIn: 2023-08-06
			this._daylightSavingAdjust( temp_daylight_day ) : null);													//FixIn: 2023-08-06
		onHover.apply((inst.input ? inst.input[0] : null),
			[(date ? this._formatDate(inst, date) : ''), date, inst]);
	},

	/* Pop-up the date picker for a given input field.
	   @param  input  (element) the input field attached to the date picker or
	                  (event) if triggered by focus */
	_showDatepick: function(input) {
		input = input.target || input;
		if ($.datepick._isDisabledDatepick(input) || $.datepick._lastInput == input) // Already here
			return;
		var inst = $.datepick._getInst(input);
		var beforeShow = $.datepick._get(inst, 'beforeShow');
		var useTR = $.datepick._get(inst, 'useThemeRoller') ? 1 : 0;
		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
		$.datepick._hideDatepick(null, '');
		$.datepick._lastInput = input;
		$.datepick._setDateFromField(inst);
		if ($.datepick._inDialog) // Hide cursor
			input.value = '';
		if (!$.datepick._pos) { // Position below input
			$.datepick._pos = $.datepick._findPos(input);
			$.datepick._pos[1] += input.offsetHeight; // Add the height
		}
		var isFixed = false;
		$(input).parents().each(function() {
			isFixed |= $(this).css('position') == 'fixed';
			return !isFixed;
		});
		if (isFixed && $.browser_is_supported_datepick.opera) { // Correction for Opera when fixed and scrolled
			$.datepick._pos[0] -= document.documentElement.scrollLeft;
			$.datepick._pos[1] -= document.documentElement.scrollTop;
		}
		var offset = {left: $.datepick._pos[0], top: $.datepick._pos[1]};
		$.datepick._pos = null;
		// Determine sizing offscreen
		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
		$.datepick._updateDatepick(inst);
		// Fix width for dynamic number of date pickers
		inst.dpDiv.width($.datepick._getNumberOfMonths(inst)[1] *
			$('.' + $.datepick._oneMonthClass[useTR], inst.dpDiv).width());
		// And adjust position before showing
		offset = $.datepick._checkOffset(inst, offset, isFixed);
		inst.dpDiv.css({position: ($.datepick._inDialog && $.blockUI ?
			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
			left: offset.left + 'px', top: offset.top + 'px'});
		if (!inst.inline) {
			var showAnim = $.datepick._get(inst, 'showAnim') || 'show';
			var duration = $.datepick._get(inst, 'duration');
			var postProcess = function() {
				$.datepick._datepickerShowing = true;
				var borders = $.datepick._getBorders(inst.dpDiv);
				inst.dpDiv.find('iframe.' + $.datepick._coverClass[useTR]). // IE6- only
					css({left: -borders[0], top: -borders[1],
						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
			};
			if ($.effects && $.effects[showAnim])
				inst.dpDiv.show(showAnim, $.datepick._get(inst, 'showOptions'), duration, postProcess);
			else
				inst.dpDiv[showAnim](duration, postProcess);
			if (duration == '')
				postProcess();
			if (inst.input[0].type != 'hidden')
			    $( inst.input ).trigger( 'focus' );		//FixIn: 8.7.11.12
			$.datepick._curInst = inst;
		}
	},

	/* Generate the date picker content.
	   @param  inst  (object) the instance settings for this datepicker */
	_updateDatepick: function(inst) {
		var borders = this._getBorders(inst.dpDiv);
		var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0;
		inst.dpDiv.empty().append(this._generateHTML(inst)).
			find('iframe.' + this._coverClass[useTR]). // IE6- only
			css({left: -borders[0], top: -borders[1],
				width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
		var numMonths = this._getNumberOfMonths(inst);
		if (!inst.inline)
			inst.dpDiv.attr('id', this._mainDivId[useTR]);
		if (!inst.inline) inst.dpDiv.attr('class', 'datepick-inline');  // Added by wpdevelop for the correct  showing of calendar in the search form.
		inst.dpDiv.removeClass(this._mainDivClass[1 - useTR]).
			addClass(this._mainDivClass[useTR]).
			removeClass(this._multiClass.join(' ')).
			addClass(numMonths[0] != 1 || numMonths[1] != 1 ? this._multiClass[useTR] : '').
			removeClass(this._rtlClass.join(' ')).
			addClass(this._get(inst, 'isRTL') ? this._rtlClass[useTR] : '');
		if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepick._curInst)
			$( inst.input ).trigger( 'focus' );		//FixIn: 8.7.11.12

		//FixIn: 9.4.4.13
		var resource_id = this._get(inst, 'wpbc_resource_id');
		if ( resource_id > 0 ){
			$( 'body' ).trigger(
								  'wpbc_datepick_inline_calendar_refresh'													// event name
								, [
									  resource_id																			// Resource ID	-	1
									, inst 																					// datepick Obj
								  ]
								);
		}
		// To catch this event: jQuery( 'body' ).on('wpbc_datepick_inline_calendar_refresh', function( event, resource_id, inst ) { ... } );
		//FixIn End: 9.4.4.13
	},

	/* Retrieve the size of left and top borders for an element.
	   @param  elem  (jQuery object) the element of interest
	   @return  (number[2]) the left and top borders */
	_getBorders: function(elem) {
		var convert = function(value) {
			var extra = ($.browser_is_supported_datepick.msie ? 1 : 0);
			return {thin: 1 + extra, medium: 3 + extra, thick: 5 + extra}[value] || value;
		};
		return [parseFloat(convert(elem.css('border-left-width'))),
			parseFloat(convert(elem.css('border-top-width')))];
	},

	/* Check positioning to remain on the screen.
	   @param  inst     (object) the instance settings for this datepicker
	   @param  offset   (object) the offset of the attached field
	   @param  isFixed  (boolean) true if control or a parent is 'fixed' in position
	   @return  (object) the updated offset for the datepicker */
	_checkOffset: function(inst, offset, isFixed) {
		var alignment = this._get(inst, 'alignment');
		var isRTL = this._get(inst, 'isRTL');
		var pos = inst.input ? this._findPos(inst.input[0]) : null;
		var browserWidth = document.documentElement.clientWidth;
		var browserHeight = document.documentElement.clientHeight;
		if (browserWidth == 0)
			return offset;
		var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
		var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
		var above = pos[1] - (this._inDialog ? 0 : inst.dpDiv.outerHeight()) -
			(isFixed && $.browser_is_supported_datepick.opera ? document.documentElement.scrollTop : 0);
		var below = offset.top;
		var alignL = offset.left;
		var alignR = pos[0] + (inst.input ? inst.input.outerWidth() : 0) - inst.dpDiv.outerWidth() -
			(isFixed && $.browser_is_supported_datepick.opera ? document.documentElement.scrollLeft : 0);
		var tooWide = (offset.left + inst.dpDiv.outerWidth() - scrollX) > browserWidth;
		var tooHigh = (offset.top + inst.dpDiv.outerHeight() - scrollY) > browserHeight;
		if (alignment == 'topLeft') {
			offset = {left: alignL, top: above};
		}
		else if (alignment == 'topRight') {
			offset = {left: alignR, top: above};
		}
		else if (alignment == 'bottomLeft') {
			offset = {left: alignL, top: below};
		}
		else if (alignment == 'bottomRight') {
			offset = {left: alignR, top: below};
		}
		else if (alignment == 'top') {
			offset = {left: (isRTL || tooWide ? alignR : alignL), top: above};
		}
		else { // bottom
			offset = {left: (isRTL || tooWide ? alignR : alignL),
				top: (tooHigh ? above : below)};
		}
		offset.left = Math.max((isFixed ? 0 : scrollX), offset.left - (isFixed ? scrollX : 0));
		offset.top = Math.max((isFixed ? 0 : scrollY), offset.top - (isFixed ? scrollY : 0));
		return offset;
	},

	/* Find an element's position on the screen.
	   @param  elem  (element) the element to check
	   @return  (number[2]) the x- and y-coordinates for the object */
	_findPos: function(elem) {
        while (elem && (elem.type == 'hidden' || elem.nodeType != 1)) {
            elem = elem.nextSibling;
        }
        var position = $(elem).offset();
	    return [position.left, position.top];
	},

	/* Hide the date picker from view.
	   @param  input     (element) the input field attached to the date picker
	   @param  duration  (string) the duration over which to close the date picker */
	_hideDatepick: function(input, duration) {
		var inst = this._curInst;
		if (!inst || (input && inst != $.data(input, PROP_NAME)))
			return false;
		var rangeSelect = this._get(inst, 'rangeSelect');
		if (rangeSelect && inst.stayOpen)
			this._updateInput('#' + inst.id);
		inst.stayOpen = false;
		if (this._datepickerShowing) {
			duration = (duration != null ? duration : this._get(inst, 'duration'));
			var showAnim = this._get(inst, 'showAnim');
			var postProcess = function() {
				$.datepick._tidyDialog(inst);
			};
			if (duration != '' && $.effects && $.effects[showAnim])
				inst.dpDiv.hide(showAnim, $.datepick._get(inst, 'showOptions'),
					duration, postProcess);
			else
				inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
			if (duration == '')
				this._tidyDialog(inst);
			var onClose = this._get(inst, 'onClose');
			if (onClose)  // Trigger custom callback
				onClose.apply((inst.input ? inst.input[0] : null),
					[(inst.input ? inst.input.val() : ''), this._getDate(inst), inst]);
			this._datepickerShowing = false;
			this._lastInput = null;
			inst.settings.prompt = null;
			if (this._inDialog) {
				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
				this.dpDiv.removeClass(this._dialogClass[this._get(inst, 'useThemeRoller') ? 1 : 0]);
				if ($.blockUI) {
					$.unblockUI();
					$('body').append(this.dpDiv);
				}
			}
			this._inDialog = false;
		}
		this._curInst = null;
		return false;
	},

	/* Tidy up after a dialog display.
	   @param  inst  (object) the instance settings for this datepicker */
	_tidyDialog: function(inst) {
		var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0;
		inst.dpDiv.removeClass(this._dialogClass[useTR]).unbind('.datepick');
		$('.' + this._promptClass[useTR], inst.dpDiv).remove();
	},

	/* Close date picker if clicked elsewhere.
	   @param  event  (MouseEvent) the mouse click to check */
	_checkExternalClick: function(event) {
		if (!$.datepick._curInst)
			return;
		var $target = $(event.target);
		var useTR = $.datepick._get($.datepick._curInst, 'useThemeRoller') ? 1 : 0;
		if (!$target.parents().andSelf().is('#' + $.datepick._mainDivId[useTR]) &&
				!$target.hasClass($.datepick.markerClassName) &&
				!$target.parents().andSelf().hasClass($.datepick._triggerClass[useTR]) &&
				$.datepick._datepickerShowing && !($.datepick._inDialog && $.blockUI))
			$.datepick._hideDatepick(null, '');
	},

	/* Adjust one of the date sub-fields.
	   @param  id      (string) the ID of the target field
	   @param  offset  (number) the amount to change by
	   @param  period  (string) 'D' for days, 'M' for months, 'Y' for years */
	_adjustDate: function(id, offset, period) {
		var inst = this._getInst($(id)[0]);
		this._adjustInstDate(inst, offset +
			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // Undo positioning
			period);
		this._updateDatepick(inst);
		return false;
	},

	/* Show the month for today or the current selection.
	   @param  id  (string) the ID of the target field */
	_gotoToday: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (this._get(inst, 'gotoCurrent') && inst.dates[0])
			inst.cursorDate = new Date(inst.dates[0].getTime());
		else
			inst.cursorDate = this._daylightSavingAdjust(new Date());
		inst.drawMonth = inst.cursorDate.getMonth();
		inst.drawYear = inst.cursorDate.getFullYear();
		this._notifyChange(inst);
		this._adjustDate(target);
		return false;
	},

	/* Selecting a new month/year.
	   @param  id      (string) the ID of the target field
	   @param  select  (element) the select being chosen from
	   @param  period  (string) 'M' for month, 'Y' for year */
	_selectMonthYear: function(id, select, period) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		inst.selectingMonthYear = false;
		var value = parseInt(select.options[select.selectedIndex].value, 10);
		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
		inst['draw' + (period == 'M' ? 'Month' : 'Year')] = value;
		inst.cursorDate.setDate(Math.min(inst.cursorDate.getDate(),
			$.datepick._getDaysInMonth(inst.drawYear, inst.drawMonth)));
		inst.cursorDate['set' + (period == 'M' ? 'Month' : 'FullYear')](value);
		this._notifyChange(inst);
		this._adjustDate(target);
	},

	/* Restore input focus after not changing month/year.
	   @param  id  (string) the ID of the target field */
	_clickMonthYear: function(id) {
		var inst = this._getInst($(id)[0]);
		if (inst.input && inst.selectingMonthYear && !$.browser_is_supported_datepick.msie)
			$( inst.input ).trigger( 'focus' );		//FixIn: 8.7.11.12
		inst.selectingMonthYear = !inst.selectingMonthYear;
	},

	/* Action for changing the first week day.
	   @param  id   (string) the ID of the target field
	   @param  day  (number) the number of the first day, 0 = Sun, 1 = Mon, ... */
	_changeFirstDay: function(id, day) {
		var inst = this._getInst($(id)[0]);
		inst.settings.firstDay = day;
		this._updateDatepick(inst);
		return false;
	},

	/* Select a particular day.
	   @param  td         (element) the table cell containing the selection
	   @param  id         (string) the ID of the target field
	   @param  timestamp  (number) the timestamp for this day */
	_selectDay: function(td, id, timestamp) {
		var inst = this._getInst($(id)[0]);
		var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0;
		if ($(td).hasClass(this._unselectableClass[useTR]))
			return false;
		var rangeSelect = this._get(inst, 'rangeSelect');
		var multiSelect = this._get(inst, 'multiSelect');
		if (rangeSelect)
			inst.stayOpen = !inst.stayOpen;
		else if (multiSelect)
			inst.stayOpen = true;
		if (inst.stayOpen) {
			$('.datepick td', inst.dpDiv).removeClass(this._selectedClass[useTR]);
			$(td).addClass(this._selectedClass[useTR]);
		}
		inst.cursorDate = this._daylightSavingAdjust(new Date(timestamp));
		var date = new Date(inst.cursorDate.getTime());
		if (rangeSelect && !inst.stayOpen)
			inst.dates[1] = date;
		else if (multiSelect) {
			var pos = -1;
			for (var i = 0; i < inst.dates.length; i++)
				if (inst.dates[i] && date.getTime() == inst.dates[i].getTime()) {
					pos = i;
					break;
				}
			if (pos > -1)
				inst.dates.splice(pos, 1);
			else if (inst.dates.length < multiSelect) {
				if (inst.dates[0])
					inst.dates.push(date);
				else
					inst.dates = [date];
				inst.stayOpen = (inst.dates.length != multiSelect);
			}
		}
		else
			inst.dates = [date];
		this._updateInput(id);
		if (inst.stayOpen)
			this._updateDatepick(inst);
		else if ((rangeSelect || multiSelect) && inst.inline)
			this._updateDatepick(inst);
		return false;
	},

	/* Erase the input field and hide the date picker.
	   @param  id  (string) the ID of the target field */
	_clearDate: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (this._get(inst, 'mandatory'))
			return false;
		inst.stayOpen = false;
		inst.dates = (this._get(inst, 'showDefault') ?
			[this._getDefaultDate(inst)] : []);
		this._updateInput(target);
		return false;
	},

	/* Update the input field with the selected date.
	   @param  id       (string) the ID of the target field or
	                    (element) the target object */
	_updateInput: function(id) {
		var inst = this._getInst($(id)[0]);
		var dateStr = this._showDate(inst);
		this._updateAlternate(inst);
		var onSelect = this._get(inst, 'onSelect');
		if (onSelect)
			onSelect.apply((inst.input ? inst.input[0] : null),
				[dateStr, this._getDate(inst), inst]);  // Trigger custom callback
		else if (inst.input)
			inst.input.trigger('change'); // Fire the change event
		if (inst.inline)
			this._updateDatepick(inst);
		else if (!inst.stayOpen) {
			this._hideDatepick(null, this._get(inst, 'duration'));
			this._lastInput = inst.input[0];
			if (typeof(inst.input[0]) != 'object')
				$( inst.input ).trigger( 'focus' );		//FixIn: 8.7.11.12	// Restore focus
			this._lastInput = null;
		}
		return false;
	},

	/* Update the input field with the current date(s).
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (string) the formatted date(s) */
	_showDate: function(inst) {
		var dateStr = '';
		if (inst.input) {
			dateStr = (inst.dates.length == 0 ? '' : this._formatDate(inst, inst.dates[0]));
			if (dateStr) {
				if (this._get(inst, 'rangeSelect'))
					dateStr += this._get(inst, 'rangeSeparator') +
						this._formatDate(inst, inst.dates[1] || inst.dates[0]);
				else if (this._get(inst, 'multiSelect'))
					for (var i = 1; i < inst.dates.length; i++)
						dateStr += this._get(inst, 'multiSeparator') +
							this._formatDate(inst, inst.dates[i]);
			}
			inst.input.val(dateStr);
		}
		return dateStr;
	},

	/* Update any alternate field to synchronise with the main field.
	   @param  inst  (object) the instance settings for this datepicker */
	_updateAlternate: function(inst) {
		var altField = this._get(inst, 'altField');
		if (altField) { // Update alternate field too
			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
			var settings = this._getFormatConfig(inst);
			var dateStr = this.formatDate(altFormat, inst.dates[0], settings);
			if (dateStr && this._get(inst, 'rangeSelect'))
				dateStr += this._get(inst, 'rangeSeparator') + this.formatDate(
					altFormat, inst.dates[1] || inst.dates[0], settings);
			else if (this._get(inst, 'multiSelect'))
				for (var i = 1; i < inst.dates.length; i++)
					dateStr += this._get(inst, 'multiSeparator') +
						this.formatDate(altFormat, inst.dates[i], settings);
			$(altField).val(dateStr);
		}
	},

	/* Set as beforeShowDay function to prevent selection of weekends.
	   @param  date  (Date) the date to customise
	   @return  ([boolean, string]) is this date selectable?, what is its CSS class? */
	noWeekends: function(date) {
		return [(date.getDay() || 7) < 6, ''];
	},

	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
	   @param  date  (Date) the date to get the week for
	   @return  (number) the number of the week within the year that contains this date */
	iso8601Week: function(date) {
		var checkDate = new Date(date.getTime());
		// Find Thursday of this week starting on Monday
		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
		var time = checkDate.getTime();
		checkDate.setMonth(0); // Compare with Jan 1
		checkDate.setDate(1);
		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
	},

	/* Provide status text for a particular date.
	   @param  date  (Date) the date to get the status for
	   @param  inst  (object) the current datepicker instance
	   @return  (string) the status display text for this date */
	dateStatus: function(date, inst) {
		return $.datepick.formatDate($.datepick._get(inst, 'dateStatus'),
			date, $.datepick._getFormatConfig(inst));
	},

	/* Parse a string value into a date object.
	   See formatDate below for the possible formats.
	   @param  format    (string) the expected format of the date
	   @param  value     (string) the date in the above format
	   @param  settings  (object) attributes include:
	                     shortYearCutoff  (number) the cutoff year for determining the century (optional)
	                     dayNamesShort    (string[7]) abbreviated names of the days from Sunday (optional)
	                     dayNames         (string[7]) names of the days from Sunday (optional)
	                     monthNamesShort  (string[12]) abbreviated names of the months (optional)
	                     monthNames       (string[12]) names of the months (optional)
	   @return  (Date) the extracted date value or null if value is blank */
	parseDate: function (format, value, settings) {
		if (format == null || value == null)
			throw 'Invalid arguments';
		value = (typeof value == 'object' ? value.toString() : value + '');
		if (value == '')
			return null;
		settings = settings || {};
		var shortYearCutoff = settings.shortYearCutoff || this._defaults.shortYearCutoff;
		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
		var dayNamesShort = settings.dayNamesShort || this._defaults.dayNamesShort;
		var dayNames = settings.dayNames || this._defaults.dayNames;
		var monthNamesShort = settings.monthNamesShort || this._defaults.monthNamesShort;
		var monthNames = settings.monthNames || this._defaults.monthNames;
		var year = -1;
		var month = -1;
		var day = -1;
		var doy = -1;
		var literal = false;
		// Check whether a format character is doubled
		var lookAhead = function(match) {
			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
			if (matches)
				iFormat++;
			return matches;
		};
		// Extract a number from the string value
		var getNumber = function(match) {
			lookAhead(match);
			var size = (match == '@' ? 14 : (match == '!' ? 20 :
				(match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
			var digits = new RegExp('^\\d{1,' + size + '}');
			var num = value.substring(iValue).match(digits);
			if (!num)
				throw 'Missing number at position ' + iValue;
			iValue += num[0].length;
			return parseInt(num[0], 10);
		};
		// Extract a name from the string value and convert to an index
		var getName = function(match, shortNames, longNames) {
			var names = (lookAhead(match) ? longNames : shortNames);
			for (var i = 0; i < names.length; i++) {
				if (value.substr(iValue, names[i].length) == names[i]) {
					iValue += names[i].length;
					return i + 1;
				}
			}
			throw 'Unknown name at position ' + iValue;
		};
		// Confirm that a literal character matches the string value
		var checkLiteral = function() {
			if (value.charAt(iValue) != format.charAt(iFormat))
				throw 'Unexpected literal at position ' + iValue;
			iValue++;
		};
		var iValue = 0;
		for (var iFormat = 0; iFormat < format.length; iFormat++) {
			if (literal)
				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
					literal = false;
				else
					checkLiteral();
			else
				switch (format.charAt(iFormat)) {
					case 'd':
						day = getNumber('d');
						break;
					case 'D':
						getName('D', dayNamesShort, dayNames);
						break;
					case 'o':
						doy = getNumber('o');
						break;
					case 'w':
						getNumber('w');
						break;
					case 'm':
						month = getNumber('m');
						break;
					case 'M':
						month = getName('M', monthNamesShort, monthNames);
						break;
					case 'y':
						year = getNumber('y');
						break;
					case '@':
						var date = new Date(getNumber('@'));
						year = date.getFullYear();
						month = date.getMonth() + 1;
						day = date.getDate();
						break;
					case '!':
						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
						year = date.getFullYear();
						month = date.getMonth() + 1;
						day = date.getDate();
						break;
					case "'":
						if (lookAhead("'"))
							checkLiteral();
						else
							literal = true;
						break;
					default:
						checkLiteral();
				}
		}
		if (iValue < value.length)
			throw 'Additional text found at end';
		if (year == -1)
			year = new Date().getFullYear();
		else if (year < 100)
			year += (shortYearCutoff == -1 ? 1900 : new Date().getFullYear() -
				new Date().getFullYear() % 100 - (year <= shortYearCutoff ? 0 : 100));
		if (doy > -1) {
			month = 1;
			day = doy;
			do {
				var dim = this._getDaysInMonth(year, month - 1);
				if (day <= dim)
					break;
				month++;
				day -= dim;
			} while (true);
		}
		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
			throw 'Invalid date'; // E.g. 31/02/*
		return date;
	},

	/* Standard date formats. */
	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
	COOKIE: 'D, dd M yy',
	ISO_8601: 'yy-mm-dd',
	RFC_822: 'D, d M y',
	RFC_850: 'DD, dd-M-y',
	RFC_1036: 'D, d M y',
	RFC_1123: 'D, d M yy',
	RFC_2822: 'D, d M yy',
	RSS: 'D, d M y', // RFC 822
	TICKS: '!',
	TIMESTAMP: '@',
	W3C: 'yy-mm-dd', // ISO 8601

	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),

	/* Format a date object into a string value.
	   The format can be combinations of the following:
	   d  - day of month (no leading zero)
	   dd - day of month (two digit)
	   o  - day of year (no leading zeros)
	   oo - day of year (three digit)
	   D  - day name short
	   DD - day name long
	   w  - week of year (no leading zero)
	   ww - week of year (two digit)
	   m  - month of year (no leading zero)
	   mm - month of year (two digit)
	   M  - month name short
	   MM - month name long
	   y  - year (two digit)
	   yy - year (four digit)
	   @ - Unix timestamp (ms since 01/01/1970)
	   ! - Windows ticks (100ns since 01/01/0001)
	   '...' - literal text
	   '' - single quote
	   @param  format    (string) the desired format of the date
	   @param  date      (Date) the date value to format
	   @param  settings  (object) attributes include:
	                     dayNamesShort    (string[7]) abbreviated names of the days from Sunday (optional)
	                     dayNames         (string[7]) names of the days from Sunday (optional)
	                     monthNamesShort  (string[12]) abbreviated names of the months (optional)
	                     monthNames       (string[12]) names of the months (optional)
						 calculateWeek    (function) function that determines week of the year (optional)
	   @return  (string) the date in the above format */
	formatDate: function (format, date, settings) {
		if (!date)
			return '';
		settings = settings || {};
		var dayNamesShort = settings.dayNamesShort || this._defaults.dayNamesShort;
		var dayNames = settings.dayNames || this._defaults.dayNames;
		var monthNamesShort = settings.monthNamesShort || this._defaults.monthNamesShort;
		var monthNames = settings.monthNames || this._defaults.monthNames;
		var calculateWeek = settings.calculateWeek || this._defaults.calculateWeek;
		// Check whether a format character is doubled
		var lookAhead = function(match) {
			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
			if (matches)
				iFormat++;
			return matches;
		};
		// Format a number, with leading zero if necessary
		var formatNumber = function(match, value, len) {
			var num = '' + value;
			if (lookAhead(match))
				while (num.length < len)
					num = '0' + num;
			return num;
		};
		// Format a name, short or long as requested
		var formatName = function(match, value, shortNames, longNames) {
			return (lookAhead(match) ? longNames[value] : shortNames[value]);
		};
		var output = '';
		var literal = false;
		if (date)
			for (var iFormat = 0; iFormat < format.length; iFormat++) {
				if (literal)
					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
						literal = false;
					else
						output += format.charAt(iFormat);
				else
					switch (format.charAt(iFormat)) {
						case 'd':
							output += formatNumber('d', date.getDate(), 2);
							break;
						case 'D':
							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
							break;
						case 'o':
							output += formatNumber('o',
								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
							break;
						case 'w':
							output += formatNumber('w', calculateWeek(date), 2);
							break;
						case 'm':
							output += formatNumber('m', date.getMonth() + 1, 2);
							break;
						case 'M':
							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
							break;
						case 'y':
							output += (lookAhead('y') ? date.getFullYear() :
								(date.getFullYear() % 100 < 10 ? '0' : '') + date.getFullYear() % 100);
							break;
						case '@':
							output += date.getTime();
							break;
						case '!':
							output += date.getTime() * 10000 + this._ticksTo1970;
							break;
						case "'":
							if (lookAhead("'"))
								output += "'";
							else
								literal = true;
							break;
						default:
							output += format.charAt(iFormat);
					}
			}
		return output;
	},

	/* Get a setting value, defaulting if necessary.
	   @param  inst  (object) the instance settings for this datepicker
	   @param  name  (string) the name of the property
	   @return  (any) the property's value */
	_get: function(inst, name) {
		return inst.settings[name] !== undefined ?
			inst.settings[name] : this._defaults[name];
	},

	/* Parse existing date and initialise date picker.
	   @param  inst  (object) the instance settings for this datepicker */
	_setDateFromField: function(inst) {
		var dateFormat = this._get(inst, 'dateFormat');
		var rangeSelect = this._get(inst, 'rangeSelect');
		var multiSelect = this._get(inst, 'multiSelect');
		inst.lastVal = (inst.input ? inst.input.val() : '');
		var dates = inst.lastVal;
		dates = (rangeSelect ? dates.split(this._get(inst, 'rangeSeparator')) :
			(multiSelect ? dates.split(this._get(inst, 'multiSeparator')) : [dates]));
		inst.dates = [];
		var settings = this._getFormatConfig(inst);
		for (var i = 0; i < dates.length; i++)
			try {
				inst.dates[i] = this.parseDate(dateFormat, dates[i], settings);
			}
			catch (event) {
				inst.dates[i] = null;
			}
		for (var i = inst.dates.length - 1; i >= 0; i--)
			if (!inst.dates[i])
				inst.dates.splice(i, 1);
		if (rangeSelect && inst.dates.length < 2)
			inst.dates[1] = inst.dates[0];
		if (multiSelect && inst.dates.length > multiSelect)
			inst.dates.splice(multiSelect, inst.dates.length);
		inst.cursorDate = new Date((inst.dates[0] || this._getDefaultDate(inst)).getTime());
		inst.drawMonth = inst.cursorDate.getMonth();
		inst.drawYear = inst.cursorDate.getFullYear();
		this._adjustInstDate(inst);
	},

	/* Retrieve the default date shown on opening.
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (Date) the default date */
	_getDefaultDate: function(inst) {
		return this._restrictMinMax(inst,
			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
	},

	/* A date may be specified as an exact value or a relative one.
	   @param  inst         (object) the instance settings for this datepicker
	   @param  date         (Date or number or string) the date or offset
	   @param  defaultDate  (Date) the date to use if no other supplied
	   @return  (Date) the decoded date */
	_determineDate: function(inst, date, defaultDate) {
		var offsetNumeric = function(offset) {
			var date = new Date();
			date.setDate(date.getDate() + offset);
			return date;
		};
		var offsetString = function(offset) {
			try {
				return $.datepick.parseDate($.datepick._get(inst, 'dateFormat'),
					offset, $.datepick._getFormatConfig(inst));
			}
			catch (e) {
				// Ignore
			}
			var date = (offset.toLowerCase().match(/^c/) ?
				$.datepick._getDate(inst) : null) || new Date();
			var year = date.getFullYear();
			var month = date.getMonth();
			var day = date.getDate();
			var pattern = /([+-]?[0-9]+)\s*(d|w|m|y)?/g;
			var matches = pattern.exec(offset.toLowerCase());
			while (matches) {
				switch (matches[2] || 'd') {
					case 'd':
						day += parseInt(matches[1], 10); break;
					case 'w':
						day += parseInt(matches[1], 10) * 7; break;
					case 'm':
						month += parseInt(matches[1], 10);
						day = Math.min(day, $.datepick._getDaysInMonth(year, month));
						break;
					case 'y':
						year += parseInt(matches[1], 10);
						day = Math.min(day, $.datepick._getDaysInMonth(year, month));
						break;
				}
				matches = pattern.exec(offset.toLowerCase());
			}
			return new Date(year, month, day);
		};
		date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
			(typeof date == 'number' ? (isNaN(date) || date == Infinity || date == -Infinity ?
			defaultDate : offsetNumeric(date)) : date)));
		date = (date && (date.toString() == 'Invalid Date' ||
			date.toString() == 'NaN') ? defaultDate : date);
		if (date) {
			date.setHours(0);
			date.setMinutes(0);
			date.setSeconds(0);
			date.setMilliseconds(0);
		}
		return this._daylightSavingAdjust(date);
	},

	/* Handle switch to/from daylight saving.
	   Hours may be non-zero on daylight saving cut-over:
	   > 12 when midnight changeover, but then cannot generate
	   midnight datetime, so jump to 1AM, otherwise reset.
	   @param  date  (Date) the date to check
	   @return  (Date) the corrected date */
	_daylightSavingAdjust: function(date) {
		if (!date) return null;
		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
		return date;
	},

	/* Set the date(s) directly.
	   @param  inst     (object) the instance settings for this datepicker
	   @param  date     (Date or Date[] or number or string) the new date or start of a range
	   @param  endDate  (Date or number or string) the end of a range */
	_setDate: function(inst, date, endDate) {
		date = (!date ? [] : (isArray(date) ? date : [date]));
		if (endDate)
			date.push(endDate);
		var clear = (date.length == 0);
		var origMonth = inst.cursorDate.getMonth();
		var origYear = inst.cursorDate.getFullYear();
		inst.dates = [this._restrictMinMax(inst, this._determineDate(inst, date[0], new Date()))];
		inst.cursorDate = new Date(inst.dates[0].getTime());
		inst.drawMonth = inst.cursorDate.getMonth();
		inst.drawYear = inst.cursorDate.getFullYear();
		if (this._get(inst, 'rangeSelect'))
			inst.dates[1] = (date.length < 1 ? inst.dates[0] :
				this._restrictMinMax(inst, this._determineDate(inst, date[1], null)));
		else if (this._get(inst, 'multiSelect'))
			for (var i = 1; i < date.length; i++)
				inst.dates[i] = this._restrictMinMax(inst, this._determineDate(inst, date[i], null));
		if (origMonth != inst.cursorDate.getMonth() || origYear != inst.cursorDate.getFullYear())
			this._notifyChange(inst);
		this._adjustInstDate(inst);
		this._showDate(inst);
	},

	/* Retrieve the date(s) directly.
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (Date or Date[2] or Date[]) the current date or dates
	            (for a range or multiples) */
	_getDate: function(inst) {
		var startDate = (inst.input && inst.input.val() == '' ? null : inst.dates[0]);
		if (this._get(inst, 'rangeSelect'))
			return (startDate ? [inst.dates[0], inst.dates[1] || inst.dates[0]] : [null, null]);
		else if (this._get(inst, 'multiSelect'))
			return inst.dates.slice(0, inst.dates.length);
		else
			return startDate;
	},


	/* Generate the HTML for the current state of the date picker.
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (string) the new HTML for the datepicker */
	_generateHTML: function(inst) {
		var today = new Date();
		today = this._daylightSavingAdjust(
			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // Clear time


		var showStatus = this._get(inst, 'showStatus');
		var initStatus = this._get(inst, 'initStatus') || '&#xa0;';
		var isRTL = this._get(inst, 'isRTL');
		var useTR = this._get(inst, 'useThemeRoller') ? 1 : 0;
		// Build the date picker HTML
		var clear = (this._get(inst, 'mandatory') ? '' :
			'<div class="' + this._clearClass[useTR] + '"><a href="javascript:void(0)" ' +
			'onclick="jQuery.datepick._clearDate(\'#' + inst.id + '\');"' +
			this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'clearStatus'), initStatus) +
			'>' + this._get(inst, 'clearText') + '</a></div>');
		var controls = '<div class="' + this._controlClass[useTR] + '">' + (isRTL ? '' : clear) +
			'<div class="' + this._closeClass[useTR] + '"><a href="javascript:void(0)" ' +
			'onclick="jQuery.datepick._hideDatepick();"' +
			this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'closeStatus'), initStatus) +
			'>' + this._get(inst, 'closeText') + '</a></div>' + (isRTL ? clear : '')  + '</div>';
		var prompt = this._get(inst, 'prompt');
		var closeAtTop = this._get(inst, 'closeAtTop');
		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
		var showBigPrevNext = this._get(inst, 'showBigPrevNext');
		var numMonths = this._getNumberOfMonths(inst);
		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
		var stepMonths = this._get(inst, 'stepMonths');
		var stepBigMonths = this._get(inst, 'stepBigMonths');
		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
		var minDate = this._getMinMaxDate(inst, 'min', true);
		var maxDate = this._getMinMaxDate(inst, 'max');
		var drawMonth = inst.drawMonth - showCurrentAtPos;
		var drawYear = inst.drawYear;
		if (drawMonth < 0) {
			drawMonth += 12;
			drawYear--;
		}
		if (maxDate) { // Don't show past maximum unless also restricted by minimum
			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
				drawMonth--;
				if (drawMonth < 0) {
					drawMonth = 11;
					drawYear--;
				}
			}
		}
		inst.drawMonth = drawMonth;
		inst.drawYear = drawYear;
		// Controls and links
		var prevText = this._get(inst, 'prevText');
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
			this._getFormatConfig(inst)));
		var prevBigText = (showBigPrevNext ? this._get(inst, 'prevBigText') : '');
		prevBigText = (!navigationAsDateFormat ? prevBigText : this.formatDate(prevBigText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepBigMonths, 1)),
			this._getFormatConfig(inst)));
		var prev = '<div class="' + this._prevClass[useTR] + '">' +
			(this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
			(showBigPrevNext ? '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' +
			inst.id + '\', -' + stepBigMonths + ', \'M\');"' +
			this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'prevBigStatus'), initStatus) +
			'>' + prevBigText + '</a>' : '') +
			'<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' +
			inst.id + '\', -' + stepMonths + ', \'M\');"' +
			this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'prevStatus'), initStatus) +
			'>' + prevText + '</a>' :
			(hideIfNoPrevNext ? '&#xa0;' : (showBigPrevNext ? '<label>' + prevBigText + '</label>' : '') +
			'<label>' + prevText + '</label>')) + '</div>';
		var nextText = this._get(inst, 'nextText');
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
			this._getFormatConfig(inst)));
		var nextBigText = (showBigPrevNext ? this._get(inst, 'nextBigText') : '');
		nextBigText = (!navigationAsDateFormat ? nextBigText : this.formatDate(nextBigText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepBigMonths, 1)),
			this._getFormatConfig(inst)));
		var next = '<div class="' + this._nextClass[useTR] + '">' +
			(this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
			'<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' +
			inst.id + '\', +' + stepMonths + ', \'M\');"' +
			this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'nextStatus'), initStatus) +
			'>' + nextText + '</a>' +
			(showBigPrevNext ? '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' +
			inst.id + '\', +' + stepBigMonths + ', \'M\');"' +
			this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'nextBigStatus'), initStatus) +
			'>' + nextBigText + '</a>' : '') :
			(hideIfNoPrevNext ? '&#xa0;' : '<label>' + nextText + '</label>' +
			(showBigPrevNext ? '<label>' + nextBigText + '</label>' : ''))) + '</div>';
		var currentText = this._get(inst, 'currentText');
		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.dates[0] ? inst.dates[0] : today);
		currentText = (!navigationAsDateFormat ? currentText :
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
		var html = (closeAtTop && !inst.inline ? controls : '');/* +
			'<div class="' + this._linksClass[useTR] + '">' + (isRTL ? next : prev) +
			'<div class="' + this._currentClass[useTR] + '">' + (this._isInRange(inst, gotoDate) ?
			'<a href="javascript:void(0)" onclick="jQuery.datepick._gotoToday(\'#' + inst.id + '\');"' +
			this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'currentStatus'), initStatus) + '>' +
			currentText + '</a>' : (hideIfNoPrevNext ? '&#xa0;' : '<label>' + currentText + '</label>')) +
			'</div>' + (isRTL ? prev : next) + '</div>' +
			(prompt ? '<div class="' + this._promptClass[useTR] + '"><span>' +
			prompt + '</span></div>' : '');/**/
                    html +=  '<div class="calendar-links">' + (isRTL ? next : prev)   ;
                    html +=    (isRTL ? prev : next) + '</div>' ;
		var firstDay = parseInt(this._get(inst, 'firstDay'), 10);
		firstDay = (isNaN(firstDay) ? 0 : firstDay);
		var changeFirstDay = this._get(inst, 'changeFirstDay');
		var dayNames = this._get(inst, 'dayNames');
		var dayNamesShort = this._get(inst, 'dayNamesShort');
		var dayNamesMin = this._get(inst, 'dayNamesMin');
		var monthNames = this._get(inst, 'monthNames');
		var beforeShowDay = this._get(inst, 'beforeShowDay');
		var showOtherMonths = this._get(inst, 'showOtherMonths');
		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
		var showWeeks = this._get(inst, 'showWeeks');
		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
		var weekStatus = this._get(inst, 'weekStatus');
		var status = (showStatus ? this._get(inst, 'dayStatus') || initStatus : '');
		var dateStatus = this._get(inst, 'statusForDate') || this.dateStatus;
		var defaultDate = this._getDefaultDate(inst);
		for (var row = 0; row < numMonths[0]; row++) {
			for (var col = 0; col < numMonths[1]; col++) {
				var cursorDate = this._daylightSavingAdjust(
					new Date(drawYear, drawMonth, inst.cursorDate.getDate()));
				html += '<div class="' + this._oneMonthClass[useTR] +            // Responsive skin
					(col == 0 && !useTR ? ' ' + this._newRowClass[useTR] : '') + '">' +
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
					cursorDate, row > 0 || col > 0, useTR, showStatus, initStatus, monthNames) + // Draw month headers
					'<table class="' + this._tableClass[useTR] + '" cellpadding="0" cellspacing="0"><thead>' +
					'<tr class="' + this._tableHeaderClass[useTR] + '">' + (showWeeks ? '<th' +
					this._addStatus(useTR, showStatus, inst.id, weekStatus, initStatus) + '>' +
					this._get(inst, 'weekHeader') + '</th>' : '');
				for (var dow = 0; dow < 7; dow++) { // Days of the week
					var day = (dow + firstDay) % 7;
					var dayStatus = (!showStatus || !changeFirstDay ? '' :
						status.replace(/DD/, dayNames[day]).replace(/D/, dayNamesShort[day]));
					html += '<th' + ((dow + firstDay + 6) % 7 < 5 ? '' :
						' class="' + this._weekendClass[useTR] + '"') + '>' +
						(!changeFirstDay ? '<span' +
						this._addStatus(useTR, showStatus, inst.id, dayNames[day], initStatus) :
						'<a href="javascript:void(0)" onclick="jQuery.datepick._changeFirstDay(\'#' +
						inst.id + '\', ' + day + ');"' +
						this._addStatus(useTR, showStatus, inst.id, dayStatus, initStatus)) +
						' title="' + dayNames[day] + '">' +
						dayNamesMin[day] + (changeFirstDay ? '</a>' : '</span>') + '</th>';
				}
				html += '</tr></thead><tbody>';
				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
				if (drawYear == inst.cursorDate.getFullYear() && drawMonth == inst.cursorDate.getMonth())
					inst.cursorDate.setDate(Math.min(inst.cursorDate.getDate(), daysInMonth));
				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7));
				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
				for (var dRow = 0; dRow < numRows; dRow++) { // Create datepicker rows
					html += '<tr class="' + this._weekRowClass[useTR] + '">' +
						(showWeeks ? '<td class="' + this._weekColClass[useTR] + '"' +
						this._addStatus(useTR, showStatus, inst.id, weekStatus, initStatus) + '>' +
						calculateWeek(printDate) + '</td>' : '');
					for (var dow = 0; dow < 7; dow++) { // Create datepicker days
						var daySettings = (beforeShowDay ?
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
						var otherMonth = (printDate.getMonth() != drawMonth);
						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
						var selected = (this._get(inst, 'rangeSelect') && inst.dates[0] &&
							printDate.getTime() >= inst.dates[0].getTime() &&
							printDate.getTime() <= (inst.dates[1] || inst.dates[0]).getTime());
						for (var i = 0; i < inst.dates.length; i++)
							selected = selected || (inst.dates[i] &&
								printDate.getTime() == inst.dates[i].getTime());
						var empty = otherMonth && !showOtherMonths;
						html += '<td data-content="" class="' + this._dayClass[useTR] +
							((dow + firstDay + 6) % 7 >= 5 ? ' ' + this._weekendClass[useTR] : '') + // Highlight weekends
							(otherMonth ? ' ' + this._otherMonthClass[useTR] : '') + // Highlight days from other months
							((printDate.getTime() == cursorDate.getTime() &&
							drawMonth == inst.cursorDate.getMonth() && inst.keyEvent) || // User pressed key
							(defaultDate.getTime() == printDate.getTime() &&
							defaultDate.getTime() == cursorDate.getTime()) ?
							// Or defaultDate is selected printedDate and defaultDate is cursorDate
							' ' /*+ $.datepick._dayOverClass[useTR]*/ : '') + // Highlight selected day		//FixIn: 9.2.1.7
							(unselectable ? ' ' + this._unselectableClass[useTR] :
							' ' + this._selectableClass[useTR]) +  // Highlight unselectable days
							(empty ? '' : ' ' + daySettings[1] + // Highlight custom dates
							(selected ? ' ' + this._selectedClass[useTR] : '') + // Currently selected
							// Highlight today (if different)
							(printDate.getTime() == today.getTime() ? ' ' + this._todayClass[useTR] : '')) + '"' +
							(!empty && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // Cell title
//							(unselectable ? '' : ' onmouseover="' + 'jQuery.datepick._doMouseOver(this,\'' +
							(false ? '' : ' onmouseover="' + 'jQuery.datepick._doMouseOver(this,\'' +					//FixIn: 2023-08-06
							inst.id + '\',' + printDate.getTime() + ')"' +
							' onmouseout="jQuery.datepick._doMouseOut(this,\'' + inst.id + '\')"' +
							' onclick="jQuery.datepick._selectDay(this,\'#' + // Select
							inst.id + '\',' + printDate.getTime() + ')"') + '>';

							/** Start content of Day cell *************************************************************/
							html += '<div class="wpbc-cell-box">' +														//FixIn: 8.9.4.13
										'<div class="wpbc-diagonal-el">' +
											'<div class="wpbc-co-out">' +
												'<svg height="100%" width="100%" viewBox="0 0 100 100" preserveAspectRatio="none">' +
													'<polygon points="0,0 0,99 99,0"></polygon>' +
													'<polygon points="0,0 0,100 49,100 49,0"></polygon>' +
												'</svg>' +
											'</div>' +
											'<div class="wpbc-co-in">' +
												'<svg height="100%" width="100%" viewBox="0 0 98 98" preserveAspectRatio="none">' +
													'<polygon points="0,99 99,99 99,0"></polygon>' +
													'<polygon points="50,98 98,98 98,0 50,0"></polygon>' +
												'</svg>' +
											'</div>' +
										'</div>' +
										    //'<div class="check-in-div"><div></div></div>' +		// Deprecated! remove this line
										    //'<div class="check-out-div"><div></div></div>' +		// Deprecated! remove this line
										'<div class="date-cell-content">' +												//FixIn: 8.9.4.13
											'<div class="date-content-top">' +
												(unselectable ? '' : ((typeof (wpbc_show_date_info_top) == 'function') ? wpbc_show_date_info_top( inst.id, printDate.getTime() ) : '')) +
											'</div>' +
											(empty ? '&#xa0;' : // Not showing other months //FixIn:6.0.1.2
											(unselectable ? '<span>' + printDate.getDate()+ '</span>' : '<a>' + printDate.getDate() + '</a>')) +
											'<div class="date-content-bottom">'+
												(unselectable ? '' : ((typeof (wpbc_show_date_info_bottom) == 'function') ? wpbc_show_date_info_bottom( inst.id, printDate.getTime() ) : '')) +
											'</div>' +
										'</div>' +
									'</div>';
						/** End content of Day cell *******************************************************************/
                        html += '</td>';
						printDate.setDate(printDate.getDate() + 1);
						printDate = this._daylightSavingAdjust(printDate);
					}
					html += '</tr>';
				}
				drawMonth++;
				if (drawMonth > 11) {
					drawMonth = 0;
					drawYear++;
				}
				html += '</tbody></table></div>';
			}
			if (useTR)
				html += '<div class="' + this._newRowClass[useTR] + '"></div>';
		}
		html += (showStatus ? '<div style="clear: both;"></div><div id="' + this._statusId[useTR] +
			inst.id +'" class="' + this._statusClass[useTR] + '">' + initStatus + '</div>' : '') +
			(!closeAtTop && !inst.inline ? controls : '') +
			'<div style="clear: both;"></div>' +
			($.browser_is_supported_datepick.msie && parseInt($.browser_is_supported_datepick.version, 10) < 7 && !inst.inline ?
			'<iframe src="javascript:false;" class="' + this._coverClass[useTR] + '"></iframe>' : '');
		inst.keyEvent = false;
		return html;
	},

	/* Generate the month and year header.
	   @param  inst        (object) the instance settings for this datepicker
	   @param  drawMonth   (number) the current month
	   @param  drawYear    (number) the current year
	   @param  minDate     (Date) the minimum allowed date or null if none
	   @param  maxDate     (Date) the maximum allowed date or null if none
	   @param  cursorDate  (Date) the current date position
	   @param  secondary   (boolean) true if not the first month/year header
	   @param  useTR       (number) 1 if applying ThemeRoller styling, 0 if not
	   @param  showStatus  (boolean) true if status bar is visible
	   @param  initStatus  (string) the default status message
	   @param  monthNames  (string[12]) the names of the months
	   @return  (string) the HTML for the month and year */
	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
			cursorDate, secondary, useTR, showStatus, initStatus, monthNames) {
		var minDraw = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1));
		minDate = (minDate && minDraw < minDate ? minDraw : minDate);
		var changeMonth = this._get(inst, 'changeMonth');
		var changeYear = this._get(inst, 'changeYear');
		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
		var html = '<div class="' + this._monthYearClass[useTR] + '">';
		var monthHtml = '';
		// Month selection
		if (secondary || !changeMonth)
			monthHtml += '<span class="' + this._monthClass[useTR] + '">' +
				monthNames[drawMonth] + '</span>';
		else {
			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
			monthHtml += '<select class="' + this._monthSelectClass[useTR] + '" ' +
				'onchange="jQuery.datepick._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
				'onclick="jQuery.datepick._clickMonthYear(\'#' + inst.id + '\');"' +
				this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'monthStatus'),
				initStatus) + '>';
			for (var month = 0; month < 12; month++) {
				if ((!inMinYear || month >= minDate.getMonth()) &&
						(!inMaxYear || month <= maxDate.getMonth()))
					monthHtml += '<option value="' + month + '"' +
						(month == drawMonth ? ' selected="selected"' : '') +
						'>' + monthNames[month] + '</option>';
			}
			monthHtml += '</select>';
		}
		if (!showMonthAfterYear)
			html += monthHtml + (secondary || !changeMonth || !changeYear ? '&#xa0;' : '');
		// Year selection
		if (secondary || !changeYear)
			html += '<span class="' + this._yearClass[useTR] + '">' + drawYear + '</span>';
		else {
			// Determine range of years to display
			var years = this._get(inst, 'yearRange').split(':');
			var year = 0;
			var endYear = 0;
			if (years.length != 2) {
				year = drawYear - 10;
				endYear = drawYear + 10;
			} else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
				year = drawYear + parseInt(years[0], 10);
				endYear = drawYear + parseInt(years[1], 10);
			} else {
				year = parseInt(years[0], 10);
				endYear = parseInt(years[1], 10);
			}
			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
			html += '<select class="' + this._yearSelectClass[useTR] + '" ' +
				'onchange="jQuery.datepick._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
				'onclick="jQuery.datepick._clickMonthYear(\'#' + inst.id + '\');"' +
				this._addStatus(useTR, showStatus, inst.id, this._get(inst, 'yearStatus'),
				initStatus) + '>';
			for (; year <= endYear; year++) {
				html += '<option value="' + year + '"' +
					(year == drawYear ? ' selected="selected"' : '') +
					'>' + year + '</option>';
			}
			html += '</select>';
		}
		html += this._get(inst, 'yearSuffix');
		if (showMonthAfterYear)
			html += (secondary || !changeMonth || !changeYear ? '&#xa0;' : '') + monthHtml;
		html += '</div>'; // Close datepicker_header
		return html;
	},

	/* Provide code to set and clear the status panel.
	   @param  useTR       (number) 1 if applying ThemeRoller styling, 0 if not
	   @param  showStatus  (boolean) true if the status bar is shown
	   @param  id          (string) the ID of the datepicker instance
	   @param  text        (string) the status text to display
	   @param  initStatus  (string) the default status message
	   @return  (string) hover actions for the status messages */
	_addStatus: function(useTR, showStatus, id, text, initStatus) {
		return (showStatus ? ' onmouseover="jQuery(\'#' + this._statusId[useTR] + id +
			'\').html(\'' + (text || initStatus) + '\');" ' +
			'onmouseout="jQuery(\'#' + this._statusId[useTR] + id +
			'\').html(\'' + initStatus + '\');"' : '');
	},

	/* Adjust one of the date sub-fields.
	   @param  inst    (object) the instance settings for this datepicker
	   @param  offset  (number) the change to apply
	   @param  period  (string) 'D' for days, 'M' for months, 'Y' for years */
	_adjustInstDate: function(inst, offset, period) {
		var yearMonth = inst.drawYear + '/' + inst.drawMonth;
		var year = inst.drawYear + (period == 'Y' ? offset : 0);
		var month = inst.drawMonth + (period == 'M' ? offset : 0);
		var day = Math.min(inst.cursorDate.getDate(), this._getDaysInMonth(year, month)) +
			(period == 'D' ? offset : 0);
		inst.cursorDate = this._restrictMinMax(inst,
			this._daylightSavingAdjust(new Date(year, month, day)));
		inst.drawMonth = inst.cursorDate.getMonth();
		inst.drawYear = inst.cursorDate.getFullYear();
		if (yearMonth != inst.drawYear + '/' + inst.drawMonth)
			this._notifyChange(inst);
	},

	/* Ensure a date is within any min/max bounds.
	   @param  inst  (object) the instance settings for this datepicker
	   @param  date  (Date) the date to check
	   @return  (Date) the restricted date */
	_restrictMinMax: function(inst, date) {
		var minDate = this._getMinMaxDate(inst, 'min', true);
		var maxDate = this._getMinMaxDate(inst, 'max');
		date = (minDate && date < minDate ? new Date(minDate.getTime()) : date);
		date = (maxDate && date > maxDate ? new Date(maxDate.getTime()) : date);
		return date;
	},

	/* Notify change of month/year.
	   @param  inst  (object) the instance settings for this datepicker */
	_notifyChange: function(inst) {
		var onChange = this._get(inst, 'onChangeMonthYear');
		if (onChange)
			onChange.apply((inst.input ? inst.input[0] : null),
				[inst.cursorDate.getFullYear(), inst.cursorDate.getMonth() + 1,
				this._daylightSavingAdjust(new Date(
				inst.cursorDate.getFullYear(), inst.cursorDate.getMonth(), 1)), inst]);
	},

	/* Determine the number of months to show.
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (number[2]) the number of rows and columns to display */
	_getNumberOfMonths: function(inst) {
		var numMonths = this._get(inst, 'numberOfMonths');
		return (numMonths == null ? [1, 1] :
			(typeof numMonths == 'number' ? [1, numMonths] : numMonths));
	},

	/* Determine the current minimum/maximum date.
	   Ensure no time components are set. May be overridden for a range.
	   @param  inst        (object) the instance settings for this datepicker
	   @param  minMax      (string) 'min' or 'max' for required date
	   @param  checkRange  (boolean) true to allow override for a range minimum
	   @return  (Date) the minimum/maximum date or null if none */
	_getMinMaxDate: function(inst, minMax, checkRange) {
		var date = this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
		var rangeMin = this._getRangeMin(inst);
		return (checkRange && rangeMin && (!date || rangeMin > date) ? rangeMin : date);
	},

	/* Retrieve the temporary range minimum when in the process of selecting.
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (Date) the temporary minimum or null */
	_getRangeMin: function(inst) {
		return (this._get(inst, 'rangeSelect') && inst.dates[0] &&
			!inst.dates[1] ? inst.dates[0] : null);
	},

	/* Find the number of days in a given month.
	   @param  year   (number) the full year
	   @param  month  (number) the month (0 to 11)
	   @return  (number) the number of days in this month */
	_getDaysInMonth: function(year, month) {
		return 32 - new Date(year, month, 32).getDate();
	},

	/* Find the day of the week of the first of a month.
	   @param  year   (number) the full year
	   @param  month  (number) the month (0 to 11)
	   @return  (number) 0 = Sunday, 1 = Monday, ... */
	_getFirstDayOfMonth: function(year, month) {
		return new Date(year, month, 1).getDay();
	},

	/* Determines if we should allow a "prev/next" month display change.
	   @param  inst      (object) the instance settings for this datepicker
	   @param  offset    (number) the number of months to change by
	   @param  curYear   (number) the full current year
	   @param  curMonth  (number) the current month (0 to 11)
	   @return  (boolean) true if prev/next allowed, false if not */
	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
		var numMonths = this._getNumberOfMonths(inst);
		var date = this._daylightSavingAdjust(new Date(curYear,
			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
		if (offset < 0)
			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
		return this._isInRange(inst, date);
	},

	/* Is the given date in the accepted range?
	   @param  inst  (object) the instance settings for this datepicker
	   @param  date  (Date) the date to check
	   @return  (boolean) true if the date is in the allowed minimum/maximum, false if not */
	_isInRange: function(inst, date) {
		// During range selection, use minimum of selected date and range start
		var minDate = this._getRangeMin(inst) || this._getMinMaxDate(inst, 'min');
		var maxDate = this._getMinMaxDate(inst, 'max');
		return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
	},

	/* Provide the configuration settings for formatting/parsing.
	   @param  inst  (object) the instance settings for this datepicker
	   @return  (object) the settings subset */
	_getFormatConfig: function(inst) {
		return {shortYearCutoff: this._get(inst, 'shortYearCutoff'),
			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
	},

	/* Format the given date for display.
	   @param  inst   (object) the instance settings for this datepicker
	   @param  year   (number, optional) the full year
	   @param  month  (number, optional) the month of the year (0 to 11)
	   @param  day    (number, optional) the day of the month
	   @return  (string) formatted date */
	_formatDate: function(inst, year, month, day) {
		if (!year)
			inst.dates[0] = new Date(inst.cursorDate.getTime());
		var date = (year ? (typeof year == 'object' ? year :
			this._daylightSavingAdjust(new Date(year, month, day))) : inst.dates[0]);
		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
	}
});

/* jQuery extend now ignores nulls!
   @param  target  (object) the object to extend
   @param  props   (object) the new settings
   @return  (object) the updated object */
function extendRemove(target, props) {
	$.extend(target, props);
	for (var name in props)
		if (props[name] == null || props[name] == undefined)
			target[name] = props[name];
	return target;
};

/* Determine whether an object is an array.
   @param  a  (object) the object to test
   @return  (boolean) true if an array, false if not */
function isArray(a) {
	return (a && a.constructor == Array);
};

/* Invoke the datepicker functionality.
   @param  options  (string) a command, optionally followed by additional parameters or
                    (object) settings for attaching new datepicker functionality
   @return  (jQuery) jQuery object */
$.fn.datepick = function(options){
	var otherArgs = Array.prototype.slice.call(arguments, 1);
	if (typeof options == 'string' && (options == 'isDisabled' ||
			options == 'getDate' || options == 'settings'))
		return $.datepick['_' + options + 'Datepick'].
			apply($.datepick, [this[0]].concat(otherArgs));
	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
		return $.datepick['_' + options + 'Datepick'].
			apply($.datepick, [this[0]].concat(otherArgs));
	return this.each(function() {
		typeof options == 'string' ?
			$.datepick['_' + options + 'Datepick'].
				apply($.datepick, [this].concat(otherArgs)) :
			$.datepick._attachDatepick(this, options);
	});
};

$.datepick = new Datepick(); // Singleton instance

$(function() {

	$( document ).on( 'mousedown', $.datepick._checkExternalClick ).find( 'body' ).append( $.datepick.dpDiv );			//FixIn: 8.7.11.12
});

})(jQuery);
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/js/datepick/jquery.datepick-fr.js?ver=9.8.12 
/* French initialisation for the jQuery UI date picker plugin. */
/* Written by Keith Wood (kbwood{at}iinet.com.au) and Stéphane Nahmani (sholby@sholby.net). */
(function($) {
	$.datepick.regional['fr'] = {
		clearText: 'Effacer', clearStatus: 'Effacer la date sélectionnée',
		closeText: 'Fermer', closeStatus: 'Fermer sans modifier',
		prevText: '&#x3c;Préc', prevStatus: 'Voir le mois précédent',
		prevBigText: '&#x3c;&#x3c;', prevBigStatus: '',
		nextText: 'Suiv&#x3e;', nextStatus: 'Voir le mois suivant',
		nextBigText: '&#x3e;&#x3e;', nextBigStatus: '',
		currentText: 'Courant', currentStatus: 'Voir le mois courant',
		monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
		'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
		monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
		'Jul','Aoû','Sep','Oct','Nov','Déc'],
		monthStatus: 'Voir un autre mois', yearStatus: 'Voir une autre année',
		weekHeader: 'Sm', weekStatus: '',
		dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
		dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
		dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
		dayStatus: 'Utiliser DD comme premier jour de la semaine', dateStatus: '\'Choisir\' le DD d MM',
		dateFormat: 'dd/mm/yy', firstDay: 1,
		initStatus: 'Choisir la date', isRTL: false,
		showMonthAfterYear: false, yearSuffix: ''};
	$.datepick.setDefaults($.datepick.regional['fr']);
})(jQuery);
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/_dist/all/_out/wpbc_all.js?ver=9.8.12 
"use strict";
/**
 * =====================================================================================================================
 *	includes/__js/wpbc/wpbc.js
 * =====================================================================================================================
 */

/**
 * Deep Clone of object or array
 *
 * @param obj
 * @returns {any}
 */

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }

function wpbc_clone_obj(obj) {
  return JSON.parse(JSON.stringify(obj));
}
/**
 * Main _wpbc JS object
 */


var _wpbc = function (obj, $) {
  // Secure parameters for Ajax	------------------------------------------------------------------------------------
  var p_secure = obj.security_obj = obj.security_obj || {
    user_id: 0,
    nonce: '',
    locale: ''
  };

  obj.set_secure_param = function (param_key, param_val) {
    p_secure[param_key] = param_val;
  };

  obj.get_secure_param = function (param_key) {
    return p_secure[param_key];
  }; // Calendars 	----------------------------------------------------------------------------------------------------


  var p_calendars = obj.calendars_obj = obj.calendars_obj || {// sort            : "booking_id",
    // sort_type       : "DESC",
    // page_num        : 1,
    // page_items_count: 10,
    // create_date     : "",
    // keyword         : "",
    // source          : ""
  };
  /**
   *  Check if calendar for specific booking resource defined   ::   true | false
   *
   * @param {string|int} resource_id
   * @returns {boolean}
   */

  obj.calendar__is_defined = function (resource_id) {
    return 'undefined' !== typeof p_calendars['calendar_' + resource_id];
  };
  /**
   *  Create Calendar initializing
   *
   * @param {string|int} resource_id
   */


  obj.calendar__init = function (resource_id) {
    p_calendars['calendar_' + resource_id] = {};
    p_calendars['calendar_' + resource_id]['id'] = resource_id;
    p_calendars['calendar_' + resource_id]['pending_days_selectable'] = false;
  };
  /**
   * Set params for all  calendars
   *
   * @param {object} calendars_obj		Object { calendar_1: {} }
   * 												 calendar_3: {}, ... }
   */


  obj.calendars_all__set = function (calendars_obj) {
    p_calendars = calendars_obj;
  };
  /**
   * Get bookings in all calendars
   *
   * @returns {object|{}}
   */


  obj.calendars_all__get = function () {
    return p_calendars;
  };
  /**
   * Get calendar object   ::   { id: 1, … }
   *
   * @param {string|int} resource_id				  '2'
   * @returns {object|boolean}					{ id: 2 ,… }
   */


  obj.calendar__get_parameters = function (resource_id) {
    if (obj.calendar__is_defined(resource_id)) {
      return p_calendars['calendar_' + resource_id];
    } else {
      return false;
    }
  };
  /**
   * Set calendar object   ::   { dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }
   *
   * if calendar object  not defined, then  it's will be defined and ID set
   * if calendar exist, then  system set  as new or overwrite only properties from calendar_property_obj parameter,  but other properties will be existed and not overwrite, like 'id'
   *
   * @param {string|int} resource_id				  '2'
   * @param {object} calendar_property_obj					  {  dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }  }
   * @param {boolean} is_complete_overwrite		  if 'true' (default: 'false'),  then  only overwrite or add  new properties in  calendar_property_obj
   * @returns {*}
   *
   * Examples:
   *
   * Common usage in PHP:
   *   			echo "  _wpbc.calendar__set(  " .intval( $resource_id ) . ", { 'dates': " . wp_json_encode( $availability_per_days_arr ) . " } );";
   */


  obj.calendar__set_parameters = function (resource_id, calendar_property_obj) {
    var is_complete_overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

    if (!obj.calendar__is_defined(resource_id) || true === is_complete_overwrite) {
      obj.calendar__init(resource_id);
    }

    for (var prop_name in calendar_property_obj) {
      p_calendars['calendar_' + resource_id][prop_name] = calendar_property_obj[prop_name];
    }

    return p_calendars['calendar_' + resource_id];
  };
  /**
   * Set property  to  calendar
   * @param resource_id	"1"
   * @param prop_name		name of property
   * @param prop_value	value of property
   * @returns {*}			calendar object
   */


  obj.calendar__set_param_value = function (resource_id, prop_name, prop_value) {
    if (!obj.calendar__is_defined(resource_id)) {
      obj.calendar__init(resource_id);
    }

    p_calendars['calendar_' + resource_id][prop_name] = prop_value;
    return p_calendars['calendar_' + resource_id];
  };
  /**
   *  Get calendar property value   	::   mixed | null
   *
   * @param {string|int}  resource_id		'1'
   * @param {string} prop_name			'selection_mode'
   * @returns {*|null}					mixed | null
   */


  obj.calendar__get_param_value = function (resource_id, prop_name) {
    if (obj.calendar__is_defined(resource_id) && 'undefined' !== typeof p_calendars['calendar_' + resource_id][prop_name]) {
      return p_calendars['calendar_' + resource_id][prop_name];
    }

    return null; // If some property not defined, then null;
  }; // -----------------------------------------------------------------------------------------------------------------
  // Bookings 	----------------------------------------------------------------------------------------------------


  var p_bookings = obj.bookings_obj = obj.bookings_obj || {// calendar_1: Object {
    //						   id:     1
    //						 , dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, …
    // }
  };
  /**
   *  Check if bookings for specific booking resource defined   ::   true | false
   *
   * @param {string|int} resource_id
   * @returns {boolean}
   */

  obj.bookings_in_calendar__is_defined = function (resource_id) {
    return 'undefined' !== typeof p_bookings['calendar_' + resource_id];
  };
  /**
   * Get bookings calendar object   ::   { id: 1 , dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }
   *
   * @param {string|int} resource_id				  '2'
   * @returns {object|boolean}					{ id: 2 , dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }
   */


  obj.bookings_in_calendar__get = function (resource_id) {
    if (obj.bookings_in_calendar__is_defined(resource_id)) {
      return p_bookings['calendar_' + resource_id];
    } else {
      return false;
    }
  };
  /**
   * Set bookings calendar object   ::   { dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }
   *
   * if calendar object  not defined, then  it's will be defined and ID set
   * if calendar exist, then  system set  as new or overwrite only properties from calendar_obj parameter,  but other properties will be existed and not overwrite, like 'id'
   *
   * @param {string|int} resource_id				  '2'
   * @param {object} calendar_obj					  {  dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }  }
   * @returns {*}
   *
   * Examples:
   *
   * Common usage in PHP:
   *   			echo "  _wpbc.bookings_in_calendar__set(  " .intval( $resource_id ) . ", { 'dates': " . wp_json_encode( $availability_per_days_arr ) . " } );";
   */


  obj.bookings_in_calendar__set = function (resource_id, calendar_obj) {
    if (!obj.bookings_in_calendar__is_defined(resource_id)) {
      p_bookings['calendar_' + resource_id] = {};
      p_bookings['calendar_' + resource_id]['id'] = resource_id;
    }

    for (var prop_name in calendar_obj) {
      p_bookings['calendar_' + resource_id][prop_name] = calendar_obj[prop_name];
    }

    return p_bookings['calendar_' + resource_id];
  }; // Dates

  /**
   *  Get bookings data for ALL Dates in calendar   ::   false | { "2023-07-22": {…}, "2023-07-23": {…}, … }
   *
   * @param {string|int} resource_id			'1'
   * @returns {object|boolean}				false | Object {
  															"2023-07-24": Object { ['summary']['status_for_day']: "available", day_availability: 1, max_capacity: 1, … }
  															"2023-07-26": Object { ['summary']['status_for_day']: "full_day_booking", ['summary']['status_for_bookings']: "pending", day_availability: 0, … }
  															"2023-07-29": Object { ['summary']['status_for_day']: "resource_availability", day_availability: 0, max_capacity: 1, … }
  															"2023-07-30": {…}, "2023-07-31": {…}, …
  														}
   */


  obj.bookings_in_calendar__get_dates = function (resource_id) {
    if (obj.bookings_in_calendar__is_defined(resource_id) && 'undefined' !== typeof p_bookings['calendar_' + resource_id]['dates']) {
      return p_bookings['calendar_' + resource_id]['dates'];
    }

    return false; // If some property not defined, then false;
  };
  /**
   * Set bookings dates in calendar object   ::    { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }
   *
   * if calendar object  not defined, then  it's will be defined and 'id', 'dates' set
   * if calendar exist, then system add a  new or overwrite only dates from dates_obj parameter,
   * but other dates not from parameter dates_obj will be existed and not overwrite.
   *
   * @param {string|int} resource_id				  '2'
   * @param {object} dates_obj					  { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }
   * @param {boolean} is_complete_overwrite		  if false,  then  only overwrite or add  dates from 	dates_obj
   * @returns {*}
   *
   * Examples:
   *   			_wpbc.bookings_in_calendar__set_dates( resource_id, { "2023-07-21": {…}, "2023-07-22": {…}, … }  );		<-   overwrite ALL dates
   *   			_wpbc.bookings_in_calendar__set_dates( resource_id, { "2023-07-22": {…} },  false  );					<-   add or overwrite only  	"2023-07-22": {}
   *
   * Common usage in PHP:
   *   			echo "  _wpbc.bookings_in_calendar__set_dates(  " . intval( $resource_id ) . ",  " . wp_json_encode( $availability_per_days_arr ) . "  );  ";
   */


  obj.bookings_in_calendar__set_dates = function (resource_id, dates_obj) {
    var is_complete_overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

    if (!obj.bookings_in_calendar__is_defined(resource_id)) {
      obj.bookings_in_calendar__set(resource_id, {
        'dates': {}
      });
    }

    if ('undefined' === typeof p_bookings['calendar_' + resource_id]['dates']) {
      p_bookings['calendar_' + resource_id]['dates'] = {};
    }

    if (is_complete_overwrite) {
      // Complete overwrite all  booking dates
      p_bookings['calendar_' + resource_id]['dates'] = dates_obj;
    } else {
      // Add only  new or overwrite exist booking dates from  parameter. Booking dates not from  parameter  will  be without chnanges
      for (var prop_name in dates_obj) {
        p_bookings['calendar_' + resource_id]['dates'][prop_name] = dates_obj[prop_name];
      }
    }

    return p_bookings['calendar_' + resource_id];
  };
  /**
   *  Get bookings data for specific date in calendar   ::   false | { day_availability: 1, ... }
   *
   * @param {string|int} resource_id			'1'
   * @param {string} sql_class_day			'2023-07-21'
   * @returns {object|boolean}				false | {
  														day_availability: 4
  														max_capacity: 4															//  >= Business Large
  														2: Object { is_day_unavailable: false, _day_status: "available" }
  														10: Object { is_day_unavailable: false, _day_status: "available" }		//  >= Business Large ...
  														11: Object { is_day_unavailable: false, _day_status: "available" }
  														12: Object { is_day_unavailable: false, _day_status: "available" }
  													}
   */


  obj.bookings_in_calendar__get_for_date = function (resource_id, sql_class_day) {
    if (obj.bookings_in_calendar__is_defined(resource_id) && 'undefined' !== typeof p_bookings['calendar_' + resource_id]['dates'] && 'undefined' !== typeof p_bookings['calendar_' + resource_id]['dates'][sql_class_day]) {
      return p_bookings['calendar_' + resource_id]['dates'][sql_class_day];
    }

    return false; // If some property not defined, then false;
  }; // Any  PARAMS   in bookings

  /**
   * Set property  to  booking
   * @param resource_id	"1"
   * @param prop_name		name of property
   * @param prop_value	value of property
   * @returns {*}			booking object
   */


  obj.booking__set_param_value = function (resource_id, prop_name, prop_value) {
    if (!obj.bookings_in_calendar__is_defined(resource_id)) {
      p_bookings['calendar_' + resource_id] = {};
      p_bookings['calendar_' + resource_id]['id'] = resource_id;
    }

    p_bookings['calendar_' + resource_id][prop_name] = prop_value;
    return p_bookings['calendar_' + resource_id];
  };
  /**
   *  Get booking property value   	::   mixed | null
   *
   * @param {string|int}  resource_id		'1'
   * @param {string} prop_name			'selection_mode'
   * @returns {*|null}					mixed | null
   */


  obj.booking__get_param_value = function (resource_id, prop_name) {
    if (obj.bookings_in_calendar__is_defined(resource_id) && 'undefined' !== typeof p_bookings['calendar_' + resource_id][prop_name]) {
      return p_bookings['calendar_' + resource_id][prop_name];
    }

    return null; // If some property not defined, then null;
  };
  /**
   * Set bookings for all  calendars
   *
   * @param {object} calendars_obj		Object { calendar_1: { id: 1, dates: Object { "2023-07-22": {…}, "2023-07-23": {…}, "2023-07-24": {…}, … } }
   * 												 calendar_3: {}, ... }
   */


  obj.bookings_in_calendars__set_all = function (calendars_obj) {
    p_bookings = calendars_obj;
  };
  /**
   * Get bookings in all calendars
   *
   * @returns {object|{}}
   */


  obj.bookings_in_calendars__get_all = function () {
    return p_bookings;
  }; // -----------------------------------------------------------------------------------------------------------------
  // Seasons 	----------------------------------------------------------------------------------------------------


  var p_seasons = obj.seasons_obj = obj.seasons_obj || {// calendar_1: Object {
    //						   id:     1
    //						 , dates:  Object { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, …
    // }
  };
  /**
   * Add season names for dates in calendar object   ::    { "2023-07-21": [ 'wpbc_season_september_2023', 'wpbc_season_september_2024' ], "2023-07-22": [...], ... }
   *
   *
   * @param {string|int} resource_id				  '2'
   * @param {object} dates_obj					  { "2023-07-21": {…}, "2023-07-22": {…}, "2023-07-23": {…}, … }
   * @param {boolean} is_complete_overwrite		  if false,  then  only  add  dates from 	dates_obj
   * @returns {*}
   *
   * Examples:
   *   			_wpbc.seasons__set( resource_id, { "2023-07-21": [ 'wpbc_season_september_2023', 'wpbc_season_september_2024' ], "2023-07-22": [...], ... }  );
   */

  obj.seasons__set = function (resource_id, dates_obj) {
    var is_complete_overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

    if ('undefined' === typeof p_seasons['calendar_' + resource_id]) {
      p_seasons['calendar_' + resource_id] = {};
    }

    if (is_complete_overwrite) {
      // Complete overwrite all  season dates
      p_seasons['calendar_' + resource_id] = dates_obj;
    } else {
      // Add only  new or overwrite exist booking dates from  parameter. Booking dates not from  parameter  will  be without chnanges
      for (var prop_name in dates_obj) {
        if ('undefined' === typeof p_seasons['calendar_' + resource_id][prop_name]) {
          p_seasons['calendar_' + resource_id][prop_name] = [];
        }

        for (var season_name_key in dates_obj[prop_name]) {
          p_seasons['calendar_' + resource_id][prop_name].push(dates_obj[prop_name][season_name_key]);
        }
      }
    }

    return p_seasons['calendar_' + resource_id];
  };
  /**
   *  Get bookings data for specific date in calendar   ::   [] | [ 'wpbc_season_september_2023', 'wpbc_season_september_2024' ]
   *
   * @param {string|int} resource_id			'1'
   * @param {string} sql_class_day			'2023-07-21'
   * @returns {object|boolean}				[]  |  [ 'wpbc_season_september_2023', 'wpbc_season_september_2024' ]
   */


  obj.seasons__get_for_date = function (resource_id, sql_class_day) {
    if ('undefined' !== typeof p_seasons['calendar_' + resource_id] && 'undefined' !== typeof p_seasons['calendar_' + resource_id][sql_class_day]) {
      return p_seasons['calendar_' + resource_id][sql_class_day];
    }

    return []; // If not defined, then [];
  }; // Other parameters 			------------------------------------------------------------------------------------


  var p_other = obj.other_obj = obj.other_obj || {};

  obj.set_other_param = function (param_key, param_val) {
    p_other[param_key] = param_val;
  };

  obj.get_other_param = function (param_key) {
    return p_other[param_key];
  }; // -----------------------------------------------------------------------------------------------------------------


  return obj;
}(_wpbc || {}, jQuery);
/**
 * Extend _wpbc with  new methods        //FixIn: 9.8.6.2
 *
 * @type {*|{}}
 * @private
 */


_wpbc = function (obj, $) {
  // Load Balancer 	-----------------------------------------------------------------------------------------------
  var p_balancer = obj.balancer_obj = obj.balancer_obj || {
    'max_threads': 2,
    'in_process': [],
    'wait': []
  };
  /**
   * Set  max parallel request  to  load
   *
   * @param max_threads
   */

  obj.balancer__set_max_threads = function (max_threads) {
    p_balancer['max_threads'] = max_threads;
  };
  /**
   *  Check if balancer for specific booking resource defined   ::   true | false
   *
   * @param {string|int} resource_id
   * @returns {boolean}
   */


  obj.balancer__is_defined = function (resource_id) {
    return 'undefined' !== typeof p_balancer['balancer_' + resource_id];
  };
  /**
   *  Create balancer initializing
   *
   * @param {string|int} resource_id
   */


  obj.balancer__init = function (resource_id, function_name) {
    var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
    var balance_obj = {};
    balance_obj['resource_id'] = resource_id;
    balance_obj['priority'] = 1;
    balance_obj['function_name'] = function_name;
    balance_obj['params'] = wpbc_clone_obj(params);

    if (obj.balancer__is_already_run(resource_id, function_name)) {
      return 'run';
    }

    if (obj.balancer__is_already_wait(resource_id, function_name)) {
      return 'wait';
    }

    if (obj.balancer__can_i_run()) {
      obj.balancer__add_to__run(balance_obj);
      return 'run';
    } else {
      obj.balancer__add_to__wait(balance_obj);
      return 'wait';
    }
  };
  /**
   * Can I Run ?
   * @returns {boolean}
   */


  obj.balancer__can_i_run = function () {
    return p_balancer['in_process'].length < p_balancer['max_threads'];
  };
  /**
   * Add to WAIT
   * @param balance_obj
   */


  obj.balancer__add_to__wait = function (balance_obj) {
    p_balancer['wait'].push(balance_obj);
  };
  /**
   * Remove from Wait
   *
   * @param resource_id
   * @param function_name
   * @returns {*|boolean}
   */


  obj.balancer__remove_from__wait_list = function (resource_id, function_name) {
    var removed_el = false;

    if (p_balancer['wait'].length) {
      //FixIn: 9.8.10.1
      for (var i in p_balancer['wait']) {
        if (resource_id === p_balancer['wait'][i]['resource_id'] && function_name === p_balancer['wait'][i]['function_name']) {
          removed_el = p_balancer['wait'].splice(i, 1);
          removed_el = removed_el.pop();
          p_balancer['wait'] = p_balancer['wait'].filter(function (v) {
            return v;
          }); // Reindex array

          return removed_el;
        }
      }
    }

    return removed_el;
  };
  /**
  * Is already WAIT
  *
  * @param resource_id
  * @param function_name
  * @returns {boolean}
  */


  obj.balancer__is_already_wait = function (resource_id, function_name) {
    if (p_balancer['wait'].length) {
      //FixIn: 9.8.10.1
      for (var i in p_balancer['wait']) {
        if (resource_id === p_balancer['wait'][i]['resource_id'] && function_name === p_balancer['wait'][i]['function_name']) {
          return true;
        }
      }
    }

    return false;
  };
  /**
   * Add to RUN
   * @param balance_obj
   */


  obj.balancer__add_to__run = function (balance_obj) {
    p_balancer['in_process'].push(balance_obj);
  };
  /**
  * Remove from RUN list
  *
  * @param resource_id
  * @param function_name
  * @returns {*|boolean}
  */


  obj.balancer__remove_from__run_list = function (resource_id, function_name) {
    var removed_el = false;

    if (p_balancer['in_process'].length) {
      //FixIn: 9.8.10.1
      for (var i in p_balancer['in_process']) {
        if (resource_id === p_balancer['in_process'][i]['resource_id'] && function_name === p_balancer['in_process'][i]['function_name']) {
          removed_el = p_balancer['in_process'].splice(i, 1);
          removed_el = removed_el.pop();
          p_balancer['in_process'] = p_balancer['in_process'].filter(function (v) {
            return v;
          }); // Reindex array

          return removed_el;
        }
      }
    }

    return removed_el;
  };
  /**
  * Is already RUN
  *
  * @param resource_id
  * @param function_name
  * @returns {boolean}
  */


  obj.balancer__is_already_run = function (resource_id, function_name) {
    if (p_balancer['in_process'].length) {
      //FixIn: 9.8.10.1
      for (var i in p_balancer['in_process']) {
        if (resource_id === p_balancer['in_process'][i]['resource_id'] && function_name === p_balancer['in_process'][i]['function_name']) {
          return true;
        }
      }
    }

    return false;
  };

  obj.balancer__run_next = function () {
    // Get 1st from  Wait list
    var removed_el = false;

    if (p_balancer['wait'].length) {
      //FixIn: 9.8.10.1
      for (var i in p_balancer['wait']) {
        removed_el = obj.balancer__remove_from__wait_list(p_balancer['wait'][i]['resource_id'], p_balancer['wait'][i]['function_name']);
        break;
      }
    }

    if (false !== removed_el) {
      // Run
      obj.balancer__run(removed_el);
    }
  };
  /**
   * Run
   * @param balance_obj
   */


  obj.balancer__run = function (balance_obj) {
    switch (balance_obj['function_name']) {
      case 'wpbc_calendar__load_data__ajx':
        // Add to run list
        obj.balancer__add_to__run(balance_obj);
        wpbc_calendar__load_data__ajx(balance_obj['params']);
        break;

      default:
    }
  };

  return obj;
}(_wpbc || {}, jQuery);
/**
 * -- Help functions ----------------------------------------------------------------------------------------------
*/


function wpbc_balancer__is_wait(params, function_name) {
  //console.log('::wpbc_balancer__is_wait',params , function_name );
  if ('undefined' !== typeof params['resource_id']) {
    var balancer_status = _wpbc.balancer__init(params['resource_id'], function_name, params);

    return 'wait' === balancer_status;
  }

  return false;
}

function wpbc_balancer__completed(resource_id, function_name) {
  //console.log('::wpbc_balancer__completed',resource_id , function_name );
  _wpbc.balancer__remove_from__run_list(resource_id, function_name);

  _wpbc.balancer__run_next();
}
/**
 * =====================================================================================================================
 *	includes/__js/cal/wpbc_cal.js
 * =====================================================================================================================
 */

/**
 * Order or child booking resources saved here:  	_wpbc.booking__get_param_value( resource_id, 'resources_id_arr__in_dates' )		[2,10,12,11]
 */

/**
 * How to check  booked times on  specific date: ?
 *
			_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21');

			console.log(
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[2].booked_time_slots.merged_seconds,
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[10].booked_time_slots.merged_seconds,
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[11].booked_time_slots.merged_seconds,
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[12].booked_time_slots.merged_seconds
					);
 *  OR
			console.log(
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[2].booked_time_slots.merged_readable,
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[10].booked_time_slots.merged_readable,
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[11].booked_time_slots.merged_readable,
						_wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[12].booked_time_slots.merged_readable
					);
 *
 */

/**
 * Days selection:
 * 					wpbc_calendar__unselect_all_dates( resource_id );
 *
 *
 *	var inst= wpbc_calendar__get_inst(3); inst.dates=[]; wpbc__calendar__on_select_days('22.09.2023 - 23.09.2023' , {'resource_id':3} , inst);  inst.stayOpen = false;jQuery.datepick._updateDatepick( inst );
 *  if it doesn't work  in 100% situations. check wpbc_select_days_in_calendar(3, [ [ 2023, "09", 26 ], [ 2023, "08", 25 ]]);
 */

/**
 * C A L E N D A R  ---------------------------------------------------------------------------------------------------
 */

/**
 *  Show WPBC Calendar
 *
 * @param resource_id			- resource ID
 * @returns {boolean}
 */


function wpbc_calendar_show(resource_id) {
  // If no calendar HTML tag,  then  exit
  if (0 === jQuery('#calendar_booking' + resource_id).length) {
    return false;
  } // If the calendar with the same Booking resource is activated already, then exit.


  if (true === jQuery('#calendar_booking' + resource_id).hasClass('hasDatepick')) {
    return false;
  } // -----------------------------------------------------------------------------------------------------------------
  // Days selection
  // -----------------------------------------------------------------------------------------------------------------


  var local__is_range_select = false;
  var local__multi_days_select_num = 365; // multiple | fixed

  if ('dynamic' === _wpbc.calendar__get_param_value(resource_id, 'days_select_mode')) {
    local__is_range_select = true;
    local__multi_days_select_num = 0;
  }

  if ('single' === _wpbc.calendar__get_param_value(resource_id, 'days_select_mode')) {
    local__multi_days_select_num = 0;
  } // -----------------------------------------------------------------------------------------------------------------
  // Min - Max days to scroll/show
  // -----------------------------------------------------------------------------------------------------------------


  var local__min_date = 0;

  var local__max_date = _wpbc.calendar__get_param_value(resource_id, 'booking_max_monthes_in_calendar'); //local__max_date = new Date(2024, 5, 28);  It is here issue of not selectable dates, but some dates showing in calendar as available, but we can not select it.
  // Define last day in calendar (as a last day of month (and not date, which is related to actual 'Today' date).
  // E.g. if today is 2023-09-25, and we set 'Number of months to scroll' as 5 months, then last day will be 2024-02-29 and not the 2024-02-25.


  var cal_last_day_in_month = jQuery.datepick._determineDate(null, local__max_date, new Date());

  cal_last_day_in_month = new Date(cal_last_day_in_month.getFullYear(), cal_last_day_in_month.getMonth() + 1, 0);
  local__max_date = cal_last_day_in_month;

  if (location.href.indexOf('page=wpbc-new') != -1 && location.href.indexOf('booking_hash') != -1 // Comment this line for ability to add  booking in past days at  Booking > Add booking page.
  ) {
    local__min_date = null;
    local__max_date = null;
  }

  var local__start_weekday = _wpbc.calendar__get_param_value(resource_id, 'booking_start_day_weeek');

  var local__number_of_months = parseInt(_wpbc.calendar__get_param_value(resource_id, 'calendar_number_of_months'));
  jQuery('#calendar_booking' + resource_id).text(''); // Remove all HTML in calendar tag
  // -----------------------------------------------------------------------------------------------------------------
  // Show calendar
  // -----------------------------------------------------------------------------------------------------------------

  jQuery('#calendar_booking' + resource_id).datepick({
    beforeShowDay: function beforeShowDay(js_date) {
      return wpbc__calendar__apply_css_to_days(js_date, {
        'resource_id': resource_id
      }, this);
    },
    onSelect: function onSelect(string_dates, js_dates_arr) {
      /**
      *	string_dates   =   '23.08.2023 - 26.08.2023'    |    '23.08.2023 - 23.08.2023'    |    '19.09.2023, 24.08.2023, 30.09.2023'
      *  js_dates_arr   =   range: [ Date (Aug 23 2023), Date (Aug 25 2023)]     |     multiple: [ Date(Oct 24 2023), Date(Oct 20 2023), Date(Oct 16 2023) ]
      */
      return wpbc__calendar__on_select_days(string_dates, {
        'resource_id': resource_id
      }, this);
    },
    onHover: function onHover(string_date, js_date) {
      return wpbc__calendar__on_hover_days(string_date, js_date, {
        'resource_id': resource_id
      }, this);
    },
    onChangeMonthYear: function onChangeMonthYear(year, real_month, js_date__1st_day_in_month) {},
    showOn: 'both',
    numberOfMonths: local__number_of_months,
    stepMonths: 1,
    prevText: '&laquo;',
    nextText: '&raquo;',
    dateFormat: 'dd.mm.yy',
    changeMonth: false,
    changeYear: false,
    minDate: local__min_date,
    maxDate: local__max_date,
    // '1Y',
    // minDate: new Date(2020, 2, 1), maxDate: new Date(2020, 9, 31),             	// Ability to set any  start and end date in calendar
    showStatus: false,
    multiSeparator: ', ',
    closeAtTop: false,
    firstDay: local__start_weekday,
    gotoCurrent: false,
    hideIfNoPrevNext: true,
    multiSelect: local__multi_days_select_num,
    rangeSelect: local__is_range_select,
    // showWeeks: true,
    useThemeRoller: false
  }); // -----------------------------------------------------------------------------------------------------------------
  // Clear today date highlighting
  // -----------------------------------------------------------------------------------------------------------------

  setTimeout(function () {
    wpbc_calendars__clear_days_highlighting(resource_id);
  }, 500); //FixIn: 7.1.2.8
  // -----------------------------------------------------------------------------------------------------------------
  // Scroll calendar to  specific month
  // -----------------------------------------------------------------------------------------------------------------

  var start_bk_month = _wpbc.calendar__get_param_value(resource_id, 'calendar_scroll_to');

  if (false !== start_bk_month) {
    wpbc_calendar__scroll_to(resource_id, start_bk_month[0], start_bk_month[1]);
  }
}
/**
 * Apply CSS to calendar date cells
 *
 * @param date										-  JavaScript Date Obj:  		Mon Dec 11 2023 00:00:00 GMT+0200 (Eastern European Standard Time)
 * @param calendar_params_arr						-  Calendar Settings Object:  	{
 *																  						"resource_id": 4
 *																					}
 * @param datepick_this								- this of datepick Obj
 * @returns {(*|string)[]|(boolean|string)[]}		- [ {true -available | false - unavailable}, 'CSS classes for calendar day cell' ]
 */


function wpbc__calendar__apply_css_to_days(date, calendar_params_arr, datepick_this) {
  var today_date = new Date(wpbc_today[0], parseInt(wpbc_today[1]) - 1, wpbc_today[2], 0, 0, 0); // Today JS_Date_Obj.

  var class_day = wpbc__get__td_class_date(date); // '1-9-2023'

  var sql_class_day = wpbc__get__sql_class_date(date); // '2023-01-09'

  var resource_id = 'undefined' !== typeof calendar_params_arr['resource_id'] ? calendar_params_arr['resource_id'] : '1'; // '1'
  // Get Data --------------------------------------------------------------------------------------------------------

  var date_bookings_obj = _wpbc.bookings_in_calendar__get_for_date(resource_id, sql_class_day); // Array with CSS classes for date ---------------------------------------------------------------------------------


  var css_classes__for_date = [];
  css_classes__for_date.push('sql_date_' + sql_class_day); //  'sql_date_2023-07-21'

  css_classes__for_date.push('cal4date-' + class_day); //  'cal4date-7-21-2023'

  css_classes__for_date.push('wpbc_weekday_' + date.getDay()); //  'wpbc_weekday_4'

  var is_day_selectable = false; // If something not defined,  then  this date closed ---------------------------------------------------------------

  if (false === date_bookings_obj) {
    css_classes__for_date.push('date_user_unavailable');
    return [is_day_selectable, css_classes__for_date.join(' ')];
  } // -----------------------------------------------------------------------------------------------------------------
  //   date_bookings_obj  - Defined.            Dates can be selectable.
  // -----------------------------------------------------------------------------------------------------------------
  // -----------------------------------------------------------------------------------------------------------------
  // Add season names to the day CSS classes -- it is required for correct  work  of conditional fields --------------


  var season_names_arr = _wpbc.seasons__get_for_date(resource_id, sql_class_day);

  for (var season_key in season_names_arr) {
    css_classes__for_date.push(season_names_arr[season_key]); //  'wpdevbk_season_september_2023'
  } // -----------------------------------------------------------------------------------------------------------------
  // Cost Rate -------------------------------------------------------------------------------------------------------


  css_classes__for_date.push('rate_' + date_bookings_obj[resource_id]['date_cost_rate'].toString().replace(/[\.\s]/g, '_')); //  'rate_99_00' -> 99.00

  if (parseInt(date_bookings_obj['day_availability']) > 0) {
    is_day_selectable = true;
    css_classes__for_date.push('date_available');
    css_classes__for_date.push('reserved_days_count' + parseInt(date_bookings_obj['max_capacity'] - date_bookings_obj['day_availability']));
  } else {
    is_day_selectable = false;
    css_classes__for_date.push('date_user_unavailable');
  }

  switch (date_bookings_obj['summary']['status_for_day']) {
    case 'available':
      break;

    case 'time_slots_booking':
      css_classes__for_date.push('timespartly', 'times_clock');
      break;

    case 'full_day_booking':
      css_classes__for_date.push('full_day_booking');
      break;

    case 'season_filter':
      css_classes__for_date.push('date_user_unavailable', 'season_unavailable');
      date_bookings_obj['summary']['status_for_bookings'] = ''; // Reset booking status color for possible old bookings on this date

      break;

    case 'resource_availability':
      css_classes__for_date.push('date_user_unavailable', 'resource_unavailable');
      date_bookings_obj['summary']['status_for_bookings'] = ''; // Reset booking status color for possible old bookings on this date

      break;

    case 'weekday_unavailable':
      css_classes__for_date.push('date_user_unavailable', 'weekday_unavailable');
      date_bookings_obj['summary']['status_for_bookings'] = ''; // Reset booking status color for possible old bookings on this date

      break;

    case 'from_today_unavailable':
      css_classes__for_date.push('date_user_unavailable', 'from_today_unavailable');
      date_bookings_obj['summary']['status_for_bookings'] = ''; // Reset booking status color for possible old bookings on this date

      break;

    case 'limit_available_from_today':
      css_classes__for_date.push('date_user_unavailable', 'limit_available_from_today');
      date_bookings_obj['summary']['status_for_bookings'] = ''; // Reset booking status color for possible old bookings on this date

      break;

    case 'change_over':
      /*
       *
      //  check_out_time_date2approve 	 	check_in_time_date2approve
      //  check_out_time_date2approve 	 	check_in_time_date_approved
      //  check_in_time_date2approve 		 	check_out_time_date_approved
      //  check_out_time_date_approved 	 	check_in_time_date_approved
       */
      css_classes__for_date.push('timespartly', 'check_in_time', 'check_out_time');
      break;

    case 'check_in':
      css_classes__for_date.push('timespartly', 'check_in_time');

      if ('pending' == date_bookings_obj['summary']['status_for_bookings']) {
        css_classes__for_date.push('check_in_time_date2approve');
      }

      if ('approved' == date_bookings_obj['summary']['status_for_bookings']) {
        css_classes__for_date.push('check_in_time_date_approved');
      }

      break;

    case 'check_out':
      css_classes__for_date.push('timespartly', 'check_out_time');

      if ('pending' == date_bookings_obj['summary']['status_for_bookings']) {
        css_classes__for_date.push('check_out_time_date2approve');
      }

      if ('approved' == date_bookings_obj['summary']['status_for_bookings']) {
        css_classes__for_date.push('check_out_time_date_approved');
      }

      break;

    default:
      // mixed statuses: 'change_over check_out' .... variations.... check more in 		function wpbc_get_availability_per_days_arr()
      date_bookings_obj['summary']['status_for_day'] = 'available';
  }

  if ('available' != date_bookings_obj['summary']['status_for_day']) {
    var is_set_pending_days_selectable = _wpbc.calendar__get_param_value(resource_id, 'pending_days_selectable'); // set pending days selectable          //FixIn: 8.6.1.18


    switch (date_bookings_obj['summary']['status_for_bookings']) {
      case '':
        // Usually  it's means that day  is available or unavailable without the bookings
        break;

      case 'pending':
        css_classes__for_date.push('date2approve');
        is_day_selectable = is_day_selectable ? true : is_set_pending_days_selectable;
        break;

      case 'approved':
        css_classes__for_date.push('date_approved');
        break;
      // Situations for "change-over" days: ----------------------------------------------------------------------

      case 'pending_pending':
        css_classes__for_date.push('check_out_time_date2approve', 'check_in_time_date2approve');
        is_day_selectable = is_day_selectable ? true : is_set_pending_days_selectable;
        break;

      case 'pending_approved':
        css_classes__for_date.push('check_out_time_date2approve', 'check_in_time_date_approved');
        is_day_selectable = is_day_selectable ? true : is_set_pending_days_selectable;
        break;

      case 'approved_pending':
        css_classes__for_date.push('check_out_time_date_approved', 'check_in_time_date2approve');
        is_day_selectable = is_day_selectable ? true : is_set_pending_days_selectable;
        break;

      case 'approved_approved':
        css_classes__for_date.push('check_out_time_date_approved', 'check_in_time_date_approved');
        break;

      default:
    }
  }

  return [is_day_selectable, css_classes__for_date.join(' ')];
}
/**
 * Mouseover calendar date cells
 *
 * @param string_date
 * @param date										-  JavaScript Date Obj:  		Mon Dec 11 2023 00:00:00 GMT+0200 (Eastern European Standard Time)
 * @param calendar_params_arr						-  Calendar Settings Object:  	{
 *																  						"resource_id": 4
 *																					}
 * @param datepick_this								- this of datepick Obj
 * @returns {boolean}
 */


function wpbc__calendar__on_hover_days(string_date, date, calendar_params_arr, datepick_this) {
  if (null === date) {
    return false;
  }

  var class_day = wpbc__get__td_class_date(date); // '1-9-2023'

  var sql_class_day = wpbc__get__sql_class_date(date); // '2023-01-09'

  var resource_id = 'undefined' !== typeof calendar_params_arr['resource_id'] ? calendar_params_arr['resource_id'] : '1'; // '1'
  // Get Data --------------------------------------------------------------------------------------------------------

  var date_booking_obj = _wpbc.bookings_in_calendar__get_for_date(resource_id, sql_class_day); // {...}


  if (!date_booking_obj) {
    return false;
  } // T o o l t i p s -------------------------------------------------------------------------------------------------


  var tooltip_text = '';

  if (date_booking_obj['summary']['tooltip_availability'].length > 0) {
    tooltip_text += date_booking_obj['summary']['tooltip_availability'];
  }

  if (date_booking_obj['summary']['tooltip_day_cost'].length > 0) {
    tooltip_text += date_booking_obj['summary']['tooltip_day_cost'];
  }

  if (date_booking_obj['summary']['tooltip_times'].length > 0) {
    tooltip_text += date_booking_obj['summary']['tooltip_times'];
  }

  if (date_booking_obj['summary']['tooltip_booking_details'].length > 0) {
    tooltip_text += date_booking_obj['summary']['tooltip_booking_details'];
  }

  wpbc_set_tooltip___for__calendar_date(tooltip_text, resource_id, class_day); //  U n h o v e r i n g    in    UNSELECTABLE_CALENDAR  ------------------------------------------------------------

  var is_unselectable_calendar = jQuery('#calendar_booking_unselectable' + resource_id).length > 0; //FixIn: 8.0.1.2

  var is_booking_form_exist = jQuery('#booking_form_div' + resource_id).length > 0;

  if (is_unselectable_calendar && !is_booking_form_exist) {
    /**
     *  Un Hover all dates in calendar (without the booking form), if only Availability Calendar here and we do not insert Booking form by mistake.
     */
    wpbc_calendars__clear_days_highlighting(resource_id); // Clear days highlighting

    var css_of_calendar = '.wpbc_only_calendar #calendar_booking' + resource_id;
    jQuery(css_of_calendar + ' .datepick-days-cell, ' + css_of_calendar + ' .datepick-days-cell a').css('cursor', 'default'); // Set cursor to Default

    return false;
  } //  D a y s    H o v e r i n g  ------------------------------------------------------------------------------------


  if (location.href.indexOf('page=wpbc') == -1 || location.href.indexOf('page=wpbc-new') > 0 || location.href.indexOf('page=wpbc-availability') > 0) {
    // The same as dates selection,  but for days hovering
    if ('function' == typeof wpbc__calendar__do_days_highlight__bs) {
      wpbc__calendar__do_days_highlight__bs(sql_class_day, date, resource_id);
    }
  }
}
/**
 * Select calendar date cells
 *
 * @param date										-  JavaScript Date Obj:  		Mon Dec 11 2023 00:00:00 GMT+0200 (Eastern European Standard Time)
 * @param calendar_params_arr						-  Calendar Settings Object:  	{
 *																  						"resource_id": 4
 *																					}
 * @param datepick_this								- this of datepick Obj
 *
 */


function wpbc__calendar__on_select_days(date, calendar_params_arr, datepick_this) {
  var resource_id = 'undefined' !== typeof calendar_params_arr['resource_id'] ? calendar_params_arr['resource_id'] : '1'; // '1'
  // Set unselectable,  if only Availability Calendar  here (and we do not insert Booking form by mistake).

  var is_unselectable_calendar = jQuery('#calendar_booking_unselectable' + resource_id).length > 0; //FixIn: 8.0.1.2

  var is_booking_form_exist = jQuery('#booking_form_div' + resource_id).length > 0;

  if (is_unselectable_calendar && !is_booking_form_exist) {
    wpbc_calendar__unselect_all_dates(resource_id); // Unselect Dates

    jQuery('.wpbc_only_calendar .popover_calendar_hover').remove(); // Hide all opened popovers

    return false;
  }

  jQuery('#date_booking' + resource_id).val(date); // Add selected dates to  hidden textarea

  if ('function' === typeof wpbc__calendar__do_days_select__bs) {
    wpbc__calendar__do_days_select__bs(date, resource_id);
  }

  wpbc_disable_time_fields_in_booking_form(resource_id); // Hook -- trigger day selection -----------------------------------------------------------------------------------

  var mouse_clicked_dates = date; // Can be: "05.10.2023 - 07.10.2023"  |  "10.10.2023 - 10.10.2023"  |

  var all_selected_dates_arr = wpbc_get__selected_dates_sql__as_arr(resource_id); // Can be: [ "2023-10-05", "2023-10-06", "2023-10-07", … ]

  jQuery(".booking_form_div").trigger("date_selected", [resource_id, mouse_clicked_dates, all_selected_dates_arr]);
}
/**
 * --  T i m e    F i e l d s     start  --------------------------------------------------------------------------
 */

/**
 * Disable time slots in booking form depend on selected dates and booked dates/times
 *
 * @param resource_id
 */


function wpbc_disable_time_fields_in_booking_form(resource_id) {
  /**
   * 	1. Get all time fields in the booking form as array  of objects
   * 					[
   * 					 	   {	jquery_option:      jQuery_Object {}
   * 								name:               'rangetime2[]'
   * 								times_as_seconds:   [ 21600, 23400 ]
   * 								value_option_24h:   '06:00 - 06:30'
   * 					     }
   * 					  ...
   * 						   {	jquery_option:      jQuery_Object {}
   * 								name:               'starttime2[]'
   * 								times_as_seconds:   [ 21600 ]
   * 								value_option_24h:   '06:00'
   *  					    }
   * 					 ]
   */
  var time_fields_obj_arr = wpbc_get__time_fields__in_booking_form__as_arr(resource_id); // 2. Get all selected dates in  SQL format  like this [ "2023-08-23", "2023-08-24", "2023-08-25", ... ]

  var selected_dates_arr = wpbc_get__selected_dates_sql__as_arr(resource_id); // 3. Get child booking resources  or single booking resource  that  exist  in dates

  var child_resources_arr = wpbc_clone_obj(_wpbc.booking__get_param_value(resource_id, 'resources_id_arr__in_dates'));
  var sql_date;
  var child_resource_id;
  var merged_seconds;
  var time_fields_obj;
  var is_intersect;
  var is_check_in; // 4. Loop  all  time Fields options

  for (var field_key in time_fields_obj_arr) {
    time_fields_obj_arr[field_key].disabled = 0; // By default this time field is not disabled

    time_fields_obj = time_fields_obj_arr[field_key]; // { times_as_seconds: [ 21600, 23400 ], value_option_24h: '06:00 - 06:30', name: 'rangetime2[]', jquery_option: jQuery_Object {}}
    // Loop  all  selected dates

    for (var i = 0; i < selected_dates_arr.length; i++) {
      // Get Date: '2023-08-18'
      sql_date = selected_dates_arr[i];
      var how_many_resources_intersected = 0; // Loop all resources ID

      for (var res_key in child_resources_arr) {
        child_resource_id = child_resources_arr[res_key]; // _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[12].booked_time_slots.merged_seconds		= [ "07:00:11 - 07:30:02", "10:00:11 - 00:00:00" ]
        // _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[2].booked_time_slots.merged_seconds			= [  [ 25211, 27002 ], [ 36011, 86400 ]  ]

        if (false !== _wpbc.bookings_in_calendar__get_for_date(resource_id, sql_date)) {
          merged_seconds = _wpbc.bookings_in_calendar__get_for_date(resource_id, sql_date)[child_resource_id].booked_time_slots.merged_seconds; // [  [ 25211, 27002 ], [ 36011, 86400 ]  ]
        } else {
          merged_seconds = [];
        }

        if (time_fields_obj.times_as_seconds.length > 1) {
          is_intersect = wpbc_is_intersect__range_time_interval([[parseInt(time_fields_obj.times_as_seconds[0]) + 20, parseInt(time_fields_obj.times_as_seconds[1]) - 20]], merged_seconds);
        } else {
          is_check_in = -1 !== time_fields_obj.name.indexOf('start');
          is_intersect = wpbc_is_intersect__one_time_interval(is_check_in ? parseInt(time_fields_obj.times_as_seconds) + 20 : parseInt(time_fields_obj.times_as_seconds) - 20, merged_seconds);
        }

        if (is_intersect) {
          how_many_resources_intersected++; // Increase
        }
      }

      if (child_resources_arr.length == how_many_resources_intersected) {
        // All resources intersected,  then  it's means that this time-slot or time must  be  Disabled, and we can  exist  from   selected_dates_arr LOOP
        time_fields_obj_arr[field_key].disabled = 1;
        break; // exist  from   Dates LOOP
      }
    }
  } // 5. Now we can disable time slot in HTML by  using  ( field.disabled == 1 ) property


  wpbc__html__time_field_options__set_disabled(time_fields_obj_arr);
  jQuery(".booking_form_div").trigger('wpbc_hook_timeslots_disabled', [resource_id, selected_dates_arr]); // Trigger hook on disabling timeslots.		Usage: 	jQuery( ".booking_form_div" ).on( 'wpbc_hook_timeslots_disabled', function ( event, bk_type, all_dates ){ ... } );		//FixIn: 8.7.11.9
}
/**
 * Is number inside /intersect  of array of intervals ?
 *
 * @param time_A		     	- 25800
 * @param time_interval_B		- [  [ 25211, 27002 ], [ 36011, 86400 ]  ]
 * @returns {boolean}
 */


function wpbc_is_intersect__one_time_interval(time_A, time_interval_B) {
  for (var j = 0; j < time_interval_B.length; j++) {
    if (parseInt(time_A) > parseInt(time_interval_B[j][0]) && parseInt(time_A) < parseInt(time_interval_B[j][1])) {
      return true;
    } // if ( ( parseInt( time_A ) == parseInt( time_interval_B[ j ][ 0 ] ) ) || ( parseInt( time_A ) == parseInt( time_interval_B[ j ][ 1 ] ) ) ) {
    // 			// Time A just  at  the border of interval
    // }

  }

  return false;
}
/**
 * Is these array of intervals intersected ?
 *
 * @param time_interval_A		- [ [ 21600, 23400 ] ]
 * @param time_interval_B		- [  [ 25211, 27002 ], [ 36011, 86400 ]  ]
 * @returns {boolean}
 */


function wpbc_is_intersect__range_time_interval(time_interval_A, time_interval_B) {
  var is_intersect;

  for (var i = 0; i < time_interval_A.length; i++) {
    for (var j = 0; j < time_interval_B.length; j++) {
      is_intersect = wpbc_intervals__is_intersected(time_interval_A[i], time_interval_B[j]);

      if (is_intersect) {
        return true;
      }
    }
  }

  return false;
}
/**
 * Get all time fields in the booking form as array  of objects
 *
 * @param resource_id
 * @returns []
 *
 * 		Example:
 * 					[
 * 					 	   {
 * 								value_option_24h:   '06:00 - 06:30'
 * 								times_as_seconds:   [ 21600, 23400 ]
 * 					 	   		jquery_option:      jQuery_Object {}
 * 								name:               'rangetime2[]'
 * 					     }
 * 					  ...
 * 						   {
 * 								value_option_24h:   '06:00'
 * 								times_as_seconds:   [ 21600 ]
 * 						   		jquery_option:      jQuery_Object {}
 * 								name:               'starttime2[]'
 *  					    }
 * 					 ]
 */


function wpbc_get__time_fields__in_booking_form__as_arr(resource_id) {
  /**
  * Fields with  []  like this   select[name="rangetime1[]"]
  * it's when we have 'multiple' in shortcode:   [select* rangetime multiple  "06:00 - 06:30" ... ]
  */
  var time_fields_arr = ['select[name="rangetime' + resource_id + '"]', 'select[name="rangetime' + resource_id + '[]"]', 'select[name="starttime' + resource_id + '"]', 'select[name="starttime' + resource_id + '[]"]', 'select[name="endtime' + resource_id + '"]', 'select[name="endtime' + resource_id + '[]"]'];
  var time_fields_obj_arr = []; // Loop all Time Fields

  for (var ctf = 0; ctf < time_fields_arr.length; ctf++) {
    var time_field = time_fields_arr[ctf];
    var time_option = jQuery(time_field + ' option'); // Loop all options in time field

    for (var j = 0; j < time_option.length; j++) {
      var jquery_option = jQuery(time_field + ' option:eq(' + j + ')');
      var value_option_seconds_arr = jquery_option.val().split('-');
      var times_as_seconds = []; // Get time as seconds

      if (value_option_seconds_arr.length) {
        //FixIn: 9.8.10.1
        for (var i in value_option_seconds_arr) {
          // value_option_seconds_arr[i] = '14:00 '  | ' 16:00'   (if from 'rangetime') and '16:00'  if (start/end time)
          var start_end_times_arr = value_option_seconds_arr[i].trim().split(':');
          var time_in_seconds = parseInt(start_end_times_arr[0]) * 60 * 60 + parseInt(start_end_times_arr[1]) * 60;
          times_as_seconds.push(time_in_seconds);
        }
      }

      time_fields_obj_arr.push({
        'name': jQuery(time_field).attr('name'),
        'value_option_24h': jquery_option.val(),
        'jquery_option': jquery_option,
        'times_as_seconds': times_as_seconds
      });
    }
  }

  return time_fields_obj_arr;
}
/**
 * Disable HTML options and add booked CSS class
 *
 * @param time_fields_obj_arr      - this value is from  the func:  	wpbc_get__time_fields__in_booking_form__as_arr( resource_id )
 * 					[
 * 					 	   {	jquery_option:      jQuery_Object {}
 * 								name:               'rangetime2[]'
 * 								times_as_seconds:   [ 21600, 23400 ]
 * 								value_option_24h:   '06:00 - 06:30'
 * 	  						    disabled = 1
 * 					     }
 * 					  ...
 * 						   {	jquery_option:      jQuery_Object {}
 * 								name:               'starttime2[]'
 * 								times_as_seconds:   [ 21600 ]
 * 								value_option_24h:   '06:00'
 *   							disabled = 0
 *  					    }
 * 					 ]
 *
 */


function wpbc__html__time_field_options__set_disabled(time_fields_obj_arr) {
  var jquery_option;

  for (var i = 0; i < time_fields_obj_arr.length; i++) {
    var jquery_option = time_fields_obj_arr[i].jquery_option;

    if (1 == time_fields_obj_arr[i].disabled) {
      jquery_option.prop('disabled', true); // Make disable some options

      jquery_option.addClass('booked'); // Add "booked" CSS class
      // if this booked element selected --> then deselect  it

      if (jquery_option.prop('selected')) {
        jquery_option.prop('selected', false);
        jquery_option.parent().find('option:not([disabled]):first').prop('selected', true).trigger("change");
      }
    } else {
      jquery_option.prop('disabled', false); // Make active all times

      jquery_option.removeClass('booked'); // Remove class "booked"
    }
  }
}
/**
 * Check if this time_range | Time_Slot is Full Day  booked
 *
 * @param timeslot_arr_in_seconds		- [ 36011, 86400 ]
 * @returns {boolean}
 */


function wpbc_is_this_timeslot__full_day_booked(timeslot_arr_in_seconds) {
  if (timeslot_arr_in_seconds.length > 1 && parseInt(timeslot_arr_in_seconds[0]) < 30 && parseInt(timeslot_arr_in_seconds[1]) > 24 * 60 * 60 - 30) {
    return true;
  }

  return false;
} // -----------------------------------------------------------------------------------------------------------------
// S e l e c t e d    D a t e s  /  T i m e - F i e l d s
// -----------------------------------------------------------------------------------------------------------------

/**
 *  Get all selected dates in SQL format like this [ "2023-08-23", "2023-08-24" , ... ]
 *
 * @param resource_id
 * @returns {[]}			[ "2023-08-23", "2023-08-24", "2023-08-25", "2023-08-26", "2023-08-27", "2023-08-28", "2023-08-29" ]
 */


function wpbc_get__selected_dates_sql__as_arr(resource_id) {
  var selected_dates_arr = [];
  selected_dates_arr = jQuery('#date_booking' + resource_id).val().split(',');

  if (selected_dates_arr.length) {
    //FixIn: 9.8.10.1
    for (var i in selected_dates_arr) {
      selected_dates_arr[i] = selected_dates_arr[i].trim();
      selected_dates_arr[i] = selected_dates_arr[i].split('.');

      if (selected_dates_arr[i].length > 1) {
        selected_dates_arr[i] = selected_dates_arr[i][2] + '-' + selected_dates_arr[i][1] + '-' + selected_dates_arr[i][0];
      }
    }
  } // Remove empty elements from an array


  selected_dates_arr = selected_dates_arr.filter(function (n) {
    return parseInt(n);
  });
  selected_dates_arr.sort();
  return selected_dates_arr;
}
/**
 * Get all time fields in the booking form as array  of objects
 *
 * @param resource_id
 * @param is_only_selected_time
 * @returns []
 *
 * 		Example:
 * 					[
 * 					 	   {
 * 								value_option_24h:   '06:00 - 06:30'
 * 								times_as_seconds:   [ 21600, 23400 ]
 * 					 	   		jquery_option:      jQuery_Object {}
 * 								name:               'rangetime2[]'
 * 					     }
 * 					  ...
 * 						   {
 * 								value_option_24h:   '06:00'
 * 								times_as_seconds:   [ 21600 ]
 * 						   		jquery_option:      jQuery_Object {}
 * 								name:               'starttime2[]'
 *  					    }
 * 					 ]
 */


function wpbc_get__selected_time_fields__in_booking_form__as_arr(resource_id) {
  var is_only_selected_time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;

  /**
   * Fields with  []  like this   select[name="rangetime1[]"]
   * it's when we have 'multiple' in shortcode:   [select* rangetime multiple  "06:00 - 06:30" ... ]
   */
  var time_fields_arr = ['select[name="rangetime' + resource_id + '"]', 'select[name="rangetime' + resource_id + '[]"]', 'select[name="starttime' + resource_id + '"]', 'select[name="starttime' + resource_id + '[]"]', 'select[name="endtime' + resource_id + '"]', 'select[name="endtime' + resource_id + '[]"]', 'select[name="durationtime' + resource_id + '"]', 'select[name="durationtime' + resource_id + '[]"]'];
  var time_fields_obj_arr = []; // Loop all Time Fields

  for (var ctf = 0; ctf < time_fields_arr.length; ctf++) {
    var time_field = time_fields_arr[ctf];
    var time_option;

    if (is_only_selected_time) {
      time_option = jQuery('#booking_form' + resource_id + ' ' + time_field + ' option:selected'); // Exclude conditional  fields,  because of using '#booking_form3 ...'
    } else {
      time_option = jQuery('#booking_form' + resource_id + ' ' + time_field + ' option'); // All  time fields
    } // Loop all options in time field


    for (var j = 0; j < time_option.length; j++) {
      var jquery_option = jQuery(time_option[j]); // Get only  selected options 	//jQuery( time_field + ' option:eq(' + j + ')' );

      var value_option_seconds_arr = jquery_option.val().split('-');
      var times_as_seconds = []; // Get time as seconds

      if (value_option_seconds_arr.length) {
        //FixIn: 9.8.10.1
        for (var i in value_option_seconds_arr) {
          // value_option_seconds_arr[i] = '14:00 '  | ' 16:00'   (if from 'rangetime') and '16:00'  if (start/end time)
          var start_end_times_arr = value_option_seconds_arr[i].trim().split(':');
          var time_in_seconds = parseInt(start_end_times_arr[0]) * 60 * 60 + parseInt(start_end_times_arr[1]) * 60;
          times_as_seconds.push(time_in_seconds);
        }
      }

      time_fields_obj_arr.push({
        'name': jQuery('#booking_form' + resource_id + ' ' + time_field).attr('name'),
        'value_option_24h': jquery_option.val(),
        'jquery_option': jquery_option,
        'times_as_seconds': times_as_seconds
      });
    }
  } // Text:   [starttime] - [endtime] -----------------------------------------------------------------------------


  var text_time_fields_arr = ['input[name="starttime' + resource_id + '"]', 'input[name="endtime' + resource_id + '"]'];

  for (var tf = 0; tf < text_time_fields_arr.length; tf++) {
    var text_jquery = jQuery('#booking_form' + resource_id + ' ' + text_time_fields_arr[tf]); // Exclude conditional  fields,  because of using '#booking_form3 ...'

    if (text_jquery.length > 0) {
      var time__h_m__arr = text_jquery.val().trim().split(':'); // '14:00'

      if (0 == time__h_m__arr.length) {
        continue; // Not entered time value in a field
      }

      if (1 == time__h_m__arr.length) {
        if ('' === time__h_m__arr[0]) {
          continue; // Not entered time value in a field
        }

        time__h_m__arr[1] = 0;
      }

      var text_time_in_seconds = parseInt(time__h_m__arr[0]) * 60 * 60 + parseInt(time__h_m__arr[1]) * 60;
      var text_times_as_seconds = [];
      text_times_as_seconds.push(text_time_in_seconds);
      time_fields_obj_arr.push({
        'name': text_jquery.attr('name'),
        'value_option_24h': text_jquery.val(),
        'jquery_option': text_jquery,
        'times_as_seconds': text_times_as_seconds
      });
    }
  }

  return time_fields_obj_arr;
} // ---------------------------------------------------------------------------------------------------------------------
// S U P P O R T    for    C A L E N D A R
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Get Calendar datepick  Instance
 * @param resource_id  of booking resource
 * @returns {*|null}
 */


function wpbc_calendar__get_inst(resource_id) {
  if ('undefined' === typeof resource_id) {
    resource_id = '1';
  }

  if (jQuery('#calendar_booking' + resource_id).length > 0) {
    return jQuery.datepick._getInst(jQuery('#calendar_booking' + resource_id).get(0));
  }

  return null;
}
/**
 * Unselect  all dates in calendar and visually update this calendar
 *
 * @param resource_id		ID of booking resource
 * @returns {boolean}		true on success | false,  if no such  calendar
 */


function wpbc_calendar__unselect_all_dates(resource_id) {
  if ('undefined' === typeof resource_id) {
    resource_id = '1';
  }

  var inst = wpbc_calendar__get_inst(resource_id);

  if (null !== inst) {
    // Unselect all dates and set  properties of Datepick
    jQuery('#date_booking' + resource_id).val(''); //FixIn: 5.4.3

    inst.stayOpen = false;
    inst.dates = [];

    jQuery.datepick._updateDatepick(inst);

    return true;
  }

  return false;
}
/**
 * Clear days highlighting in All or specific Calendars
 *
    * @param resource_id  - can be skiped to  clear highlighting in all calendars
    */


function wpbc_calendars__clear_days_highlighting(resource_id) {
  if ('undefined' !== typeof resource_id) {
    jQuery('#calendar_booking' + resource_id + ' .datepick-days-cell-over').removeClass('datepick-days-cell-over'); // Clear in specific calendar
  } else {
    jQuery('.datepick-days-cell-over').removeClass('datepick-days-cell-over'); // Clear in all calendars
  }
}
/**
 * Scroll to specific month in calendar
 *
 * @param resource_id		ID of resource
 * @param year				- real year  - 2023
 * @param month				- real month - 12
 * @returns {boolean}
 */


function wpbc_calendar__scroll_to(resource_id, year, month) {
  if ('undefined' === typeof resource_id) {
    resource_id = '1';
  }

  var inst = wpbc_calendar__get_inst(resource_id);

  if (null !== inst) {
    year = parseInt(year);
    month = parseInt(month) - 1; // In JS date,  month -1

    inst.cursorDate = new Date(); // In some cases,  the setFullYear can  set  only Year,  and not the Month and day      //FixIn:6.2.3.5

    inst.cursorDate.setFullYear(year, month, 1);
    inst.cursorDate.setMonth(month);
    inst.cursorDate.setDate(1);
    inst.drawMonth = inst.cursorDate.getMonth();
    inst.drawYear = inst.cursorDate.getFullYear();

    jQuery.datepick._notifyChange(inst);

    jQuery.datepick._adjustInstDate(inst);

    jQuery.datepick._showDate(inst);

    jQuery.datepick._updateDatepick(inst);

    return true;
  }

  return false;
}
/**
 * Is this date selectable in calendar (mainly it's means AVAILABLE date)
 *
 * @param {int|string} resource_id		1
 * @param {string} sql_class_day		'2023-08-11'
 * @returns {boolean}					true | false
 */


function wpbc_is_this_day_selectable(resource_id, sql_class_day) {
  // Get Data --------------------------------------------------------------------------------------------------------
  var date_bookings_obj = _wpbc.bookings_in_calendar__get_for_date(resource_id, sql_class_day);

  var is_day_selectable = parseInt(date_bookings_obj['day_availability']) > 0;

  if ('available' != date_bookings_obj['summary']['status_for_day']) {
    var is_set_pending_days_selectable = _wpbc.calendar__get_param_value(resource_id, 'pending_days_selectable'); // set pending days selectable          //FixIn: 8.6.1.18


    switch (date_bookings_obj['summary']['status_for_bookings']) {
      case 'pending': // Situations for "change-over" days:

      case 'pending_pending':
      case 'pending_approved':
      case 'approved_pending':
        is_day_selectable = is_day_selectable ? true : is_set_pending_days_selectable;
        break;

      default:
    }
  }

  return is_day_selectable;
}
/**
 * Is date to check IN array of selected dates
 *
 * @param {date}js_date_to_check		- JS Date			- simple  JavaScript Date object
 * @param {[]} js_dates_arr			- [ JSDate, ... ]   - array  of JS dates
 * @returns {boolean}
 */


function wpbc_is_this_day_among_selected_days(js_date_to_check, js_dates_arr) {
  for (var date_index = 0; date_index < js_dates_arr.length; date_index++) {
    //FixIn: 8.4.5.16
    if (js_dates_arr[date_index].getFullYear() === js_date_to_check.getFullYear() && js_dates_arr[date_index].getMonth() === js_date_to_check.getMonth() && js_dates_arr[date_index].getDate() === js_date_to_check.getDate()) {
      return true;
    }
  }

  return false;
}
/**
 * Get SQL Class Date '2023-08-01' from  JS Date
 *
 * @param date				JS Date
 * @returns {string}		'2023-08-12'
 */


function wpbc__get__sql_class_date(date) {
  var sql_class_day = date.getFullYear() + '-';
  sql_class_day += date.getMonth() + 1 < 10 ? '0' : '';
  sql_class_day += date.getMonth() + 1 + '-';
  sql_class_day += date.getDate() < 10 ? '0' : '';
  sql_class_day += date.getDate();
  return sql_class_day;
}
/**
 * Get TD Class Date '1-31-2023' from  JS Date
 *
 * @param date				JS Date
 * @returns {string}		'1-31-2023'
 */


function wpbc__get__td_class_date(date) {
  var td_class_day = date.getMonth() + 1 + '-' + date.getDate() + '-' + date.getFullYear(); // '1-9-2023'

  return td_class_day;
}
/**
 * Get date params from  string date
 *
 * @param date			string date like '31.5.2023'
 * @param separator		default '.'  can be skipped.
 * @returns {  {date: number, month: number, year: number}  }
 */


function wpbc__get__date_params__from_string_date(date, separator) {
  separator = 'undefined' !== typeof separator ? separator : '.';
  var date_arr = date.split(separator);
  var date_obj = {
    'year': parseInt(date_arr[2]),
    'month': parseInt(date_arr[1]) - 1,
    'date': parseInt(date_arr[0])
  };
  return date_obj; // for 		 = new Date( date_obj.year , date_obj.month , date_obj.date );
}
/**
 * Add Spin Loader to  calendar
 * @param resource_id
 */


function wpbc_calendar__loading__start(resource_id) {
  if (!jQuery('#calendar_booking' + resource_id).next().hasClass('wpbc_spins_loader_wrapper')) {
    jQuery('#calendar_booking' + resource_id).after('<div class="wpbc_spins_loader_wrapper"><div class="wpbc_spins_loader"></div></div>');
  }

  if (!jQuery('#calendar_booking' + resource_id).hasClass('wpbc_calendar_blur_small')) {
    jQuery('#calendar_booking' + resource_id).addClass('wpbc_calendar_blur_small');
  }

  wpbc_calendar__blur__start(resource_id);
}
/**
 * Remove Spin Loader to  calendar
 * @param resource_id
 */


function wpbc_calendar__loading__stop(resource_id) {
  jQuery('#calendar_booking' + resource_id + ' + .wpbc_spins_loader_wrapper').remove();
  jQuery('#calendar_booking' + resource_id).removeClass('wpbc_calendar_blur_small');
  wpbc_calendar__blur__stop(resource_id);
}
/**
 * Add Blur to  calendar
 * @param resource_id
 */


function wpbc_calendar__blur__start(resource_id) {
  if (!jQuery('#calendar_booking' + resource_id).hasClass('wpbc_calendar_blur')) {
    jQuery('#calendar_booking' + resource_id).addClass('wpbc_calendar_blur');
  }
}
/**
 * Remove Blur in  calendar
 * @param resource_id
 */


function wpbc_calendar__blur__stop(resource_id) {
  jQuery('#calendar_booking' + resource_id).removeClass('wpbc_calendar_blur');
}
/**
 * Update Look  of calendar
 *
 * @param resource_id
 */


function wpbc_calendar__update_look(resource_id) {
  var inst = wpbc_calendar__get_inst(resource_id);

  jQuery.datepick._updateDatepick(inst);
} // ---------------------------------------------------------------------------------------------------------------------
// S U P P O R T    M A T H
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Merge several  intersected intervals or return not intersected:                        [[1,3],[2,6],[8,10],[15,18]]  ->   [[1,6],[8,10],[15,18]]
 *
 * @param [] intervals			 [ [1,3],[2,4],[6,8],[9,10],[3,7] ]
 * @returns []					 [ [1,8],[9,10] ]
 *
 * Exmample: wpbc_intervals__merge_inersected(  [ [1,3],[2,4],[6,8],[9,10],[3,7] ]  );
 */


function wpbc_intervals__merge_inersected(intervals) {
  if (!intervals || intervals.length === 0) {
    return [];
  }

  var merged = [];
  intervals.sort(function (a, b) {
    return a[0] - b[0];
  });
  var mergedInterval = intervals[0];

  for (var i = 1; i < intervals.length; i++) {
    var interval = intervals[i];

    if (interval[0] <= mergedInterval[1]) {
      mergedInterval[1] = Math.max(mergedInterval[1], interval[1]);
    } else {
      merged.push(mergedInterval);
      mergedInterval = interval;
    }
  }

  merged.push(mergedInterval);
  return merged;
}
/**
 * Is 2 intervals intersected:       [36011, 86392]    <=>    [1, 43192]  =>  true      ( intersected )
 *
 * Good explanation  here https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap
 *
 * @param  interval_A   - [ 36011, 86392 ]
 * @param  interval_B   - [     1, 43192 ]
 *
 * @return bool
 */


function wpbc_intervals__is_intersected(interval_A, interval_B) {
  if (0 == interval_A.length || 0 == interval_B.length) {
    return false;
  }

  interval_A[0] = parseInt(interval_A[0]);
  interval_A[1] = parseInt(interval_A[1]);
  interval_B[0] = parseInt(interval_B[0]);
  interval_B[1] = parseInt(interval_B[1]);
  var is_intersected = Math.max(interval_A[0], interval_B[0]) - Math.min(interval_A[1], interval_B[1]); // if ( 0 == is_intersected ) {
  //	                                 // Such ranges going one after other, e.g.: [ 12, 15 ] and [ 15, 21 ]
  // }

  if (is_intersected < 0) {
    return true; // INTERSECTED
  }

  return false; // Not intersected
}
/**
 * Get the closets ABS value of element in array to the current myValue
 *
 * @param myValue 	- int element to search closet 			4
 * @param myArray	- array of elements where to search 	[5,8,1,7]
 * @returns int												5
 */


function wpbc_get_abs_closest_value_in_arr(myValue, myArray) {
  if (myArray.length == 0) {
    // If the array is empty -> return  the myValue
    return myValue;
  }

  var obj = myArray[0];
  var diff = Math.abs(myValue - obj); // Get distance between  1st element

  var closetValue = myArray[0]; // Save 1st element

  for (var i = 1; i < myArray.length; i++) {
    obj = myArray[i];

    if (Math.abs(myValue - obj) < diff) {
      // we found closer value -> save it
      diff = Math.abs(myValue - obj);
      closetValue = obj;
    }
  }

  return closetValue;
} // ---------------------------------------------------------------------------------------------------------------------
//  T O O L T I P S
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Define tooltip to show,  when  mouse over Date in Calendar
 *
 * @param  tooltip_text			- Text to show				'Booked time: 12:00 - 13:00<br>Cost: $20.00'
 * @param  resource_id			- ID of booking resource	'1'
 * @param  td_class				- SQL class					'1-9-2023'
 * @returns {boolean}					- defined to show or not
 */


function wpbc_set_tooltip___for__calendar_date(tooltip_text, resource_id, td_class) {
  //TODO: make escaping of text for quot symbols,  and JS/HTML...
  jQuery('#calendar_booking' + resource_id + ' td.cal4date-' + td_class).attr('data-content', tooltip_text);
  var td_el = jQuery('#calendar_booking' + resource_id + ' td.cal4date-' + td_class).get(0); //FixIn: 9.0.1.1

  if ('undefined' !== typeof td_el && undefined == td_el._tippy && '' !== tooltip_text) {
    wpbc_tippy(td_el, {
      content: function content(reference) {
        var popover_content = reference.getAttribute('data-content');
        return '<div class="popover popover_tippy">' + '<div class="popover-content">' + popover_content + '</div>' + '</div>';
      },
      allowHTML: true,
      trigger: 'mouseenter focus',
      interactive: false,
      hideOnClick: true,
      interactiveBorder: 10,
      maxWidth: 550,
      theme: 'wpbc-tippy-times',
      placement: 'top',
      delay: [400, 0],
      //FixIn: 9.4.2.2
      //delay			 : [0, 9999999999],						// Debuge  tooltip
      ignoreAttributes: true,
      touch: true,
      //['hold', 500], // 500ms delay				//FixIn: 9.2.1.5
      appendTo: function appendTo() {
        return document.body;
      }
    });
    return true;
  }

  return false;
}
/**
 * ====================================================================================================================
 *	includes/__js/cal/days_select_custom.js
 * ====================================================================================================================
 */
//FixIn: 9.8.9.2

/**
 * Re-Init Calendar and Re-Render it.
 *
 * @param resource_id
 */


function wpbc_cal__re_init(resource_id) {
  // Remove CLASS  for ability to re-render and reinit calendar.
  jQuery('#calendar_booking' + resource_id).removeClass('hasDatepick');
  wpbc_calendar_show(resource_id);
}
/**
 * Re-Init previously  saved days selection  variables.
 *
 * @param resource_id
 */


function wpbc_cal_days_select__re_init(resource_id) {
  _wpbc.calendar__set_param_value(resource_id, 'saved_variable___days_select_initial', {
    'dynamic__days_min': _wpbc.calendar__get_param_value(resource_id, 'dynamic__days_min'),
    'dynamic__days_max': _wpbc.calendar__get_param_value(resource_id, 'dynamic__days_max'),
    'dynamic__days_specific': _wpbc.calendar__get_param_value(resource_id, 'dynamic__days_specific'),
    'dynamic__week_days__start': _wpbc.calendar__get_param_value(resource_id, 'dynamic__week_days__start'),
    'fixed__days_num': _wpbc.calendar__get_param_value(resource_id, 'fixed__days_num'),
    'fixed__week_days__start': _wpbc.calendar__get_param_value(resource_id, 'fixed__week_days__start')
  });
} // ---------------------------------------------------------------------------------------------------------------------

/**
 * Set Single Day selection - after page load
 *
 * @param resource_id		ID of booking resource
 */


function wpbc_cal_ready_days_select__single(resource_id) {
  // Re-define selection, only after page loaded with all init vars
  jQuery(document).ready(function () {
    // Wait 1 second, just to  be sure, that all init vars defined
    setTimeout(function () {
      wpbc_cal_days_select__single(resource_id);
    }, 1000);
  });
}
/**
 * Set Single Day selection
 * Can be run at any  time,  when  calendar defined - useful for console run.
 *
 * @param resource_id		ID of booking resource
 */


function wpbc_cal_days_select__single(resource_id) {
  _wpbc.calendar__set_parameters(resource_id, {
    'days_select_mode': 'single'
  });

  wpbc_cal_days_select__re_init(resource_id);
  wpbc_cal__re_init(resource_id);
} // ---------------------------------------------------------------------------------------------------------------------

/**
 * Set Multiple Days selection  - after page load
 *
 * @param resource_id		ID of booking resource
 */


function wpbc_cal_ready_days_select__multiple(resource_id) {
  // Re-define selection, only after page loaded with all init vars
  jQuery(document).ready(function () {
    // Wait 1 second, just to  be sure, that all init vars defined
    setTimeout(function () {
      wpbc_cal_days_select__multiple(resource_id);
    }, 1000);
  });
}
/**
 * Set Multiple Days selection
 * Can be run at any  time,  when  calendar defined - useful for console run.
 *
 * @param resource_id		ID of booking resource
 */


function wpbc_cal_days_select__multiple(resource_id) {
  _wpbc.calendar__set_parameters(resource_id, {
    'days_select_mode': 'multiple'
  });

  wpbc_cal_days_select__re_init(resource_id);
  wpbc_cal__re_init(resource_id);
} // ---------------------------------------------------------------------------------------------------------------------

/**
 * Set Fixed Days selection with  1 mouse click  - after page load
 *
 * @integer resource_id			- 1				   -- ID of booking resource (calendar) -
 * @integer days_number			- 3				   -- number of days to  select	-
 * @array week_days__start	- [-1] | [ 1, 5]   --  { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }
 */


function wpbc_cal_ready_days_select__fixed(resource_id, days_number) {
  var week_days__start = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [-1];
  // Re-define selection, only after page loaded with all init vars
  jQuery(document).ready(function () {
    // Wait 1 second, just to  be sure, that all init vars defined
    setTimeout(function () {
      wpbc_cal_days_select__fixed(resource_id, days_number, week_days__start);
    }, 1000);
  });
}
/**
 * Set Fixed Days selection with  1 mouse click
 * Can be run at any  time,  when  calendar defined - useful for console run.
 *
 * @integer resource_id			- 1				   -- ID of booking resource (calendar) -
 * @integer days_number			- 3				   -- number of days to  select	-
 * @array week_days__start	- [-1] | [ 1, 5]   --  { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }
 */


function wpbc_cal_days_select__fixed(resource_id, days_number) {
  var week_days__start = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [-1];

  _wpbc.calendar__set_parameters(resource_id, {
    'days_select_mode': 'fixed'
  });

  _wpbc.calendar__set_parameters(resource_id, {
    'fixed__days_num': parseInt(days_number)
  }); // Number of days selection with 1 mouse click


  _wpbc.calendar__set_parameters(resource_id, {
    'fixed__week_days__start': week_days__start
  }); // { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }


  wpbc_cal_days_select__re_init(resource_id);
  wpbc_cal__re_init(resource_id);
} // ---------------------------------------------------------------------------------------------------------------------

/**
 * Set Range Days selection  with  2 mouse clicks  - after page load
 *
 * @integer resource_id			- 1				   		-- ID of booking resource (calendar)
 * @integer days_min			- 7				   		-- Min number of days to select
 * @integer days_max			- 30			   		-- Max number of days to select
 * @array days_specific			- [] | [7,14,21,28]		-- Restriction for Specific number of days selection
 * @array week_days__start		- [-1] | [ 1, 5]   		--  { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }
 */


function wpbc_cal_ready_days_select__range(resource_id, days_min, days_max) {
  var days_specific = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
  var week_days__start = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [-1];
  // Re-define selection, only after page loaded with all init vars
  jQuery(document).ready(function () {
    // Wait 1 second, just to  be sure, that all init vars defined
    setTimeout(function () {
      wpbc_cal_days_select__range(resource_id, days_min, days_max, days_specific, week_days__start);
    }, 1000);
  });
}
/**
 * Set Range Days selection  with  2 mouse clicks
 * Can be run at any  time,  when  calendar defined - useful for console run.
 *
 * @integer resource_id			- 1				   		-- ID of booking resource (calendar)
 * @integer days_min			- 7				   		-- Min number of days to select
 * @integer days_max			- 30			   		-- Max number of days to select
 * @array days_specific			- [] | [7,14,21,28]		-- Restriction for Specific number of days selection
 * @array week_days__start		- [-1] | [ 1, 5]   		--  { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }
 */


function wpbc_cal_days_select__range(resource_id, days_min, days_max) {
  var days_specific = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
  var week_days__start = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [-1];

  _wpbc.calendar__set_parameters(resource_id, {
    'days_select_mode': 'dynamic'
  });

  _wpbc.calendar__set_param_value(resource_id, 'dynamic__days_min', parseInt(days_min)); // Min. Number of days selection with 2 mouse clicks


  _wpbc.calendar__set_param_value(resource_id, 'dynamic__days_max', parseInt(days_max)); // Max. Number of days selection with 2 mouse clicks


  _wpbc.calendar__set_param_value(resource_id, 'dynamic__days_specific', days_specific); // Example [5,7]


  _wpbc.calendar__set_param_value(resource_id, 'dynamic__week_days__start', week_days__start); // { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }


  wpbc_cal_days_select__re_init(resource_id);
  wpbc_cal__re_init(resource_id);
}
/**
 * ====================================================================================================================
 *	includes/__js/cal_ajx_load/wpbc_cal_ajx.js
 * ====================================================================================================================
 */
// ---------------------------------------------------------------------------------------------------------------------
//  A j a x    L o a d    C a l e n d a r    D a t a
// ---------------------------------------------------------------------------------------------------------------------


function wpbc_calendar__load_data__ajx(params) {
  //FixIn: 9.8.6.2
  wpbc_calendar__loading__start(params['resource_id']);

  if (wpbc_balancer__is_wait(params, 'wpbc_calendar__load_data__ajx')) {
    return false;
  } //FixIn: 9.8.6.2


  wpbc_calendar__blur__stop(params['resource_id']); // console.groupEnd(); console.time('resource_id_' + params['resource_id']);

  console.groupCollapsed('WPBC_AJX_CALENDAR_LOAD');
  console.log(' == Before Ajax Send - calendars_all__get() == ', _wpbc.calendars_all__get()); // Start Ajax

  jQuery.post(wpbc_global1.wpbc_ajaxurl, {
    action: 'WPBC_AJX_CALENDAR_LOAD',
    wpbc_ajx_user_id: _wpbc.get_secure_param('user_id'),
    nonce: _wpbc.get_secure_param('nonce'),
    wpbc_ajx_locale: _wpbc.get_secure_param('locale'),
    calendar_request_params: params // Usually like: { 'resource_id': 1, 'max_days_count': 365 }

  },
  /**
   * S u c c e s s
   *
   * @param response_data		-	its object returned from  Ajax - class-live-search.php
   * @param textStatus		-	'success'
   * @param jqXHR				-	Object
   */
  function (response_data, textStatus, jqXHR) {
    // console.timeEnd('resource_id_' + response_data['resource_id']);
    console.log(' == Response WPBC_AJX_CALENDAR_LOAD == ', response_data);
    console.groupEnd(); //FixIn: 9.8.6.2

    var ajx_post_data__resource_id = wpbc_get_resource_id__from_ajx_post_data_url(this.data);
    wpbc_balancer__completed(ajx_post_data__resource_id, 'wpbc_calendar__load_data__ajx'); // Probably Error

    if (_typeof(response_data) !== 'object' || response_data === null) {
      var jq_node = wpbc_get_calendar__jq_node__for_messages(this.data);
      var message_type = 'info';

      if ('' === response_data) {
        response_data = 'The server responds with an empty string. The server probably stopped working unexpectedly. <br>Please check your <strong>error.log</strong> in your server configuration for relative errors.';
        message_type = 'warning';
      } // Show Message


      wpbc_front_end__show_message(response_data, {
        'type': message_type,
        'show_here': {
          'jq_node': jq_node,
          'where': 'after'
        },
        'is_append': true,
        'style': 'text-align:left;',
        'delay': 0
      });
      return;
    } // Show Calendar


    wpbc_calendar__loading__stop(response_data['resource_id']); // -------------------------------------------------------------------------------------------------
    // Bookings - Dates

    _wpbc.bookings_in_calendar__set_dates(response_data['resource_id'], response_data['ajx_data']['dates']); // Bookings - Child or only single booking resource in dates


    _wpbc.booking__set_param_value(response_data['resource_id'], 'resources_id_arr__in_dates', response_data['ajx_data']['resources_id_arr__in_dates']); // Aggregate booking resources,  if any ?


    _wpbc.booking__set_param_value(response_data['resource_id'], 'aggregate_resource_id_arr', response_data['ajx_data']['aggregate_resource_id_arr']); // -------------------------------------------------------------------------------------------------
    // Update calendar


    wpbc_calendar__update_look(response_data['resource_id']);

    if ('undefined' !== typeof response_data['ajx_data']['ajx_after_action_message'] && '' != response_data['ajx_data']['ajx_after_action_message'].replace(/\n/g, "<br />")) {
      var jq_node = wpbc_get_calendar__jq_node__for_messages(this.data); // Show Message

      wpbc_front_end__show_message(response_data['ajx_data']['ajx_after_action_message'].replace(/\n/g, "<br />"), {
        'type': 'undefined' !== typeof response_data['ajx_data']['ajx_after_action_message_status'] ? response_data['ajx_data']['ajx_after_action_message_status'] : 'info',
        'show_here': {
          'jq_node': jq_node,
          'where': 'after'
        },
        'is_append': true,
        'style': 'text-align:left;',
        'delay': 10000
      });
    } //jQuery( '#ajax_respond' ).html( response_data );		// For ability to show response, add such DIV element to page

  }).fail(function (jqXHR, textStatus, errorThrown) {
    if (window.console && window.console.log) {
      console.log('Ajax_Error', jqXHR, textStatus, errorThrown);
    }

    var ajx_post_data__resource_id = wpbc_get_resource_id__from_ajx_post_data_url(this.data);
    wpbc_balancer__completed(ajx_post_data__resource_id, 'wpbc_calendar__load_data__ajx'); // Get Content of Error Message

    var error_message = '<strong>' + 'Error!' + '</strong> ' + errorThrown;

    if (jqXHR.status) {
      error_message += ' (<b>' + jqXHR.status + '</b>)';

      if (403 == jqXHR.status) {
        error_message += '<br> Probably nonce for this page has been expired. Please <a href="javascript:void(0)" onclick="javascript:location.reload();">reload the page</a>.';
        error_message += '<br> Otherwise, please check this <a style="font-weight: 600;" href="https://wpbookingcalendar.com/faq/request-do-not-pass-security-check/">troubleshooting instruction</a>.<br>';
      }
    }

    var message_show_delay = 3000;

    if (jqXHR.responseText) {
      error_message += ' ' + jqXHR.responseText;
      message_show_delay = 10;
    }

    error_message = error_message.replace(/\n/g, "<br />");
    var jq_node = wpbc_get_calendar__jq_node__for_messages(this.data);
    /**
     * If we make fast clicking on different pages,
     * then under calendar will show error message with  empty  text, because ajax was not received.
     * To  not show such warnings we are set delay  in 3 seconds.  var message_show_delay = 3000;
     */

    var closed_timer = setTimeout(function () {
      // Show Message
      wpbc_front_end__show_message(error_message, {
        'type': 'error',
        'show_here': {
          'jq_node': jq_node,
          'where': 'after'
        },
        'is_append': true,
        'style': 'text-align:left;',
        'css_class': 'wpbc_fe_message_alt',
        'delay': 0
      });
    }, parseInt(message_show_delay));
  }) // .done(   function ( data, textStatus, jqXHR ) {   if ( window.console && window.console.log ){ console.log( 'second success', data, textStatus, jqXHR ); }    })
  // .always( function ( data_jqXHR, textStatus, jqXHR_errorThrown ) {   if ( window.console && window.console.log ){ console.log( 'always finished', data_jqXHR, textStatus, jqXHR_errorThrown ); }     })
  ; // End Ajax
} // ---------------------------------------------------------------------------------------------------------------------
// Support
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Get Calendar jQuery node for showing messages during Ajax
 * This parameter:   calendar_request_params[resource_id]   parsed from this.data Ajax post  data
 *
 * @param ajx_post_data_url_params		 'action=WPBC_AJX_CALENDAR_LOAD...&calendar_request_params%5Bresource_id%5D=2&calendar_request_params%5Bbooking_hash%5D=&calendar_request_params'
 * @returns {string}	''#calendar_booking1'  |   '.booking_form_div' ...
 *
 * Example    var jq_node  = wpbc_get_calendar__jq_node__for_messages( this.data );
 */


function wpbc_get_calendar__jq_node__for_messages(ajx_post_data_url_params) {
  var jq_node = '.booking_form_div';
  var calendar_resource_id = wpbc_get_resource_id__from_ajx_post_data_url(ajx_post_data_url_params);

  if (calendar_resource_id > 0) {
    jq_node = '#calendar_booking' + calendar_resource_id;
  }

  return jq_node;
}
/**
 * Get resource ID from ajx post data url   usually  from  this.data  = 'action=WPBC_AJX_CALENDAR_LOAD...&calendar_request_params%5Bresource_id%5D=2&calendar_request_params%5Bbooking_hash%5D=&calendar_request_params'
 *
 * @param ajx_post_data_url_params		 'action=WPBC_AJX_CALENDAR_LOAD...&calendar_request_params%5Bresource_id%5D=2&calendar_request_params%5Bbooking_hash%5D=&calendar_request_params'
 * @returns {int}						 1 | 0  (if errror then  0)
 *
 * Example    var jq_node  = wpbc_get_calendar__jq_node__for_messages( this.data );
 */


function wpbc_get_resource_id__from_ajx_post_data_url(ajx_post_data_url_params) {
  // Get booking resource ID from Ajax Post Request  -> this.data = 'action=WPBC_AJX_CALENDAR_LOAD...&calendar_request_params%5Bresource_id%5D=2&calendar_request_params%5Bbooking_hash%5D=&calendar_request_params'
  var calendar_resource_id = wpbc_get_uri_param_by_name('calendar_request_params[resource_id]', ajx_post_data_url_params);

  if (null !== calendar_resource_id && '' !== calendar_resource_id) {
    calendar_resource_id = parseInt(calendar_resource_id);

    if (calendar_resource_id > 0) {
      return calendar_resource_id;
    }
  }

  return 0;
}
/**
 * Get parameter from URL  -  parse URL parameters,  like this: action=WPBC_AJX_CALENDAR_LOAD...&calendar_request_params%5Bresource_id%5D=2&calendar_request_params%5Bbooking_hash%5D=&calendar_request_params
 * @param name  parameter  name,  like 'calendar_request_params[resource_id]'
 * @param url	'parameter  string URL'
 * @returns {string|null}   parameter value
 *
 * Example: 		wpbc_get_uri_param_by_name( 'calendar_request_params[resource_id]', this.data );  -> '2'
 */


function wpbc_get_uri_param_by_name(name, url) {
  url = decodeURIComponent(url);
  name = name.replace(/[\[\]]/g, '\\$&');
  var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
      results = regex.exec(url);
  if (!results) return null;
  if (!results[2]) return '';
  return decodeURIComponent(results[2].replace(/\+/g, ' '));
} //TODO: remove vars:       bk_2clicks_mode_days_start, bk_1click_mode_days_start     date2approve   date_approved

/**
 * =====================================================================================================================
 *	includes/__js/front_end_messages/wpbc_fe_messages.js
 * =====================================================================================================================
 */
// ---------------------------------------------------------------------------------------------------------------------
// Show Messages at Front-Edn side
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Show message in content
 *
 * @param message				Message HTML
 * @param params = {
 *								'type'     : 'warning',							// 'error' | 'warning' | 'info' | 'success'
 *								'show_here' : {
 *													'jq_node' : '',				// any jQuery node definition
 *													'where'   : 'inside'		// 'inside' | 'before' | 'after' | 'right' | 'left'
 *											  },
 *								'is_append': true,								// Apply  only if 	'where'   : 'inside'
 *								'style'    : 'text-align:left;',				// styles, if needed
 *							    'css_class': '',								// For example can  be: 'wpbc_fe_message_alt'
 *								'delay'    : 0,									// how many microsecond to  show,  if 0  then  show forever
 *								'if_visible_not_show': false					// if true,  then do not show message,  if previos message was not hided (not apply if 'where'   : 'inside' )
 *				};
 * Examples:
 * 			var html_id = wpbc_front_end__show_message( 'You can test days selection in calendar', {} );
 *
 *			var notice_message_id = wpbc_front_end__show_message( message_verif_requred, { 'type': 'warning', 'delay': 10000, 'if_visible_not_show': true,
 *																  'show_here': {'where': 'right', 'jq_node': el,} } );
 *
 *			wpbc_front_end__show_message( response_data[ 'ajx_data' ][ 'ajx_after_action_message' ].replace( /\n/g, "<br />" ),
 *											{   'type'     : ( 'undefined' !== typeof( response_data[ 'ajx_data' ][ 'ajx_after_action_message_status' ] ) )
 *															  ? response_data[ 'ajx_data' ][ 'ajx_after_action_message_status' ] : 'info',
 *												'show_here': {'jq_node': jq_node, 'where': 'after'},
 *												'css_class':'wpbc_fe_message_alt',
 *												'delay'    : 10000
 *											} );
 *
 *
 * @returns string  - HTML ID		or 0 if not showing during this time.
 */


function wpbc_front_end__show_message(message) {
  var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var params_default = {
    'type': 'warning',
    // 'error' | 'warning' | 'info' | 'success'
    'show_here': {
      'jq_node': '',
      // any jQuery node definition
      'where': 'inside' // 'inside' | 'before' | 'after' | 'right' | 'left'

    },
    'is_append': true,
    // Apply  only if 	'where'   : 'inside'
    'style': 'text-align:left;',
    // styles, if needed
    'css_class': '',
    // For example can  be: 'wpbc_fe_message_alt'
    'delay': 0,
    // how many microsecond to  show,  if 0  then  show forever
    'if_visible_not_show': false,
    // if true,  then do not show message,  if previos message was not hided (not apply if 'where'   : 'inside' )
    'is_scroll': true // is scroll  to  this element

  };

  for (var p_key in params) {
    params_default[p_key] = params[p_key];
  }

  params = params_default;
  var unique_div_id = new Date();
  unique_div_id = 'wpbc_notice_' + unique_div_id.getTime();
  params['css_class'] += ' wpbc_fe_message';

  if (params['type'] == 'error') {
    params['css_class'] += ' wpbc_fe_message_error';
    message = '<i class="menu_icon icon-1x wpbc_icn_report_gmailerrorred"></i>' + message;
  }

  if (params['type'] == 'warning') {
    params['css_class'] += ' wpbc_fe_message_warning';
    message = '<i class="menu_icon icon-1x wpbc_icn_warning"></i>' + message;
  }

  if (params['type'] == 'info') {
    params['css_class'] += ' wpbc_fe_message_info';
  }

  if (params['type'] == 'success') {
    params['css_class'] += ' wpbc_fe_message_success';
    message = '<i class="menu_icon icon-1x wpbc_icn_done_outline"></i>' + message;
  }

  var scroll_to_element = '<div id="' + unique_div_id + '_scroll" style="display:none;"></div>';
  message = '<div id="' + unique_div_id + '" class="wpbc_front_end__message ' + params['css_class'] + '" style="' + params['style'] + '">' + message + '</div>';
  var jq_el_message = false;
  var is_show_message = true;

  if ('inside' === params['show_here']['where']) {
    if (params['is_append']) {
      jQuery(params['show_here']['jq_node']).append(scroll_to_element);
      jQuery(params['show_here']['jq_node']).append(message);
    } else {
      jQuery(params['show_here']['jq_node']).html(scroll_to_element + message);
    }
  } else if ('before' === params['show_here']['where']) {
    jq_el_message = jQuery(params['show_here']['jq_node']).siblings('[id^="wpbc_notice_"]');

    if (params['if_visible_not_show'] && jq_el_message.is(':visible')) {
      is_show_message = false;
      unique_div_id = jQuery(jq_el_message.get(0)).attr('id');
    }

    if (is_show_message) {
      jQuery(params['show_here']['jq_node']).before(scroll_to_element);
      jQuery(params['show_here']['jq_node']).before(message);
    }
  } else if ('after' === params['show_here']['where']) {
    jq_el_message = jQuery(params['show_here']['jq_node']).nextAll('[id^="wpbc_notice_"]');

    if (params['if_visible_not_show'] && jq_el_message.is(':visible')) {
      is_show_message = false;
      unique_div_id = jQuery(jq_el_message.get(0)).attr('id');
    }

    if (is_show_message) {
      jQuery(params['show_here']['jq_node']).before(scroll_to_element); // We need to  set  here before(for handy scroll)

      jQuery(params['show_here']['jq_node']).after(message);
    }
  } else if ('right' === params['show_here']['where']) {
    jq_el_message = jQuery(params['show_here']['jq_node']).nextAll('.wpbc_front_end__message_container_right').find('[id^="wpbc_notice_"]');

    if (params['if_visible_not_show'] && jq_el_message.is(':visible')) {
      is_show_message = false;
      unique_div_id = jQuery(jq_el_message.get(0)).attr('id');
    }

    if (is_show_message) {
      jQuery(params['show_here']['jq_node']).before(scroll_to_element); // We need to  set  here before(for handy scroll)

      jQuery(params['show_here']['jq_node']).after('<div class="wpbc_front_end__message_container_right">' + message + '</div>');
    }
  } else if ('left' === params['show_here']['where']) {
    jq_el_message = jQuery(params['show_here']['jq_node']).siblings('.wpbc_front_end__message_container_left').find('[id^="wpbc_notice_"]');

    if (params['if_visible_not_show'] && jq_el_message.is(':visible')) {
      is_show_message = false;
      unique_div_id = jQuery(jq_el_message.get(0)).attr('id');
    }

    if (is_show_message) {
      jQuery(params['show_here']['jq_node']).before(scroll_to_element); // We need to  set  here before(for handy scroll)

      jQuery(params['show_here']['jq_node']).before('<div class="wpbc_front_end__message_container_left">' + message + '</div>');
    }
  }

  if (is_show_message && parseInt(params['delay']) > 0) {
    var closed_timer = setTimeout(function () {
      jQuery('#' + unique_div_id).fadeOut(1500);
    }, parseInt(params['delay']));
    var closed_timer2 = setTimeout(function () {
      jQuery('#' + unique_div_id).trigger('hide');
    }, parseInt(params['delay']) + 1501);
  } // Check  if showed message in some hidden parent section and show it. But it must  be lower than '.wpbc_container'


  var parent_els = jQuery('#' + unique_div_id).parents().map(function () {
    if (!jQuery(this).is('visible') && jQuery('.wpbc_container').has(this)) {
      jQuery(this).show();
    }
  });

  if (params['is_scroll']) {
    wpbc_do_scroll('#' + unique_div_id + '_scroll');
  }

  return unique_div_id;
}
/**
 * Error message. 	Preset of parameters for real message function.
 *
 * @param el		- any jQuery node definition
 * @param message	- Message HTML
 * @returns string  - HTML ID		or 0 if not showing during this time.
 */


function wpbc_front_end__show_message__error(jq_node, message) {
  var notice_message_id = wpbc_front_end__show_message(message, {
    'type': 'error',
    'delay': 10000,
    'if_visible_not_show': true,
    'show_here': {
      'where': 'right',
      'jq_node': jq_node
    }
  });
  return notice_message_id;
}
/**
 * Error message UNDER element. 	Preset of parameters for real message function.
 *
 * @param el		- any jQuery node definition
 * @param message	- Message HTML
 * @returns string  - HTML ID		or 0 if not showing during this time.
 */


function wpbc_front_end__show_message__error_under_element(jq_node, message, message_delay) {
  if ('undefined' === typeof message_delay) {
    message_delay = 0;
  }

  var notice_message_id = wpbc_front_end__show_message(message, {
    'type': 'error',
    'delay': message_delay,
    'if_visible_not_show': true,
    'show_here': {
      'where': 'after',
      'jq_node': jq_node
    }
  });
  return notice_message_id;
}
/**
 * Error message UNDER element. 	Preset of parameters for real message function.
 *
 * @param el		- any jQuery node definition
 * @param message	- Message HTML
 * @returns string  - HTML ID		or 0 if not showing during this time.
 */


function wpbc_front_end__show_message__error_above_element(jq_node, message, message_delay) {
  if ('undefined' === typeof message_delay) {
    message_delay = 10000;
  }

  var notice_message_id = wpbc_front_end__show_message(message, {
    'type': 'error',
    'delay': message_delay,
    'if_visible_not_show': true,
    'show_here': {
      'where': 'before',
      'jq_node': jq_node
    }
  });
  return notice_message_id;
}
/**
 * Warning message. 	Preset of parameters for real message function.
 *
 * @param el		- any jQuery node definition
 * @param message	- Message HTML
 * @returns string  - HTML ID		or 0 if not showing during this time.
 */


function wpbc_front_end__show_message__warning(jq_node, message) {
  var notice_message_id = wpbc_front_end__show_message(message, {
    'type': 'warning',
    'delay': 10000,
    'if_visible_not_show': true,
    'show_here': {
      'where': 'right',
      'jq_node': jq_node
    }
  });
  return notice_message_id;
}
/**
 * Warning message UNDER element. 	Preset of parameters for real message function.
 *
 * @param el		- any jQuery node definition
 * @param message	- Message HTML
 * @returns string  - HTML ID		or 0 if not showing during this time.
 */


function wpbc_front_end__show_message__warning_under_element(jq_node, message) {
  var notice_message_id = wpbc_front_end__show_message(message, {
    'type': 'warning',
    'delay': 10000,
    'if_visible_not_show': true,
    'show_here': {
      'where': 'after',
      'jq_node': jq_node
    }
  });
  return notice_message_id;
}
/**
 * Warning message ABOVE element. 	Preset of parameters for real message function.
 *
 * @param el		- any jQuery node definition
 * @param message	- Message HTML
 * @returns string  - HTML ID		or 0 if not showing during this time.
 */


function wpbc_front_end__show_message__warning_above_element(jq_node, message) {
  var notice_message_id = wpbc_front_end__show_message(message, {
    'type': 'warning',
    'delay': 10000,
    'if_visible_not_show': true,
    'show_here': {
      'where': 'before',
      'jq_node': jq_node
    }
  });
  return notice_message_id;
}
/**
 * Scroll to specific element
 *
 * @param jq_node					string or jQuery element,  where scroll  to
 * @param extra_shift_offset		int shift offset from  jq_node
 */


function wpbc_do_scroll(jq_node) {
  var extra_shift_offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

  if (!jQuery(jq_node).length) {
    return;
  }

  var targetOffset = jQuery(jq_node).offset().top;

  if (targetOffset <= 0) {
    if (0 != jQuery(jq_node).nextAll(':visible').length) {
      targetOffset = jQuery(jq_node).nextAll(':visible').first().offset().top;
    } else if (0 != jQuery(jq_node).parent().nextAll(':visible').length) {
      targetOffset = jQuery(jq_node).parent().nextAll(':visible').first().offset().top;
    }
  }

  if (jQuery('#wpadminbar').length > 0) {
    targetOffset = targetOffset - 50 - 50;
  } else {
    targetOffset = targetOffset - 20 - 50;
  }

  targetOffset += extra_shift_offset; // Scroll only  if we did not scroll before

  if (!jQuery('html,body').is(':animated')) {
    jQuery('html,body').animate({
      scrollTop: targetOffset
    }, 500);
  }
}
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndwYmMuanMiLCJhanhfbG9hZF9iYWxhbmNlci5qcyIsIndwYmNfY2FsLmpzIiwiZGF5c19zZWxlY3RfY3VzdG9tLmpzIiwid3BiY19jYWxfYWp4LmpzIiwid3BiY19mZV9tZXNzYWdlcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBQ0EsU0FBQSxjQUFBLENBQUEsR0FBQSxFQUFBO0FBRUEsU0FBQSxJQUFBLENBQUEsS0FBQSxDQUFBLElBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxDQUFBLENBQUE7QUFDQTtBQUlBO0FBQ0E7QUFDQTs7O0FBRUEsSUFBQSxLQUFBLEdBQUEsVUFBQSxHQUFBLEVBQUEsQ0FBQSxFQUFBO0FBRUE7QUFDQSxNQUFBLFFBQUEsR0FBQSxHQUFBLENBQUEsWUFBQSxHQUFBLEdBQUEsQ0FBQSxZQUFBLElBQUE7QUFDQSxJQUFBLE9BQUEsRUFBQSxDQURBO0FBRUEsSUFBQSxLQUFBLEVBQUEsRUFGQTtBQUdBLElBQUEsTUFBQSxFQUFBO0FBSEEsR0FBQTs7QUFLQSxFQUFBLEdBQUEsQ0FBQSxnQkFBQSxHQUFBLFVBQUEsU0FBQSxFQUFBLFNBQUEsRUFBQTtBQUNBLElBQUEsUUFBQSxDQUFBLFNBQUEsQ0FBQSxHQUFBLFNBQUE7QUFDQSxHQUZBOztBQUlBLEVBQUEsR0FBQSxDQUFBLGdCQUFBLEdBQUEsVUFBQSxTQUFBLEVBQUE7QUFDQSxXQUFBLFFBQUEsQ0FBQSxTQUFBLENBQUE7QUFDQSxHQUZBLENBWkEsQ0FpQkE7OztBQUNBLE1BQUEsV0FBQSxHQUFBLEdBQUEsQ0FBQSxhQUFBLEdBQUEsR0FBQSxDQUFBLGFBQUEsSUFBQSxDQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUEEsR0FBQTtBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxvQkFBQSxHQUFBLFVBQUEsV0FBQSxFQUFBO0FBRUEsV0FBQSxnQkFBQSxPQUFBLFdBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQTtBQUNBLEdBSEE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxjQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUE7QUFFQSxJQUFBLFdBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxHQUFBLEVBQUE7QUFDQSxJQUFBLFdBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxDQUFBLElBQUEsSUFBQSxXQUFBO0FBQ0EsSUFBQSxXQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSx5QkFBQSxJQUFBLEtBQUE7QUFFQSxHQU5BO0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxrQkFBQSxHQUFBLFVBQUEsYUFBQSxFQUFBO0FBQ0EsSUFBQSxXQUFBLEdBQUEsYUFBQTtBQUNBLEdBRkE7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxrQkFBQSxHQUFBLFlBQUE7QUFDQSxXQUFBLFdBQUE7QUFDQSxHQUZBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSx3QkFBQSxHQUFBLFVBQUEsV0FBQSxFQUFBO0FBRUEsUUFBQSxHQUFBLENBQUEsb0JBQUEsQ0FBQSxXQUFBLENBQUEsRUFBQTtBQUVBLGFBQUEsV0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBO0FBQ0EsS0FIQSxNQUdBO0FBQ0EsYUFBQSxLQUFBO0FBQ0E7QUFDQSxHQVJBO0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLHdCQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUEscUJBQUEsRUFBQTtBQUFBLFFBQUEscUJBQUEsdUVBQUEsS0FBQTs7QUFFQSxRQUFBLENBQUEsR0FBQSxDQUFBLG9CQUFBLENBQUEsV0FBQSxDQUFBLElBQUEsU0FBQSxxQkFBQSxFQUFBO0FBQ0EsTUFBQSxHQUFBLENBQUEsY0FBQSxDQUFBLFdBQUE7QUFDQTs7QUFFQSxTQUFBLElBQUEsU0FBQSxJQUFBLHFCQUFBLEVBQUE7QUFFQSxNQUFBLFdBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsSUFBQSxxQkFBQSxDQUFBLFNBQUEsQ0FBQTtBQUNBOztBQUVBLFdBQUEsV0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBO0FBQ0EsR0FaQTtBQWNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSx5QkFBQSxHQUFBLFVBQUEsV0FBQSxFQUFBLFNBQUEsRUFBQSxVQUFBLEVBQUE7QUFFQSxRQUFBLENBQUEsR0FBQSxDQUFBLG9CQUFBLENBQUEsV0FBQSxDQUFBLEVBQUE7QUFDQSxNQUFBLEdBQUEsQ0FBQSxjQUFBLENBQUEsV0FBQTtBQUNBOztBQUVBLElBQUEsV0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxJQUFBLFVBQUE7QUFFQSxXQUFBLFdBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQTtBQUNBLEdBVEE7QUFXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsRUFBQSxHQUFBLENBQUEseUJBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQSxTQUFBLEVBQUE7QUFFQSxRQUNBLEdBQUEsQ0FBQSxvQkFBQSxDQUFBLFdBQUEsQ0FBQSxJQUNBLGdCQUFBLE9BQUEsV0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxDQUZBLEVBR0E7QUFDQSxhQUFBLFdBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsQ0FBQTtBQUNBOztBQUVBLFdBQUEsSUFBQSxDQVRBLENBU0E7QUFDQSxHQVZBLENBOUlBLENBeUpBO0FBR0E7OztBQUNBLE1BQUEsVUFBQSxHQUFBLEdBQUEsQ0FBQSxZQUFBLEdBQUEsR0FBQSxDQUFBLFlBQUEsSUFBQSxDQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkEsR0FBQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxnQ0FBQSxHQUFBLFVBQUEsV0FBQSxFQUFBO0FBRUEsV0FBQSxnQkFBQSxPQUFBLFVBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQTtBQUNBLEdBSEE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLHlCQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUE7QUFFQSxRQUFBLEdBQUEsQ0FBQSxnQ0FBQSxDQUFBLFdBQUEsQ0FBQSxFQUFBO0FBRUEsYUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUE7QUFDQSxLQUhBLE1BR0E7QUFDQSxhQUFBLEtBQUE7QUFDQTtBQUNBLEdBUkE7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLHlCQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUEsWUFBQSxFQUFBO0FBRUEsUUFBQSxDQUFBLEdBQUEsQ0FBQSxnQ0FBQSxDQUFBLFdBQUEsQ0FBQSxFQUFBO0FBQ0EsTUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsR0FBQSxFQUFBO0FBQ0EsTUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxJQUFBLElBQUEsV0FBQTtBQUNBOztBQUVBLFNBQUEsSUFBQSxTQUFBLElBQUEsWUFBQSxFQUFBO0FBRUEsTUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxTQUFBLElBQUEsWUFBQSxDQUFBLFNBQUEsQ0FBQTtBQUNBOztBQUVBLFdBQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBO0FBQ0EsR0FiQSxDQTlNQSxDQTZOQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSwrQkFBQSxHQUFBLFVBQUEsV0FBQSxFQUFBO0FBRUEsUUFDQSxHQUFBLENBQUEsZ0NBQUEsQ0FBQSxXQUFBLENBQUEsSUFDQSxnQkFBQSxPQUFBLFVBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxDQUFBLE9BQUEsQ0FGQSxFQUdBO0FBQ0EsYUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxPQUFBLENBQUE7QUFDQTs7QUFFQSxXQUFBLEtBQUEsQ0FUQSxDQVNBO0FBQ0EsR0FWQTtBQVlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSwrQkFBQSxHQUFBLFVBQUEsV0FBQSxFQUFBLFNBQUEsRUFBQTtBQUFBLFFBQUEscUJBQUEsdUVBQUEsSUFBQTs7QUFFQSxRQUFBLENBQUEsR0FBQSxDQUFBLGdDQUFBLENBQUEsV0FBQSxDQUFBLEVBQUE7QUFDQSxNQUFBLEdBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQTtBQUFBLGlCQUFBO0FBQUEsT0FBQTtBQUNBOztBQUVBLFFBQUEsZ0JBQUEsT0FBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxPQUFBLENBQUEsRUFBQTtBQUNBLE1BQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsT0FBQSxJQUFBLEVBQUE7QUFDQTs7QUFFQSxRQUFBLHFCQUFBLEVBQUE7QUFFQTtBQUNBLE1BQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsT0FBQSxJQUFBLFNBQUE7QUFDQSxLQUpBLE1BSUE7QUFFQTtBQUNBLFdBQUEsSUFBQSxTQUFBLElBQUEsU0FBQSxFQUFBO0FBRUEsUUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxPQUFBLEVBQUEsU0FBQSxJQUFBLFNBQUEsQ0FBQSxTQUFBLENBQUE7QUFDQTtBQUNBOztBQUVBLFdBQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBO0FBQ0EsR0F4QkE7QUEyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsRUFBQSxHQUFBLENBQUEsa0NBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQSxhQUFBLEVBQUE7QUFFQSxRQUNBLEdBQUEsQ0FBQSxnQ0FBQSxDQUFBLFdBQUEsQ0FBQSxJQUNBLGdCQUFBLE9BQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsT0FBQSxDQURBLElBRUEsZ0JBQUEsT0FBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxPQUFBLEVBQUEsYUFBQSxDQUhBLEVBSUE7QUFDQSxhQUFBLFVBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxDQUFBLE9BQUEsRUFBQSxhQUFBLENBQUE7QUFDQTs7QUFFQSxXQUFBLEtBQUEsQ0FWQSxDQVVBO0FBQ0EsR0FYQSxDQWxUQSxDQWdVQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsRUFBQSxHQUFBLENBQUEsd0JBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQSxTQUFBLEVBQUEsVUFBQSxFQUFBO0FBRUEsUUFBQSxDQUFBLEdBQUEsQ0FBQSxnQ0FBQSxDQUFBLFdBQUEsQ0FBQSxFQUFBO0FBQ0EsTUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsR0FBQSxFQUFBO0FBQ0EsTUFBQSxVQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxJQUFBLElBQUEsV0FBQTtBQUNBOztBQUVBLElBQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxJQUFBLFVBQUE7QUFFQSxXQUFBLFVBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQTtBQUNBLEdBVkE7QUFZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsRUFBQSxHQUFBLENBQUEsd0JBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQSxTQUFBLEVBQUE7QUFFQSxRQUNBLEdBQUEsQ0FBQSxnQ0FBQSxDQUFBLFdBQUEsQ0FBQSxJQUNBLGdCQUFBLE9BQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxDQUZBLEVBR0E7QUFDQSxhQUFBLFVBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsQ0FBQTtBQUNBOztBQUVBLFdBQUEsSUFBQSxDQVRBLENBU0E7QUFDQSxHQVZBO0FBZUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSw4QkFBQSxHQUFBLFVBQUEsYUFBQSxFQUFBO0FBQ0EsSUFBQSxVQUFBLEdBQUEsYUFBQTtBQUNBLEdBRkE7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSw4QkFBQSxHQUFBLFlBQUE7QUFDQSxXQUFBLFVBQUE7QUFDQSxHQUZBLENBMVhBLENBNlhBO0FBS0E7OztBQUNBLE1BQUEsU0FBQSxHQUFBLEdBQUEsQ0FBQSxXQUFBLEdBQUEsR0FBQSxDQUFBLFdBQUEsSUFBQSxDQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkEsR0FBQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxZQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUEsU0FBQSxFQUFBO0FBQUEsUUFBQSxxQkFBQSx1RUFBQSxLQUFBOztBQUVBLFFBQUEsZ0JBQUEsT0FBQSxTQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsRUFBQTtBQUNBLE1BQUEsU0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLEdBQUEsRUFBQTtBQUNBOztBQUVBLFFBQUEscUJBQUEsRUFBQTtBQUVBO0FBQ0EsTUFBQSxTQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsR0FBQSxTQUFBO0FBRUEsS0FMQSxNQUtBO0FBRUE7QUFDQSxXQUFBLElBQUEsU0FBQSxJQUFBLFNBQUEsRUFBQTtBQUVBLFlBQUEsZ0JBQUEsT0FBQSxTQUFBLENBQUEsY0FBQSxXQUFBLENBQUEsQ0FBQSxTQUFBLENBQUEsRUFBQTtBQUNBLFVBQUEsU0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxJQUFBLEVBQUE7QUFDQTs7QUFDQSxhQUFBLElBQUEsZUFBQSxJQUFBLFNBQUEsQ0FBQSxTQUFBLENBQUEsRUFBQTtBQUNBLFVBQUEsU0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxFQUFBLElBQUEsQ0FBQSxTQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsZUFBQSxDQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFdBQUEsU0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBO0FBQ0EsR0ExQkE7QUE2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLHFCQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUEsYUFBQSxFQUFBO0FBRUEsUUFDQSxnQkFBQSxPQUFBLFNBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxJQUNBLGdCQUFBLE9BQUEsU0FBQSxDQUFBLGNBQUEsV0FBQSxDQUFBLENBQUEsYUFBQSxDQUZBLEVBR0E7QUFDQSxhQUFBLFNBQUEsQ0FBQSxjQUFBLFdBQUEsQ0FBQSxDQUFBLGFBQUEsQ0FBQTtBQUNBOztBQUVBLFdBQUEsRUFBQSxDQVRBLENBU0E7QUFDQSxHQVZBLENBMWJBLENBdWNBOzs7QUFDQSxNQUFBLE9BQUEsR0FBQSxHQUFBLENBQUEsU0FBQSxHQUFBLEdBQUEsQ0FBQSxTQUFBLElBQUEsRUFBQTs7QUFFQSxFQUFBLEdBQUEsQ0FBQSxlQUFBLEdBQUEsVUFBQSxTQUFBLEVBQUEsU0FBQSxFQUFBO0FBQ0EsSUFBQSxPQUFBLENBQUEsU0FBQSxDQUFBLEdBQUEsU0FBQTtBQUNBLEdBRkE7O0FBSUEsRUFBQSxHQUFBLENBQUEsZUFBQSxHQUFBLFVBQUEsU0FBQSxFQUFBO0FBQ0EsV0FBQSxPQUFBLENBQUEsU0FBQSxDQUFBO0FBQ0EsR0FGQSxDQTljQSxDQWlkQTs7O0FBR0EsU0FBQSxHQUFBO0FBRUEsQ0F0ZEEsQ0FzZEEsS0FBQSxJQUFBLEVBdGRBLEVBc2RBLE1BdGRBLENBQUE7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxLQUFBLEdBQUEsVUFBQSxHQUFBLEVBQUEsQ0FBQSxFQUFBO0FBRUE7QUFFQSxNQUFBLFVBQUEsR0FBQSxHQUFBLENBQUEsWUFBQSxHQUFBLEdBQUEsQ0FBQSxZQUFBLElBQUE7QUFDQSxtQkFBQSxDQURBO0FBRUEsa0JBQUEsRUFGQTtBQUdBLFlBQUE7QUFIQSxHQUFBO0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDQSxFQUFBLEdBQUEsQ0FBQSx5QkFBQSxHQUFBLFVBQUEsV0FBQSxFQUFBO0FBRUEsSUFBQSxVQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsV0FBQTtBQUNBLEdBSEE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLG9CQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUE7QUFFQSxXQUFBLGdCQUFBLE9BQUEsVUFBQSxDQUFBLGNBQUEsV0FBQSxDQUFBO0FBQ0EsR0FIQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLGNBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQSxhQUFBLEVBQUE7QUFBQSxRQUFBLE1BQUEsdUVBQUEsRUFBQTtBQUVBLFFBQUEsV0FBQSxHQUFBLEVBQUE7QUFDQSxJQUFBLFdBQUEsQ0FBQSxhQUFBLENBQUEsR0FBQSxXQUFBO0FBQ0EsSUFBQSxXQUFBLENBQUEsVUFBQSxDQUFBLEdBQUEsQ0FBQTtBQUNBLElBQUEsV0FBQSxDQUFBLGVBQUEsQ0FBQSxHQUFBLGFBQUE7QUFDQSxJQUFBLFdBQUEsQ0FBQSxRQUFBLENBQUEsR0FBQSxjQUFBLENBQUEsTUFBQSxDQUFBOztBQUdBLFFBQUEsR0FBQSxDQUFBLHdCQUFBLENBQUEsV0FBQSxFQUFBLGFBQUEsQ0FBQSxFQUFBO0FBQ0EsYUFBQSxLQUFBO0FBQ0E7O0FBQ0EsUUFBQSxHQUFBLENBQUEseUJBQUEsQ0FBQSxXQUFBLEVBQUEsYUFBQSxDQUFBLEVBQUE7QUFDQSxhQUFBLE1BQUE7QUFDQTs7QUFHQSxRQUFBLEdBQUEsQ0FBQSxtQkFBQSxFQUFBLEVBQUE7QUFDQSxNQUFBLEdBQUEsQ0FBQSxxQkFBQSxDQUFBLFdBQUE7QUFDQSxhQUFBLEtBQUE7QUFDQSxLQUhBLE1BR0E7QUFDQSxNQUFBLEdBQUEsQ0FBQSxzQkFBQSxDQUFBLFdBQUE7QUFDQSxhQUFBLE1BQUE7QUFDQTtBQUNBLEdBeEJBO0FBMEJBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxtQkFBQSxHQUFBLFlBQUE7QUFDQSxXQUFBLFVBQUEsQ0FBQSxZQUFBLENBQUEsQ0FBQSxNQUFBLEdBQUEsVUFBQSxDQUFBLGFBQUEsQ0FBQTtBQUNBLEdBRkE7QUFJQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsRUFBQSxHQUFBLENBQUEsc0JBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQTtBQUNBLElBQUEsVUFBQSxDQUFBLE1BQUEsQ0FBQSxDQUFBLElBQUEsQ0FBQSxXQUFBO0FBQ0EsR0FGQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSxnQ0FBQSxHQUFBLFVBQUEsV0FBQSxFQUFBLGFBQUEsRUFBQTtBQUVBLFFBQUEsVUFBQSxHQUFBLEtBQUE7O0FBRUEsUUFBQSxVQUFBLENBQUEsTUFBQSxDQUFBLENBQUEsTUFBQSxFQUFBO0FBQUE7QUFDQSxXQUFBLElBQUEsQ0FBQSxJQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsRUFBQTtBQUNBLFlBQ0EsV0FBQSxLQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUEsYUFBQSxDQUFBLElBQ0EsYUFBQSxLQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUEsZUFBQSxDQUZBLEVBR0E7QUFDQSxVQUFBLFVBQUEsR0FBQSxVQUFBLENBQUEsTUFBQSxDQUFBLENBQUEsTUFBQSxDQUFBLENBQUEsRUFBQSxDQUFBLENBQUE7QUFDQSxVQUFBLFVBQUEsR0FBQSxVQUFBLENBQUEsR0FBQSxFQUFBO0FBQ0EsVUFBQSxVQUFBLENBQUEsTUFBQSxDQUFBLEdBQUEsVUFBQSxDQUFBLE1BQUEsQ0FBQSxDQUFBLE1BQUEsQ0FBQSxVQUFBLENBQUEsRUFBQTtBQUNBLG1CQUFBLENBQUE7QUFDQSxXQUZBLENBQUEsQ0FIQSxDQUtBOztBQUNBLGlCQUFBLFVBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBQ0EsV0FBQSxVQUFBO0FBQ0EsR0FwQkE7QUFzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLHlCQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUEsYUFBQSxFQUFBO0FBRUEsUUFBQSxVQUFBLENBQUEsTUFBQSxDQUFBLENBQUEsTUFBQSxFQUFBO0FBQUE7QUFDQSxXQUFBLElBQUEsQ0FBQSxJQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsRUFBQTtBQUNBLFlBQ0EsV0FBQSxLQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUEsYUFBQSxDQUFBLElBQ0EsYUFBQSxLQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUEsZUFBQSxDQUZBLEVBR0E7QUFDQSxpQkFBQSxJQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUNBLFdBQUEsS0FBQTtBQUNBLEdBYkE7QUFnQkE7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLHFCQUFBLEdBQUEsVUFBQSxXQUFBLEVBQUE7QUFDQSxJQUFBLFVBQUEsQ0FBQSxZQUFBLENBQUEsQ0FBQSxJQUFBLENBQUEsV0FBQTtBQUNBLEdBRkE7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsRUFBQSxHQUFBLENBQUEsK0JBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQSxhQUFBLEVBQUE7QUFFQSxRQUFBLFVBQUEsR0FBQSxLQUFBOztBQUVBLFFBQUEsVUFBQSxDQUFBLFlBQUEsQ0FBQSxDQUFBLE1BQUEsRUFBQTtBQUFBO0FBQ0EsV0FBQSxJQUFBLENBQUEsSUFBQSxVQUFBLENBQUEsWUFBQSxDQUFBLEVBQUE7QUFDQSxZQUNBLFdBQUEsS0FBQSxVQUFBLENBQUEsWUFBQSxDQUFBLENBQUEsQ0FBQSxFQUFBLGFBQUEsQ0FBQSxJQUNBLGFBQUEsS0FBQSxVQUFBLENBQUEsWUFBQSxDQUFBLENBQUEsQ0FBQSxFQUFBLGVBQUEsQ0FGQSxFQUdBO0FBQ0EsVUFBQSxVQUFBLEdBQUEsVUFBQSxDQUFBLFlBQUEsQ0FBQSxDQUFBLE1BQUEsQ0FBQSxDQUFBLEVBQUEsQ0FBQSxDQUFBO0FBQ0EsVUFBQSxVQUFBLEdBQUEsVUFBQSxDQUFBLEdBQUEsRUFBQTtBQUNBLFVBQUEsVUFBQSxDQUFBLFlBQUEsQ0FBQSxHQUFBLFVBQUEsQ0FBQSxZQUFBLENBQUEsQ0FBQSxNQUFBLENBQUEsVUFBQSxDQUFBLEVBQUE7QUFDQSxtQkFBQSxDQUFBO0FBQ0EsV0FGQSxDQUFBLENBSEEsQ0FLQTs7QUFDQSxpQkFBQSxVQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUNBLFdBQUEsVUFBQTtBQUNBLEdBcEJBO0FBc0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxFQUFBLEdBQUEsQ0FBQSx3QkFBQSxHQUFBLFVBQUEsV0FBQSxFQUFBLGFBQUEsRUFBQTtBQUVBLFFBQUEsVUFBQSxDQUFBLFlBQUEsQ0FBQSxDQUFBLE1BQUEsRUFBQTtBQUFBO0FBQ0EsV0FBQSxJQUFBLENBQUEsSUFBQSxVQUFBLENBQUEsWUFBQSxDQUFBLEVBQUE7QUFDQSxZQUNBLFdBQUEsS0FBQSxVQUFBLENBQUEsWUFBQSxDQUFBLENBQUEsQ0FBQSxFQUFBLGFBQUEsQ0FBQSxJQUNBLGFBQUEsS0FBQSxVQUFBLENBQUEsWUFBQSxDQUFBLENBQUEsQ0FBQSxFQUFBLGVBQUEsQ0FGQSxFQUdBO0FBQ0EsaUJBQUEsSUFBQTtBQUNBO0FBQ0E7QUFDQTs7QUFDQSxXQUFBLEtBQUE7QUFDQSxHQWJBOztBQWlCQSxFQUFBLEdBQUEsQ0FBQSxrQkFBQSxHQUFBLFlBQUE7QUFFQTtBQUNBLFFBQUEsVUFBQSxHQUFBLEtBQUE7O0FBQ0EsUUFBQSxVQUFBLENBQUEsTUFBQSxDQUFBLENBQUEsTUFBQSxFQUFBO0FBQUE7QUFDQSxXQUFBLElBQUEsQ0FBQSxJQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsRUFBQTtBQUNBLFFBQUEsVUFBQSxHQUFBLEdBQUEsQ0FBQSxnQ0FBQSxDQUFBLFVBQUEsQ0FBQSxNQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUEsYUFBQSxDQUFBLEVBQUEsVUFBQSxDQUFBLE1BQUEsQ0FBQSxDQUFBLENBQUEsRUFBQSxlQUFBLENBQUEsQ0FBQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFBLFVBQUEsVUFBQSxFQUFBO0FBRUE7QUFDQSxNQUFBLEdBQUEsQ0FBQSxhQUFBLENBQUEsVUFBQTtBQUNBO0FBQ0EsR0FoQkE7QUFrQkE7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLEVBQUEsR0FBQSxDQUFBLGFBQUEsR0FBQSxVQUFBLFdBQUEsRUFBQTtBQUVBLFlBQUEsV0FBQSxDQUFBLGVBQUEsQ0FBQTtBQUVBLFdBQUEsK0JBQUE7QUFFQTtBQUNBLFFBQUEsR0FBQSxDQUFBLHFCQUFBLENBQUEsV0FBQTtBQUVBLFFBQUEsNkJBQUEsQ0FBQSxXQUFBLENBQUEsUUFBQSxDQUFBLENBQUE7QUFDQTs7QUFFQTtBQVZBO0FBWUEsR0FkQTs7QUFnQkEsU0FBQSxHQUFBO0FBRUEsQ0F4T0EsQ0F3T0EsS0FBQSxJQUFBLEVBeE9BLEVBd09BLE1BeE9BLENBQUE7QUEyT0E7QUFDQTtBQUNBOzs7QUFFQSxTQUFBLHNCQUFBLENBQUEsTUFBQSxFQUFBLGFBQUEsRUFBQTtBQUNBO0FBQ0EsTUFBQSxnQkFBQSxPQUFBLE1BQUEsQ0FBQSxhQUFBLENBQUEsRUFBQTtBQUVBLFFBQUEsZUFBQSxHQUFBLEtBQUEsQ0FBQSxjQUFBLENBQUEsTUFBQSxDQUFBLGFBQUEsQ0FBQSxFQUFBLGFBQUEsRUFBQSxNQUFBLENBQUE7O0FBRUEsV0FBQSxXQUFBLGVBQUE7QUFDQTs7QUFFQSxTQUFBLEtBQUE7QUFDQTs7QUFHQSxTQUFBLHdCQUFBLENBQUEsV0FBQSxFQUFBLGFBQUEsRUFBQTtBQUNBO0FBQ0EsRUFBQSxLQUFBLENBQUEsK0JBQUEsQ0FBQSxXQUFBLEVBQUEsYUFBQTs7QUFDQSxFQUFBLEtBQUEsQ0FBQSxrQkFBQTtBQUNBO0FDdFFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQTtBQUNBO0FBQ0E7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLGtCQUFBLENBQUEsV0FBQSxFQUFBO0FBRUE7QUFDQSxNQUFBLE1BQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLE1BQUEsRUFBQTtBQUFBLFdBQUEsS0FBQTtBQUFBLEdBSEEsQ0FLQTs7O0FBQ0EsTUFBQSxTQUFBLE1BQUEsQ0FBQSxzQkFBQSxXQUFBLENBQUEsQ0FBQSxRQUFBLENBQUEsYUFBQSxDQUFBLEVBQUE7QUFBQSxXQUFBLEtBQUE7QUFBQSxHQU5BLENBUUE7QUFDQTtBQUNBOzs7QUFDQSxNQUFBLHNCQUFBLEdBQUEsS0FBQTtBQUNBLE1BQUEsNEJBQUEsR0FBQSxHQUFBLENBWkEsQ0FZQTs7QUFDQSxNQUFBLGNBQUEsS0FBQSxDQUFBLHlCQUFBLENBQUEsV0FBQSxFQUFBLGtCQUFBLENBQUEsRUFBQTtBQUNBLElBQUEsc0JBQUEsR0FBQSxJQUFBO0FBQ0EsSUFBQSw0QkFBQSxHQUFBLENBQUE7QUFDQTs7QUFDQSxNQUFBLGFBQUEsS0FBQSxDQUFBLHlCQUFBLENBQUEsV0FBQSxFQUFBLGtCQUFBLENBQUEsRUFBQTtBQUNBLElBQUEsNEJBQUEsR0FBQSxDQUFBO0FBQ0EsR0FuQkEsQ0FxQkE7QUFDQTtBQUNBOzs7QUFDQSxNQUFBLGVBQUEsR0FBQSxDQUFBOztBQUNBLE1BQUEsZUFBQSxHQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSxpQ0FBQSxDQUFBLENBekJBLENBMEJBO0FBRUE7QUFDQTs7O0FBQ0EsTUFBQSxxQkFBQSxHQUFBLE1BQUEsQ0FBQSxRQUFBLENBQUEsY0FBQSxDQUFBLElBQUEsRUFBQSxlQUFBLEVBQUEsSUFBQSxJQUFBLEVBQUEsQ0FBQTs7QUFDQSxFQUFBLHFCQUFBLEdBQUEsSUFBQSxJQUFBLENBQUEscUJBQUEsQ0FBQSxXQUFBLEVBQUEsRUFBQSxxQkFBQSxDQUFBLFFBQUEsS0FBQSxDQUFBLEVBQUEsQ0FBQSxDQUFBO0FBQ0EsRUFBQSxlQUFBLEdBQUEscUJBQUE7O0FBRUEsTUFBQSxRQUFBLENBQUEsSUFBQSxDQUFBLE9BQUEsQ0FBQSxlQUFBLEtBQUEsQ0FBQSxDQUFBLElBQ0EsUUFBQSxDQUFBLElBQUEsQ0FBQSxPQUFBLENBQUEsY0FBQSxLQUFBLENBQUEsQ0FEQSxDQUNBO0FBREEsSUFFQTtBQUNBLElBQUEsZUFBQSxHQUFBLElBQUE7QUFDQSxJQUFBLGVBQUEsR0FBQSxJQUFBO0FBQ0E7O0FBRUEsTUFBQSxvQkFBQSxHQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSx5QkFBQSxDQUFBOztBQUNBLE1BQUEsdUJBQUEsR0FBQSxRQUFBLENBQUEsS0FBQSxDQUFBLHlCQUFBLENBQUEsV0FBQSxFQUFBLDJCQUFBLENBQUEsQ0FBQTtBQUVBLEVBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLElBQUEsQ0FBQSxFQUFBLEVBNUNBLENBNENBO0FBQ0E7QUFDQTtBQUNBOztBQUNBLEVBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLFFBQUEsQ0FDQTtBQUNBLElBQUEsYUFBQSxFQUFBLHVCQUFBLE9BQUEsRUFBQTtBQUNBLGFBQUEsaUNBQUEsQ0FBQSxPQUFBLEVBQUE7QUFBQSx1QkFBQTtBQUFBLE9BQUEsRUFBQSxJQUFBLENBQUE7QUFDQSxLQUhBO0FBSUEsSUFBQSxRQUFBLEVBQUEsa0JBQUEsWUFBQSxFQUFBLFlBQUEsRUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBQSw4QkFBQSxDQUFBLFlBQUEsRUFBQTtBQUFBLHVCQUFBO0FBQUEsT0FBQSxFQUFBLElBQUEsQ0FBQTtBQUNBLEtBVEE7QUFVQSxJQUFBLE9BQUEsRUFBQSxpQkFBQSxXQUFBLEVBQUEsT0FBQSxFQUFBO0FBQ0EsYUFBQSw2QkFBQSxDQUFBLFdBQUEsRUFBQSxPQUFBLEVBQUE7QUFBQSx1QkFBQTtBQUFBLE9BQUEsRUFBQSxJQUFBLENBQUE7QUFDQSxLQVpBO0FBYUEsSUFBQSxpQkFBQSxFQUFBLDJCQUFBLElBQUEsRUFBQSxVQUFBLEVBQUEseUJBQUEsRUFBQSxDQUFBLENBYkE7QUFjQSxJQUFBLE1BQUEsRUFBQSxNQWRBO0FBZUEsSUFBQSxjQUFBLEVBQUEsdUJBZkE7QUFnQkEsSUFBQSxVQUFBLEVBQUEsQ0FoQkE7QUFpQkEsSUFBQSxRQUFBLEVBQUEsU0FqQkE7QUFrQkEsSUFBQSxRQUFBLEVBQUEsU0FsQkE7QUFtQkEsSUFBQSxVQUFBLEVBQUEsVUFuQkE7QUFvQkEsSUFBQSxXQUFBLEVBQUEsS0FwQkE7QUFxQkEsSUFBQSxVQUFBLEVBQUEsS0FyQkE7QUFzQkEsSUFBQSxPQUFBLEVBQUEsZUF0QkE7QUF1QkEsSUFBQSxPQUFBLEVBQUEsZUF2QkE7QUF1QkE7QUFDQTtBQUNBLElBQUEsVUFBQSxFQUFBLEtBekJBO0FBMEJBLElBQUEsY0FBQSxFQUFBLElBMUJBO0FBMkJBLElBQUEsVUFBQSxFQUFBLEtBM0JBO0FBNEJBLElBQUEsUUFBQSxFQUFBLG9CQTVCQTtBQTZCQSxJQUFBLFdBQUEsRUFBQSxLQTdCQTtBQThCQSxJQUFBLGdCQUFBLEVBQUEsSUE5QkE7QUErQkEsSUFBQSxXQUFBLEVBQUEsNEJBL0JBO0FBZ0NBLElBQUEsV0FBQSxFQUFBLHNCQWhDQTtBQWlDQTtBQUNBLElBQUEsY0FBQSxFQUFBO0FBbENBLEdBREEsRUFoREEsQ0F5RkE7QUFDQTtBQUNBOztBQUNBLEVBQUEsVUFBQSxDQUFBLFlBQUE7QUFBQSxJQUFBLHVDQUFBLENBQUEsV0FBQSxDQUFBO0FBQUEsR0FBQSxFQUFBLEdBQUEsQ0FBQSxDQTVGQSxDQTRGQTtBQUVBO0FBQ0E7QUFDQTs7QUFDQSxNQUFBLGNBQUEsR0FBQSxLQUFBLENBQUEseUJBQUEsQ0FBQSxXQUFBLEVBQUEsb0JBQUEsQ0FBQTs7QUFDQSxNQUFBLFVBQUEsY0FBQSxFQUFBO0FBQ0EsSUFBQSx3QkFBQSxDQUFBLFdBQUEsRUFBQSxjQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUEsY0FBQSxDQUFBLENBQUEsQ0FBQSxDQUFBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLGlDQUFBLENBQUEsSUFBQSxFQUFBLG1CQUFBLEVBQUEsYUFBQSxFQUFBO0FBRUEsTUFBQSxVQUFBLEdBQUEsSUFBQSxJQUFBLENBQUEsVUFBQSxDQUFBLENBQUEsQ0FBQSxFQUFBLFFBQUEsQ0FBQSxVQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsR0FBQSxDQUFBLEVBQUEsVUFBQSxDQUFBLENBQUEsQ0FBQSxFQUFBLENBQUEsRUFBQSxDQUFBLEVBQUEsQ0FBQSxDQUFBLENBRkEsQ0FFQTs7QUFDQSxNQUFBLFNBQUEsR0FBQSx3QkFBQSxDQUFBLElBQUEsQ0FBQSxDQUhBLENBR0E7O0FBQ0EsTUFBQSxhQUFBLEdBQUEseUJBQUEsQ0FBQSxJQUFBLENBQUEsQ0FKQSxDQUlBOztBQUNBLE1BQUEsV0FBQSxHQUFBLGdCQUFBLE9BQUEsbUJBQUEsQ0FBQSxhQUFBLENBQUEsR0FBQSxtQkFBQSxDQUFBLGFBQUEsQ0FBQSxHQUFBLEdBQUEsQ0FMQSxDQUtBO0FBRUE7O0FBQ0EsTUFBQSxpQkFBQSxHQUFBLEtBQUEsQ0FBQSxrQ0FBQSxDQUFBLFdBQUEsRUFBQSxhQUFBLENBQUEsQ0FSQSxDQVdBOzs7QUFDQSxNQUFBLHFCQUFBLEdBQUEsRUFBQTtBQUNBLEVBQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsY0FBQSxhQUFBLEVBYkEsQ0FhQTs7QUFDQSxFQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLGNBQUEsU0FBQSxFQWRBLENBY0E7O0FBQ0EsRUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSxrQkFBQSxJQUFBLENBQUEsTUFBQSxFQUFBLEVBZkEsQ0FlQTs7QUFFQSxNQUFBLGlCQUFBLEdBQUEsS0FBQSxDQWpCQSxDQW1CQTs7QUFDQSxNQUFBLFVBQUEsaUJBQUEsRUFBQTtBQUVBLElBQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsdUJBQUE7QUFFQSxXQUFBLENBQUEsaUJBQUEsRUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQTtBQUNBLEdBekJBLENBNEJBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7OztBQUNBLE1BQUEsZ0JBQUEsR0FBQSxLQUFBLENBQUEscUJBQUEsQ0FBQSxXQUFBLEVBQUEsYUFBQSxDQUFBOztBQUNBLE9BQUEsSUFBQSxVQUFBLElBQUEsZ0JBQUEsRUFBQTtBQUNBLElBQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsZ0JBQUEsQ0FBQSxVQUFBLENBQUEsRUFEQSxDQUNBO0FBQ0EsR0FyQ0EsQ0FzQ0E7QUFHQTs7O0FBQ0EsRUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSxVQUFBLGlCQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsZ0JBQUEsRUFBQSxRQUFBLEdBQUEsT0FBQSxDQUFBLFNBQUEsRUFBQSxHQUFBLENBQUEsRUExQ0EsQ0EwQ0E7O0FBR0EsTUFBQSxRQUFBLENBQUEsaUJBQUEsQ0FBQSxrQkFBQSxDQUFBLENBQUEsR0FBQSxDQUFBLEVBQUE7QUFDQSxJQUFBLGlCQUFBLEdBQUEsSUFBQTtBQUNBLElBQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsZ0JBQUE7QUFDQSxJQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLHdCQUFBLFFBQUEsQ0FBQSxpQkFBQSxDQUFBLGNBQUEsQ0FBQSxHQUFBLGlCQUFBLENBQUEsa0JBQUEsQ0FBQSxDQUFBO0FBQ0EsR0FKQSxNQUlBO0FBQ0EsSUFBQSxpQkFBQSxHQUFBLEtBQUE7QUFDQSxJQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLHVCQUFBO0FBQ0E7O0FBR0EsVUFBQSxpQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLGdCQUFBLENBQUE7QUFFQSxTQUFBLFdBQUE7QUFDQTs7QUFFQSxTQUFBLG9CQUFBO0FBQ0EsTUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSxhQUFBLEVBQUEsYUFBQTtBQUNBOztBQUVBLFNBQUEsa0JBQUE7QUFDQSxNQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLGtCQUFBO0FBQ0E7O0FBRUEsU0FBQSxlQUFBO0FBQ0EsTUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSx1QkFBQSxFQUFBLG9CQUFBO0FBQ0EsTUFBQSxpQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLHFCQUFBLElBQUEsRUFBQSxDQUZBLENBRUE7O0FBQ0E7O0FBRUEsU0FBQSx1QkFBQTtBQUNBLE1BQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsdUJBQUEsRUFBQSxzQkFBQTtBQUNBLE1BQUEsaUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxxQkFBQSxJQUFBLEVBQUEsQ0FGQSxDQUVBOztBQUNBOztBQUVBLFNBQUEscUJBQUE7QUFDQSxNQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLHVCQUFBLEVBQUEscUJBQUE7QUFDQSxNQUFBLGlCQUFBLENBQUEsU0FBQSxDQUFBLENBQUEscUJBQUEsSUFBQSxFQUFBLENBRkEsQ0FFQTs7QUFDQTs7QUFFQSxTQUFBLHdCQUFBO0FBQ0EsTUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSx1QkFBQSxFQUFBLHdCQUFBO0FBQ0EsTUFBQSxpQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLHFCQUFBLElBQUEsRUFBQSxDQUZBLENBRUE7O0FBQ0E7O0FBRUEsU0FBQSw0QkFBQTtBQUNBLE1BQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsdUJBQUEsRUFBQSw0QkFBQTtBQUNBLE1BQUEsaUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxxQkFBQSxJQUFBLEVBQUEsQ0FGQSxDQUVBOztBQUNBOztBQUVBLFNBQUEsYUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUEsTUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSxhQUFBLEVBQUEsZUFBQSxFQUFBLGdCQUFBO0FBQ0E7O0FBRUEsU0FBQSxVQUFBO0FBQ0EsTUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSxhQUFBLEVBQUEsZUFBQTs7QUFFQSxVQUFBLGFBQUEsaUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxxQkFBQSxDQUFBLEVBQUE7QUFDQSxRQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLDRCQUFBO0FBQ0E7O0FBQ0EsVUFBQSxjQUFBLGlCQUFBLENBQUEsU0FBQSxDQUFBLENBQUEscUJBQUEsQ0FBQSxFQUFBO0FBQ0EsUUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSw2QkFBQTtBQUNBOztBQUNBOztBQUVBLFNBQUEsV0FBQTtBQUNBLE1BQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsYUFBQSxFQUFBLGdCQUFBOztBQUVBLFVBQUEsYUFBQSxpQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLHFCQUFBLENBQUEsRUFBQTtBQUNBLFFBQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsNkJBQUE7QUFDQTs7QUFDQSxVQUFBLGNBQUEsaUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxxQkFBQSxDQUFBLEVBQUE7QUFDQSxRQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLDhCQUFBO0FBQ0E7O0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQUEsaUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxnQkFBQSxJQUFBLFdBQUE7QUExRUE7O0FBK0VBLE1BQUEsZUFBQSxpQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLGdCQUFBLENBQUEsRUFBQTtBQUVBLFFBQUEsOEJBQUEsR0FBQSxLQUFBLENBQUEseUJBQUEsQ0FBQSxXQUFBLEVBQUEseUJBQUEsQ0FBQSxDQUZBLENBRUE7OztBQUVBLFlBQUEsaUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxxQkFBQSxDQUFBO0FBRUEsV0FBQSxFQUFBO0FBQ0E7QUFDQTs7QUFFQSxXQUFBLFNBQUE7QUFDQSxRQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLGNBQUE7QUFDQSxRQUFBLGlCQUFBLEdBQUEsaUJBQUEsR0FBQSxJQUFBLEdBQUEsOEJBQUE7QUFDQTs7QUFFQSxXQUFBLFVBQUE7QUFDQSxRQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLGVBQUE7QUFDQTtBQUVBOztBQUNBLFdBQUEsaUJBQUE7QUFDQSxRQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLDZCQUFBLEVBQUEsNEJBQUE7QUFDQSxRQUFBLGlCQUFBLEdBQUEsaUJBQUEsR0FBQSxJQUFBLEdBQUEsOEJBQUE7QUFDQTs7QUFFQSxXQUFBLGtCQUFBO0FBQ0EsUUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSw2QkFBQSxFQUFBLDZCQUFBO0FBQ0EsUUFBQSxpQkFBQSxHQUFBLGlCQUFBLEdBQUEsSUFBQSxHQUFBLDhCQUFBO0FBQ0E7O0FBRUEsV0FBQSxrQkFBQTtBQUNBLFFBQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsOEJBQUEsRUFBQSw0QkFBQTtBQUNBLFFBQUEsaUJBQUEsR0FBQSxpQkFBQSxHQUFBLElBQUEsR0FBQSw4QkFBQTtBQUNBOztBQUVBLFdBQUEsbUJBQUE7QUFDQSxRQUFBLHFCQUFBLENBQUEsSUFBQSxDQUFBLDhCQUFBLEVBQUEsNkJBQUE7QUFDQTs7QUFFQTtBQW5DQTtBQXNDQTs7QUFFQSxTQUFBLENBQUEsaUJBQUEsRUFBQSxxQkFBQSxDQUFBLElBQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSw2QkFBQSxDQUFBLFdBQUEsRUFBQSxJQUFBLEVBQUEsbUJBQUEsRUFBQSxhQUFBLEVBQUE7QUFFQSxNQUFBLFNBQUEsSUFBQSxFQUFBO0FBQUEsV0FBQSxLQUFBO0FBQUE7O0FBRUEsTUFBQSxTQUFBLEdBQUEsd0JBQUEsQ0FBQSxJQUFBLENBQUEsQ0FKQSxDQUlBOztBQUNBLE1BQUEsYUFBQSxHQUFBLHlCQUFBLENBQUEsSUFBQSxDQUFBLENBTEEsQ0FLQTs7QUFDQSxNQUFBLFdBQUEsR0FBQSxnQkFBQSxPQUFBLG1CQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsbUJBQUEsQ0FBQSxhQUFBLENBQUEsR0FBQSxHQUFBLENBTkEsQ0FNQTtBQUVBOztBQUNBLE1BQUEsZ0JBQUEsR0FBQSxLQUFBLENBQUEsa0NBQUEsQ0FBQSxXQUFBLEVBQUEsYUFBQSxDQUFBLENBVEEsQ0FTQTs7O0FBRUEsTUFBQSxDQUFBLGdCQUFBLEVBQUE7QUFBQSxXQUFBLEtBQUE7QUFBQSxHQVhBLENBY0E7OztBQUNBLE1BQUEsWUFBQSxHQUFBLEVBQUE7O0FBQ0EsTUFBQSxnQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLHNCQUFBLEVBQUEsTUFBQSxHQUFBLENBQUEsRUFBQTtBQUNBLElBQUEsWUFBQSxJQUFBLGdCQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsc0JBQUEsQ0FBQTtBQUNBOztBQUNBLE1BQUEsZ0JBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxrQkFBQSxFQUFBLE1BQUEsR0FBQSxDQUFBLEVBQUE7QUFDQSxJQUFBLFlBQUEsSUFBQSxnQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLGtCQUFBLENBQUE7QUFDQTs7QUFDQSxNQUFBLGdCQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsZUFBQSxFQUFBLE1BQUEsR0FBQSxDQUFBLEVBQUE7QUFDQSxJQUFBLFlBQUEsSUFBQSxnQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLGVBQUEsQ0FBQTtBQUNBOztBQUNBLE1BQUEsZ0JBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSx5QkFBQSxFQUFBLE1BQUEsR0FBQSxDQUFBLEVBQUE7QUFDQSxJQUFBLFlBQUEsSUFBQSxnQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLHlCQUFBLENBQUE7QUFDQTs7QUFDQSxFQUFBLHFDQUFBLENBQUEsWUFBQSxFQUFBLFdBQUEsRUFBQSxTQUFBLENBQUEsQ0E1QkEsQ0FnQ0E7O0FBQ0EsTUFBQSx3QkFBQSxHQUFBLE1BQUEsQ0FBQSxtQ0FBQSxXQUFBLENBQUEsQ0FBQSxNQUFBLEdBQUEsQ0FBQSxDQWpDQSxDQWlDQTs7QUFDQSxNQUFBLHFCQUFBLEdBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLE1BQUEsR0FBQSxDQUFBOztBQUVBLE1BQUEsd0JBQUEsSUFBQSxDQUFBLHFCQUFBLEVBQUE7QUFFQTtBQUNBO0FBQ0E7QUFFQSxJQUFBLHVDQUFBLENBQUEsV0FBQSxDQUFBLENBTkEsQ0FNQTs7QUFFQSxRQUFBLGVBQUEsR0FBQSwwQ0FBQSxXQUFBO0FBQ0EsSUFBQSxNQUFBLENBQUEsZUFBQSxHQUFBLHdCQUFBLEdBQ0EsZUFEQSxHQUNBLHdCQURBLENBQUEsQ0FDQSxHQURBLENBQ0EsUUFEQSxFQUNBLFNBREEsRUFUQSxDQVVBOztBQUNBLFdBQUEsS0FBQTtBQUNBLEdBaERBLENBb0RBOzs7QUFDQSxNQUNBLFFBQUEsQ0FBQSxJQUFBLENBQUEsT0FBQSxDQUFBLFdBQUEsS0FBQSxDQUFBLENBQUEsSUFDQSxRQUFBLENBQUEsSUFBQSxDQUFBLE9BQUEsQ0FBQSxlQUFBLElBQUEsQ0FEQSxJQUVBLFFBQUEsQ0FBQSxJQUFBLENBQUEsT0FBQSxDQUFBLHdCQUFBLElBQUEsQ0FIQSxFQUlBO0FBQ0E7QUFFQSxRQUFBLGNBQUEsT0FBQSxxQ0FBQSxFQUFBO0FBQ0EsTUFBQSxxQ0FBQSxDQUFBLGFBQUEsRUFBQSxJQUFBLEVBQUEsV0FBQSxDQUFBO0FBQ0E7QUFDQTtBQUVBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsOEJBQUEsQ0FBQSxJQUFBLEVBQUEsbUJBQUEsRUFBQSxhQUFBLEVBQUE7QUFFQSxNQUFBLFdBQUEsR0FBQSxnQkFBQSxPQUFBLG1CQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsbUJBQUEsQ0FBQSxhQUFBLENBQUEsR0FBQSxHQUFBLENBRkEsQ0FFQTtBQUVBOztBQUNBLE1BQUEsd0JBQUEsR0FBQSxNQUFBLENBQUEsbUNBQUEsV0FBQSxDQUFBLENBQUEsTUFBQSxHQUFBLENBQUEsQ0FMQSxDQUtBOztBQUNBLE1BQUEscUJBQUEsR0FBQSxNQUFBLENBQUEsc0JBQUEsV0FBQSxDQUFBLENBQUEsTUFBQSxHQUFBLENBQUE7O0FBQ0EsTUFBQSx3QkFBQSxJQUFBLENBQUEscUJBQUEsRUFBQTtBQUNBLElBQUEsaUNBQUEsQ0FBQSxXQUFBLENBQUEsQ0FEQSxDQUNBOztBQUNBLElBQUEsTUFBQSxDQUFBLDZDQUFBLENBQUEsQ0FBQSxNQUFBLEdBRkEsQ0FFQTs7QUFDQSxXQUFBLEtBQUE7QUFDQTs7QUFFQSxFQUFBLE1BQUEsQ0FBQSxrQkFBQSxXQUFBLENBQUEsQ0FBQSxHQUFBLENBQUEsSUFBQSxFQWJBLENBYUE7O0FBR0EsTUFBQSxlQUFBLE9BQUEsa0NBQUEsRUFBQTtBQUFBLElBQUEsa0NBQUEsQ0FBQSxJQUFBLEVBQUEsV0FBQSxDQUFBO0FBQUE7O0FBRUEsRUFBQSx3Q0FBQSxDQUFBLFdBQUEsQ0FBQSxDQWxCQSxDQW9CQTs7QUFDQSxNQUFBLG1CQUFBLEdBQUEsSUFBQSxDQXJCQSxDQXFCQTs7QUFDQSxNQUFBLHNCQUFBLEdBQUEsb0NBQUEsQ0FBQSxXQUFBLENBQUEsQ0F0QkEsQ0FzQkE7O0FBQ0EsRUFBQSxNQUFBLENBQUEsbUJBQUEsQ0FBQSxDQUFBLE9BQUEsQ0FBQSxlQUFBLEVBQUEsQ0FBQSxXQUFBLEVBQUEsbUJBQUEsRUFBQSxzQkFBQSxDQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSx3Q0FBQSxDQUFBLFdBQUEsRUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBQSxtQkFBQSxHQUFBLDhDQUFBLENBQUEsV0FBQSxDQUFBLENBbEJBLENBb0JBOztBQUNBLE1BQUEsa0JBQUEsR0FBQSxvQ0FBQSxDQUFBLFdBQUEsQ0FBQSxDQXJCQSxDQXVCQTs7QUFDQSxNQUFBLG1CQUFBLEdBQUEsY0FBQSxDQUFBLEtBQUEsQ0FBQSx3QkFBQSxDQUFBLFdBQUEsRUFBQSw0QkFBQSxDQUFBLENBQUE7QUFFQSxNQUFBLFFBQUE7QUFDQSxNQUFBLGlCQUFBO0FBQ0EsTUFBQSxjQUFBO0FBQ0EsTUFBQSxlQUFBO0FBQ0EsTUFBQSxZQUFBO0FBQ0EsTUFBQSxXQUFBLENBL0JBLENBaUNBOztBQUNBLE9BQUEsSUFBQSxTQUFBLElBQUEsbUJBQUEsRUFBQTtBQUVBLElBQUEsbUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxRQUFBLEdBQUEsQ0FBQSxDQUZBLENBRUE7O0FBRUEsSUFBQSxlQUFBLEdBQUEsbUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FKQSxDQUlBO0FBRUE7O0FBQ0EsU0FBQSxJQUFBLENBQUEsR0FBQSxDQUFBLEVBQUEsQ0FBQSxHQUFBLGtCQUFBLENBQUEsTUFBQSxFQUFBLENBQUEsRUFBQSxFQUFBO0FBRUE7QUFDQSxNQUFBLFFBQUEsR0FBQSxrQkFBQSxDQUFBLENBQUEsQ0FBQTtBQUdBLFVBQUEsOEJBQUEsR0FBQSxDQUFBLENBTkEsQ0FPQTs7QUFDQSxXQUFBLElBQUEsT0FBQSxJQUFBLG1CQUFBLEVBQUE7QUFFQSxRQUFBLGlCQUFBLEdBQUEsbUJBQUEsQ0FBQSxPQUFBLENBQUEsQ0FGQSxDQUlBO0FBQ0E7O0FBRUEsWUFBQSxVQUFBLEtBQUEsQ0FBQSxrQ0FBQSxDQUFBLFdBQUEsRUFBQSxRQUFBLENBQUEsRUFBQTtBQUNBLFVBQUEsY0FBQSxHQUFBLEtBQUEsQ0FBQSxrQ0FBQSxDQUFBLFdBQUEsRUFBQSxRQUFBLEVBQUEsaUJBQUEsRUFBQSxpQkFBQSxDQUFBLGNBQUEsQ0FEQSxDQUNBO0FBQ0EsU0FGQSxNQUVBO0FBQ0EsVUFBQSxjQUFBLEdBQUEsRUFBQTtBQUNBOztBQUNBLFlBQUEsZUFBQSxDQUFBLGdCQUFBLENBQUEsTUFBQSxHQUFBLENBQUEsRUFBQTtBQUNBLFVBQUEsWUFBQSxHQUFBLHNDQUFBLENBQUEsQ0FDQSxDQUNBLFFBQUEsQ0FBQSxlQUFBLENBQUEsZ0JBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLEVBREEsRUFFQSxRQUFBLENBQUEsZUFBQSxDQUFBLGdCQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsR0FBQSxFQUZBLENBREEsQ0FBQSxFQU1BLGNBTkEsQ0FBQTtBQU9BLFNBUkEsTUFRQTtBQUNBLFVBQUEsV0FBQSxHQUFBLENBQUEsQ0FBQSxLQUFBLGVBQUEsQ0FBQSxJQUFBLENBQUEsT0FBQSxDQUFBLE9BQUEsQ0FBQTtBQUNBLFVBQUEsWUFBQSxHQUFBLG9DQUFBLENBQ0EsV0FBQSxHQUNBLFFBQUEsQ0FBQSxlQUFBLENBQUEsZ0JBQUEsQ0FBQSxHQUFBLEVBREEsR0FFQSxRQUFBLENBQUEsZUFBQSxDQUFBLGdCQUFBLENBQUEsR0FBQSxFQUhBLEVBS0EsY0FMQSxDQUFBO0FBTUE7O0FBQ0EsWUFBQSxZQUFBLEVBQUE7QUFDQSxVQUFBLDhCQUFBLEdBREEsQ0FDQTtBQUNBO0FBRUE7O0FBRUEsVUFBQSxtQkFBQSxDQUFBLE1BQUEsSUFBQSw4QkFBQSxFQUFBO0FBQ0E7QUFFQSxRQUFBLG1CQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsUUFBQSxHQUFBLENBQUE7QUFDQSxjQUpBLENBSUE7QUFDQTtBQUNBO0FBQ0EsR0EzRkEsQ0E4RkE7OztBQUNBLEVBQUEsNENBQUEsQ0FBQSxtQkFBQSxDQUFBO0FBRUEsRUFBQSxNQUFBLENBQUEsbUJBQUEsQ0FBQSxDQUFBLE9BQUEsQ0FBQSw4QkFBQSxFQUFBLENBQUEsV0FBQSxFQUFBLGtCQUFBLENBQUEsRUFqR0EsQ0FpR0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLG9DQUFBLENBQUEsTUFBQSxFQUFBLGVBQUEsRUFBQTtBQUVBLE9BQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxFQUFBLENBQUEsR0FBQSxlQUFBLENBQUEsTUFBQSxFQUFBLENBQUEsRUFBQSxFQUFBO0FBRUEsUUFBQSxRQUFBLENBQUEsTUFBQSxDQUFBLEdBQUEsUUFBQSxDQUFBLGVBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLFFBQUEsQ0FBQSxNQUFBLENBQUEsR0FBQSxRQUFBLENBQUEsZUFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUE7QUFDQSxhQUFBLElBQUE7QUFDQSxLQUpBLENBTUE7QUFDQTtBQUNBOztBQUNBOztBQUVBLFNBQUEsS0FBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsc0NBQUEsQ0FBQSxlQUFBLEVBQUEsZUFBQSxFQUFBO0FBRUEsTUFBQSxZQUFBOztBQUVBLE9BQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxFQUFBLENBQUEsR0FBQSxlQUFBLENBQUEsTUFBQSxFQUFBLENBQUEsRUFBQSxFQUFBO0FBRUEsU0FBQSxJQUFBLENBQUEsR0FBQSxDQUFBLEVBQUEsQ0FBQSxHQUFBLGVBQUEsQ0FBQSxNQUFBLEVBQUEsQ0FBQSxFQUFBLEVBQUE7QUFFQSxNQUFBLFlBQUEsR0FBQSw4QkFBQSxDQUFBLGVBQUEsQ0FBQSxDQUFBLENBQUEsRUFBQSxlQUFBLENBQUEsQ0FBQSxDQUFBLENBQUE7O0FBRUEsVUFBQSxZQUFBLEVBQUE7QUFDQSxlQUFBLElBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBQSxLQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLDhDQUFBLENBQUEsV0FBQSxFQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFBLGVBQUEsR0FBQSxDQUNBLDJCQUFBLFdBQUEsR0FBQSxJQURBLEVBRUEsMkJBQUEsV0FBQSxHQUFBLE1BRkEsRUFHQSwyQkFBQSxXQUFBLEdBQUEsSUFIQSxFQUlBLDJCQUFBLFdBQUEsR0FBQSxNQUpBLEVBS0EseUJBQUEsV0FBQSxHQUFBLElBTEEsRUFNQSx5QkFBQSxXQUFBLEdBQUEsTUFOQSxDQUFBO0FBU0EsTUFBQSxtQkFBQSxHQUFBLEVBQUEsQ0FkQSxDQWdCQTs7QUFDQSxPQUFBLElBQUEsR0FBQSxHQUFBLENBQUEsRUFBQSxHQUFBLEdBQUEsZUFBQSxDQUFBLE1BQUEsRUFBQSxHQUFBLEVBQUEsRUFBQTtBQUVBLFFBQUEsVUFBQSxHQUFBLGVBQUEsQ0FBQSxHQUFBLENBQUE7QUFDQSxRQUFBLFdBQUEsR0FBQSxNQUFBLENBQUEsVUFBQSxHQUFBLFNBQUEsQ0FBQSxDQUhBLENBS0E7O0FBQ0EsU0FBQSxJQUFBLENBQUEsR0FBQSxDQUFBLEVBQUEsQ0FBQSxHQUFBLFdBQUEsQ0FBQSxNQUFBLEVBQUEsQ0FBQSxFQUFBLEVBQUE7QUFFQSxVQUFBLGFBQUEsR0FBQSxNQUFBLENBQUEsVUFBQSxHQUFBLGFBQUEsR0FBQSxDQUFBLEdBQUEsR0FBQSxDQUFBO0FBQ0EsVUFBQSx3QkFBQSxHQUFBLGFBQUEsQ0FBQSxHQUFBLEdBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQTtBQUNBLFVBQUEsZ0JBQUEsR0FBQSxFQUFBLENBSkEsQ0FNQTs7QUFDQSxVQUFBLHdCQUFBLENBQUEsTUFBQSxFQUFBO0FBQUE7QUFDQSxhQUFBLElBQUEsQ0FBQSxJQUFBLHdCQUFBLEVBQUE7QUFFQTtBQUVBLGNBQUEsbUJBQUEsR0FBQSx3QkFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLElBQUEsR0FBQSxLQUFBLENBQUEsR0FBQSxDQUFBO0FBRUEsY0FBQSxlQUFBLEdBQUEsUUFBQSxDQUFBLG1CQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsR0FBQSxFQUFBLEdBQUEsRUFBQSxHQUFBLFFBQUEsQ0FBQSxtQkFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsRUFBQTtBQUVBLFVBQUEsZ0JBQUEsQ0FBQSxJQUFBLENBQUEsZUFBQTtBQUNBO0FBQ0E7O0FBRUEsTUFBQSxtQkFBQSxDQUFBLElBQUEsQ0FBQTtBQUNBLGdCQUFBLE1BQUEsQ0FBQSxVQUFBLENBQUEsQ0FBQSxJQUFBLENBQUEsTUFBQSxDQURBO0FBRUEsNEJBQUEsYUFBQSxDQUFBLEdBQUEsRUFGQTtBQUdBLHlCQUFBLGFBSEE7QUFJQSw0QkFBQTtBQUpBLE9BQUE7QUFNQTtBQUNBOztBQUVBLFNBQUEsbUJBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSw0Q0FBQSxDQUFBLG1CQUFBLEVBQUE7QUFFQSxNQUFBLGFBQUE7O0FBRUEsT0FBQSxJQUFBLENBQUEsR0FBQSxDQUFBLEVBQUEsQ0FBQSxHQUFBLG1CQUFBLENBQUEsTUFBQSxFQUFBLENBQUEsRUFBQSxFQUFBO0FBRUEsUUFBQSxhQUFBLEdBQUEsbUJBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxhQUFBOztBQUVBLFFBQUEsS0FBQSxtQkFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLFFBQUEsRUFBQTtBQUNBLE1BQUEsYUFBQSxDQUFBLElBQUEsQ0FBQSxVQUFBLEVBQUEsSUFBQSxFQURBLENBQ0E7O0FBQ0EsTUFBQSxhQUFBLENBQUEsUUFBQSxDQUFBLFFBQUEsRUFGQSxDQUVBO0FBRUE7O0FBQ0EsVUFBQSxhQUFBLENBQUEsSUFBQSxDQUFBLFVBQUEsQ0FBQSxFQUFBO0FBQ0EsUUFBQSxhQUFBLENBQUEsSUFBQSxDQUFBLFVBQUEsRUFBQSxLQUFBO0FBRUEsUUFBQSxhQUFBLENBQUEsTUFBQSxHQUFBLElBQUEsQ0FBQSw4QkFBQSxFQUFBLElBQUEsQ0FBQSxVQUFBLEVBQUEsSUFBQSxFQUFBLE9BQUEsQ0FBQSxRQUFBO0FBQ0E7QUFFQSxLQVhBLE1BV0E7QUFDQSxNQUFBLGFBQUEsQ0FBQSxJQUFBLENBQUEsVUFBQSxFQUFBLEtBQUEsRUFEQSxDQUNBOztBQUNBLE1BQUEsYUFBQSxDQUFBLFdBQUEsQ0FBQSxRQUFBLEVBRkEsQ0FFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSxzQ0FBQSxDQUFBLHVCQUFBLEVBQUE7QUFFQSxNQUNBLHVCQUFBLENBQUEsTUFBQSxHQUFBLENBQUEsSUFDQSxRQUFBLENBQUEsdUJBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLEVBREEsSUFFQSxRQUFBLENBQUEsdUJBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLEtBQUEsRUFBQSxHQUFBLEVBQUEsR0FBQSxFQUhBLEVBSUE7QUFDQSxXQUFBLElBQUE7QUFDQTs7QUFFQSxTQUFBLEtBQUE7QUFDQSxDLENBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSxvQ0FBQSxDQUFBLFdBQUEsRUFBQTtBQUVBLE1BQUEsa0JBQUEsR0FBQSxFQUFBO0FBQ0EsRUFBQSxrQkFBQSxHQUFBLE1BQUEsQ0FBQSxrQkFBQSxXQUFBLENBQUEsQ0FBQSxHQUFBLEdBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQTs7QUFFQSxNQUFBLGtCQUFBLENBQUEsTUFBQSxFQUFBO0FBQUE7QUFDQSxTQUFBLElBQUEsQ0FBQSxJQUFBLGtCQUFBLEVBQUE7QUFDQSxNQUFBLGtCQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsa0JBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLEVBQUE7QUFDQSxNQUFBLGtCQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsa0JBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxLQUFBLENBQUEsR0FBQSxDQUFBOztBQUNBLFVBQUEsa0JBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxNQUFBLEdBQUEsQ0FBQSxFQUFBO0FBQ0EsUUFBQSxrQkFBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLGtCQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLEdBQUEsR0FBQSxrQkFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLEdBQUEsR0FBQSxrQkFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQTtBQUNBO0FBQ0E7QUFDQSxHQWJBLENBZUE7OztBQUNBLEVBQUEsa0JBQUEsR0FBQSxrQkFBQSxDQUFBLE1BQUEsQ0FBQSxVQUFBLENBQUEsRUFBQTtBQUFBLFdBQUEsUUFBQSxDQUFBLENBQUEsQ0FBQTtBQUFBLEdBQUEsQ0FBQTtBQUVBLEVBQUEsa0JBQUEsQ0FBQSxJQUFBO0FBRUEsU0FBQSxrQkFBQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLHVEQUFBLENBQUEsV0FBQSxFQUFBO0FBQUEsTUFBQSxxQkFBQSx1RUFBQSxJQUFBOztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBQSxlQUFBLEdBQUEsQ0FDQSwyQkFBQSxXQUFBLEdBQUEsSUFEQSxFQUVBLDJCQUFBLFdBQUEsR0FBQSxNQUZBLEVBR0EsMkJBQUEsV0FBQSxHQUFBLElBSEEsRUFJQSwyQkFBQSxXQUFBLEdBQUEsTUFKQSxFQUtBLHlCQUFBLFdBQUEsR0FBQSxJQUxBLEVBTUEseUJBQUEsV0FBQSxHQUFBLE1BTkEsRUFPQSw4QkFBQSxXQUFBLEdBQUEsSUFQQSxFQVFBLDhCQUFBLFdBQUEsR0FBQSxNQVJBLENBQUE7QUFXQSxNQUFBLG1CQUFBLEdBQUEsRUFBQSxDQWhCQSxDQWtCQTs7QUFDQSxPQUFBLElBQUEsR0FBQSxHQUFBLENBQUEsRUFBQSxHQUFBLEdBQUEsZUFBQSxDQUFBLE1BQUEsRUFBQSxHQUFBLEVBQUEsRUFBQTtBQUVBLFFBQUEsVUFBQSxHQUFBLGVBQUEsQ0FBQSxHQUFBLENBQUE7QUFFQSxRQUFBLFdBQUE7O0FBQ0EsUUFBQSxxQkFBQSxFQUFBO0FBQ0EsTUFBQSxXQUFBLEdBQUEsTUFBQSxDQUFBLGtCQUFBLFdBQUEsR0FBQSxHQUFBLEdBQUEsVUFBQSxHQUFBLGtCQUFBLENBQUEsQ0FEQSxDQUNBO0FBQ0EsS0FGQSxNQUVBO0FBQ0EsTUFBQSxXQUFBLEdBQUEsTUFBQSxDQUFBLGtCQUFBLFdBQUEsR0FBQSxHQUFBLEdBQUEsVUFBQSxHQUFBLFNBQUEsQ0FBQSxDQURBLENBQ0E7QUFDQSxLQVRBLENBWUE7OztBQUNBLFNBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxFQUFBLENBQUEsR0FBQSxXQUFBLENBQUEsTUFBQSxFQUFBLENBQUEsRUFBQSxFQUFBO0FBRUEsVUFBQSxhQUFBLEdBQUEsTUFBQSxDQUFBLFdBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxDQUZBLENBRUE7O0FBQ0EsVUFBQSx3QkFBQSxHQUFBLGFBQUEsQ0FBQSxHQUFBLEdBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQTtBQUNBLFVBQUEsZ0JBQUEsR0FBQSxFQUFBLENBSkEsQ0FNQTs7QUFDQSxVQUFBLHdCQUFBLENBQUEsTUFBQSxFQUFBO0FBQUE7QUFDQSxhQUFBLElBQUEsQ0FBQSxJQUFBLHdCQUFBLEVBQUE7QUFFQTtBQUVBLGNBQUEsbUJBQUEsR0FBQSx3QkFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLElBQUEsR0FBQSxLQUFBLENBQUEsR0FBQSxDQUFBO0FBRUEsY0FBQSxlQUFBLEdBQUEsUUFBQSxDQUFBLG1CQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsR0FBQSxFQUFBLEdBQUEsRUFBQSxHQUFBLFFBQUEsQ0FBQSxtQkFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsRUFBQTtBQUVBLFVBQUEsZ0JBQUEsQ0FBQSxJQUFBLENBQUEsZUFBQTtBQUNBO0FBQ0E7O0FBRUEsTUFBQSxtQkFBQSxDQUFBLElBQUEsQ0FBQTtBQUNBLGdCQUFBLE1BQUEsQ0FBQSxrQkFBQSxXQUFBLEdBQUEsR0FBQSxHQUFBLFVBQUEsQ0FBQSxDQUFBLElBQUEsQ0FBQSxNQUFBLENBREE7QUFFQSw0QkFBQSxhQUFBLENBQUEsR0FBQSxFQUZBO0FBR0EseUJBQUEsYUFIQTtBQUlBLDRCQUFBO0FBSkEsT0FBQTtBQU1BO0FBQ0EsR0EzREEsQ0E2REE7OztBQUVBLE1BQUEsb0JBQUEsR0FBQSxDQUNBLDBCQUFBLFdBQUEsR0FBQSxJQURBLEVBRUEsd0JBQUEsV0FBQSxHQUFBLElBRkEsQ0FBQTs7QUFJQSxPQUFBLElBQUEsRUFBQSxHQUFBLENBQUEsRUFBQSxFQUFBLEdBQUEsb0JBQUEsQ0FBQSxNQUFBLEVBQUEsRUFBQSxFQUFBLEVBQUE7QUFFQSxRQUFBLFdBQUEsR0FBQSxNQUFBLENBQUEsa0JBQUEsV0FBQSxHQUFBLEdBQUEsR0FBQSxvQkFBQSxDQUFBLEVBQUEsQ0FBQSxDQUFBLENBRkEsQ0FFQTs7QUFDQSxRQUFBLFdBQUEsQ0FBQSxNQUFBLEdBQUEsQ0FBQSxFQUFBO0FBRUEsVUFBQSxjQUFBLEdBQUEsV0FBQSxDQUFBLEdBQUEsR0FBQSxJQUFBLEdBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUZBLENBRUE7O0FBQ0EsVUFBQSxLQUFBLGNBQUEsQ0FBQSxNQUFBLEVBQUE7QUFDQSxpQkFEQSxDQUNBO0FBQ0E7O0FBQ0EsVUFBQSxLQUFBLGNBQUEsQ0FBQSxNQUFBLEVBQUE7QUFDQSxZQUFBLE9BQUEsY0FBQSxDQUFBLENBQUEsQ0FBQSxFQUFBO0FBQ0EsbUJBREEsQ0FDQTtBQUNBOztBQUNBLFFBQUEsY0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLENBQUE7QUFDQTs7QUFDQSxVQUFBLG9CQUFBLEdBQUEsUUFBQSxDQUFBLGNBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLEVBQUEsR0FBQSxFQUFBLEdBQUEsUUFBQSxDQUFBLGNBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLEVBQUE7QUFFQSxVQUFBLHFCQUFBLEdBQUEsRUFBQTtBQUNBLE1BQUEscUJBQUEsQ0FBQSxJQUFBLENBQUEsb0JBQUE7QUFFQSxNQUFBLG1CQUFBLENBQUEsSUFBQSxDQUFBO0FBQ0EsZ0JBQUEsV0FBQSxDQUFBLElBQUEsQ0FBQSxNQUFBLENBREE7QUFFQSw0QkFBQSxXQUFBLENBQUEsR0FBQSxFQUZBO0FBR0EseUJBQUEsV0FIQTtBQUlBLDRCQUFBO0FBSkEsT0FBQTtBQU1BO0FBQ0E7O0FBRUEsU0FBQSxtQkFBQTtBQUNBLEMsQ0FJQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSx1QkFBQSxDQUFBLFdBQUEsRUFBQTtBQUVBLE1BQUEsZ0JBQUEsT0FBQSxXQUFBLEVBQUE7QUFDQSxJQUFBLFdBQUEsR0FBQSxHQUFBO0FBQ0E7O0FBRUEsTUFBQSxNQUFBLENBQUEsc0JBQUEsV0FBQSxDQUFBLENBQUEsTUFBQSxHQUFBLENBQUEsRUFBQTtBQUNBLFdBQUEsTUFBQSxDQUFBLFFBQUEsQ0FBQSxRQUFBLENBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQTtBQUNBOztBQUVBLFNBQUEsSUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLGlDQUFBLENBQUEsV0FBQSxFQUFBO0FBRUEsTUFBQSxnQkFBQSxPQUFBLFdBQUEsRUFBQTtBQUNBLElBQUEsV0FBQSxHQUFBLEdBQUE7QUFDQTs7QUFFQSxNQUFBLElBQUEsR0FBQSx1QkFBQSxDQUFBLFdBQUEsQ0FBQTs7QUFFQSxNQUFBLFNBQUEsSUFBQSxFQUFBO0FBRUE7QUFDQSxJQUFBLE1BQUEsQ0FBQSxrQkFBQSxXQUFBLENBQUEsQ0FBQSxHQUFBLENBQUEsRUFBQSxFQUhBLENBR0E7O0FBQ0EsSUFBQSxJQUFBLENBQUEsUUFBQSxHQUFBLEtBQUE7QUFDQSxJQUFBLElBQUEsQ0FBQSxLQUFBLEdBQUEsRUFBQTs7QUFDQSxJQUFBLE1BQUEsQ0FBQSxRQUFBLENBQUEsZUFBQSxDQUFBLElBQUE7O0FBRUEsV0FBQSxJQUFBO0FBQ0E7O0FBRUEsU0FBQSxLQUFBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLHVDQUFBLENBQUEsV0FBQSxFQUFBO0FBRUEsTUFBQSxnQkFBQSxPQUFBLFdBQUEsRUFBQTtBQUVBLElBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsR0FBQSwyQkFBQSxDQUFBLENBQUEsV0FBQSxDQUFBLHlCQUFBLEVBRkEsQ0FFQTtBQUVBLEdBSkEsTUFJQTtBQUNBLElBQUEsTUFBQSxDQUFBLDBCQUFBLENBQUEsQ0FBQSxXQUFBLENBQUEseUJBQUEsRUFEQSxDQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsd0JBQUEsQ0FBQSxXQUFBLEVBQUEsSUFBQSxFQUFBLEtBQUEsRUFBQTtBQUVBLE1BQUEsZ0JBQUEsT0FBQSxXQUFBLEVBQUE7QUFBQSxJQUFBLFdBQUEsR0FBQSxHQUFBO0FBQUE7O0FBQ0EsTUFBQSxJQUFBLEdBQUEsdUJBQUEsQ0FBQSxXQUFBLENBQUE7O0FBQ0EsTUFBQSxTQUFBLElBQUEsRUFBQTtBQUVBLElBQUEsSUFBQSxHQUFBLFFBQUEsQ0FBQSxJQUFBLENBQUE7QUFDQSxJQUFBLEtBQUEsR0FBQSxRQUFBLENBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUhBLENBR0E7O0FBRUEsSUFBQSxJQUFBLENBQUEsVUFBQSxHQUFBLElBQUEsSUFBQSxFQUFBLENBTEEsQ0FNQTs7QUFDQSxJQUFBLElBQUEsQ0FBQSxVQUFBLENBQUEsV0FBQSxDQUFBLElBQUEsRUFBQSxLQUFBLEVBQUEsQ0FBQTtBQUNBLElBQUEsSUFBQSxDQUFBLFVBQUEsQ0FBQSxRQUFBLENBQUEsS0FBQTtBQUNBLElBQUEsSUFBQSxDQUFBLFVBQUEsQ0FBQSxPQUFBLENBQUEsQ0FBQTtBQUVBLElBQUEsSUFBQSxDQUFBLFNBQUEsR0FBQSxJQUFBLENBQUEsVUFBQSxDQUFBLFFBQUEsRUFBQTtBQUNBLElBQUEsSUFBQSxDQUFBLFFBQUEsR0FBQSxJQUFBLENBQUEsVUFBQSxDQUFBLFdBQUEsRUFBQTs7QUFFQSxJQUFBLE1BQUEsQ0FBQSxRQUFBLENBQUEsYUFBQSxDQUFBLElBQUE7O0FBQ0EsSUFBQSxNQUFBLENBQUEsUUFBQSxDQUFBLGVBQUEsQ0FBQSxJQUFBOztBQUNBLElBQUEsTUFBQSxDQUFBLFFBQUEsQ0FBQSxTQUFBLENBQUEsSUFBQTs7QUFDQSxJQUFBLE1BQUEsQ0FBQSxRQUFBLENBQUEsZUFBQSxDQUFBLElBQUE7O0FBRUEsV0FBQSxJQUFBO0FBQ0E7O0FBQ0EsU0FBQSxLQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSwyQkFBQSxDQUFBLFdBQUEsRUFBQSxhQUFBLEVBQUE7QUFFQTtBQUNBLE1BQUEsaUJBQUEsR0FBQSxLQUFBLENBQUEsa0NBQUEsQ0FBQSxXQUFBLEVBQUEsYUFBQSxDQUFBOztBQUVBLE1BQUEsaUJBQUEsR0FBQSxRQUFBLENBQUEsaUJBQUEsQ0FBQSxrQkFBQSxDQUFBLENBQUEsR0FBQSxDQUFBOztBQUVBLE1BQUEsZUFBQSxpQkFBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLGdCQUFBLENBQUEsRUFBQTtBQUVBLFFBQUEsOEJBQUEsR0FBQSxLQUFBLENBQUEseUJBQUEsQ0FBQSxXQUFBLEVBQUEseUJBQUEsQ0FBQSxDQUZBLENBRUE7OztBQUVBLFlBQUEsaUJBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxxQkFBQSxDQUFBO0FBQ0EsV0FBQSxTQUFBLENBREEsQ0FFQTs7QUFDQSxXQUFBLGlCQUFBO0FBQ0EsV0FBQSxrQkFBQTtBQUNBLFdBQUEsa0JBQUE7QUFDQSxRQUFBLGlCQUFBLEdBQUEsaUJBQUEsR0FBQSxJQUFBLEdBQUEsOEJBQUE7QUFDQTs7QUFDQTtBQVJBO0FBVUE7O0FBRUEsU0FBQSxpQkFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsb0NBQUEsQ0FBQSxnQkFBQSxFQUFBLFlBQUEsRUFBQTtBQUVBLE9BQUEsSUFBQSxVQUFBLEdBQUEsQ0FBQSxFQUFBLFVBQUEsR0FBQSxZQUFBLENBQUEsTUFBQSxFQUFBLFVBQUEsRUFBQSxFQUFBO0FBQUE7QUFDQSxRQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsQ0FBQSxXQUFBLE9BQUEsZ0JBQUEsQ0FBQSxXQUFBLEVBQUEsSUFDQSxZQUFBLENBQUEsVUFBQSxDQUFBLENBQUEsUUFBQSxPQUFBLGdCQUFBLENBQUEsUUFBQSxFQURBLElBRUEsWUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLE9BQUEsT0FBQSxnQkFBQSxDQUFBLE9BQUEsRUFGQSxFQUVBO0FBQ0EsYUFBQSxJQUFBO0FBQ0E7QUFDQTs7QUFFQSxTQUFBLEtBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSx5QkFBQSxDQUFBLElBQUEsRUFBQTtBQUVBLE1BQUEsYUFBQSxHQUFBLElBQUEsQ0FBQSxXQUFBLEtBQUEsR0FBQTtBQUNBLEVBQUEsYUFBQSxJQUFBLElBQUEsQ0FBQSxRQUFBLEtBQUEsQ0FBQSxHQUFBLEVBQUEsR0FBQSxHQUFBLEdBQUEsRUFBQTtBQUNBLEVBQUEsYUFBQSxJQUFBLElBQUEsQ0FBQSxRQUFBLEtBQUEsQ0FBQSxHQUFBLEdBQUE7QUFDQSxFQUFBLGFBQUEsSUFBQSxJQUFBLENBQUEsT0FBQSxLQUFBLEVBQUEsR0FBQSxHQUFBLEdBQUEsRUFBQTtBQUNBLEVBQUEsYUFBQSxJQUFBLElBQUEsQ0FBQSxPQUFBLEVBQUE7QUFFQSxTQUFBLGFBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSx3QkFBQSxDQUFBLElBQUEsRUFBQTtBQUVBLE1BQUEsWUFBQSxHQUFBLElBQUEsQ0FBQSxRQUFBLEtBQUEsQ0FBQSxHQUFBLEdBQUEsR0FBQSxJQUFBLENBQUEsT0FBQSxFQUFBLEdBQUEsR0FBQSxHQUFBLElBQUEsQ0FBQSxXQUFBLEVBQUEsQ0FGQSxDQUVBOztBQUVBLFNBQUEsWUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsd0NBQUEsQ0FBQSxJQUFBLEVBQUEsU0FBQSxFQUFBO0FBRUEsRUFBQSxTQUFBLEdBQUEsZ0JBQUEsT0FBQSxTQUFBLEdBQUEsU0FBQSxHQUFBLEdBQUE7QUFFQSxNQUFBLFFBQUEsR0FBQSxJQUFBLENBQUEsS0FBQSxDQUFBLFNBQUEsQ0FBQTtBQUNBLE1BQUEsUUFBQSxHQUFBO0FBQ0EsWUFBQSxRQUFBLENBQUEsUUFBQSxDQUFBLENBQUEsQ0FBQSxDQURBO0FBRUEsYUFBQSxRQUFBLENBQUEsUUFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsQ0FGQTtBQUdBLFlBQUEsUUFBQSxDQUFBLFFBQUEsQ0FBQSxDQUFBLENBQUE7QUFIQSxHQUFBO0FBS0EsU0FBQSxRQUFBLENBVkEsQ0FVQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsNkJBQUEsQ0FBQSxXQUFBLEVBQUE7QUFDQSxNQUFBLENBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLElBQUEsR0FBQSxRQUFBLENBQUEsMkJBQUEsQ0FBQSxFQUFBO0FBQ0EsSUFBQSxNQUFBLENBQUEsc0JBQUEsV0FBQSxDQUFBLENBQUEsS0FBQSxDQUFBLG9GQUFBO0FBQ0E7O0FBQ0EsTUFBQSxDQUFBLE1BQUEsQ0FBQSxzQkFBQSxXQUFBLENBQUEsQ0FBQSxRQUFBLENBQUEsMEJBQUEsQ0FBQSxFQUFBO0FBQ0EsSUFBQSxNQUFBLENBQUEsc0JBQUEsV0FBQSxDQUFBLENBQUEsUUFBQSxDQUFBLDBCQUFBO0FBQ0E7O0FBQ0EsRUFBQSwwQkFBQSxDQUFBLFdBQUEsQ0FBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsNEJBQUEsQ0FBQSxXQUFBLEVBQUE7QUFDQSxFQUFBLE1BQUEsQ0FBQSxzQkFBQSxXQUFBLEdBQUEsK0JBQUEsQ0FBQSxDQUFBLE1BQUE7QUFDQSxFQUFBLE1BQUEsQ0FBQSxzQkFBQSxXQUFBLENBQUEsQ0FBQSxXQUFBLENBQUEsMEJBQUE7QUFDQSxFQUFBLHlCQUFBLENBQUEsV0FBQSxDQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSwwQkFBQSxDQUFBLFdBQUEsRUFBQTtBQUNBLE1BQUEsQ0FBQSxNQUFBLENBQUEsc0JBQUEsV0FBQSxDQUFBLENBQUEsUUFBQSxDQUFBLG9CQUFBLENBQUEsRUFBQTtBQUNBLElBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLFFBQUEsQ0FBQSxvQkFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQTtBQUNBLEVBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsQ0FBQSxDQUFBLFdBQUEsQ0FBQSxvQkFBQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSwwQkFBQSxDQUFBLFdBQUEsRUFBQTtBQUVBLE1BQUEsSUFBQSxHQUFBLHVCQUFBLENBQUEsV0FBQSxDQUFBOztBQUVBLEVBQUEsTUFBQSxDQUFBLFFBQUEsQ0FBQSxlQUFBLENBQUEsSUFBQTtBQUNBLEMsQ0FHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSxnQ0FBQSxDQUFBLFNBQUEsRUFBQTtBQUVBLE1BQUEsQ0FBQSxTQUFBLElBQUEsU0FBQSxDQUFBLE1BQUEsS0FBQSxDQUFBLEVBQUE7QUFDQSxXQUFBLEVBQUE7QUFDQTs7QUFFQSxNQUFBLE1BQUEsR0FBQSxFQUFBO0FBQ0EsRUFBQSxTQUFBLENBQUEsSUFBQSxDQUFBLFVBQUEsQ0FBQSxFQUFBLENBQUEsRUFBQTtBQUNBLFdBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxDQUFBLENBQUE7QUFDQSxHQUZBO0FBSUEsTUFBQSxjQUFBLEdBQUEsU0FBQSxDQUFBLENBQUEsQ0FBQTs7QUFFQSxPQUFBLElBQUEsQ0FBQSxHQUFBLENBQUEsRUFBQSxDQUFBLEdBQUEsU0FBQSxDQUFBLE1BQUEsRUFBQSxDQUFBLEVBQUEsRUFBQTtBQUNBLFFBQUEsUUFBQSxHQUFBLFNBQUEsQ0FBQSxDQUFBLENBQUE7O0FBRUEsUUFBQSxRQUFBLENBQUEsQ0FBQSxDQUFBLElBQUEsY0FBQSxDQUFBLENBQUEsQ0FBQSxFQUFBO0FBQ0EsTUFBQSxjQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxjQUFBLENBQUEsQ0FBQSxDQUFBLEVBQUEsUUFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBO0FBQ0EsS0FGQSxNQUVBO0FBQ0EsTUFBQSxNQUFBLENBQUEsSUFBQSxDQUFBLGNBQUE7QUFDQSxNQUFBLGNBQUEsR0FBQSxRQUFBO0FBQ0E7QUFDQTs7QUFFQSxFQUFBLE1BQUEsQ0FBQSxJQUFBLENBQUEsY0FBQTtBQUNBLFNBQUEsTUFBQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsOEJBQUEsQ0FBQSxVQUFBLEVBQUEsVUFBQSxFQUFBO0FBRUEsTUFDQSxLQUFBLFVBQUEsQ0FBQSxNQUFBLElBQ0EsS0FBQSxVQUFBLENBQUEsTUFGQSxFQUdBO0FBQ0EsV0FBQSxLQUFBO0FBQ0E7O0FBRUEsRUFBQSxVQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsUUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQTtBQUNBLEVBQUEsVUFBQSxDQUFBLENBQUEsQ0FBQSxHQUFBLFFBQUEsQ0FBQSxVQUFBLENBQUEsQ0FBQSxDQUFBLENBQUE7QUFDQSxFQUFBLFVBQUEsQ0FBQSxDQUFBLENBQUEsR0FBQSxRQUFBLENBQUEsVUFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBO0FBQ0EsRUFBQSxVQUFBLENBQUEsQ0FBQSxDQUFBLEdBQUEsUUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQTtBQUVBLE1BQUEsY0FBQSxHQUFBLElBQUEsQ0FBQSxHQUFBLENBQUEsVUFBQSxDQUFBLENBQUEsQ0FBQSxFQUFBLFVBQUEsQ0FBQSxDQUFBLENBQUEsSUFBQSxJQUFBLENBQUEsR0FBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLENBQUEsRUFBQSxVQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FkQSxDQWdCQTtBQUNBO0FBQ0E7O0FBRUEsTUFBQSxjQUFBLEdBQUEsQ0FBQSxFQUFBO0FBQ0EsV0FBQSxJQUFBLENBREEsQ0FDQTtBQUNBOztBQUVBLFNBQUEsS0FBQSxDQXhCQSxDQXdCQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsaUNBQUEsQ0FBQSxPQUFBLEVBQUEsT0FBQSxFQUFBO0FBRUEsTUFBQSxPQUFBLENBQUEsTUFBQSxJQUFBLENBQUEsRUFBQTtBQUFBO0FBQ0EsV0FBQSxPQUFBO0FBQ0E7O0FBRUEsTUFBQSxHQUFBLEdBQUEsT0FBQSxDQUFBLENBQUEsQ0FBQTtBQUNBLE1BQUEsSUFBQSxHQUFBLElBQUEsQ0FBQSxHQUFBLENBQUEsT0FBQSxHQUFBLEdBQUEsQ0FBQSxDQVBBLENBT0E7O0FBQ0EsTUFBQSxXQUFBLEdBQUEsT0FBQSxDQUFBLENBQUEsQ0FBQSxDQVJBLENBUUE7O0FBRUEsT0FBQSxJQUFBLENBQUEsR0FBQSxDQUFBLEVBQUEsQ0FBQSxHQUFBLE9BQUEsQ0FBQSxNQUFBLEVBQUEsQ0FBQSxFQUFBLEVBQUE7QUFDQSxJQUFBLEdBQUEsR0FBQSxPQUFBLENBQUEsQ0FBQSxDQUFBOztBQUVBLFFBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxPQUFBLEdBQUEsR0FBQSxJQUFBLElBQUEsRUFBQTtBQUFBO0FBQ0EsTUFBQSxJQUFBLEdBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxPQUFBLEdBQUEsR0FBQSxDQUFBO0FBQ0EsTUFBQSxXQUFBLEdBQUEsR0FBQTtBQUNBO0FBQ0E7O0FBRUEsU0FBQSxXQUFBO0FBQ0EsQyxDQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLHFDQUFBLENBQUEsWUFBQSxFQUFBLFdBQUEsRUFBQSxRQUFBLEVBQUE7QUFFQTtBQUVBLEVBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsR0FBQSxlQUFBLEdBQUEsUUFBQSxDQUFBLENBQUEsSUFBQSxDQUFBLGNBQUEsRUFBQSxZQUFBO0FBRUEsTUFBQSxLQUFBLEdBQUEsTUFBQSxDQUFBLHNCQUFBLFdBQUEsR0FBQSxlQUFBLEdBQUEsUUFBQSxDQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsQ0FBQSxDQU5BLENBTUE7O0FBRUEsTUFDQSxnQkFBQSxPQUFBLEtBQUEsSUFDQSxTQUFBLElBQUEsS0FBQSxDQUFBLE1BREEsSUFFQSxPQUFBLFlBSEEsRUFJQTtBQUVBLElBQUEsVUFBQSxDQUFBLEtBQUEsRUFBQTtBQUNBLE1BQUEsT0FEQSxtQkFDQSxTQURBLEVBQ0E7QUFFQSxZQUFBLGVBQUEsR0FBQSxTQUFBLENBQUEsWUFBQSxDQUFBLGNBQUEsQ0FBQTtBQUVBLGVBQUEsd0NBQ0EsK0JBREEsR0FFQSxlQUZBLEdBR0EsUUFIQSxHQUlBLFFBSkE7QUFLQSxPQVZBO0FBV0EsTUFBQSxTQUFBLEVBQUEsSUFYQTtBQVlBLE1BQUEsT0FBQSxFQUFBLGtCQVpBO0FBYUEsTUFBQSxXQUFBLEVBQUEsS0FiQTtBQWNBLE1BQUEsV0FBQSxFQUFBLElBZEE7QUFlQSxNQUFBLGlCQUFBLEVBQUEsRUFmQTtBQWdCQSxNQUFBLFFBQUEsRUFBQSxHQWhCQTtBQWlCQSxNQUFBLEtBQUEsRUFBQSxrQkFqQkE7QUFrQkEsTUFBQSxTQUFBLEVBQUEsS0FsQkE7QUFtQkEsTUFBQSxLQUFBLEVBQUEsQ0FBQSxHQUFBLEVBQUEsQ0FBQSxDQW5CQTtBQW1CQTtBQUNBO0FBQ0EsTUFBQSxnQkFBQSxFQUFBLElBckJBO0FBc0JBLE1BQUEsS0FBQSxFQUFBLElBdEJBO0FBc0JBO0FBQ0EsTUFBQSxRQUFBLEVBQUE7QUFBQSxlQUFBLFFBQUEsQ0FBQSxJQUFBO0FBQUE7QUF2QkEsS0FBQSxDQUFBO0FBMEJBLFdBQUEsSUFBQTtBQUNBOztBQUVBLFNBQUEsS0FBQTtBQUNBO0FDNTBDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSxpQkFBQSxDQUFBLFdBQUEsRUFBQTtBQUVBO0FBQ0EsRUFBQSxNQUFBLENBQUEsc0JBQUEsV0FBQSxDQUFBLENBQUEsV0FBQSxDQUFBLGFBQUE7QUFDQSxFQUFBLGtCQUFBLENBQUEsV0FBQSxDQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLDZCQUFBLENBQUEsV0FBQSxFQUFBO0FBRUEsRUFBQSxLQUFBLENBQUEseUJBQUEsQ0FBQSxXQUFBLEVBQUEsc0NBQUEsRUFDQTtBQUNBLHlCQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSxtQkFBQSxDQURBO0FBRUEseUJBQUEsS0FBQSxDQUFBLHlCQUFBLENBQUEsV0FBQSxFQUFBLG1CQUFBLENBRkE7QUFHQSw4QkFBQSxLQUFBLENBQUEseUJBQUEsQ0FBQSxXQUFBLEVBQUEsd0JBQUEsQ0FIQTtBQUlBLGlDQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSwyQkFBQSxDQUpBO0FBS0EsdUJBQUEsS0FBQSxDQUFBLHlCQUFBLENBQUEsV0FBQSxFQUFBLGlCQUFBLENBTEE7QUFNQSwrQkFBQSxLQUFBLENBQUEseUJBQUEsQ0FBQSxXQUFBLEVBQUEseUJBQUE7QUFOQSxHQURBO0FBVUEsQyxDQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsa0NBQUEsQ0FBQSxXQUFBLEVBQUE7QUFFQTtBQUNBLEVBQUEsTUFBQSxDQUFBLFFBQUEsQ0FBQSxDQUFBLEtBQUEsQ0FBQSxZQUFBO0FBRUE7QUFDQSxJQUFBLFVBQUEsQ0FBQSxZQUFBO0FBRUEsTUFBQSw0QkFBQSxDQUFBLFdBQUEsQ0FBQTtBQUVBLEtBSkEsRUFJQSxJQUpBLENBQUE7QUFLQSxHQVJBO0FBU0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsNEJBQUEsQ0FBQSxXQUFBLEVBQUE7QUFFQSxFQUFBLEtBQUEsQ0FBQSx3QkFBQSxDQUFBLFdBQUEsRUFBQTtBQUFBLHdCQUFBO0FBQUEsR0FBQTs7QUFFQSxFQUFBLDZCQUFBLENBQUEsV0FBQSxDQUFBO0FBQ0EsRUFBQSxpQkFBQSxDQUFBLFdBQUEsQ0FBQTtBQUNBLEMsQ0FFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLG9DQUFBLENBQUEsV0FBQSxFQUFBO0FBRUE7QUFDQSxFQUFBLE1BQUEsQ0FBQSxRQUFBLENBQUEsQ0FBQSxLQUFBLENBQUEsWUFBQTtBQUVBO0FBQ0EsSUFBQSxVQUFBLENBQUEsWUFBQTtBQUVBLE1BQUEsOEJBQUEsQ0FBQSxXQUFBLENBQUE7QUFFQSxLQUpBLEVBSUEsSUFKQSxDQUFBO0FBS0EsR0FSQTtBQVNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLDhCQUFBLENBQUEsV0FBQSxFQUFBO0FBRUEsRUFBQSxLQUFBLENBQUEsd0JBQUEsQ0FBQSxXQUFBLEVBQUE7QUFBQSx3QkFBQTtBQUFBLEdBQUE7O0FBRUEsRUFBQSw2QkFBQSxDQUFBLFdBQUEsQ0FBQTtBQUNBLEVBQUEsaUJBQUEsQ0FBQSxXQUFBLENBQUE7QUFDQSxDLENBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsaUNBQUEsQ0FBQSxXQUFBLEVBQUEsV0FBQSxFQUFBO0FBQUEsTUFBQSxnQkFBQSx1RUFBQSxDQUFBLENBQUEsQ0FBQSxDQUFBO0FBRUE7QUFDQSxFQUFBLE1BQUEsQ0FBQSxRQUFBLENBQUEsQ0FBQSxLQUFBLENBQUEsWUFBQTtBQUVBO0FBQ0EsSUFBQSxVQUFBLENBQUEsWUFBQTtBQUVBLE1BQUEsMkJBQUEsQ0FBQSxXQUFBLEVBQUEsV0FBQSxFQUFBLGdCQUFBLENBQUE7QUFFQSxLQUpBLEVBSUEsSUFKQSxDQUFBO0FBS0EsR0FSQTtBQVNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSwyQkFBQSxDQUFBLFdBQUEsRUFBQSxXQUFBLEVBQUE7QUFBQSxNQUFBLGdCQUFBLHVFQUFBLENBQUEsQ0FBQSxDQUFBLENBQUE7O0FBRUEsRUFBQSxLQUFBLENBQUEsd0JBQUEsQ0FBQSxXQUFBLEVBQUE7QUFBQSx3QkFBQTtBQUFBLEdBQUE7O0FBRUEsRUFBQSxLQUFBLENBQUEsd0JBQUEsQ0FBQSxXQUFBLEVBQUE7QUFBQSx1QkFBQSxRQUFBLENBQUEsV0FBQTtBQUFBLEdBQUEsRUFKQSxDQUlBOzs7QUFDQSxFQUFBLEtBQUEsQ0FBQSx3QkFBQSxDQUFBLFdBQUEsRUFBQTtBQUFBLCtCQUFBO0FBQUEsR0FBQSxFQUxBLENBS0E7OztBQUVBLEVBQUEsNkJBQUEsQ0FBQSxXQUFBLENBQUE7QUFDQSxFQUFBLGlCQUFBLENBQUEsV0FBQSxDQUFBO0FBQ0EsQyxDQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSxpQ0FBQSxDQUFBLFdBQUEsRUFBQSxRQUFBLEVBQUEsUUFBQSxFQUFBO0FBQUEsTUFBQSxhQUFBLHVFQUFBLEVBQUE7QUFBQSxNQUFBLGdCQUFBLHVFQUFBLENBQUEsQ0FBQSxDQUFBLENBQUE7QUFFQTtBQUNBLEVBQUEsTUFBQSxDQUFBLFFBQUEsQ0FBQSxDQUFBLEtBQUEsQ0FBQSxZQUFBO0FBRUE7QUFDQSxJQUFBLFVBQUEsQ0FBQSxZQUFBO0FBRUEsTUFBQSwyQkFBQSxDQUFBLFdBQUEsRUFBQSxRQUFBLEVBQUEsUUFBQSxFQUFBLGFBQUEsRUFBQSxnQkFBQSxDQUFBO0FBQ0EsS0FIQSxFQUdBLElBSEEsQ0FBQTtBQUlBLEdBUEE7QUFRQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLDJCQUFBLENBQUEsV0FBQSxFQUFBLFFBQUEsRUFBQSxRQUFBLEVBQUE7QUFBQSxNQUFBLGFBQUEsdUVBQUEsRUFBQTtBQUFBLE1BQUEsZ0JBQUEsdUVBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQTs7QUFFQSxFQUFBLEtBQUEsQ0FBQSx3QkFBQSxDQUFBLFdBQUEsRUFBQTtBQUFBLHdCQUFBO0FBQUEsR0FBQTs7QUFDQSxFQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSxtQkFBQSxFQUFBLFFBQUEsQ0FBQSxRQUFBLENBQUEsRUFIQSxDQUdBOzs7QUFDQSxFQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSxtQkFBQSxFQUFBLFFBQUEsQ0FBQSxRQUFBLENBQUEsRUFKQSxDQUlBOzs7QUFDQSxFQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSx3QkFBQSxFQUFBLGFBQUEsRUFMQSxDQUtBOzs7QUFDQSxFQUFBLEtBQUEsQ0FBQSx5QkFBQSxDQUFBLFdBQUEsRUFBQSwyQkFBQSxFQUFBLGdCQUFBLEVBTkEsQ0FNQTs7O0FBRUEsRUFBQSw2QkFBQSxDQUFBLFdBQUEsQ0FBQTtBQUNBLEVBQUEsaUJBQUEsQ0FBQSxXQUFBLENBQUE7QUFDQTtBQ3ZNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBOzs7QUFFQSxTQUFBLDZCQUFBLENBQUEsTUFBQSxFQUFBO0FBRUE7QUFDQSxFQUFBLDZCQUFBLENBQUEsTUFBQSxDQUFBLGFBQUEsQ0FBQSxDQUFBOztBQUNBLE1BQUEsc0JBQUEsQ0FBQSxNQUFBLEVBQUEsK0JBQUEsQ0FBQSxFQUFBO0FBQ0EsV0FBQSxLQUFBO0FBQ0EsR0FOQSxDQVFBOzs7QUFDQSxFQUFBLHlCQUFBLENBQUEsTUFBQSxDQUFBLGFBQUEsQ0FBQSxDQUFBLENBVEEsQ0FZQTs7QUFDQSxFQUFBLE9BQUEsQ0FBQSxjQUFBLENBQUEsd0JBQUE7QUFBQSxFQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsaURBQUEsRUFBQSxLQUFBLENBQUEsa0JBQUEsRUFBQSxFQWJBLENBZUE7O0FBQ0EsRUFBQSxNQUFBLENBQUEsSUFBQSxDQUFBLFlBQUEsQ0FBQSxZQUFBLEVBQ0E7QUFDQSxJQUFBLE1BQUEsRUFBQSx3QkFEQTtBQUVBLElBQUEsZ0JBQUEsRUFBQSxLQUFBLENBQUEsZ0JBQUEsQ0FBQSxTQUFBLENBRkE7QUFHQSxJQUFBLEtBQUEsRUFBQSxLQUFBLENBQUEsZ0JBQUEsQ0FBQSxPQUFBLENBSEE7QUFJQSxJQUFBLGVBQUEsRUFBQSxLQUFBLENBQUEsZ0JBQUEsQ0FBQSxRQUFBLENBSkE7QUFNQSxJQUFBLHVCQUFBLEVBQUEsTUFOQSxDQU1BOztBQU5BLEdBREE7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQUEsYUFBQSxFQUFBLFVBQUEsRUFBQSxLQUFBLEVBQUE7QUFDQTtBQUNBLElBQUEsT0FBQSxDQUFBLEdBQUEsQ0FBQSx5Q0FBQSxFQUFBLGFBQUE7QUFBQSxJQUFBLE9BQUEsQ0FBQSxRQUFBLEdBRkEsQ0FJQTs7QUFDQSxRQUFBLDBCQUFBLEdBQUEsNENBQUEsQ0FBQSxLQUFBLElBQUEsQ0FBQTtBQUNBLElBQUEsd0JBQUEsQ0FBQSwwQkFBQSxFQUFBLCtCQUFBLENBQUEsQ0FOQSxDQVFBOztBQUNBLFFBQUEsUUFBQSxhQUFBLE1BQUEsUUFBQSxJQUFBLGFBQUEsS0FBQSxJQUFBLEVBQUE7QUFFQSxVQUFBLE9BQUEsR0FBQSx3Q0FBQSxDQUFBLEtBQUEsSUFBQSxDQUFBO0FBQ0EsVUFBQSxZQUFBLEdBQUEsTUFBQTs7QUFFQSxVQUFBLE9BQUEsYUFBQSxFQUFBO0FBQ0EsUUFBQSxhQUFBLEdBQUEsZ01BQUE7QUFDQSxRQUFBLFlBQUEsR0FBQSxTQUFBO0FBQ0EsT0FSQSxDQVVBOzs7QUFDQSxNQUFBLDRCQUFBLENBQUEsYUFBQSxFQUFBO0FBQUEsZ0JBQUEsWUFBQTtBQUNBLHFCQUFBO0FBQUEscUJBQUEsT0FBQTtBQUFBLG1CQUFBO0FBQUEsU0FEQTtBQUVBLHFCQUFBLElBRkE7QUFHQSxpQkFBQSxrQkFIQTtBQUlBLGlCQUFBO0FBSkEsT0FBQSxDQUFBO0FBTUE7QUFDQSxLQTNCQSxDQTZCQTs7O0FBQ0EsSUFBQSw0QkFBQSxDQUFBLGFBQUEsQ0FBQSxhQUFBLENBQUEsQ0FBQSxDQTlCQSxDQWdDQTtBQUNBOztBQUNBLElBQUEsS0FBQSxDQUFBLCtCQUFBLENBQUEsYUFBQSxDQUFBLGFBQUEsQ0FBQSxFQUFBLGFBQUEsQ0FBQSxVQUFBLENBQUEsQ0FBQSxPQUFBLENBQUEsRUFsQ0EsQ0FvQ0E7OztBQUNBLElBQUEsS0FBQSxDQUFBLHdCQUFBLENBQUEsYUFBQSxDQUFBLGFBQUEsQ0FBQSxFQUFBLDRCQUFBLEVBQUEsYUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLDRCQUFBLENBQUEsRUFyQ0EsQ0F1Q0E7OztBQUNBLElBQUEsS0FBQSxDQUFBLHdCQUFBLENBQUEsYUFBQSxDQUFBLGFBQUEsQ0FBQSxFQUFBLDJCQUFBLEVBQUEsYUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLDJCQUFBLENBQUEsRUF4Q0EsQ0F5Q0E7QUFFQTs7O0FBQ0EsSUFBQSwwQkFBQSxDQUFBLGFBQUEsQ0FBQSxhQUFBLENBQUEsQ0FBQTs7QUFHQSxRQUNBLGdCQUFBLE9BQUEsYUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLDBCQUFBLENBQUEsSUFDQSxNQUFBLGFBQUEsQ0FBQSxVQUFBLENBQUEsQ0FBQSwwQkFBQSxFQUFBLE9BQUEsQ0FBQSxLQUFBLEVBQUEsUUFBQSxDQUZBLEVBR0E7QUFFQSxVQUFBLE9BQUEsR0FBQSx3Q0FBQSxDQUFBLEtBQUEsSUFBQSxDQUFBLENBRkEsQ0FJQTs7QUFDQSxNQUFBLDRCQUFBLENBQUEsYUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLDBCQUFBLEVBQUEsT0FBQSxDQUFBLEtBQUEsRUFBQSxRQUFBLENBQUEsRUFDQTtBQUFBLGdCQUFBLGdCQUFBLE9BQUEsYUFBQSxDQUFBLFVBQUEsQ0FBQSxDQUFBLGlDQUFBLENBQUEsR0FDQSxhQUFBLENBQUEsVUFBQSxDQUFBLENBQUEsaUNBQUEsQ0FEQSxHQUNBLE1BREE7QUFFQSxxQkFBQTtBQUFBLHFCQUFBLE9BQUE7QUFBQSxtQkFBQTtBQUFBLFNBRkE7QUFHQSxxQkFBQSxJQUhBO0FBSUEsaUJBQUEsa0JBSkE7QUFLQSxpQkFBQTtBQUxBLE9BREEsQ0FBQTtBQVFBLEtBL0RBLENBaUVBOztBQUNBLEdBbkZBLEVBb0ZBLElBcEZBLENBb0ZBLFVBQUEsS0FBQSxFQUFBLFVBQUEsRUFBQSxXQUFBLEVBQUE7QUFBQSxRQUFBLE1BQUEsQ0FBQSxPQUFBLElBQUEsTUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLEVBQUE7QUFBQSxNQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsWUFBQSxFQUFBLEtBQUEsRUFBQSxVQUFBLEVBQUEsV0FBQTtBQUFBOztBQUVBLFFBQUEsMEJBQUEsR0FBQSw0Q0FBQSxDQUFBLEtBQUEsSUFBQSxDQUFBO0FBQ0EsSUFBQSx3QkFBQSxDQUFBLDBCQUFBLEVBQUEsK0JBQUEsQ0FBQSxDQUhBLENBS0E7O0FBQ0EsUUFBQSxhQUFBLEdBQUEsYUFBQSxRQUFBLEdBQUEsWUFBQSxHQUFBLFdBQUE7O0FBQ0EsUUFBQSxLQUFBLENBQUEsTUFBQSxFQUFBO0FBQ0EsTUFBQSxhQUFBLElBQUEsVUFBQSxLQUFBLENBQUEsTUFBQSxHQUFBLE9BQUE7O0FBQ0EsVUFBQSxPQUFBLEtBQUEsQ0FBQSxNQUFBLEVBQUE7QUFDQSxRQUFBLGFBQUEsSUFBQSxzSkFBQTtBQUNBLFFBQUEsYUFBQSxJQUFBLGtMQUFBO0FBQ0E7QUFDQTs7QUFDQSxRQUFBLGtCQUFBLEdBQUEsSUFBQTs7QUFDQSxRQUFBLEtBQUEsQ0FBQSxZQUFBLEVBQUE7QUFDQSxNQUFBLGFBQUEsSUFBQSxNQUFBLEtBQUEsQ0FBQSxZQUFBO0FBQ0EsTUFBQSxrQkFBQSxHQUFBLEVBQUE7QUFDQTs7QUFDQSxJQUFBLGFBQUEsR0FBQSxhQUFBLENBQUEsT0FBQSxDQUFBLEtBQUEsRUFBQSxRQUFBLENBQUE7QUFFQSxRQUFBLE9BQUEsR0FBQSx3Q0FBQSxDQUFBLEtBQUEsSUFBQSxDQUFBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDQSxRQUFBLFlBQUEsR0FBQSxVQUFBLENBQUEsWUFBQTtBQUVBO0FBQ0EsTUFBQSw0QkFBQSxDQUFBLGFBQUEsRUFBQTtBQUFBLGdCQUFBLE9BQUE7QUFDQSxxQkFBQTtBQUFBLHFCQUFBLE9BQUE7QUFBQSxtQkFBQTtBQUFBLFNBREE7QUFFQSxxQkFBQSxJQUZBO0FBR0EsaUJBQUEsa0JBSEE7QUFJQSxxQkFBQSxxQkFKQTtBQUtBLGlCQUFBO0FBTEEsT0FBQSxDQUFBO0FBT0EsS0FWQSxFQVdBLFFBQUEsQ0FBQSxrQkFBQSxDQVhBLENBQUE7QUFhQSxHQTdIQSxFQThIQTtBQUNBO0FBL0hBLEdBaEJBLENBZ0pBO0FBQ0EsQyxDQUlBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsd0NBQUEsQ0FBQSx3QkFBQSxFQUFBO0FBRUEsTUFBQSxPQUFBLEdBQUEsbUJBQUE7QUFFQSxNQUFBLG9CQUFBLEdBQUEsNENBQUEsQ0FBQSx3QkFBQSxDQUFBOztBQUVBLE1BQUEsb0JBQUEsR0FBQSxDQUFBLEVBQUE7QUFDQSxJQUFBLE9BQUEsR0FBQSxzQkFBQSxvQkFBQTtBQUNBOztBQUVBLFNBQUEsT0FBQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSw0Q0FBQSxDQUFBLHdCQUFBLEVBQUE7QUFFQTtBQUNBLE1BQUEsb0JBQUEsR0FBQSwwQkFBQSxDQUFBLHNDQUFBLEVBQUEsd0JBQUEsQ0FBQTs7QUFDQSxNQUFBLFNBQUEsb0JBQUEsSUFBQSxPQUFBLG9CQUFBLEVBQUE7QUFDQSxJQUFBLG9CQUFBLEdBQUEsUUFBQSxDQUFBLG9CQUFBLENBQUE7O0FBQ0EsUUFBQSxvQkFBQSxHQUFBLENBQUEsRUFBQTtBQUNBLGFBQUEsb0JBQUE7QUFDQTtBQUNBOztBQUNBLFNBQUEsQ0FBQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSwwQkFBQSxDQUFBLElBQUEsRUFBQSxHQUFBLEVBQUE7QUFFQSxFQUFBLEdBQUEsR0FBQSxrQkFBQSxDQUFBLEdBQUEsQ0FBQTtBQUVBLEVBQUEsSUFBQSxHQUFBLElBQUEsQ0FBQSxPQUFBLENBQUEsU0FBQSxFQUFBLE1BQUEsQ0FBQTtBQUNBLE1BQUEsS0FBQSxHQUFBLElBQUEsTUFBQSxDQUFBLFNBQUEsSUFBQSxHQUFBLG1CQUFBLENBQUE7QUFBQSxNQUNBLE9BQUEsR0FBQSxLQUFBLENBQUEsSUFBQSxDQUFBLEdBQUEsQ0FEQTtBQUVBLE1BQUEsQ0FBQSxPQUFBLEVBQUEsT0FBQSxJQUFBO0FBQ0EsTUFBQSxDQUFBLE9BQUEsQ0FBQSxDQUFBLENBQUEsRUFBQSxPQUFBLEVBQUE7QUFDQSxTQUFBLGtCQUFBLENBQUEsT0FBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLE9BQUEsQ0FBQSxLQUFBLEVBQUEsR0FBQSxDQUFBLENBQUE7QUFDQSxDLENBR0E7O0FDck9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLDRCQUFBLENBQUEsT0FBQSxFQUFBO0FBQUEsTUFBQSxNQUFBLHVFQUFBLEVBQUE7QUFFQSxNQUFBLGNBQUEsR0FBQTtBQUNBLFlBQUEsU0FEQTtBQUNBO0FBQ0EsaUJBQUE7QUFDQSxpQkFBQSxFQURBO0FBQ0E7QUFDQSxlQUFBLFFBRkEsQ0FFQTs7QUFGQSxLQUZBO0FBTUEsaUJBQUEsSUFOQTtBQU1BO0FBQ0EsYUFBQSxrQkFQQTtBQU9BO0FBQ0EsaUJBQUEsRUFSQTtBQVFBO0FBQ0EsYUFBQSxDQVRBO0FBU0E7QUFDQSwyQkFBQSxLQVZBO0FBVUE7QUFDQSxpQkFBQSxJQVhBLENBV0E7O0FBWEEsR0FBQTs7QUFhQSxPQUFBLElBQUEsS0FBQSxJQUFBLE1BQUEsRUFBQTtBQUNBLElBQUEsY0FBQSxDQUFBLEtBQUEsQ0FBQSxHQUFBLE1BQUEsQ0FBQSxLQUFBLENBQUE7QUFDQTs7QUFDQSxFQUFBLE1BQUEsR0FBQSxjQUFBO0FBRUEsTUFBQSxhQUFBLEdBQUEsSUFBQSxJQUFBLEVBQUE7QUFDQSxFQUFBLGFBQUEsR0FBQSxpQkFBQSxhQUFBLENBQUEsT0FBQSxFQUFBO0FBRUEsRUFBQSxNQUFBLENBQUEsV0FBQSxDQUFBLElBQUEsa0JBQUE7O0FBQ0EsTUFBQSxNQUFBLENBQUEsTUFBQSxDQUFBLElBQUEsT0FBQSxFQUFBO0FBQ0EsSUFBQSxNQUFBLENBQUEsV0FBQSxDQUFBLElBQUEsd0JBQUE7QUFDQSxJQUFBLE9BQUEsR0FBQSxvRUFBQSxPQUFBO0FBQ0E7O0FBQ0EsTUFBQSxNQUFBLENBQUEsTUFBQSxDQUFBLElBQUEsU0FBQSxFQUFBO0FBQ0EsSUFBQSxNQUFBLENBQUEsV0FBQSxDQUFBLElBQUEsMEJBQUE7QUFDQSxJQUFBLE9BQUEsR0FBQSx1REFBQSxPQUFBO0FBQ0E7O0FBQ0EsTUFBQSxNQUFBLENBQUEsTUFBQSxDQUFBLElBQUEsTUFBQSxFQUFBO0FBQ0EsSUFBQSxNQUFBLENBQUEsV0FBQSxDQUFBLElBQUEsdUJBQUE7QUFDQTs7QUFDQSxNQUFBLE1BQUEsQ0FBQSxNQUFBLENBQUEsSUFBQSxTQUFBLEVBQUE7QUFDQSxJQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsSUFBQSwwQkFBQTtBQUNBLElBQUEsT0FBQSxHQUFBLDREQUFBLE9BQUE7QUFDQTs7QUFFQSxNQUFBLGlCQUFBLEdBQUEsY0FBQSxhQUFBLEdBQUEsdUNBQUE7QUFDQSxFQUFBLE9BQUEsR0FBQSxjQUFBLGFBQUEsR0FBQSxtQ0FBQSxHQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsR0FBQSxXQUFBLEdBQUEsTUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLElBQUEsR0FBQSxPQUFBLEdBQUEsUUFBQTtBQUdBLE1BQUEsYUFBQSxHQUFBLEtBQUE7QUFDQSxNQUFBLGVBQUEsR0FBQSxJQUFBOztBQUVBLE1BQUEsYUFBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsT0FBQSxDQUFBLEVBQUE7QUFFQSxRQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsRUFBQTtBQUNBLE1BQUEsTUFBQSxDQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxDQUFBLE1BQUEsQ0FBQSxpQkFBQTtBQUNBLE1BQUEsTUFBQSxDQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxDQUFBLE1BQUEsQ0FBQSxPQUFBO0FBQ0EsS0FIQSxNQUdBO0FBQ0EsTUFBQSxNQUFBLENBQUEsTUFBQSxDQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLENBQUEsSUFBQSxDQUFBLGlCQUFBLEdBQUEsT0FBQTtBQUNBO0FBRUEsR0FUQSxNQVNBLElBQUEsYUFBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsT0FBQSxDQUFBLEVBQUE7QUFFQSxJQUFBLGFBQUEsR0FBQSxNQUFBLENBQUEsTUFBQSxDQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLENBQUEsUUFBQSxDQUFBLHNCQUFBLENBQUE7O0FBQ0EsUUFBQSxNQUFBLENBQUEscUJBQUEsQ0FBQSxJQUFBLGFBQUEsQ0FBQSxFQUFBLENBQUEsVUFBQSxDQUFBLEVBQUE7QUFDQSxNQUFBLGVBQUEsR0FBQSxLQUFBO0FBQ0EsTUFBQSxhQUFBLEdBQUEsTUFBQSxDQUFBLGFBQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLENBQUEsSUFBQSxDQUFBO0FBQ0E7O0FBQ0EsUUFBQSxlQUFBLEVBQUE7QUFDQSxNQUFBLE1BQUEsQ0FBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsQ0FBQSxNQUFBLENBQUEsaUJBQUE7QUFDQSxNQUFBLE1BQUEsQ0FBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsQ0FBQSxNQUFBLENBQUEsT0FBQTtBQUNBO0FBRUEsR0FaQSxNQVlBLElBQUEsWUFBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsT0FBQSxDQUFBLEVBQUE7QUFFQSxJQUFBLGFBQUEsR0FBQSxNQUFBLENBQUEsTUFBQSxDQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLENBQUEsT0FBQSxDQUFBLHNCQUFBLENBQUE7O0FBQ0EsUUFBQSxNQUFBLENBQUEscUJBQUEsQ0FBQSxJQUFBLGFBQUEsQ0FBQSxFQUFBLENBQUEsVUFBQSxDQUFBLEVBQUE7QUFDQSxNQUFBLGVBQUEsR0FBQSxLQUFBO0FBQ0EsTUFBQSxhQUFBLEdBQUEsTUFBQSxDQUFBLGFBQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLENBQUEsSUFBQSxDQUFBO0FBQ0E7O0FBQ0EsUUFBQSxlQUFBLEVBQUE7QUFDQSxNQUFBLE1BQUEsQ0FBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsQ0FBQSxNQUFBLENBQUEsaUJBQUEsRUFEQSxDQUNBOztBQUNBLE1BQUEsTUFBQSxDQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxDQUFBLEtBQUEsQ0FBQSxPQUFBO0FBQ0E7QUFFQSxHQVpBLE1BWUEsSUFBQSxZQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxPQUFBLENBQUEsRUFBQTtBQUVBLElBQUEsYUFBQSxHQUFBLE1BQUEsQ0FBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsQ0FBQSxPQUFBLENBQUEsMENBQUEsRUFBQSxJQUFBLENBQUEsc0JBQUEsQ0FBQTs7QUFDQSxRQUFBLE1BQUEsQ0FBQSxxQkFBQSxDQUFBLElBQUEsYUFBQSxDQUFBLEVBQUEsQ0FBQSxVQUFBLENBQUEsRUFBQTtBQUNBLE1BQUEsZUFBQSxHQUFBLEtBQUE7QUFDQSxNQUFBLGFBQUEsR0FBQSxNQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLElBQUEsQ0FBQSxJQUFBLENBQUE7QUFDQTs7QUFDQSxRQUFBLGVBQUEsRUFBQTtBQUNBLE1BQUEsTUFBQSxDQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxDQUFBLE1BQUEsQ0FBQSxpQkFBQSxFQURBLENBQ0E7O0FBQ0EsTUFBQSxNQUFBLENBQUEsTUFBQSxDQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLENBQUEsS0FBQSxDQUFBLDBEQUFBLE9BQUEsR0FBQSxRQUFBO0FBQ0E7QUFDQSxHQVhBLE1BV0EsSUFBQSxXQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxPQUFBLENBQUEsRUFBQTtBQUVBLElBQUEsYUFBQSxHQUFBLE1BQUEsQ0FBQSxNQUFBLENBQUEsV0FBQSxDQUFBLENBQUEsU0FBQSxDQUFBLENBQUEsQ0FBQSxRQUFBLENBQUEseUNBQUEsRUFBQSxJQUFBLENBQUEsc0JBQUEsQ0FBQTs7QUFDQSxRQUFBLE1BQUEsQ0FBQSxxQkFBQSxDQUFBLElBQUEsYUFBQSxDQUFBLEVBQUEsQ0FBQSxVQUFBLENBQUEsRUFBQTtBQUNBLE1BQUEsZUFBQSxHQUFBLEtBQUE7QUFDQSxNQUFBLGFBQUEsR0FBQSxNQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLENBQUEsQ0FBQSxDQUFBLElBQUEsQ0FBQSxJQUFBLENBQUE7QUFDQTs7QUFDQSxRQUFBLGVBQUEsRUFBQTtBQUNBLE1BQUEsTUFBQSxDQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxTQUFBLENBQUEsQ0FBQSxDQUFBLE1BQUEsQ0FBQSxpQkFBQSxFQURBLENBQ0E7O0FBQ0EsTUFBQSxNQUFBLENBQUEsTUFBQSxDQUFBLFdBQUEsQ0FBQSxDQUFBLFNBQUEsQ0FBQSxDQUFBLENBQUEsTUFBQSxDQUFBLHlEQUFBLE9BQUEsR0FBQSxRQUFBO0FBQ0E7QUFDQTs7QUFFQSxNQUFBLGVBQUEsSUFBQSxRQUFBLENBQUEsTUFBQSxDQUFBLE9BQUEsQ0FBQSxDQUFBLEdBQUEsQ0FBQSxFQUFBO0FBQ0EsUUFBQSxZQUFBLEdBQUEsVUFBQSxDQUFBLFlBQUE7QUFDQSxNQUFBLE1BQUEsQ0FBQSxNQUFBLGFBQUEsQ0FBQSxDQUFBLE9BQUEsQ0FBQSxJQUFBO0FBQ0EsS0FGQSxFQUVBLFFBQUEsQ0FBQSxNQUFBLENBQUEsT0FBQSxDQUFBLENBRkEsQ0FBQTtBQUlBLFFBQUEsYUFBQSxHQUFBLFVBQUEsQ0FBQSxZQUFBO0FBQ0EsTUFBQSxNQUFBLENBQUEsTUFBQSxhQUFBLENBQUEsQ0FBQSxPQUFBLENBQUEsTUFBQTtBQUNBLEtBRkEsRUFFQSxRQUFBLENBQUEsTUFBQSxDQUFBLE9BQUEsQ0FBQSxDQUFBLEdBQUEsSUFGQSxDQUFBO0FBR0EsR0FoSEEsQ0FrSEE7OztBQUNBLE1BQUEsVUFBQSxHQUFBLE1BQUEsQ0FBQSxNQUFBLGFBQUEsQ0FBQSxDQUFBLE9BQUEsR0FBQSxHQUFBLENBQUEsWUFBQTtBQUNBLFFBQUEsQ0FBQSxNQUFBLENBQUEsSUFBQSxDQUFBLENBQUEsRUFBQSxDQUFBLFNBQUEsQ0FBQSxJQUFBLE1BQUEsQ0FBQSxpQkFBQSxDQUFBLENBQUEsR0FBQSxDQUFBLElBQUEsQ0FBQSxFQUFBO0FBQ0EsTUFBQSxNQUFBLENBQUEsSUFBQSxDQUFBLENBQUEsSUFBQTtBQUNBO0FBQ0EsR0FKQSxDQUFBOztBQU1BLE1BQUEsTUFBQSxDQUFBLFdBQUEsQ0FBQSxFQUFBO0FBQ0EsSUFBQSxjQUFBLENBQUEsTUFBQSxhQUFBLEdBQUEsU0FBQSxDQUFBO0FBQ0E7O0FBRUEsU0FBQSxhQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSxtQ0FBQSxDQUFBLE9BQUEsRUFBQSxPQUFBLEVBQUE7QUFFQSxNQUFBLGlCQUFBLEdBQUEsNEJBQUEsQ0FDQSxPQURBLEVBRUE7QUFDQSxZQUFBLE9BREE7QUFFQSxhQUFBLEtBRkE7QUFHQSwyQkFBQSxJQUhBO0FBSUEsaUJBQUE7QUFDQSxlQUFBLE9BREE7QUFFQSxpQkFBQTtBQUZBO0FBSkEsR0FGQSxDQUFBO0FBWUEsU0FBQSxpQkFBQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsaURBQUEsQ0FBQSxPQUFBLEVBQUEsT0FBQSxFQUFBLGFBQUEsRUFBQTtBQUVBLE1BQUEsZ0JBQUEsT0FBQSxhQUFBLEVBQUE7QUFDQSxJQUFBLGFBQUEsR0FBQSxDQUFBO0FBQ0E7O0FBRUEsTUFBQSxpQkFBQSxHQUFBLDRCQUFBLENBQ0EsT0FEQSxFQUVBO0FBQ0EsWUFBQSxPQURBO0FBRUEsYUFBQSxhQUZBO0FBR0EsMkJBQUEsSUFIQTtBQUlBLGlCQUFBO0FBQ0EsZUFBQSxPQURBO0FBRUEsaUJBQUE7QUFGQTtBQUpBLEdBRkEsQ0FBQTtBQVlBLFNBQUEsaUJBQUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLGlEQUFBLENBQUEsT0FBQSxFQUFBLE9BQUEsRUFBQSxhQUFBLEVBQUE7QUFFQSxNQUFBLGdCQUFBLE9BQUEsYUFBQSxFQUFBO0FBQ0EsSUFBQSxhQUFBLEdBQUEsS0FBQTtBQUNBOztBQUVBLE1BQUEsaUJBQUEsR0FBQSw0QkFBQSxDQUNBLE9BREEsRUFFQTtBQUNBLFlBQUEsT0FEQTtBQUVBLGFBQUEsYUFGQTtBQUdBLDJCQUFBLElBSEE7QUFJQSxpQkFBQTtBQUNBLGVBQUEsUUFEQTtBQUVBLGlCQUFBO0FBRkE7QUFKQSxHQUZBLENBQUE7QUFZQSxTQUFBLGlCQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBQSxxQ0FBQSxDQUFBLE9BQUEsRUFBQSxPQUFBLEVBQUE7QUFFQSxNQUFBLGlCQUFBLEdBQUEsNEJBQUEsQ0FDQSxPQURBLEVBRUE7QUFDQSxZQUFBLFNBREE7QUFFQSxhQUFBLEtBRkE7QUFHQSwyQkFBQSxJQUhBO0FBSUEsaUJBQUE7QUFDQSxlQUFBLE9BREE7QUFFQSxpQkFBQTtBQUZBO0FBSkEsR0FGQSxDQUFBO0FBWUEsU0FBQSxpQkFBQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsbURBQUEsQ0FBQSxPQUFBLEVBQUEsT0FBQSxFQUFBO0FBRUEsTUFBQSxpQkFBQSxHQUFBLDRCQUFBLENBQ0EsT0FEQSxFQUVBO0FBQ0EsWUFBQSxTQURBO0FBRUEsYUFBQSxLQUZBO0FBR0EsMkJBQUEsSUFIQTtBQUlBLGlCQUFBO0FBQ0EsZUFBQSxPQURBO0FBRUEsaUJBQUE7QUFGQTtBQUpBLEdBRkEsQ0FBQTtBQVlBLFNBQUEsaUJBQUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDQSxTQUFBLG1EQUFBLENBQUEsT0FBQSxFQUFBLE9BQUEsRUFBQTtBQUVBLE1BQUEsaUJBQUEsR0FBQSw0QkFBQSxDQUNBLE9BREEsRUFFQTtBQUNBLFlBQUEsU0FEQTtBQUVBLGFBQUEsS0FGQTtBQUdBLDJCQUFBLElBSEE7QUFJQSxpQkFBQTtBQUNBLGVBQUEsUUFEQTtBQUVBLGlCQUFBO0FBRkE7QUFKQSxHQUZBLENBQUE7QUFZQSxTQUFBLGlCQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQUEsY0FBQSxDQUFBLE9BQUEsRUFBQTtBQUFBLE1BQUEsa0JBQUEsdUVBQUEsQ0FBQTs7QUFFQSxNQUFBLENBQUEsTUFBQSxDQUFBLE9BQUEsQ0FBQSxDQUFBLE1BQUEsRUFBQTtBQUNBO0FBQ0E7O0FBQ0EsTUFBQSxZQUFBLEdBQUEsTUFBQSxDQUFBLE9BQUEsQ0FBQSxDQUFBLE1BQUEsR0FBQSxHQUFBOztBQUVBLE1BQUEsWUFBQSxJQUFBLENBQUEsRUFBQTtBQUNBLFFBQUEsS0FBQSxNQUFBLENBQUEsT0FBQSxDQUFBLENBQUEsT0FBQSxDQUFBLFVBQUEsRUFBQSxNQUFBLEVBQUE7QUFDQSxNQUFBLFlBQUEsR0FBQSxNQUFBLENBQUEsT0FBQSxDQUFBLENBQUEsT0FBQSxDQUFBLFVBQUEsRUFBQSxLQUFBLEdBQUEsTUFBQSxHQUFBLEdBQUE7QUFDQSxLQUZBLE1BRUEsSUFBQSxLQUFBLE1BQUEsQ0FBQSxPQUFBLENBQUEsQ0FBQSxNQUFBLEdBQUEsT0FBQSxDQUFBLFVBQUEsRUFBQSxNQUFBLEVBQUE7QUFDQSxNQUFBLFlBQUEsR0FBQSxNQUFBLENBQUEsT0FBQSxDQUFBLENBQUEsTUFBQSxHQUFBLE9BQUEsQ0FBQSxVQUFBLEVBQUEsS0FBQSxHQUFBLE1BQUEsR0FBQSxHQUFBO0FBQ0E7QUFDQTs7QUFFQSxNQUFBLE1BQUEsQ0FBQSxhQUFBLENBQUEsQ0FBQSxNQUFBLEdBQUEsQ0FBQSxFQUFBO0FBQ0EsSUFBQSxZQUFBLEdBQUEsWUFBQSxHQUFBLEVBQUEsR0FBQSxFQUFBO0FBQ0EsR0FGQSxNQUVBO0FBQ0EsSUFBQSxZQUFBLEdBQUEsWUFBQSxHQUFBLEVBQUEsR0FBQSxFQUFBO0FBQ0E7O0FBQ0EsRUFBQSxZQUFBLElBQUEsa0JBQUEsQ0FwQkEsQ0FzQkE7O0FBQ0EsTUFBQSxDQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxFQUFBLENBQUEsV0FBQSxDQUFBLEVBQUE7QUFDQSxJQUFBLE1BQUEsQ0FBQSxXQUFBLENBQUEsQ0FBQSxPQUFBLENBQUE7QUFBQSxNQUFBLFNBQUEsRUFBQTtBQUFBLEtBQUEsRUFBQSxHQUFBO0FBQ0E7QUFDQSIsInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xyXG4vKipcclxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAqXHRpbmNsdWRlcy9fX2pzL3dwYmMvd3BiYy5qc1xyXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICovXHJcblxyXG4vKipcclxuICogRGVlcCBDbG9uZSBvZiBvYmplY3Qgb3IgYXJyYXlcclxuICpcclxuICogQHBhcmFtIG9ialxyXG4gKiBAcmV0dXJucyB7YW55fVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jbG9uZV9vYmooIG9iaiApe1xyXG5cclxuXHRyZXR1cm4gSlNPTi5wYXJzZSggSlNPTi5zdHJpbmdpZnkoIG9iaiApICk7XHJcbn1cclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIE1haW4gX3dwYmMgSlMgb2JqZWN0XHJcbiAqL1xyXG5cclxudmFyIF93cGJjID0gKGZ1bmN0aW9uICggb2JqLCAkKSB7XHJcblxyXG5cdC8vIFNlY3VyZSBwYXJhbWV0ZXJzIGZvciBBamF4XHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHR2YXIgcF9zZWN1cmUgPSBvYmouc2VjdXJpdHlfb2JqID0gb2JqLnNlY3VyaXR5X29iaiB8fCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHVzZXJfaWQ6IDAsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG5vbmNlICA6ICcnLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRsb2NhbGUgOiAnJ1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICB9O1xyXG5cdG9iai5zZXRfc2VjdXJlX3BhcmFtID0gZnVuY3Rpb24gKCBwYXJhbV9rZXksIHBhcmFtX3ZhbCApIHtcclxuXHRcdHBfc2VjdXJlWyBwYXJhbV9rZXkgXSA9IHBhcmFtX3ZhbDtcclxuXHR9O1xyXG5cclxuXHRvYmouZ2V0X3NlY3VyZV9wYXJhbSA9IGZ1bmN0aW9uICggcGFyYW1fa2V5ICkge1xyXG5cdFx0cmV0dXJuIHBfc2VjdXJlWyBwYXJhbV9rZXkgXTtcclxuXHR9O1xyXG5cclxuXHJcblx0Ly8gQ2FsZW5kYXJzIFx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdHZhciBwX2NhbGVuZGFycyA9IG9iai5jYWxlbmRhcnNfb2JqID0gb2JqLmNhbGVuZGFyc19vYmogfHwge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBzb3J0ICAgICAgICAgICAgOiBcImJvb2tpbmdfaWRcIixcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gc29ydF90eXBlICAgICAgIDogXCJERVNDXCIsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIHBhZ2VfbnVtICAgICAgICA6IDEsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIHBhZ2VfaXRlbXNfY291bnQ6IDEwLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBjcmVhdGVfZGF0ZSAgICAgOiBcIlwiLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBrZXl3b3JkICAgICAgICAgOiBcIlwiLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBzb3VyY2UgICAgICAgICAgOiBcIlwiXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogIENoZWNrIGlmIGNhbGVuZGFyIGZvciBzcGVjaWZpYyBib29raW5nIHJlc291cmNlIGRlZmluZWQgICA6OiAgIHRydWUgfCBmYWxzZVxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50fSByZXNvdXJjZV9pZFxyXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxyXG5cdCAqL1xyXG5cdG9iai5jYWxlbmRhcl9faXNfZGVmaW5lZCA9IGZ1bmN0aW9uICggcmVzb3VyY2VfaWQgKSB7XHJcblxyXG5cdFx0cmV0dXJuICgndW5kZWZpbmVkJyAhPT0gdHlwZW9mKCBwX2NhbGVuZGFyc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdICkgKTtcclxuXHR9O1xyXG5cclxuXHQvKipcclxuXHQgKiAgQ3JlYXRlIENhbGVuZGFyIGluaXRpYWxpemluZ1xyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50fSByZXNvdXJjZV9pZFxyXG5cdCAqL1xyXG5cdG9iai5jYWxlbmRhcl9faW5pdCA9IGZ1bmN0aW9uICggcmVzb3VyY2VfaWQgKSB7XHJcblxyXG5cdFx0cF9jYWxlbmRhcnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXSA9IHt9O1xyXG5cdFx0cF9jYWxlbmRhcnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgJ2lkJyBdID0gcmVzb3VyY2VfaWQ7XHJcblx0XHRwX2NhbGVuZGFyc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdWyAncGVuZGluZ19kYXlzX3NlbGVjdGFibGUnIF0gPSBmYWxzZTtcclxuXHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogU2V0IHBhcmFtcyBmb3IgYWxsICBjYWxlbmRhcnNcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBjYWxlbmRhcnNfb2JqXHRcdE9iamVjdCB7IGNhbGVuZGFyXzE6IHt9IH1cclxuXHQgKiBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgY2FsZW5kYXJfMzoge30sIC4uLiB9XHJcblx0ICovXHJcblx0b2JqLmNhbGVuZGFyc19hbGxfX3NldCA9IGZ1bmN0aW9uICggY2FsZW5kYXJzX29iaiApIHtcclxuXHRcdHBfY2FsZW5kYXJzID0gY2FsZW5kYXJzX29iajtcclxuXHR9O1xyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgYm9va2luZ3MgaW4gYWxsIGNhbGVuZGFyc1xyXG5cdCAqXHJcblx0ICogQHJldHVybnMge29iamVjdHx7fX1cclxuXHQgKi9cclxuXHRvYmouY2FsZW5kYXJzX2FsbF9fZ2V0ID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHBfY2FsZW5kYXJzO1xyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBjYWxlbmRhciBvYmplY3QgICA6OiAgIHsgaWQ6IDEsIOKApiB9XHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge3N0cmluZ3xpbnR9IHJlc291cmNlX2lkXHRcdFx0XHQgICcyJ1xyXG5cdCAqIEByZXR1cm5zIHtvYmplY3R8Ym9vbGVhbn1cdFx0XHRcdFx0eyBpZDogMiAs4oCmIH1cclxuXHQgKi9cclxuXHRvYmouY2FsZW5kYXJfX2dldF9wYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCByZXNvdXJjZV9pZCApIHtcclxuXHJcblx0XHRpZiAoIG9iai5jYWxlbmRhcl9faXNfZGVmaW5lZCggcmVzb3VyY2VfaWQgKSApe1xyXG5cclxuXHRcdFx0cmV0dXJuIHBfY2FsZW5kYXJzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF07XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogU2V0IGNhbGVuZGFyIG9iamVjdCAgIDo6ICAgeyBkYXRlczogIE9iamVjdCB7IFwiMjAyMy0wNy0yMVwiOiB74oCmfSwgXCIyMDIzLTA3LTIyXCI6IHvigKZ9LCBcIjIwMjMtMDctMjNcIjoge+KApn0sIOKApiB9XHJcblx0ICpcclxuXHQgKiBpZiBjYWxlbmRhciBvYmplY3QgIG5vdCBkZWZpbmVkLCB0aGVuICBpdCdzIHdpbGwgYmUgZGVmaW5lZCBhbmQgSUQgc2V0XHJcblx0ICogaWYgY2FsZW5kYXIgZXhpc3QsIHRoZW4gIHN5c3RlbSBzZXQgIGFzIG5ldyBvciBvdmVyd3JpdGUgb25seSBwcm9wZXJ0aWVzIGZyb20gY2FsZW5kYXJfcHJvcGVydHlfb2JqIHBhcmFtZXRlciwgIGJ1dCBvdGhlciBwcm9wZXJ0aWVzIHdpbGwgYmUgZXhpc3RlZCBhbmQgbm90IG92ZXJ3cml0ZSwgbGlrZSAnaWQnXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge3N0cmluZ3xpbnR9IHJlc291cmNlX2lkXHRcdFx0XHQgICcyJ1xyXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBjYWxlbmRhcl9wcm9wZXJ0eV9vYmpcdFx0XHRcdFx0ICB7ICBkYXRlczogIE9iamVjdCB7IFwiMjAyMy0wNy0yMVwiOiB74oCmfSwgXCIyMDIzLTA3LTIyXCI6IHvigKZ9LCBcIjIwMjMtMDctMjNcIjoge+KApn0sIOKApiB9ICB9XHJcblx0ICogQHBhcmFtIHtib29sZWFufSBpc19jb21wbGV0ZV9vdmVyd3JpdGVcdFx0ICBpZiAndHJ1ZScgKGRlZmF1bHQ6ICdmYWxzZScpLCAgdGhlbiAgb25seSBvdmVyd3JpdGUgb3IgYWRkICBuZXcgcHJvcGVydGllcyBpbiAgY2FsZW5kYXJfcHJvcGVydHlfb2JqXHJcblx0ICogQHJldHVybnMgeyp9XHJcblx0ICpcclxuXHQgKiBFeGFtcGxlczpcclxuXHQgKlxyXG5cdCAqIENvbW1vbiB1c2FnZSBpbiBQSFA6XHJcblx0ICogICBcdFx0XHRlY2hvIFwiICBfd3BiYy5jYWxlbmRhcl9fc2V0KCAgXCIgLmludHZhbCggJHJlc291cmNlX2lkICkgLiBcIiwgeyAnZGF0ZXMnOiBcIiAuIHdwX2pzb25fZW5jb2RlKCAkYXZhaWxhYmlsaXR5X3Blcl9kYXlzX2FyciApIC4gXCIgfSApO1wiO1xyXG5cdCAqL1xyXG5cdG9iai5jYWxlbmRhcl9fc2V0X3BhcmFtZXRlcnMgPSBmdW5jdGlvbiAoIHJlc291cmNlX2lkLCBjYWxlbmRhcl9wcm9wZXJ0eV9vYmosIGlzX2NvbXBsZXRlX292ZXJ3cml0ZSA9IGZhbHNlICApIHtcclxuXHJcblx0XHRpZiAoICghb2JqLmNhbGVuZGFyX19pc19kZWZpbmVkKCByZXNvdXJjZV9pZCApKSB8fCAodHJ1ZSA9PT0gaXNfY29tcGxldGVfb3ZlcndyaXRlKSApe1xyXG5cdFx0XHRvYmouY2FsZW5kYXJfX2luaXQoIHJlc291cmNlX2lkICk7XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yICggdmFyIHByb3BfbmFtZSBpbiBjYWxlbmRhcl9wcm9wZXJ0eV9vYmogKXtcclxuXHJcblx0XHRcdHBfY2FsZW5kYXJzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bIHByb3BfbmFtZSBdID0gY2FsZW5kYXJfcHJvcGVydHlfb2JqWyBwcm9wX25hbWUgXTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gcF9jYWxlbmRhcnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXTtcclxuXHR9O1xyXG5cclxuXHQvKipcclxuXHQgKiBTZXQgcHJvcGVydHkgIHRvICBjYWxlbmRhclxyXG5cdCAqIEBwYXJhbSByZXNvdXJjZV9pZFx0XCIxXCJcclxuXHQgKiBAcGFyYW0gcHJvcF9uYW1lXHRcdG5hbWUgb2YgcHJvcGVydHlcclxuXHQgKiBAcGFyYW0gcHJvcF92YWx1ZVx0dmFsdWUgb2YgcHJvcGVydHlcclxuXHQgKiBAcmV0dXJucyB7Kn1cdFx0XHRjYWxlbmRhciBvYmplY3RcclxuXHQgKi9cclxuXHRvYmouY2FsZW5kYXJfX3NldF9wYXJhbV92YWx1ZSA9IGZ1bmN0aW9uICggcmVzb3VyY2VfaWQsIHByb3BfbmFtZSwgcHJvcF92YWx1ZSApIHtcclxuXHJcblx0XHRpZiAoICghb2JqLmNhbGVuZGFyX19pc19kZWZpbmVkKCByZXNvdXJjZV9pZCApKSApe1xyXG5cdFx0XHRvYmouY2FsZW5kYXJfX2luaXQoIHJlc291cmNlX2lkICk7XHJcblx0XHR9XHJcblxyXG5cdFx0cF9jYWxlbmRhcnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgcHJvcF9uYW1lIF0gPSBwcm9wX3ZhbHVlO1xyXG5cclxuXHRcdHJldHVybiBwX2NhbGVuZGFyc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdO1xyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqICBHZXQgY2FsZW5kYXIgcHJvcGVydHkgdmFsdWUgICBcdDo6ICAgbWl4ZWQgfCBudWxsXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge3N0cmluZ3xpbnR9ICByZXNvdXJjZV9pZFx0XHQnMSdcclxuXHQgKiBAcGFyYW0ge3N0cmluZ30gcHJvcF9uYW1lXHRcdFx0J3NlbGVjdGlvbl9tb2RlJ1xyXG5cdCAqIEByZXR1cm5zIHsqfG51bGx9XHRcdFx0XHRcdG1peGVkIHwgbnVsbFxyXG5cdCAqL1xyXG5cdG9iai5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlID0gZnVuY3Rpb24oIHJlc291cmNlX2lkLCBwcm9wX25hbWUgKXtcclxuXHJcblx0XHRpZiAoXHJcblx0XHRcdCAgICggb2JqLmNhbGVuZGFyX19pc19kZWZpbmVkKCByZXNvdXJjZV9pZCApIClcclxuXHRcdFx0JiYgKCAndW5kZWZpbmVkJyAhPT0gdHlwZW9mICggcF9jYWxlbmRhcnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgcHJvcF9uYW1lIF0gKSApXHJcblx0XHQpe1xyXG5cdFx0XHRyZXR1cm4gIHBfY2FsZW5kYXJzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bIHByb3BfbmFtZSBdO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBudWxsO1x0XHQvLyBJZiBzb21lIHByb3BlcnR5IG5vdCBkZWZpbmVkLCB0aGVuIG51bGw7XHJcblx0fTtcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHJcblx0Ly8gQm9va2luZ3MgXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0dmFyIHBfYm9va2luZ3MgPSBvYmouYm9va2luZ3Nfb2JqID0gb2JqLmJvb2tpbmdzX29iaiB8fCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gY2FsZW5kYXJfMTogT2JqZWN0IHtcclxuIFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9cdFx0XHRcdFx0XHQgICBpZDogICAgIDFcclxuIFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9cdFx0XHRcdFx0XHQgLCBkYXRlczogIE9iamVjdCB7IFwiMjAyMy0wNy0yMVwiOiB74oCmfSwgXCIyMDIzLTA3LTIyXCI6IHvigKZ9LCBcIjIwMjMtMDctMjNcIjoge+KApn0sIOKAplxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogIENoZWNrIGlmIGJvb2tpbmdzIGZvciBzcGVjaWZpYyBib29raW5nIHJlc291cmNlIGRlZmluZWQgICA6OiAgIHRydWUgfCBmYWxzZVxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50fSByZXNvdXJjZV9pZFxyXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxyXG5cdCAqL1xyXG5cdG9iai5ib29raW5nc19pbl9jYWxlbmRhcl9faXNfZGVmaW5lZCA9IGZ1bmN0aW9uICggcmVzb3VyY2VfaWQgKSB7XHJcblxyXG5cdFx0cmV0dXJuICgndW5kZWZpbmVkJyAhPT0gdHlwZW9mKCBwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF0gKSApO1xyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBib29raW5ncyBjYWxlbmRhciBvYmplY3QgICA6OiAgIHsgaWQ6IDEgLCBkYXRlczogIE9iamVjdCB7IFwiMjAyMy0wNy0yMVwiOiB74oCmfSwgXCIyMDIzLTA3LTIyXCI6IHvigKZ9LCBcIjIwMjMtMDctMjNcIjoge+KApn0sIOKApiB9XHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge3N0cmluZ3xpbnR9IHJlc291cmNlX2lkXHRcdFx0XHQgICcyJ1xyXG5cdCAqIEByZXR1cm5zIHtvYmplY3R8Ym9vbGVhbn1cdFx0XHRcdFx0eyBpZDogMiAsIGRhdGVzOiAgT2JqZWN0IHsgXCIyMDIzLTA3LTIxXCI6IHvigKZ9LCBcIjIwMjMtMDctMjJcIjoge+KApn0sIFwiMjAyMy0wNy0yM1wiOiB74oCmfSwg4oCmIH1cclxuXHQgKi9cclxuXHRvYmouYm9va2luZ3NfaW5fY2FsZW5kYXJfX2dldCA9IGZ1bmN0aW9uKCByZXNvdXJjZV9pZCApe1xyXG5cclxuXHRcdGlmICggb2JqLmJvb2tpbmdzX2luX2NhbGVuZGFyX19pc19kZWZpbmVkKCByZXNvdXJjZV9pZCApICl7XHJcblxyXG5cdFx0XHRyZXR1cm4gcF9ib29raW5nc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIFNldCBib29raW5ncyBjYWxlbmRhciBvYmplY3QgICA6OiAgIHsgZGF0ZXM6ICBPYmplY3QgeyBcIjIwMjMtMDctMjFcIjoge+KApn0sIFwiMjAyMy0wNy0yMlwiOiB74oCmfSwgXCIyMDIzLTA3LTIzXCI6IHvigKZ9LCDigKYgfVxyXG5cdCAqXHJcblx0ICogaWYgY2FsZW5kYXIgb2JqZWN0ICBub3QgZGVmaW5lZCwgdGhlbiAgaXQncyB3aWxsIGJlIGRlZmluZWQgYW5kIElEIHNldFxyXG5cdCAqIGlmIGNhbGVuZGFyIGV4aXN0LCB0aGVuICBzeXN0ZW0gc2V0ICBhcyBuZXcgb3Igb3ZlcndyaXRlIG9ubHkgcHJvcGVydGllcyBmcm9tIGNhbGVuZGFyX29iaiBwYXJhbWV0ZXIsICBidXQgb3RoZXIgcHJvcGVydGllcyB3aWxsIGJlIGV4aXN0ZWQgYW5kIG5vdCBvdmVyd3JpdGUsIGxpa2UgJ2lkJ1xyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50fSByZXNvdXJjZV9pZFx0XHRcdFx0ICAnMidcclxuXHQgKiBAcGFyYW0ge29iamVjdH0gY2FsZW5kYXJfb2JqXHRcdFx0XHRcdCAgeyAgZGF0ZXM6ICBPYmplY3QgeyBcIjIwMjMtMDctMjFcIjoge+KApn0sIFwiMjAyMy0wNy0yMlwiOiB74oCmfSwgXCIyMDIzLTA3LTIzXCI6IHvigKZ9LCDigKYgfSAgfVxyXG5cdCAqIEByZXR1cm5zIHsqfVxyXG5cdCAqXHJcblx0ICogRXhhbXBsZXM6XHJcblx0ICpcclxuXHQgKiBDb21tb24gdXNhZ2UgaW4gUEhQOlxyXG5cdCAqICAgXHRcdFx0ZWNobyBcIiAgX3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX3NldCggIFwiIC5pbnR2YWwoICRyZXNvdXJjZV9pZCApIC4gXCIsIHsgJ2RhdGVzJzogXCIgLiB3cF9qc29uX2VuY29kZSggJGF2YWlsYWJpbGl0eV9wZXJfZGF5c19hcnIgKSAuIFwiIH0gKTtcIjtcclxuXHQgKi9cclxuXHRvYmouYm9va2luZ3NfaW5fY2FsZW5kYXJfX3NldCA9IGZ1bmN0aW9uKCByZXNvdXJjZV9pZCwgY2FsZW5kYXJfb2JqICl7XHJcblxyXG5cdFx0aWYgKCAhIG9iai5ib29raW5nc19pbl9jYWxlbmRhcl9faXNfZGVmaW5lZCggcmVzb3VyY2VfaWQgKSApe1xyXG5cdFx0XHRwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF0gPSB7fTtcclxuXHRcdFx0cF9ib29raW5nc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdWyAnaWQnIF0gPSByZXNvdXJjZV9pZDtcclxuXHRcdH1cclxuXHJcblx0XHRmb3IgKCB2YXIgcHJvcF9uYW1lIGluIGNhbGVuZGFyX29iaiApe1xyXG5cclxuXHRcdFx0cF9ib29raW5nc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdWyBwcm9wX25hbWUgXSA9IGNhbGVuZGFyX29ialsgcHJvcF9uYW1lIF07XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHBfYm9va2luZ3NbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXTtcclxuXHR9O1xyXG5cclxuXHQvLyBEYXRlc1xyXG5cclxuXHQvKipcclxuXHQgKiAgR2V0IGJvb2tpbmdzIGRhdGEgZm9yIEFMTCBEYXRlcyBpbiBjYWxlbmRhciAgIDo6ICAgZmFsc2UgfCB7IFwiMjAyMy0wNy0yMlwiOiB74oCmfSwgXCIyMDIzLTA3LTIzXCI6IHvigKZ9LCDigKYgfVxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50fSByZXNvdXJjZV9pZFx0XHRcdCcxJ1xyXG5cdCAqIEByZXR1cm5zIHtvYmplY3R8Ym9vbGVhbn1cdFx0XHRcdGZhbHNlIHwgT2JqZWN0IHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIjIwMjMtMDctMjRcIjogT2JqZWN0IHsgWydzdW1tYXJ5J11bJ3N0YXR1c19mb3JfZGF5J106IFwiYXZhaWxhYmxlXCIsIGRheV9hdmFpbGFiaWxpdHk6IDEsIG1heF9jYXBhY2l0eTogMSwg4oCmIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIjIwMjMtMDctMjZcIjogT2JqZWN0IHsgWydzdW1tYXJ5J11bJ3N0YXR1c19mb3JfZGF5J106IFwiZnVsbF9kYXlfYm9va2luZ1wiLCBbJ3N1bW1hcnknXVsnc3RhdHVzX2Zvcl9ib29raW5ncyddOiBcInBlbmRpbmdcIiwgZGF5X2F2YWlsYWJpbGl0eTogMCwg4oCmIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIjIwMjMtMDctMjlcIjogT2JqZWN0IHsgWydzdW1tYXJ5J11bJ3N0YXR1c19mb3JfZGF5J106IFwicmVzb3VyY2VfYXZhaWxhYmlsaXR5XCIsIGRheV9hdmFpbGFiaWxpdHk6IDAsIG1heF9jYXBhY2l0eTogMSwg4oCmIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIjIwMjMtMDctMzBcIjoge+KApn0sIFwiMjAyMy0wNy0zMVwiOiB74oCmfSwg4oCmXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHQgKi9cclxuXHRvYmouYm9va2luZ3NfaW5fY2FsZW5kYXJfX2dldF9kYXRlcyA9IGZ1bmN0aW9uKCByZXNvdXJjZV9pZCl7XHJcblxyXG5cdFx0aWYgKFxyXG5cdFx0XHQgICAoIG9iai5ib29raW5nc19pbl9jYWxlbmRhcl9faXNfZGVmaW5lZCggcmVzb3VyY2VfaWQgKSApXHJcblx0XHRcdCYmICggJ3VuZGVmaW5lZCcgIT09IHR5cGVvZiAoIHBfYm9va2luZ3NbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgJ2RhdGVzJyBdICkgKVxyXG5cdFx0KXtcclxuXHRcdFx0cmV0dXJuICBwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bICdkYXRlcycgXTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gZmFsc2U7XHRcdC8vIElmIHNvbWUgcHJvcGVydHkgbm90IGRlZmluZWQsIHRoZW4gZmFsc2U7XHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogU2V0IGJvb2tpbmdzIGRhdGVzIGluIGNhbGVuZGFyIG9iamVjdCAgIDo6ICAgIHsgXCIyMDIzLTA3LTIxXCI6IHvigKZ9LCBcIjIwMjMtMDctMjJcIjoge+KApn0sIFwiMjAyMy0wNy0yM1wiOiB74oCmfSwg4oCmIH1cclxuXHQgKlxyXG5cdCAqIGlmIGNhbGVuZGFyIG9iamVjdCAgbm90IGRlZmluZWQsIHRoZW4gIGl0J3Mgd2lsbCBiZSBkZWZpbmVkIGFuZCAnaWQnLCAnZGF0ZXMnIHNldFxyXG5cdCAqIGlmIGNhbGVuZGFyIGV4aXN0LCB0aGVuIHN5c3RlbSBhZGQgYSAgbmV3IG9yIG92ZXJ3cml0ZSBvbmx5IGRhdGVzIGZyb20gZGF0ZXNfb2JqIHBhcmFtZXRlcixcclxuXHQgKiBidXQgb3RoZXIgZGF0ZXMgbm90IGZyb20gcGFyYW1ldGVyIGRhdGVzX29iaiB3aWxsIGJlIGV4aXN0ZWQgYW5kIG5vdCBvdmVyd3JpdGUuXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge3N0cmluZ3xpbnR9IHJlc291cmNlX2lkXHRcdFx0XHQgICcyJ1xyXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBkYXRlc19vYmpcdFx0XHRcdFx0ICB7IFwiMjAyMy0wNy0yMVwiOiB74oCmfSwgXCIyMDIzLTA3LTIyXCI6IHvigKZ9LCBcIjIwMjMtMDctMjNcIjoge+KApn0sIOKApiB9XHJcblx0ICogQHBhcmFtIHtib29sZWFufSBpc19jb21wbGV0ZV9vdmVyd3JpdGVcdFx0ICBpZiBmYWxzZSwgIHRoZW4gIG9ubHkgb3ZlcndyaXRlIG9yIGFkZCAgZGF0ZXMgZnJvbSBcdGRhdGVzX29ialxyXG5cdCAqIEByZXR1cm5zIHsqfVxyXG5cdCAqXHJcblx0ICogRXhhbXBsZXM6XHJcblx0ICogICBcdFx0XHRfd3BiYy5ib29raW5nc19pbl9jYWxlbmRhcl9fc2V0X2RhdGVzKCByZXNvdXJjZV9pZCwgeyBcIjIwMjMtMDctMjFcIjoge+KApn0sIFwiMjAyMy0wNy0yMlwiOiB74oCmfSwg4oCmIH0gICk7XHRcdDwtICAgb3ZlcndyaXRlIEFMTCBkYXRlc1xyXG5cdCAqICAgXHRcdFx0X3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX3NldF9kYXRlcyggcmVzb3VyY2VfaWQsIHsgXCIyMDIzLTA3LTIyXCI6IHvigKZ9IH0sICBmYWxzZSAgKTtcdFx0XHRcdFx0PC0gICBhZGQgb3Igb3ZlcndyaXRlIG9ubHkgIFx0XCIyMDIzLTA3LTIyXCI6IHt9XHJcblx0ICpcclxuXHQgKiBDb21tb24gdXNhZ2UgaW4gUEhQOlxyXG5cdCAqICAgXHRcdFx0ZWNobyBcIiAgX3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX3NldF9kYXRlcyggIFwiIC4gaW50dmFsKCAkcmVzb3VyY2VfaWQgKSAuIFwiLCAgXCIgLiB3cF9qc29uX2VuY29kZSggJGF2YWlsYWJpbGl0eV9wZXJfZGF5c19hcnIgKSAuIFwiICApOyAgXCI7XHJcblx0ICovXHJcblx0b2JqLmJvb2tpbmdzX2luX2NhbGVuZGFyX19zZXRfZGF0ZXMgPSBmdW5jdGlvbiggcmVzb3VyY2VfaWQsIGRhdGVzX29iaiAsIGlzX2NvbXBsZXRlX292ZXJ3cml0ZSA9IHRydWUgKXtcclxuXHJcblx0XHRpZiAoICFvYmouYm9va2luZ3NfaW5fY2FsZW5kYXJfX2lzX2RlZmluZWQoIHJlc291cmNlX2lkICkgKXtcclxuXHRcdFx0b2JqLmJvb2tpbmdzX2luX2NhbGVuZGFyX19zZXQoIHJlc291cmNlX2lkLCB7ICdkYXRlcyc6IHt9IH0gKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoICd1bmRlZmluZWQnID09PSB0eXBlb2YgKHBfYm9va2luZ3NbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgJ2RhdGVzJyBdKSApe1xyXG5cdFx0XHRwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bICdkYXRlcycgXSA9IHt9XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGlzX2NvbXBsZXRlX292ZXJ3cml0ZSl7XHJcblxyXG5cdFx0XHQvLyBDb21wbGV0ZSBvdmVyd3JpdGUgYWxsICBib29raW5nIGRhdGVzXHJcblx0XHRcdHBfYm9va2luZ3NbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgJ2RhdGVzJyBdID0gZGF0ZXNfb2JqO1xyXG5cdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdC8vIEFkZCBvbmx5ICBuZXcgb3Igb3ZlcndyaXRlIGV4aXN0IGJvb2tpbmcgZGF0ZXMgZnJvbSAgcGFyYW1ldGVyLiBCb29raW5nIGRhdGVzIG5vdCBmcm9tICBwYXJhbWV0ZXIgIHdpbGwgIGJlIHdpdGhvdXQgY2huYW5nZXNcclxuXHRcdFx0Zm9yICggdmFyIHByb3BfbmFtZSBpbiBkYXRlc19vYmogKXtcclxuXHJcblx0XHRcdFx0cF9ib29raW5nc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdWydkYXRlcyddWyBwcm9wX25hbWUgXSA9IGRhdGVzX29ialsgcHJvcF9uYW1lIF07XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gcF9ib29raW5nc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdO1xyXG5cdH07XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiAgR2V0IGJvb2tpbmdzIGRhdGEgZm9yIHNwZWNpZmljIGRhdGUgaW4gY2FsZW5kYXIgICA6OiAgIGZhbHNlIHwgeyBkYXlfYXZhaWxhYmlsaXR5OiAxLCAuLi4gfVxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50fSByZXNvdXJjZV9pZFx0XHRcdCcxJ1xyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzcWxfY2xhc3NfZGF5XHRcdFx0JzIwMjMtMDctMjEnXHJcblx0ICogQHJldHVybnMge29iamVjdHxib29sZWFufVx0XHRcdFx0ZmFsc2UgfCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGRheV9hdmFpbGFiaWxpdHk6IDRcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0bWF4X2NhcGFjaXR5OiA0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gID49IEJ1c2luZXNzIExhcmdlXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdDI6IE9iamVjdCB7IGlzX2RheV91bmF2YWlsYWJsZTogZmFsc2UsIF9kYXlfc3RhdHVzOiBcImF2YWlsYWJsZVwiIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0MTA6IE9iamVjdCB7IGlzX2RheV91bmF2YWlsYWJsZTogZmFsc2UsIF9kYXlfc3RhdHVzOiBcImF2YWlsYWJsZVwiIH1cdFx0Ly8gID49IEJ1c2luZXNzIExhcmdlIC4uLlxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQxMTogT2JqZWN0IHsgaXNfZGF5X3VuYXZhaWxhYmxlOiBmYWxzZSwgX2RheV9zdGF0dXM6IFwiYXZhaWxhYmxlXCIgfVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQxMjogT2JqZWN0IHsgaXNfZGF5X3VuYXZhaWxhYmxlOiBmYWxzZSwgX2RheV9zdGF0dXM6IFwiYXZhaWxhYmxlXCIgfVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdCAqL1xyXG5cdG9iai5ib29raW5nc19pbl9jYWxlbmRhcl9fZ2V0X2Zvcl9kYXRlID0gZnVuY3Rpb24oIHJlc291cmNlX2lkLCBzcWxfY2xhc3NfZGF5ICl7XHJcblxyXG5cdFx0aWYgKFxyXG5cdFx0XHQgICAoIG9iai5ib29raW5nc19pbl9jYWxlbmRhcl9faXNfZGVmaW5lZCggcmVzb3VyY2VfaWQgKSApXHJcblx0XHRcdCYmICggJ3VuZGVmaW5lZCcgIT09IHR5cGVvZiAoIHBfYm9va2luZ3NbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgJ2RhdGVzJyBdICkgKVxyXG5cdFx0XHQmJiAoICd1bmRlZmluZWQnICE9PSB0eXBlb2YgKCBwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bICdkYXRlcycgXVsgc3FsX2NsYXNzX2RheSBdICkgKVxyXG5cdFx0KXtcclxuXHRcdFx0cmV0dXJuICBwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bICdkYXRlcycgXVsgc3FsX2NsYXNzX2RheSBdO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBmYWxzZTtcdFx0Ly8gSWYgc29tZSBwcm9wZXJ0eSBub3QgZGVmaW5lZCwgdGhlbiBmYWxzZTtcclxuXHR9O1xyXG5cclxuXHJcblx0Ly8gQW55ICBQQVJBTVMgICBpbiBib29raW5nc1xyXG5cclxuXHQvKipcclxuXHQgKiBTZXQgcHJvcGVydHkgIHRvICBib29raW5nXHJcblx0ICogQHBhcmFtIHJlc291cmNlX2lkXHRcIjFcIlxyXG5cdCAqIEBwYXJhbSBwcm9wX25hbWVcdFx0bmFtZSBvZiBwcm9wZXJ0eVxyXG5cdCAqIEBwYXJhbSBwcm9wX3ZhbHVlXHR2YWx1ZSBvZiBwcm9wZXJ0eVxyXG5cdCAqIEByZXR1cm5zIHsqfVx0XHRcdGJvb2tpbmcgb2JqZWN0XHJcblx0ICovXHJcblx0b2JqLmJvb2tpbmdfX3NldF9wYXJhbV92YWx1ZSA9IGZ1bmN0aW9uICggcmVzb3VyY2VfaWQsIHByb3BfbmFtZSwgcHJvcF92YWx1ZSApIHtcclxuXHJcblx0XHRpZiAoICEgb2JqLmJvb2tpbmdzX2luX2NhbGVuZGFyX19pc19kZWZpbmVkKCByZXNvdXJjZV9pZCApICl7XHJcblx0XHRcdHBfYm9va2luZ3NbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXSA9IHt9O1xyXG5cdFx0XHRwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bICdpZCcgXSA9IHJlc291cmNlX2lkO1xyXG5cdFx0fVxyXG5cclxuXHRcdHBfYm9va2luZ3NbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgcHJvcF9uYW1lIF0gPSBwcm9wX3ZhbHVlO1xyXG5cclxuXHRcdHJldHVybiBwX2Jvb2tpbmdzWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF07XHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogIEdldCBib29raW5nIHByb3BlcnR5IHZhbHVlICAgXHQ6OiAgIG1peGVkIHwgbnVsbFxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50fSAgcmVzb3VyY2VfaWRcdFx0JzEnXHJcblx0ICogQHBhcmFtIHtzdHJpbmd9IHByb3BfbmFtZVx0XHRcdCdzZWxlY3Rpb25fbW9kZSdcclxuXHQgKiBAcmV0dXJucyB7KnxudWxsfVx0XHRcdFx0XHRtaXhlZCB8IG51bGxcclxuXHQgKi9cclxuXHRvYmouYm9va2luZ19fZ2V0X3BhcmFtX3ZhbHVlID0gZnVuY3Rpb24oIHJlc291cmNlX2lkLCBwcm9wX25hbWUgKXtcclxuXHJcblx0XHRpZiAoXHJcblx0XHRcdCAgICggb2JqLmJvb2tpbmdzX2luX2NhbGVuZGFyX19pc19kZWZpbmVkKCByZXNvdXJjZV9pZCApIClcclxuXHRcdFx0JiYgKCAndW5kZWZpbmVkJyAhPT0gdHlwZW9mICggcF9ib29raW5nc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdWyBwcm9wX25hbWUgXSApIClcclxuXHRcdCl7XHJcblx0XHRcdHJldHVybiAgcF9ib29raW5nc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdWyBwcm9wX25hbWUgXTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gbnVsbDtcdFx0Ly8gSWYgc29tZSBwcm9wZXJ0eSBub3QgZGVmaW5lZCwgdGhlbiBudWxsO1xyXG5cdH07XHJcblxyXG5cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFNldCBib29raW5ncyBmb3IgYWxsICBjYWxlbmRhcnNcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBjYWxlbmRhcnNfb2JqXHRcdE9iamVjdCB7IGNhbGVuZGFyXzE6IHsgaWQ6IDEsIGRhdGVzOiBPYmplY3QgeyBcIjIwMjMtMDctMjJcIjoge+KApn0sIFwiMjAyMy0wNy0yM1wiOiB74oCmfSwgXCIyMDIzLTA3LTI0XCI6IHvigKZ9LCDigKYgfSB9XHJcblx0ICogXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0IGNhbGVuZGFyXzM6IHt9LCAuLi4gfVxyXG5cdCAqL1xyXG5cdG9iai5ib29raW5nc19pbl9jYWxlbmRhcnNfX3NldF9hbGwgPSBmdW5jdGlvbiAoIGNhbGVuZGFyc19vYmogKSB7XHJcblx0XHRwX2Jvb2tpbmdzID0gY2FsZW5kYXJzX29iajtcclxuXHR9O1xyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgYm9va2luZ3MgaW4gYWxsIGNhbGVuZGFyc1xyXG5cdCAqXHJcblx0ICogQHJldHVybnMge29iamVjdHx7fX1cclxuXHQgKi9cclxuXHRvYmouYm9va2luZ3NfaW5fY2FsZW5kYXJzX19nZXRfYWxsID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHBfYm9va2luZ3M7XHJcblx0fTtcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHJcblxyXG5cclxuXHQvLyBTZWFzb25zIFx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdHZhciBwX3NlYXNvbnMgPSBvYmouc2Vhc29uc19vYmogPSBvYmouc2Vhc29uc19vYmogfHwge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGNhbGVuZGFyXzE6IE9iamVjdCB7XHJcbiBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vXHRcdFx0XHRcdFx0ICAgaWQ6ICAgICAxXHJcbiBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vXHRcdFx0XHRcdFx0ICwgZGF0ZXM6ICBPYmplY3QgeyBcIjIwMjMtMDctMjFcIjoge+KApn0sIFwiMjAyMy0wNy0yMlwiOiB74oCmfSwgXCIyMDIzLTA3LTIzXCI6IHvigKZ9LCDigKZcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyB9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIEFkZCBzZWFzb24gbmFtZXMgZm9yIGRhdGVzIGluIGNhbGVuZGFyIG9iamVjdCAgIDo6ICAgIHsgXCIyMDIzLTA3LTIxXCI6IFsgJ3dwYmNfc2Vhc29uX3NlcHRlbWJlcl8yMDIzJywgJ3dwYmNfc2Vhc29uX3NlcHRlbWJlcl8yMDI0JyBdLCBcIjIwMjMtMDctMjJcIjogWy4uLl0sIC4uLiB9XHJcblx0ICpcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfGludH0gcmVzb3VyY2VfaWRcdFx0XHRcdCAgJzInXHJcblx0ICogQHBhcmFtIHtvYmplY3R9IGRhdGVzX29ialx0XHRcdFx0XHQgIHsgXCIyMDIzLTA3LTIxXCI6IHvigKZ9LCBcIjIwMjMtMDctMjJcIjoge+KApn0sIFwiMjAyMy0wNy0yM1wiOiB74oCmfSwg4oCmIH1cclxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IGlzX2NvbXBsZXRlX292ZXJ3cml0ZVx0XHQgIGlmIGZhbHNlLCAgdGhlbiAgb25seSAgYWRkICBkYXRlcyBmcm9tIFx0ZGF0ZXNfb2JqXHJcblx0ICogQHJldHVybnMgeyp9XHJcblx0ICpcclxuXHQgKiBFeGFtcGxlczpcclxuXHQgKiAgIFx0XHRcdF93cGJjLnNlYXNvbnNfX3NldCggcmVzb3VyY2VfaWQsIHsgXCIyMDIzLTA3LTIxXCI6IFsgJ3dwYmNfc2Vhc29uX3NlcHRlbWJlcl8yMDIzJywgJ3dwYmNfc2Vhc29uX3NlcHRlbWJlcl8yMDI0JyBdLCBcIjIwMjMtMDctMjJcIjogWy4uLl0sIC4uLiB9ICApO1xyXG5cdCAqL1xyXG5cdG9iai5zZWFzb25zX19zZXQgPSBmdW5jdGlvbiggcmVzb3VyY2VfaWQsIGRhdGVzX29iaiAsIGlzX2NvbXBsZXRlX292ZXJ3cml0ZSA9IGZhbHNlICl7XHJcblxyXG5cdFx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIChwX3NlYXNvbnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXSkgKXtcclxuXHRcdFx0cF9zZWFzb25zWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF0gPSB7fTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIGlzX2NvbXBsZXRlX292ZXJ3cml0ZSApe1xyXG5cclxuXHRcdFx0Ly8gQ29tcGxldGUgb3ZlcndyaXRlIGFsbCAgc2Vhc29uIGRhdGVzXHJcblx0XHRcdHBfc2Vhc29uc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdID0gZGF0ZXNfb2JqO1xyXG5cclxuXHRcdH0gZWxzZSB7XHJcblxyXG5cdFx0XHQvLyBBZGQgb25seSAgbmV3IG9yIG92ZXJ3cml0ZSBleGlzdCBib29raW5nIGRhdGVzIGZyb20gIHBhcmFtZXRlci4gQm9va2luZyBkYXRlcyBub3QgZnJvbSAgcGFyYW1ldGVyICB3aWxsICBiZSB3aXRob3V0IGNobmFuZ2VzXHJcblx0XHRcdGZvciAoIHZhciBwcm9wX25hbWUgaW4gZGF0ZXNfb2JqICl7XHJcblxyXG5cdFx0XHRcdGlmICggJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiAocF9zZWFzb25zWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bIHByb3BfbmFtZSBdKSApe1xyXG5cdFx0XHRcdFx0cF9zZWFzb25zWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bIHByb3BfbmFtZSBdID0gW107XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGZvciAoIHZhciBzZWFzb25fbmFtZV9rZXkgaW4gZGF0ZXNfb2JqWyBwcm9wX25hbWUgXSApe1xyXG5cdFx0XHRcdFx0cF9zZWFzb25zWyAnY2FsZW5kYXJfJyArIHJlc291cmNlX2lkIF1bIHByb3BfbmFtZSBdLnB1c2goIGRhdGVzX29ialsgcHJvcF9uYW1lIF1bIHNlYXNvbl9uYW1lX2tleSBdICk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHBfc2Vhc29uc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdO1xyXG5cdH07XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiAgR2V0IGJvb2tpbmdzIGRhdGEgZm9yIHNwZWNpZmljIGRhdGUgaW4gY2FsZW5kYXIgICA6OiAgIFtdIHwgWyAnd3BiY19zZWFzb25fc2VwdGVtYmVyXzIwMjMnLCAnd3BiY19zZWFzb25fc2VwdGVtYmVyXzIwMjQnIF1cclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfGludH0gcmVzb3VyY2VfaWRcdFx0XHQnMSdcclxuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3FsX2NsYXNzX2RheVx0XHRcdCcyMDIzLTA3LTIxJ1xyXG5cdCAqIEByZXR1cm5zIHtvYmplY3R8Ym9vbGVhbn1cdFx0XHRcdFtdICB8ICBbICd3cGJjX3NlYXNvbl9zZXB0ZW1iZXJfMjAyMycsICd3cGJjX3NlYXNvbl9zZXB0ZW1iZXJfMjAyNCcgXVxyXG5cdCAqL1xyXG5cdG9iai5zZWFzb25zX19nZXRfZm9yX2RhdGUgPSBmdW5jdGlvbiggcmVzb3VyY2VfaWQsIHNxbF9jbGFzc19kYXkgKXtcclxuXHJcblx0XHRpZiAoXHJcblx0XHRcdCAgICggJ3VuZGVmaW5lZCcgIT09IHR5cGVvZiAoIHBfc2Vhc29uc1sgJ2NhbGVuZGFyXycgKyByZXNvdXJjZV9pZCBdICkgKVxyXG5cdFx0XHQmJiAoICd1bmRlZmluZWQnICE9PSB0eXBlb2YgKCBwX3NlYXNvbnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgc3FsX2NsYXNzX2RheSBdICkgKVxyXG5cdFx0KXtcclxuXHRcdFx0cmV0dXJuICBwX3NlYXNvbnNbICdjYWxlbmRhcl8nICsgcmVzb3VyY2VfaWQgXVsgc3FsX2NsYXNzX2RheSBdO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBbXTtcdFx0Ly8gSWYgbm90IGRlZmluZWQsIHRoZW4gW107XHJcblx0fTtcclxuXHJcblxyXG5cdC8vIE90aGVyIHBhcmFtZXRlcnMgXHRcdFx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0dmFyIHBfb3RoZXIgPSBvYmoub3RoZXJfb2JqID0gb2JqLm90aGVyX29iaiB8fCB7IH07XHJcblxyXG5cdG9iai5zZXRfb3RoZXJfcGFyYW0gPSBmdW5jdGlvbiAoIHBhcmFtX2tleSwgcGFyYW1fdmFsICkge1xyXG5cdFx0cF9vdGhlclsgcGFyYW1fa2V5IF0gPSBwYXJhbV92YWw7XHJcblx0fTtcclxuXHJcblx0b2JqLmdldF9vdGhlcl9wYXJhbSA9IGZ1bmN0aW9uICggcGFyYW1fa2V5ICkge1xyXG5cdFx0cmV0dXJuIHBfb3RoZXJbIHBhcmFtX2tleSBdO1xyXG5cdH07XHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblxyXG5cdHJldHVybiBvYmo7XHJcblxyXG59KCBfd3BiYyB8fCB7fSwgalF1ZXJ5ICkpO1xyXG4iLCIvKipcclxuICogRXh0ZW5kIF93cGJjIHdpdGggIG5ldyBtZXRob2RzICAgICAgICAvL0ZpeEluOiA5LjguNi4yXHJcbiAqXHJcbiAqIEB0eXBlIHsqfHt9fVxyXG4gKiBAcHJpdmF0ZVxyXG4gKi9cclxuIF93cGJjID0gKGZ1bmN0aW9uICggb2JqLCAkKSB7XHJcblxyXG5cdC8vIExvYWQgQmFsYW5jZXIgXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHR2YXIgcF9iYWxhbmNlciA9IG9iai5iYWxhbmNlcl9vYmogPSBvYmouYmFsYW5jZXJfb2JqIHx8IHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnbWF4X3RocmVhZHMnOiAyLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdpbl9wcm9jZXNzJyA6IFtdLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd3YWl0JyAgICAgICA6IFtdXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH07XHJcblxyXG5cdCAvKipcclxuXHQgICogU2V0ICBtYXggcGFyYWxsZWwgcmVxdWVzdCAgdG8gIGxvYWRcclxuXHQgICpcclxuXHQgICogQHBhcmFtIG1heF90aHJlYWRzXHJcblx0ICAqL1xyXG5cdG9iai5iYWxhbmNlcl9fc2V0X21heF90aHJlYWRzID0gZnVuY3Rpb24gKCBtYXhfdGhyZWFkcyApe1xyXG5cclxuXHRcdHBfYmFsYW5jZXJbICdtYXhfdGhyZWFkcycgXSA9IG1heF90aHJlYWRzO1xyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqICBDaGVjayBpZiBiYWxhbmNlciBmb3Igc3BlY2lmaWMgYm9va2luZyByZXNvdXJjZSBkZWZpbmVkICAgOjogICB0cnVlIHwgZmFsc2VcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfGludH0gcmVzb3VyY2VfaWRcclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuXHQgKi9cclxuXHRvYmouYmFsYW5jZXJfX2lzX2RlZmluZWQgPSBmdW5jdGlvbiAoIHJlc291cmNlX2lkICkge1xyXG5cclxuXHRcdHJldHVybiAoJ3VuZGVmaW5lZCcgIT09IHR5cGVvZiggcF9iYWxhbmNlclsgJ2JhbGFuY2VyXycgKyByZXNvdXJjZV9pZCBdICkgKTtcclxuXHR9O1xyXG5cclxuXHJcblx0LyoqXHJcblx0ICogIENyZWF0ZSBiYWxhbmNlciBpbml0aWFsaXppbmdcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfGludH0gcmVzb3VyY2VfaWRcclxuXHQgKi9cclxuXHRvYmouYmFsYW5jZXJfX2luaXQgPSBmdW5jdGlvbiAoIHJlc291cmNlX2lkLCBmdW5jdGlvbl9uYW1lICwgcGFyYW1zID17fSkge1xyXG5cclxuXHRcdHZhciBiYWxhbmNlX29iaiA9IHt9O1xyXG5cdFx0YmFsYW5jZV9vYmpbICdyZXNvdXJjZV9pZCcgXSAgID0gcmVzb3VyY2VfaWQ7XHJcblx0XHRiYWxhbmNlX29ialsgJ3ByaW9yaXR5JyBdICAgICAgPSAxO1xyXG5cdFx0YmFsYW5jZV9vYmpbICdmdW5jdGlvbl9uYW1lJyBdID0gZnVuY3Rpb25fbmFtZTtcclxuXHRcdGJhbGFuY2Vfb2JqWyAncGFyYW1zJyBdICAgICAgICA9IHdwYmNfY2xvbmVfb2JqKCBwYXJhbXMgKTtcclxuXHJcblxyXG5cdFx0aWYgKCBvYmouYmFsYW5jZXJfX2lzX2FscmVhZHlfcnVuKCByZXNvdXJjZV9pZCwgZnVuY3Rpb25fbmFtZSApICl7XHJcblx0XHRcdHJldHVybiAncnVuJztcclxuXHRcdH1cclxuXHRcdGlmICggb2JqLmJhbGFuY2VyX19pc19hbHJlYWR5X3dhaXQoIHJlc291cmNlX2lkLCBmdW5jdGlvbl9uYW1lICkgKXtcclxuXHRcdFx0cmV0dXJuICd3YWl0JztcclxuXHRcdH1cclxuXHJcblxyXG5cdFx0aWYgKCBvYmouYmFsYW5jZXJfX2Nhbl9pX3J1bigpICl7XHJcblx0XHRcdG9iai5iYWxhbmNlcl9fYWRkX3RvX19ydW4oIGJhbGFuY2Vfb2JqICk7XHJcblx0XHRcdHJldHVybiAncnVuJztcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdG9iai5iYWxhbmNlcl9fYWRkX3RvX193YWl0KCBiYWxhbmNlX29iaiApO1xyXG5cdFx0XHRyZXR1cm4gJ3dhaXQnO1xyXG5cdFx0fVxyXG5cdH07XHJcblxyXG5cdCAvKipcclxuXHQgICogQ2FuIEkgUnVuID9cclxuXHQgICogQHJldHVybnMge2Jvb2xlYW59XHJcblx0ICAqL1xyXG5cdG9iai5iYWxhbmNlcl9fY2FuX2lfcnVuID0gZnVuY3Rpb24gKCl7XHJcblx0XHRyZXR1cm4gKCBwX2JhbGFuY2VyWyAnaW5fcHJvY2VzcycgXS5sZW5ndGggPCBwX2JhbGFuY2VyWyAnbWF4X3RocmVhZHMnIF0gKTtcclxuXHR9XHJcblxyXG5cdFx0IC8qKlxyXG5cdFx0ICAqIEFkZCB0byBXQUlUXHJcblx0XHQgICogQHBhcmFtIGJhbGFuY2Vfb2JqXHJcblx0XHQgICovXHJcblx0XHRvYmouYmFsYW5jZXJfX2FkZF90b19fd2FpdCA9IGZ1bmN0aW9uICggYmFsYW5jZV9vYmogKSB7XHJcblx0XHRcdHBfYmFsYW5jZXJbJ3dhaXQnXS5wdXNoKCBiYWxhbmNlX29iaiApO1xyXG5cdFx0fVxyXG5cclxuXHRcdCAvKipcclxuXHRcdCAgKiBSZW1vdmUgZnJvbSBXYWl0XHJcblx0XHQgICpcclxuXHRcdCAgKiBAcGFyYW0gcmVzb3VyY2VfaWRcclxuXHRcdCAgKiBAcGFyYW0gZnVuY3Rpb25fbmFtZVxyXG5cdFx0ICAqIEByZXR1cm5zIHsqfGJvb2xlYW59XHJcblx0XHQgICovXHJcblx0XHRvYmouYmFsYW5jZXJfX3JlbW92ZV9mcm9tX193YWl0X2xpc3QgPSBmdW5jdGlvbiAoIHJlc291cmNlX2lkLCBmdW5jdGlvbl9uYW1lICl7XHJcblxyXG5cdFx0XHR2YXIgcmVtb3ZlZF9lbCA9IGZhbHNlO1xyXG5cclxuXHRcdFx0aWYgKCBwX2JhbGFuY2VyWyAnd2FpdCcgXS5sZW5ndGggKXtcdFx0XHRcdFx0Ly9GaXhJbjogOS44LjEwLjFcclxuXHRcdFx0XHRmb3IgKCB2YXIgaSBpbiBwX2JhbGFuY2VyWyAnd2FpdCcgXSApe1xyXG5cdFx0XHRcdFx0aWYgKFxyXG5cdFx0XHRcdFx0XHQocmVzb3VyY2VfaWQgPT09IHBfYmFsYW5jZXJbICd3YWl0JyBdWyBpIF1bICdyZXNvdXJjZV9pZCcgXSlcclxuXHRcdFx0XHRcdFx0JiYgKGZ1bmN0aW9uX25hbWUgPT09IHBfYmFsYW5jZXJbICd3YWl0JyBdWyBpIF1bICdmdW5jdGlvbl9uYW1lJyBdKVxyXG5cdFx0XHRcdFx0KXtcclxuXHRcdFx0XHRcdFx0cmVtb3ZlZF9lbCA9IHBfYmFsYW5jZXJbICd3YWl0JyBdLnNwbGljZSggaSwgMSApO1xyXG5cdFx0XHRcdFx0XHRyZW1vdmVkX2VsID0gcmVtb3ZlZF9lbC5wb3AoKTtcclxuXHRcdFx0XHRcdFx0cF9iYWxhbmNlclsgJ3dhaXQnIF0gPSBwX2JhbGFuY2VyWyAnd2FpdCcgXS5maWx0ZXIoIGZ1bmN0aW9uICggdiApe1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiB2O1xyXG5cdFx0XHRcdFx0XHR9ICk7XHRcdFx0XHRcdC8vIFJlaW5kZXggYXJyYXlcclxuXHRcdFx0XHRcdFx0cmV0dXJuIHJlbW92ZWRfZWw7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiByZW1vdmVkX2VsO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0KiBJcyBhbHJlYWR5IFdBSVRcclxuXHRcdCpcclxuXHRcdCogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0XHQqIEBwYXJhbSBmdW5jdGlvbl9uYW1lXHJcblx0XHQqIEByZXR1cm5zIHtib29sZWFufVxyXG5cdFx0Ki9cclxuXHRcdG9iai5iYWxhbmNlcl9faXNfYWxyZWFkeV93YWl0ID0gZnVuY3Rpb24gKCByZXNvdXJjZV9pZCwgZnVuY3Rpb25fbmFtZSApe1xyXG5cclxuXHRcdFx0aWYgKCBwX2JhbGFuY2VyWyAnd2FpdCcgXS5sZW5ndGggKXtcdFx0XHRcdC8vRml4SW46IDkuOC4xMC4xXHJcblx0XHRcdFx0Zm9yICggdmFyIGkgaW4gcF9iYWxhbmNlclsgJ3dhaXQnIF0gKXtcclxuXHRcdFx0XHRcdGlmIChcclxuXHRcdFx0XHRcdFx0KHJlc291cmNlX2lkID09PSBwX2JhbGFuY2VyWyAnd2FpdCcgXVsgaSBdWyAncmVzb3VyY2VfaWQnIF0pXHJcblx0XHRcdFx0XHRcdCYmIChmdW5jdGlvbl9uYW1lID09PSBwX2JhbGFuY2VyWyAnd2FpdCcgXVsgaSBdWyAnZnVuY3Rpb25fbmFtZScgXSlcclxuXHRcdFx0XHRcdCl7XHJcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblxyXG5cclxuXHRcdCAvKipcclxuXHRcdCAgKiBBZGQgdG8gUlVOXHJcblx0XHQgICogQHBhcmFtIGJhbGFuY2Vfb2JqXHJcblx0XHQgICovXHJcblx0XHRvYmouYmFsYW5jZXJfX2FkZF90b19fcnVuID0gZnVuY3Rpb24gKCBiYWxhbmNlX29iaiApIHtcclxuXHRcdFx0cF9iYWxhbmNlclsnaW5fcHJvY2VzcyddLnB1c2goIGJhbGFuY2Vfb2JqICk7XHJcblx0XHR9XHJcblxyXG5cdFx0LyoqXHJcblx0XHQqIFJlbW92ZSBmcm9tIFJVTiBsaXN0XHJcblx0XHQqXHJcblx0XHQqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG5cdFx0KiBAcGFyYW0gZnVuY3Rpb25fbmFtZVxyXG5cdFx0KiBAcmV0dXJucyB7Knxib29sZWFufVxyXG5cdFx0Ki9cclxuXHRcdG9iai5iYWxhbmNlcl9fcmVtb3ZlX2Zyb21fX3J1bl9saXN0ID0gZnVuY3Rpb24gKCByZXNvdXJjZV9pZCwgZnVuY3Rpb25fbmFtZSApe1xyXG5cclxuXHRcdFx0IHZhciByZW1vdmVkX2VsID0gZmFsc2U7XHJcblxyXG5cdFx0XHQgaWYgKCBwX2JhbGFuY2VyWyAnaW5fcHJvY2VzcycgXS5sZW5ndGggKXtcdFx0XHRcdC8vRml4SW46IDkuOC4xMC4xXHJcblx0XHRcdFx0IGZvciAoIHZhciBpIGluIHBfYmFsYW5jZXJbICdpbl9wcm9jZXNzJyBdICl7XHJcblx0XHRcdFx0XHQgaWYgKFxyXG5cdFx0XHRcdFx0XHQgKHJlc291cmNlX2lkID09PSBwX2JhbGFuY2VyWyAnaW5fcHJvY2VzcycgXVsgaSBdWyAncmVzb3VyY2VfaWQnIF0pXHJcblx0XHRcdFx0XHRcdCAmJiAoZnVuY3Rpb25fbmFtZSA9PT0gcF9iYWxhbmNlclsgJ2luX3Byb2Nlc3MnIF1bIGkgXVsgJ2Z1bmN0aW9uX25hbWUnIF0pXHJcblx0XHRcdFx0XHQgKXtcclxuXHRcdFx0XHRcdFx0IHJlbW92ZWRfZWwgPSBwX2JhbGFuY2VyWyAnaW5fcHJvY2VzcycgXS5zcGxpY2UoIGksIDEgKTtcclxuXHRcdFx0XHRcdFx0IHJlbW92ZWRfZWwgPSByZW1vdmVkX2VsLnBvcCgpO1xyXG5cdFx0XHRcdFx0XHQgcF9iYWxhbmNlclsgJ2luX3Byb2Nlc3MnIF0gPSBwX2JhbGFuY2VyWyAnaW5fcHJvY2VzcycgXS5maWx0ZXIoIGZ1bmN0aW9uICggdiApe1xyXG5cdFx0XHRcdFx0XHRcdCByZXR1cm4gdjtcclxuXHRcdFx0XHRcdFx0IH0gKTtcdFx0Ly8gUmVpbmRleCBhcnJheVxyXG5cdFx0XHRcdFx0XHQgcmV0dXJuIHJlbW92ZWRfZWw7XHJcblx0XHRcdFx0XHQgfVxyXG5cdFx0XHRcdCB9XHJcblx0XHRcdCB9XHJcblx0XHRcdCByZXR1cm4gcmVtb3ZlZF9lbDtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCogSXMgYWxyZWFkeSBSVU5cclxuXHRcdCpcclxuXHRcdCogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0XHQqIEBwYXJhbSBmdW5jdGlvbl9uYW1lXHJcblx0XHQqIEByZXR1cm5zIHtib29sZWFufVxyXG5cdFx0Ki9cclxuXHRcdG9iai5iYWxhbmNlcl9faXNfYWxyZWFkeV9ydW4gPSBmdW5jdGlvbiAoIHJlc291cmNlX2lkLCBmdW5jdGlvbl9uYW1lICl7XHJcblxyXG5cdFx0XHRpZiAoIHBfYmFsYW5jZXJbICdpbl9wcm9jZXNzJyBdLmxlbmd0aCApe1x0XHRcdFx0XHQvL0ZpeEluOiA5LjguMTAuMVxyXG5cdFx0XHRcdGZvciAoIHZhciBpIGluIHBfYmFsYW5jZXJbICdpbl9wcm9jZXNzJyBdICl7XHJcblx0XHRcdFx0XHRpZiAoXHJcblx0XHRcdFx0XHRcdChyZXNvdXJjZV9pZCA9PT0gcF9iYWxhbmNlclsgJ2luX3Byb2Nlc3MnIF1bIGkgXVsgJ3Jlc291cmNlX2lkJyBdKVxyXG5cdFx0XHRcdFx0XHQmJiAoZnVuY3Rpb25fbmFtZSA9PT0gcF9iYWxhbmNlclsgJ2luX3Byb2Nlc3MnIF1bIGkgXVsgJ2Z1bmN0aW9uX25hbWUnIF0pXHJcblx0XHRcdFx0XHQpe1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHJcblxyXG5cdG9iai5iYWxhbmNlcl9fcnVuX25leHQgPSBmdW5jdGlvbiAoKXtcclxuXHJcblx0XHQvLyBHZXQgMXN0IGZyb20gIFdhaXQgbGlzdFxyXG5cdFx0dmFyIHJlbW92ZWRfZWwgPSBmYWxzZTtcclxuXHRcdGlmICggcF9iYWxhbmNlclsgJ3dhaXQnIF0ubGVuZ3RoICl7XHRcdFx0XHRcdC8vRml4SW46IDkuOC4xMC4xXHJcblx0XHRcdGZvciAoIHZhciBpIGluIHBfYmFsYW5jZXJbICd3YWl0JyBdICl7XHJcblx0XHRcdFx0cmVtb3ZlZF9lbCA9IG9iai5iYWxhbmNlcl9fcmVtb3ZlX2Zyb21fX3dhaXRfbGlzdCggcF9iYWxhbmNlclsgJ3dhaXQnIF1bIGkgXVsgJ3Jlc291cmNlX2lkJyBdLCBwX2JhbGFuY2VyWyAnd2FpdCcgXVsgaSBdWyAnZnVuY3Rpb25fbmFtZScgXSApO1xyXG5cdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCBmYWxzZSAhPT0gcmVtb3ZlZF9lbCApe1xyXG5cclxuXHRcdFx0Ly8gUnVuXHJcblx0XHRcdG9iai5iYWxhbmNlcl9fcnVuKCByZW1vdmVkX2VsICk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQgLyoqXHJcblx0ICAqIFJ1blxyXG5cdCAgKiBAcGFyYW0gYmFsYW5jZV9vYmpcclxuXHQgICovXHJcblx0b2JqLmJhbGFuY2VyX19ydW4gPSBmdW5jdGlvbiAoIGJhbGFuY2Vfb2JqICl7XHJcblxyXG5cdFx0c3dpdGNoICggYmFsYW5jZV9vYmpbICdmdW5jdGlvbl9uYW1lJyBdICl7XHJcblxyXG5cdFx0XHRjYXNlICd3cGJjX2NhbGVuZGFyX19sb2FkX2RhdGFfX2FqeCc6XHJcblxyXG5cdFx0XHRcdC8vIEFkZCB0byBydW4gbGlzdFxyXG5cdFx0XHRcdG9iai5iYWxhbmNlcl9fYWRkX3RvX19ydW4oIGJhbGFuY2Vfb2JqICk7XHJcblxyXG5cdFx0XHRcdHdwYmNfY2FsZW5kYXJfX2xvYWRfZGF0YV9fYWp4KCBiYWxhbmNlX29ialsgJ3BhcmFtcycgXSApXHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRkZWZhdWx0OlxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIG9iajtcclxuXHJcbn0oIF93cGJjIHx8IHt9LCBqUXVlcnkgKSk7XHJcblxyXG5cclxuIFx0LyoqXHJcbiBcdCAqIC0tIEhlbHAgZnVuY3Rpb25zIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gd3BiY19iYWxhbmNlcl9faXNfd2FpdCggcGFyYW1zLCBmdW5jdGlvbl9uYW1lICl7XHJcbi8vY29uc29sZS5sb2coJzo6d3BiY19iYWxhbmNlcl9faXNfd2FpdCcscGFyYW1zICwgZnVuY3Rpb25fbmFtZSApO1xyXG5cdFx0aWYgKCAndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChwYXJhbXNbICdyZXNvdXJjZV9pZCcgXSkgKXtcclxuXHJcblx0XHRcdHZhciBiYWxhbmNlcl9zdGF0dXMgPSBfd3BiYy5iYWxhbmNlcl9faW5pdCggcGFyYW1zWyAncmVzb3VyY2VfaWQnIF0sIGZ1bmN0aW9uX25hbWUsIHBhcmFtcyApO1xyXG5cclxuXHRcdFx0cmV0dXJuICggJ3dhaXQnID09PSBiYWxhbmNlcl9zdGF0dXMgKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gZmFsc2U7XHJcblx0fVxyXG5cclxuXHJcblx0ZnVuY3Rpb24gd3BiY19iYWxhbmNlcl9fY29tcGxldGVkKCByZXNvdXJjZV9pZCAsIGZ1bmN0aW9uX25hbWUgKXtcclxuLy9jb25zb2xlLmxvZygnOjp3cGJjX2JhbGFuY2VyX19jb21wbGV0ZWQnLHJlc291cmNlX2lkICwgZnVuY3Rpb25fbmFtZSApO1xyXG5cdFx0X3dwYmMuYmFsYW5jZXJfX3JlbW92ZV9mcm9tX19ydW5fbGlzdCggcmVzb3VyY2VfaWQsIGZ1bmN0aW9uX25hbWUgKTtcclxuXHRcdF93cGJjLmJhbGFuY2VyX19ydW5fbmV4dCgpO1xyXG5cdH0iLCIvKipcclxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAqXHRpbmNsdWRlcy9fX2pzL2NhbC93cGJjX2NhbC5qc1xyXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICovXHJcblxyXG4vKipcclxuICogT3JkZXIgb3IgY2hpbGQgYm9va2luZyByZXNvdXJjZXMgc2F2ZWQgaGVyZTogIFx0X3dwYmMuYm9va2luZ19fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ3Jlc291cmNlc19pZF9hcnJfX2luX2RhdGVzJyApXHRcdFsyLDEwLDEyLDExXVxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBIb3cgdG8gY2hlY2sgIGJvb2tlZCB0aW1lcyBvbiAgc3BlY2lmaWMgZGF0ZTogP1xyXG4gKlxyXG5cdFx0XHRfd3BiYy5ib29raW5nc19pbl9jYWxlbmRhcl9fZ2V0X2Zvcl9kYXRlKDIsJzIwMjMtMDgtMjEnKTtcclxuXHJcblx0XHRcdGNvbnNvbGUubG9nKFxyXG5cdFx0XHRcdFx0XHRfd3BiYy5ib29raW5nc19pbl9jYWxlbmRhcl9fZ2V0X2Zvcl9kYXRlKDIsJzIwMjMtMDgtMjEnKVsyXS5ib29rZWRfdGltZV9zbG90cy5tZXJnZWRfc2Vjb25kcyxcclxuXHRcdFx0XHRcdFx0X3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX2dldF9mb3JfZGF0ZSgyLCcyMDIzLTA4LTIxJylbMTBdLmJvb2tlZF90aW1lX3Nsb3RzLm1lcmdlZF9zZWNvbmRzLFxyXG5cdFx0XHRcdFx0XHRfd3BiYy5ib29raW5nc19pbl9jYWxlbmRhcl9fZ2V0X2Zvcl9kYXRlKDIsJzIwMjMtMDgtMjEnKVsxMV0uYm9va2VkX3RpbWVfc2xvdHMubWVyZ2VkX3NlY29uZHMsXHJcblx0XHRcdFx0XHRcdF93cGJjLmJvb2tpbmdzX2luX2NhbGVuZGFyX19nZXRfZm9yX2RhdGUoMiwnMjAyMy0wOC0yMScpWzEyXS5ib29rZWRfdGltZV9zbG90cy5tZXJnZWRfc2Vjb25kc1xyXG5cdFx0XHRcdFx0KTtcclxuICogIE9SXHJcblx0XHRcdGNvbnNvbGUubG9nKFxyXG5cdFx0XHRcdFx0XHRfd3BiYy5ib29raW5nc19pbl9jYWxlbmRhcl9fZ2V0X2Zvcl9kYXRlKDIsJzIwMjMtMDgtMjEnKVsyXS5ib29rZWRfdGltZV9zbG90cy5tZXJnZWRfcmVhZGFibGUsXHJcblx0XHRcdFx0XHRcdF93cGJjLmJvb2tpbmdzX2luX2NhbGVuZGFyX19nZXRfZm9yX2RhdGUoMiwnMjAyMy0wOC0yMScpWzEwXS5ib29rZWRfdGltZV9zbG90cy5tZXJnZWRfcmVhZGFibGUsXHJcblx0XHRcdFx0XHRcdF93cGJjLmJvb2tpbmdzX2luX2NhbGVuZGFyX19nZXRfZm9yX2RhdGUoMiwnMjAyMy0wOC0yMScpWzExXS5ib29rZWRfdGltZV9zbG90cy5tZXJnZWRfcmVhZGFibGUsXHJcblx0XHRcdFx0XHRcdF93cGJjLmJvb2tpbmdzX2luX2NhbGVuZGFyX19nZXRfZm9yX2RhdGUoMiwnMjAyMy0wOC0yMScpWzEyXS5ib29rZWRfdGltZV9zbG90cy5tZXJnZWRfcmVhZGFibGVcclxuXHRcdFx0XHRcdCk7XHJcbiAqXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIERheXMgc2VsZWN0aW9uOlxyXG4gKiBcdFx0XHRcdFx0d3BiY19jYWxlbmRhcl9fdW5zZWxlY3RfYWxsX2RhdGVzKCByZXNvdXJjZV9pZCApO1xyXG4gKlxyXG4gKlxyXG4gKlx0dmFyIGluc3Q9IHdwYmNfY2FsZW5kYXJfX2dldF9pbnN0KDMpOyBpbnN0LmRhdGVzPVtdOyB3cGJjX19jYWxlbmRhcl9fb25fc2VsZWN0X2RheXMoJzIyLjA5LjIwMjMgLSAyMy4wOS4yMDIzJyAsIHsncmVzb3VyY2VfaWQnOjN9ICwgaW5zdCk7ICBpbnN0LnN0YXlPcGVuID0gZmFsc2U7alF1ZXJ5LmRhdGVwaWNrLl91cGRhdGVEYXRlcGljayggaW5zdCApO1xyXG4gKiAgaWYgaXQgZG9lc24ndCB3b3JrICBpbiAxMDAlIHNpdHVhdGlvbnMuIGNoZWNrIHdwYmNfc2VsZWN0X2RheXNfaW5fY2FsZW5kYXIoMywgWyBbIDIwMjMsIFwiMDlcIiwgMjYgXSwgWyAyMDIzLCBcIjA4XCIsIDI1IF1dKTtcclxuICovXHJcblxyXG5cclxuLyoqXHJcbiAqIEMgQSBMIEUgTiBEIEEgUiAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAqL1xyXG5cclxuXHJcbi8qKlxyXG4gKiAgU2hvdyBXUEJDIENhbGVuZGFyXHJcbiAqXHJcbiAqIEBwYXJhbSByZXNvdXJjZV9pZFx0XHRcdC0gcmVzb3VyY2UgSURcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2NhbGVuZGFyX3Nob3coIHJlc291cmNlX2lkICl7XHJcblxyXG5cdC8vIElmIG5vIGNhbGVuZGFyIEhUTUwgdGFnLCAgdGhlbiAgZXhpdFxyXG5cdGlmICggMCA9PT0galF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS5sZW5ndGggKXsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdC8vIElmIHRoZSBjYWxlbmRhciB3aXRoIHRoZSBzYW1lIEJvb2tpbmcgcmVzb3VyY2UgaXMgYWN0aXZhdGVkIGFscmVhZHksIHRoZW4gZXhpdC5cclxuXHRpZiAoIHRydWUgPT09IGpRdWVyeSggJyNjYWxlbmRhcl9ib29raW5nJyArIHJlc291cmNlX2lkICkuaGFzQ2xhc3MoICdoYXNEYXRlcGljaycgKSApeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBEYXlzIHNlbGVjdGlvblxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0dmFyIGxvY2FsX19pc19yYW5nZV9zZWxlY3QgPSBmYWxzZTtcclxuXHR2YXIgbG9jYWxfX211bHRpX2RheXNfc2VsZWN0X251bSAgID0gMzY1O1x0XHRcdFx0XHQvLyBtdWx0aXBsZSB8IGZpeGVkXHJcblx0aWYgKCAnZHluYW1pYycgPT09IF93cGJjLmNhbGVuZGFyX19nZXRfcGFyYW1fdmFsdWUoIHJlc291cmNlX2lkLCAnZGF5c19zZWxlY3RfbW9kZScgKSApe1xyXG5cdFx0bG9jYWxfX2lzX3JhbmdlX3NlbGVjdCA9IHRydWU7XHJcblx0XHRsb2NhbF9fbXVsdGlfZGF5c19zZWxlY3RfbnVtID0gMDtcclxuXHR9XHJcblx0aWYgKCAnc2luZ2xlJyAgPT09IF93cGJjLmNhbGVuZGFyX19nZXRfcGFyYW1fdmFsdWUoIHJlc291cmNlX2lkLCAnZGF5c19zZWxlY3RfbW9kZScgKSApe1xyXG5cdFx0bG9jYWxfX211bHRpX2RheXNfc2VsZWN0X251bSA9IDA7XHJcblx0fVxyXG5cclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIE1pbiAtIE1heCBkYXlzIHRvIHNjcm9sbC9zaG93XHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHR2YXIgbG9jYWxfX21pbl9kYXRlID0gMDtcclxuXHR2YXIgbG9jYWxfX21heF9kYXRlID0gX3dwYmMuY2FsZW5kYXJfX2dldF9wYXJhbV92YWx1ZSggcmVzb3VyY2VfaWQsICdib29raW5nX21heF9tb250aGVzX2luX2NhbGVuZGFyJyApO1xyXG5cdC8vbG9jYWxfX21heF9kYXRlID0gbmV3IERhdGUoMjAyNCwgNSwgMjgpOyAgSXQgaXMgaGVyZSBpc3N1ZSBvZiBub3Qgc2VsZWN0YWJsZSBkYXRlcywgYnV0IHNvbWUgZGF0ZXMgc2hvd2luZyBpbiBjYWxlbmRhciBhcyBhdmFpbGFibGUsIGJ1dCB3ZSBjYW4gbm90IHNlbGVjdCBpdC5cclxuXHJcblx0Ly8gRGVmaW5lIGxhc3QgZGF5IGluIGNhbGVuZGFyIChhcyBhIGxhc3QgZGF5IG9mIG1vbnRoIChhbmQgbm90IGRhdGUsIHdoaWNoIGlzIHJlbGF0ZWQgdG8gYWN0dWFsICdUb2RheScgZGF0ZSkuXHJcblx0Ly8gRS5nLiBpZiB0b2RheSBpcyAyMDIzLTA5LTI1LCBhbmQgd2Ugc2V0ICdOdW1iZXIgb2YgbW9udGhzIHRvIHNjcm9sbCcgYXMgNSBtb250aHMsIHRoZW4gbGFzdCBkYXkgd2lsbCBiZSAyMDI0LTAyLTI5IGFuZCBub3QgdGhlIDIwMjQtMDItMjUuXHJcblx0dmFyIGNhbF9sYXN0X2RheV9pbl9tb250aCA9IGpRdWVyeS5kYXRlcGljay5fZGV0ZXJtaW5lRGF0ZSggbnVsbCwgbG9jYWxfX21heF9kYXRlLCBuZXcgRGF0ZSgpICk7XHJcblx0Y2FsX2xhc3RfZGF5X2luX21vbnRoID0gbmV3IERhdGUoIGNhbF9sYXN0X2RheV9pbl9tb250aC5nZXRGdWxsWWVhcigpLCBjYWxfbGFzdF9kYXlfaW5fbW9udGguZ2V0TW9udGgoKSArIDEsIDAgKTtcclxuXHRsb2NhbF9fbWF4X2RhdGUgPSBjYWxfbGFzdF9kYXlfaW5fbW9udGg7XHJcblxyXG5cdGlmICggICAoIGxvY2F0aW9uLmhyZWYuaW5kZXhPZigncGFnZT13cGJjLW5ldycpICE9IC0xIClcclxuXHRcdCYmICggbG9jYXRpb24uaHJlZi5pbmRleE9mKCdib29raW5nX2hhc2gnKSAhPSAtMSApICAgICAgICAgICAgICAgICAgLy8gQ29tbWVudCB0aGlzIGxpbmUgZm9yIGFiaWxpdHkgdG8gYWRkICBib29raW5nIGluIHBhc3QgZGF5cyBhdCAgQm9va2luZyA+IEFkZCBib29raW5nIHBhZ2UuXHJcblx0XHQpe1xyXG5cdFx0bG9jYWxfX21pbl9kYXRlID0gbnVsbDtcclxuXHRcdGxvY2FsX19tYXhfZGF0ZSA9IG51bGw7XHJcblx0fVxyXG5cclxuXHR2YXIgbG9jYWxfX3N0YXJ0X3dlZWtkYXkgICAgPSBfd3BiYy5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ2Jvb2tpbmdfc3RhcnRfZGF5X3dlZWVrJyApO1xyXG5cdHZhciBsb2NhbF9fbnVtYmVyX29mX21vbnRocyA9IHBhcnNlSW50KCBfd3BiYy5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ2NhbGVuZGFyX251bWJlcl9vZl9tb250aHMnICkgKTtcclxuXHJcblx0alF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS50ZXh0KCAnJyApO1x0XHRcdFx0XHQvLyBSZW1vdmUgYWxsIEhUTUwgaW4gY2FsZW5kYXIgdGFnXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBTaG93IGNhbGVuZGFyXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRqUXVlcnkoJyNjYWxlbmRhcl9ib29raW5nJysgcmVzb3VyY2VfaWQpLmRhdGVwaWNrKFxyXG5cdFx0XHR7XHJcblx0XHRcdFx0YmVmb3JlU2hvd0RheTogZnVuY3Rpb24gKCBqc19kYXRlICl7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiB3cGJjX19jYWxlbmRhcl9fYXBwbHlfY3NzX3RvX2RheXMoIGpzX2RhdGUsIHsncmVzb3VyY2VfaWQnOiByZXNvdXJjZV9pZH0sIHRoaXMgKTtcclxuXHRcdFx0XHRcdFx0XHQgIH0sXHJcblx0XHRcdFx0b25TZWxlY3Q6IGZ1bmN0aW9uICggc3RyaW5nX2RhdGVzLCBqc19kYXRlc19hcnIgKXsgIC8qKlxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICpcdHN0cmluZ19kYXRlcyAgID0gICAnMjMuMDguMjAyMyAtIDI2LjA4LjIwMjMnICAgIHwgICAgJzIzLjA4LjIwMjMgLSAyMy4wOC4yMDIzJyAgICB8ICAgICcxOS4wOS4yMDIzLCAyNC4wOC4yMDIzLCAzMC4wOS4yMDIzJ1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICogIGpzX2RhdGVzX2FyciAgID0gICByYW5nZTogWyBEYXRlIChBdWcgMjMgMjAyMyksIERhdGUgKEF1ZyAyNSAyMDIzKV0gICAgIHwgICAgIG11bHRpcGxlOiBbIERhdGUoT2N0IDI0IDIwMjMpLCBEYXRlKE9jdCAyMCAyMDIzKSwgRGF0ZShPY3QgMTYgMjAyMykgXVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiB3cGJjX19jYWxlbmRhcl9fb25fc2VsZWN0X2RheXMoIHN0cmluZ19kYXRlcywgeydyZXNvdXJjZV9pZCc6IHJlc291cmNlX2lkfSwgdGhpcyApO1xyXG5cdFx0XHRcdFx0XHRcdCAgfSxcclxuXHRcdFx0XHRvbkhvdmVyOiBmdW5jdGlvbiAoIHN0cmluZ19kYXRlLCBqc19kYXRlICl7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiB3cGJjX19jYWxlbmRhcl9fb25faG92ZXJfZGF5cyggc3RyaW5nX2RhdGUsIGpzX2RhdGUsIHsncmVzb3VyY2VfaWQnOiByZXNvdXJjZV9pZH0sIHRoaXMgKTtcclxuXHRcdFx0XHRcdFx0XHQgIH0sXHJcblx0XHRcdFx0b25DaGFuZ2VNb250aFllYXI6IGZ1bmN0aW9uICggeWVhciwgcmVhbF9tb250aCwganNfZGF0ZV9fMXN0X2RheV9pbl9tb250aCApeyB9LFxyXG5cdFx0XHRcdHNob3dPbiAgICAgICAgOiAnYm90aCcsXHJcblx0XHRcdFx0bnVtYmVyT2ZNb250aHM6IGxvY2FsX19udW1iZXJfb2ZfbW9udGhzLFxyXG5cdFx0XHRcdHN0ZXBNb250aHMgICAgOiAxLFxyXG5cdFx0XHRcdHByZXZUZXh0ICAgICAgOiAnJmxhcXVvOycsXHJcblx0XHRcdFx0bmV4dFRleHQgICAgICA6ICcmcmFxdW87JyxcclxuXHRcdFx0XHRkYXRlRm9ybWF0ICAgIDogJ2RkLm1tLnl5JyxcclxuXHRcdFx0XHRjaGFuZ2VNb250aCAgIDogZmFsc2UsXHJcblx0XHRcdFx0Y2hhbmdlWWVhciAgICA6IGZhbHNlLFxyXG5cdFx0XHRcdG1pbkRhdGUgICAgICAgOiBsb2NhbF9fbWluX2RhdGUsXHJcblx0XHRcdFx0bWF4RGF0ZSAgICAgICA6IGxvY2FsX19tYXhfZGF0ZSwgXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vICcxWScsXHJcblx0XHRcdFx0Ly8gbWluRGF0ZTogbmV3IERhdGUoMjAyMCwgMiwgMSksIG1heERhdGU6IG5ldyBEYXRlKDIwMjAsIDksIDMxKSwgICAgICAgICAgICAgXHQvLyBBYmlsaXR5IHRvIHNldCBhbnkgIHN0YXJ0IGFuZCBlbmQgZGF0ZSBpbiBjYWxlbmRhclxyXG5cdFx0XHRcdHNob3dTdGF0dXMgICAgICA6IGZhbHNlLFxyXG5cdFx0XHRcdG11bHRpU2VwYXJhdG9yICA6ICcsICcsXHJcblx0XHRcdFx0Y2xvc2VBdFRvcCAgICAgIDogZmFsc2UsXHJcblx0XHRcdFx0Zmlyc3REYXkgICAgICAgIDogbG9jYWxfX3N0YXJ0X3dlZWtkYXksXHJcblx0XHRcdFx0Z290b0N1cnJlbnQgICAgIDogZmFsc2UsXHJcblx0XHRcdFx0aGlkZUlmTm9QcmV2TmV4dDogdHJ1ZSxcclxuXHRcdFx0XHRtdWx0aVNlbGVjdCAgICAgOiBsb2NhbF9fbXVsdGlfZGF5c19zZWxlY3RfbnVtLFxyXG5cdFx0XHRcdHJhbmdlU2VsZWN0ICAgICA6IGxvY2FsX19pc19yYW5nZV9zZWxlY3QsXHJcblx0XHRcdFx0Ly8gc2hvd1dlZWtzOiB0cnVlLFxyXG5cdFx0XHRcdHVzZVRoZW1lUm9sbGVyOiBmYWxzZVxyXG5cdFx0XHR9XHJcblx0KTtcclxuXHJcblxyXG5cdFxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gQ2xlYXIgdG9kYXkgZGF0ZSBoaWdobGlnaHRpbmdcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdHNldFRpbWVvdXQoIGZ1bmN0aW9uICgpeyAgd3BiY19jYWxlbmRhcnNfX2NsZWFyX2RheXNfaGlnaGxpZ2h0aW5nKCByZXNvdXJjZV9pZCApOyAgfSwgNTAwICk7ICAgICAgICAgICAgICAgICAgICBcdC8vRml4SW46IDcuMS4yLjhcclxuXHRcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIFNjcm9sbCBjYWxlbmRhciB0byAgc3BlY2lmaWMgbW9udGhcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdHZhciBzdGFydF9ia19tb250aCA9IF93cGJjLmNhbGVuZGFyX19nZXRfcGFyYW1fdmFsdWUoIHJlc291cmNlX2lkLCAnY2FsZW5kYXJfc2Nyb2xsX3RvJyApO1xyXG5cdGlmICggZmFsc2UgIT09IHN0YXJ0X2JrX21vbnRoICl7XHJcblx0XHR3cGJjX2NhbGVuZGFyX19zY3JvbGxfdG8oIHJlc291cmNlX2lkLCBzdGFydF9ia19tb250aFsgMCBdLCBzdGFydF9ia19tb250aFsgMSBdICk7XHJcblx0fVxyXG59XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBBcHBseSBDU1MgdG8gY2FsZW5kYXIgZGF0ZSBjZWxsc1xyXG5cdCAqXHJcblx0ICogQHBhcmFtIGRhdGVcdFx0XHRcdFx0XHRcdFx0XHRcdC0gIEphdmFTY3JpcHQgRGF0ZSBPYmo6ICBcdFx0TW9uIERlYyAxMSAyMDIzIDAwOjAwOjAwIEdNVCswMjAwIChFYXN0ZXJuIEV1cm9wZWFuIFN0YW5kYXJkIFRpbWUpXHJcblx0ICogQHBhcmFtIGNhbGVuZGFyX3BhcmFtc19hcnJcdFx0XHRcdFx0XHQtICBDYWxlbmRhciBTZXR0aW5ncyBPYmplY3Q6ICBcdHtcclxuXHQgKlx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICBcdFx0XHRcdFx0XHRcInJlc291cmNlX2lkXCI6IDRcclxuXHQgKlx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHQgKiBAcGFyYW0gZGF0ZXBpY2tfdGhpc1x0XHRcdFx0XHRcdFx0XHQtIHRoaXMgb2YgZGF0ZXBpY2sgT2JqXHJcblx0ICogQHJldHVybnMgeygqfHN0cmluZylbXXwoYm9vbGVhbnxzdHJpbmcpW119XHRcdC0gWyB7dHJ1ZSAtYXZhaWxhYmxlIHwgZmFsc2UgLSB1bmF2YWlsYWJsZX0sICdDU1MgY2xhc3NlcyBmb3IgY2FsZW5kYXIgZGF5IGNlbGwnIF1cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX19jYWxlbmRhcl9fYXBwbHlfY3NzX3RvX2RheXMoIGRhdGUsIGNhbGVuZGFyX3BhcmFtc19hcnIsIGRhdGVwaWNrX3RoaXMgKXtcclxuXHJcblx0XHR2YXIgdG9kYXlfZGF0ZSA9IG5ldyBEYXRlKCB3cGJjX3RvZGF5WyAwIF0sIChwYXJzZUludCggd3BiY190b2RheVsgMSBdICkgLSAxKSwgd3BiY190b2RheVsgMiBdLCAwLCAwLCAwICk7XHRcdFx0XHRcdFx0XHRcdC8vIFRvZGF5IEpTX0RhdGVfT2JqLlxyXG5cdFx0dmFyIGNsYXNzX2RheSAgICAgPSB3cGJjX19nZXRfX3RkX2NsYXNzX2RhdGUoIGRhdGUgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyAnMS05LTIwMjMnXHJcblx0XHR2YXIgc3FsX2NsYXNzX2RheSA9IHdwYmNfX2dldF9fc3FsX2NsYXNzX2RhdGUoIGRhdGUgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyAnMjAyMy0wMS0wOSdcclxuXHRcdHZhciByZXNvdXJjZV9pZCA9ICggJ3VuZGVmaW5lZCcgIT09IHR5cGVvZihjYWxlbmRhcl9wYXJhbXNfYXJyWyAncmVzb3VyY2VfaWQnIF0pICkgPyBjYWxlbmRhcl9wYXJhbXNfYXJyWyAncmVzb3VyY2VfaWQnIF0gOiAnMSc7IFx0XHQvLyAnMSdcclxuXHJcblx0XHQvLyBHZXQgRGF0YSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0dmFyIGRhdGVfYm9va2luZ3Nfb2JqID0gX3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX2dldF9mb3JfZGF0ZSggcmVzb3VyY2VfaWQsIHNxbF9jbGFzc19kYXkgKTtcclxuXHJcblxyXG5cdFx0Ly8gQXJyYXkgd2l0aCBDU1MgY2xhc3NlcyBmb3IgZGF0ZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdHZhciBjc3NfY2xhc3Nlc19fZm9yX2RhdGUgPSBbXTtcclxuXHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnc3FsX2RhdGVfJyAgICAgKyBzcWxfY2xhc3NfZGF5ICk7XHRcdFx0XHQvLyAgJ3NxbF9kYXRlXzIwMjMtMDctMjEnXHJcblx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2NhbDRkYXRlLScgICAgICsgY2xhc3NfZGF5ICk7XHRcdFx0XHRcdC8vICAnY2FsNGRhdGUtNy0yMS0yMDIzJ1xyXG5cdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICd3cGJjX3dlZWtkYXlfJyArIGRhdGUuZ2V0RGF5KCkgKTtcdFx0XHRcdC8vICAnd3BiY193ZWVrZGF5XzQnXHJcblxyXG5cdFx0dmFyIGlzX2RheV9zZWxlY3RhYmxlID0gZmFsc2U7XHJcblxyXG5cdFx0Ly8gSWYgc29tZXRoaW5nIG5vdCBkZWZpbmVkLCAgdGhlbiAgdGhpcyBkYXRlIGNsb3NlZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdGlmICggZmFsc2UgPT09IGRhdGVfYm9va2luZ3Nfb2JqICl7XHJcblxyXG5cdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2RhdGVfdXNlcl91bmF2YWlsYWJsZScgKTtcclxuXHJcblx0XHRcdHJldHVybiBbIGlzX2RheV9zZWxlY3RhYmxlLCBjc3NfY2xhc3Nlc19fZm9yX2RhdGUuam9pbignICcpICBdO1xyXG5cdFx0fVxyXG5cclxuXHJcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0Ly8gICBkYXRlX2Jvb2tpbmdzX29iaiAgLSBEZWZpbmVkLiAgICAgICAgICAgIERhdGVzIGNhbiBiZSBzZWxlY3RhYmxlLlxyXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0Ly8gQWRkIHNlYXNvbiBuYW1lcyB0byB0aGUgZGF5IENTUyBjbGFzc2VzIC0tIGl0IGlzIHJlcXVpcmVkIGZvciBjb3JyZWN0ICB3b3JrICBvZiBjb25kaXRpb25hbCBmaWVsZHMgLS0tLS0tLS0tLS0tLS1cclxuXHRcdHZhciBzZWFzb25fbmFtZXNfYXJyID0gX3dwYmMuc2Vhc29uc19fZ2V0X2Zvcl9kYXRlKCByZXNvdXJjZV9pZCwgc3FsX2NsYXNzX2RheSApO1xyXG5cdFx0Zm9yICggdmFyIHNlYXNvbl9rZXkgaW4gc2Vhc29uX25hbWVzX2FyciApe1xyXG5cdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggc2Vhc29uX25hbWVzX2Fyclsgc2Vhc29uX2tleSBdICk7XHRcdFx0XHQvLyAgJ3dwZGV2Ymtfc2Vhc29uX3NlcHRlbWJlcl8yMDIzJ1xyXG5cdFx0fVxyXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblxyXG5cdFx0Ly8gQ29zdCBSYXRlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAncmF0ZV8nICsgZGF0ZV9ib29raW5nc19vYmpbIHJlc291cmNlX2lkIF1bICdkYXRlX2Nvc3RfcmF0ZScgXS50b1N0cmluZygpLnJlcGxhY2UoIC9bXFwuXFxzXS9nLCAnXycgKSApO1x0XHRcdFx0XHRcdC8vICAncmF0ZV85OV8wMCcgLT4gOTkuMDBcclxuXHJcblxyXG5cdFx0aWYgKCBwYXJzZUludCggZGF0ZV9ib29raW5nc19vYmpbICdkYXlfYXZhaWxhYmlsaXR5JyBdICkgPiAwICl7XHJcblx0XHRcdGlzX2RheV9zZWxlY3RhYmxlID0gdHJ1ZTtcclxuXHRcdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICdkYXRlX2F2YWlsYWJsZScgKTtcclxuXHRcdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICdyZXNlcnZlZF9kYXlzX2NvdW50JyArIHBhcnNlSW50KCBkYXRlX2Jvb2tpbmdzX29ialsgJ21heF9jYXBhY2l0eScgXSAtIGRhdGVfYm9va2luZ3Nfb2JqWyAnZGF5X2F2YWlsYWJpbGl0eScgXSApICk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRpc19kYXlfc2VsZWN0YWJsZSA9IGZhbHNlO1xyXG5cdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2RhdGVfdXNlcl91bmF2YWlsYWJsZScgKTtcclxuXHRcdH1cclxuXHJcblxyXG5cdFx0c3dpdGNoICggZGF0ZV9ib29raW5nc19vYmpbICdzdW1tYXJ5J11bJ3N0YXR1c19mb3JfZGF5JyBdICl7XHJcblxyXG5cdFx0XHRjYXNlICdhdmFpbGFibGUnOlxyXG5cdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0Y2FzZSAndGltZV9zbG90c19ib29raW5nJzpcclxuXHRcdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ3RpbWVzcGFydGx5JywgJ3RpbWVzX2Nsb2NrJyApO1xyXG5cdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0Y2FzZSAnZnVsbF9kYXlfYm9va2luZyc6XHJcblx0XHRcdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICdmdWxsX2RheV9ib29raW5nJyApO1xyXG5cdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0Y2FzZSAnc2Vhc29uX2ZpbHRlcic6XHJcblx0XHRcdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICdkYXRlX3VzZXJfdW5hdmFpbGFibGUnLCAnc2Vhc29uX3VuYXZhaWxhYmxlJyApO1xyXG5cdFx0XHRcdGRhdGVfYm9va2luZ3Nfb2JqWyAnc3VtbWFyeSddWydzdGF0dXNfZm9yX2Jvb2tpbmdzJyBdID0gJyc7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFJlc2V0IGJvb2tpbmcgc3RhdHVzIGNvbG9yIGZvciBwb3NzaWJsZSBvbGQgYm9va2luZ3Mgb24gdGhpcyBkYXRlXHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRjYXNlICdyZXNvdXJjZV9hdmFpbGFiaWxpdHknOlxyXG5cdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnZGF0ZV91c2VyX3VuYXZhaWxhYmxlJywgJ3Jlc291cmNlX3VuYXZhaWxhYmxlJyApO1xyXG5cdFx0XHRcdGRhdGVfYm9va2luZ3Nfb2JqWyAnc3VtbWFyeSddWydzdGF0dXNfZm9yX2Jvb2tpbmdzJyBdID0gJyc7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFJlc2V0IGJvb2tpbmcgc3RhdHVzIGNvbG9yIGZvciBwb3NzaWJsZSBvbGQgYm9va2luZ3Mgb24gdGhpcyBkYXRlXHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRjYXNlICd3ZWVrZGF5X3VuYXZhaWxhYmxlJzpcclxuXHRcdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2RhdGVfdXNlcl91bmF2YWlsYWJsZScsICd3ZWVrZGF5X3VuYXZhaWxhYmxlJyApO1xyXG5cdFx0XHRcdGRhdGVfYm9va2luZ3Nfb2JqWyAnc3VtbWFyeSddWydzdGF0dXNfZm9yX2Jvb2tpbmdzJyBdID0gJyc7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFJlc2V0IGJvb2tpbmcgc3RhdHVzIGNvbG9yIGZvciBwb3NzaWJsZSBvbGQgYm9va2luZ3Mgb24gdGhpcyBkYXRlXHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRjYXNlICdmcm9tX3RvZGF5X3VuYXZhaWxhYmxlJzpcclxuXHRcdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2RhdGVfdXNlcl91bmF2YWlsYWJsZScsICdmcm9tX3RvZGF5X3VuYXZhaWxhYmxlJyApO1xyXG5cdFx0XHRcdGRhdGVfYm9va2luZ3Nfb2JqWyAnc3VtbWFyeSddWydzdGF0dXNfZm9yX2Jvb2tpbmdzJyBdID0gJyc7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFJlc2V0IGJvb2tpbmcgc3RhdHVzIGNvbG9yIGZvciBwb3NzaWJsZSBvbGQgYm9va2luZ3Mgb24gdGhpcyBkYXRlXHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRjYXNlICdsaW1pdF9hdmFpbGFibGVfZnJvbV90b2RheSc6XHJcblx0XHRcdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICdkYXRlX3VzZXJfdW5hdmFpbGFibGUnLCAnbGltaXRfYXZhaWxhYmxlX2Zyb21fdG9kYXknICk7XHJcblx0XHRcdFx0ZGF0ZV9ib29raW5nc19vYmpbICdzdW1tYXJ5J11bJ3N0YXR1c19mb3JfYm9va2luZ3MnIF0gPSAnJztcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gUmVzZXQgYm9va2luZyBzdGF0dXMgY29sb3IgZm9yIHBvc3NpYmxlIG9sZCBib29raW5ncyBvbiB0aGlzIGRhdGVcclxuXHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdGNhc2UgJ2NoYW5nZV9vdmVyJzpcclxuXHRcdFx0XHQvKlxyXG5cdFx0XHRcdCAqXHJcblx0XHRcdFx0Ly8gIGNoZWNrX291dF90aW1lX2RhdGUyYXBwcm92ZSBcdCBcdGNoZWNrX2luX3RpbWVfZGF0ZTJhcHByb3ZlXHJcblx0XHRcdFx0Ly8gIGNoZWNrX291dF90aW1lX2RhdGUyYXBwcm92ZSBcdCBcdGNoZWNrX2luX3RpbWVfZGF0ZV9hcHByb3ZlZFxyXG5cdFx0XHRcdC8vICBjaGVja19pbl90aW1lX2RhdGUyYXBwcm92ZSBcdFx0IFx0Y2hlY2tfb3V0X3RpbWVfZGF0ZV9hcHByb3ZlZFxyXG5cdFx0XHRcdC8vICBjaGVja19vdXRfdGltZV9kYXRlX2FwcHJvdmVkIFx0IFx0Y2hlY2tfaW5fdGltZV9kYXRlX2FwcHJvdmVkXHJcblx0XHRcdFx0ICovXHJcblxyXG5cdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAndGltZXNwYXJ0bHknLCAnY2hlY2tfaW5fdGltZScsICdjaGVja19vdXRfdGltZScgKTtcclxuXHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdGNhc2UgJ2NoZWNrX2luJzpcclxuXHRcdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ3RpbWVzcGFydGx5JywgJ2NoZWNrX2luX3RpbWUnICk7XHJcblxyXG5cdFx0XHRcdGlmICggJ3BlbmRpbmcnID09IGRhdGVfYm9va2luZ3Nfb2JqWyAnc3VtbWFyeSddWydzdGF0dXNfZm9yX2Jvb2tpbmdzJyBdICl7XHJcblx0XHRcdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2NoZWNrX2luX3RpbWVfZGF0ZTJhcHByb3ZlJyApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZiAoICdhcHByb3ZlZCcgPT0gZGF0ZV9ib29raW5nc19vYmpbICdzdW1tYXJ5J11bJ3N0YXR1c19mb3JfYm9va2luZ3MnIF0gKXtcclxuXHRcdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnY2hlY2tfaW5fdGltZV9kYXRlX2FwcHJvdmVkJyApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdGNhc2UgJ2NoZWNrX291dCc6XHJcblx0XHRcdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICd0aW1lc3BhcnRseScsICdjaGVja19vdXRfdGltZScgKTtcclxuXHJcblx0XHRcdFx0aWYgKCAncGVuZGluZycgPT0gZGF0ZV9ib29raW5nc19vYmpbICdzdW1tYXJ5J11bJ3N0YXR1c19mb3JfYm9va2luZ3MnIF0gKXtcclxuXHRcdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnY2hlY2tfb3V0X3RpbWVfZGF0ZTJhcHByb3ZlJyApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZiAoICdhcHByb3ZlZCcgPT0gZGF0ZV9ib29raW5nc19vYmpbICdzdW1tYXJ5J11bJ3N0YXR1c19mb3JfYm9va2luZ3MnIF0gKXtcclxuXHRcdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnY2hlY2tfb3V0X3RpbWVfZGF0ZV9hcHByb3ZlZCcgKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRkZWZhdWx0OlxyXG5cdFx0XHRcdC8vIG1peGVkIHN0YXR1c2VzOiAnY2hhbmdlX292ZXIgY2hlY2tfb3V0JyAuLi4uIHZhcmlhdGlvbnMuLi4uIGNoZWNrIG1vcmUgaW4gXHRcdGZ1bmN0aW9uIHdwYmNfZ2V0X2F2YWlsYWJpbGl0eV9wZXJfZGF5c19hcnIoKVxyXG5cdFx0XHRcdGRhdGVfYm9va2luZ3Nfb2JqWyAnc3VtbWFyeSddWydzdGF0dXNfZm9yX2RheScgXSA9ICdhdmFpbGFibGUnO1xyXG5cdFx0fVxyXG5cclxuXHJcblxyXG5cdFx0aWYgKCAnYXZhaWxhYmxlJyAhPSBkYXRlX2Jvb2tpbmdzX29ialsgJ3N1bW1hcnknXVsnc3RhdHVzX2Zvcl9kYXknIF0gKXtcclxuXHJcblx0XHRcdHZhciBpc19zZXRfcGVuZGluZ19kYXlzX3NlbGVjdGFibGUgPSBfd3BiYy5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ3BlbmRpbmdfZGF5c19zZWxlY3RhYmxlJyApO1x0Ly8gc2V0IHBlbmRpbmcgZGF5cyBzZWxlY3RhYmxlICAgICAgICAgIC8vRml4SW46IDguNi4xLjE4XHJcblxyXG5cdFx0XHRzd2l0Y2ggKCBkYXRlX2Jvb2tpbmdzX29ialsgJ3N1bW1hcnknXVsnc3RhdHVzX2Zvcl9ib29raW5ncycgXSApe1xyXG5cclxuXHRcdFx0XHRjYXNlICcnOlxyXG5cdFx0XHRcdFx0Ly8gVXN1YWxseSAgaXQncyBtZWFucyB0aGF0IGRheSAgaXMgYXZhaWxhYmxlIG9yIHVuYXZhaWxhYmxlIHdpdGhvdXQgdGhlIGJvb2tpbmdzXHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0Y2FzZSAncGVuZGluZyc6XHJcblx0XHRcdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2RhdGUyYXBwcm92ZScgKTtcclxuXHRcdFx0XHRcdGlzX2RheV9zZWxlY3RhYmxlID0gKGlzX2RheV9zZWxlY3RhYmxlKSA/IHRydWUgOiBpc19zZXRfcGVuZGluZ19kYXlzX3NlbGVjdGFibGU7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0Y2FzZSAnYXBwcm92ZWQnOlxyXG5cdFx0XHRcdFx0Y3NzX2NsYXNzZXNfX2Zvcl9kYXRlLnB1c2goICdkYXRlX2FwcHJvdmVkJyApO1xyXG5cdFx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRcdC8vIFNpdHVhdGlvbnMgZm9yIFwiY2hhbmdlLW92ZXJcIiBkYXlzOiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHRcdFx0Y2FzZSAncGVuZGluZ19wZW5kaW5nJzpcclxuXHRcdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnY2hlY2tfb3V0X3RpbWVfZGF0ZTJhcHByb3ZlJywgJ2NoZWNrX2luX3RpbWVfZGF0ZTJhcHByb3ZlJyApO1xyXG5cdFx0XHRcdFx0aXNfZGF5X3NlbGVjdGFibGUgPSAoaXNfZGF5X3NlbGVjdGFibGUpID8gdHJ1ZSA6IGlzX3NldF9wZW5kaW5nX2RheXNfc2VsZWN0YWJsZTtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0XHRjYXNlICdwZW5kaW5nX2FwcHJvdmVkJzpcclxuXHRcdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnY2hlY2tfb3V0X3RpbWVfZGF0ZTJhcHByb3ZlJywgJ2NoZWNrX2luX3RpbWVfZGF0ZV9hcHByb3ZlZCcgKTtcclxuXHRcdFx0XHRcdGlzX2RheV9zZWxlY3RhYmxlID0gKGlzX2RheV9zZWxlY3RhYmxlKSA/IHRydWUgOiBpc19zZXRfcGVuZGluZ19kYXlzX3NlbGVjdGFibGU7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0Y2FzZSAnYXBwcm92ZWRfcGVuZGluZyc6XHJcblx0XHRcdFx0XHRjc3NfY2xhc3Nlc19fZm9yX2RhdGUucHVzaCggJ2NoZWNrX291dF90aW1lX2RhdGVfYXBwcm92ZWQnLCAnY2hlY2tfaW5fdGltZV9kYXRlMmFwcHJvdmUnICk7XHJcblx0XHRcdFx0XHRpc19kYXlfc2VsZWN0YWJsZSA9IChpc19kYXlfc2VsZWN0YWJsZSkgPyB0cnVlIDogaXNfc2V0X3BlbmRpbmdfZGF5c19zZWxlY3RhYmxlO1xyXG5cdFx0XHRcdFx0YnJlYWs7XHJcblxyXG5cdFx0XHRcdGNhc2UgJ2FwcHJvdmVkX2FwcHJvdmVkJzpcclxuXHRcdFx0XHRcdGNzc19jbGFzc2VzX19mb3JfZGF0ZS5wdXNoKCAnY2hlY2tfb3V0X3RpbWVfZGF0ZV9hcHByb3ZlZCcsICdjaGVja19pbl90aW1lX2RhdGVfYXBwcm92ZWQnICk7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0ZGVmYXVsdDpcclxuXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gWyBpc19kYXlfc2VsZWN0YWJsZSwgY3NzX2NsYXNzZXNfX2Zvcl9kYXRlLmpvaW4oICcgJyApIF07XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogTW91c2VvdmVyIGNhbGVuZGFyIGRhdGUgY2VsbHNcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSBzdHJpbmdfZGF0ZVxyXG5cdCAqIEBwYXJhbSBkYXRlXHRcdFx0XHRcdFx0XHRcdFx0XHQtICBKYXZhU2NyaXB0IERhdGUgT2JqOiAgXHRcdE1vbiBEZWMgMTEgMjAyMyAwMDowMDowMCBHTVQrMDIwMCAoRWFzdGVybiBFdXJvcGVhbiBTdGFuZGFyZCBUaW1lKVxyXG5cdCAqIEBwYXJhbSBjYWxlbmRhcl9wYXJhbXNfYXJyXHRcdFx0XHRcdFx0LSAgQ2FsZW5kYXIgU2V0dGluZ3MgT2JqZWN0OiAgXHR7XHJcblx0ICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgXHRcdFx0XHRcdFx0XCJyZXNvdXJjZV9pZFwiOiA0XHJcblx0ICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0ICogQHBhcmFtIGRhdGVwaWNrX3RoaXNcdFx0XHRcdFx0XHRcdFx0LSB0aGlzIG9mIGRhdGVwaWNrIE9ialxyXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfX2NhbGVuZGFyX19vbl9ob3Zlcl9kYXlzKCBzdHJpbmdfZGF0ZSwgZGF0ZSwgY2FsZW5kYXJfcGFyYW1zX2FyciwgZGF0ZXBpY2tfdGhpcyApIHtcclxuXHJcblx0XHRpZiAoIG51bGwgPT09IGRhdGUgKXsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdFx0dmFyIGNsYXNzX2RheSAgICAgPSB3cGJjX19nZXRfX3RkX2NsYXNzX2RhdGUoIGRhdGUgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyAnMS05LTIwMjMnXHJcblx0XHR2YXIgc3FsX2NsYXNzX2RheSA9IHdwYmNfX2dldF9fc3FsX2NsYXNzX2RhdGUoIGRhdGUgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyAnMjAyMy0wMS0wOSdcclxuXHRcdHZhciByZXNvdXJjZV9pZCA9ICggJ3VuZGVmaW5lZCcgIT09IHR5cGVvZihjYWxlbmRhcl9wYXJhbXNfYXJyWyAncmVzb3VyY2VfaWQnIF0pICkgPyBjYWxlbmRhcl9wYXJhbXNfYXJyWyAncmVzb3VyY2VfaWQnIF0gOiAnMSc7XHRcdC8vICcxJ1xyXG5cclxuXHRcdC8vIEdldCBEYXRhIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHR2YXIgZGF0ZV9ib29raW5nX29iaiA9IF93cGJjLmJvb2tpbmdzX2luX2NhbGVuZGFyX19nZXRfZm9yX2RhdGUoIHJlc291cmNlX2lkLCBzcWxfY2xhc3NfZGF5ICk7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIHsuLi59XHJcblxyXG5cdFx0aWYgKCAhIGRhdGVfYm9va2luZ19vYmogKXsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cclxuXHRcdC8vIFQgbyBvIGwgdCBpIHAgcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHR2YXIgdG9vbHRpcF90ZXh0ID0gJyc7XHJcblx0XHRpZiAoIGRhdGVfYm9va2luZ19vYmpbICdzdW1tYXJ5J11bJ3Rvb2x0aXBfYXZhaWxhYmlsaXR5JyBdLmxlbmd0aCA+IDAgKXtcclxuXHRcdFx0dG9vbHRpcF90ZXh0ICs9ICBkYXRlX2Jvb2tpbmdfb2JqWyAnc3VtbWFyeSddWyd0b29sdGlwX2F2YWlsYWJpbGl0eScgXTtcclxuXHRcdH1cclxuXHRcdGlmICggZGF0ZV9ib29raW5nX29ialsgJ3N1bW1hcnknXVsndG9vbHRpcF9kYXlfY29zdCcgXS5sZW5ndGggPiAwICl7XHJcblx0XHRcdHRvb2x0aXBfdGV4dCArPSAgZGF0ZV9ib29raW5nX29ialsgJ3N1bW1hcnknXVsndG9vbHRpcF9kYXlfY29zdCcgXTtcclxuXHRcdH1cclxuXHRcdGlmICggZGF0ZV9ib29raW5nX29ialsgJ3N1bW1hcnknXVsndG9vbHRpcF90aW1lcycgXS5sZW5ndGggPiAwICl7XHJcblx0XHRcdHRvb2x0aXBfdGV4dCArPSAgZGF0ZV9ib29raW5nX29ialsgJ3N1bW1hcnknXVsndG9vbHRpcF90aW1lcycgXTtcclxuXHRcdH1cclxuXHRcdGlmICggZGF0ZV9ib29raW5nX29ialsgJ3N1bW1hcnknXVsndG9vbHRpcF9ib29raW5nX2RldGFpbHMnIF0ubGVuZ3RoID4gMCApe1xyXG5cdFx0XHR0b29sdGlwX3RleHQgKz0gIGRhdGVfYm9va2luZ19vYmpbICdzdW1tYXJ5J11bJ3Rvb2x0aXBfYm9va2luZ19kZXRhaWxzJyBdO1xyXG5cdFx0fVxyXG5cdFx0d3BiY19zZXRfdG9vbHRpcF9fX2Zvcl9fY2FsZW5kYXJfZGF0ZSggdG9vbHRpcF90ZXh0LCByZXNvdXJjZV9pZCwgY2xhc3NfZGF5ICk7XHJcblxyXG5cclxuXHJcblx0XHQvLyAgVSBuIGggbyB2IGUgciBpIG4gZyAgICBpbiAgICBVTlNFTEVDVEFCTEVfQ0FMRU5EQVIgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0dmFyIGlzX3Vuc2VsZWN0YWJsZV9jYWxlbmRhciA9ICggalF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmdfdW5zZWxlY3RhYmxlJyArIHJlc291cmNlX2lkICkubGVuZ3RoID4gMCk7XHRcdFx0XHQvL0ZpeEluOiA4LjAuMS4yXHJcblx0XHR2YXIgaXNfYm9va2luZ19mb3JtX2V4aXN0ICAgID0gKCBqUXVlcnkoICcjYm9va2luZ19mb3JtX2RpdicgKyByZXNvdXJjZV9pZCApLmxlbmd0aCA+IDAgKTtcclxuXHJcblx0XHRpZiAoICggaXNfdW5zZWxlY3RhYmxlX2NhbGVuZGFyICkgJiYgKCAhIGlzX2Jvb2tpbmdfZm9ybV9leGlzdCApICl7XHJcblxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogIFVuIEhvdmVyIGFsbCBkYXRlcyBpbiBjYWxlbmRhciAod2l0aG91dCB0aGUgYm9va2luZyBmb3JtKSwgaWYgb25seSBBdmFpbGFiaWxpdHkgQ2FsZW5kYXIgaGVyZSBhbmQgd2UgZG8gbm90IGluc2VydCBCb29raW5nIGZvcm0gYnkgbWlzdGFrZS5cclxuXHRcdFx0ICovXHJcblxyXG5cdFx0XHR3cGJjX2NhbGVuZGFyc19fY2xlYXJfZGF5c19oaWdobGlnaHRpbmcoIHJlc291cmNlX2lkICk7IFx0XHRcdFx0XHRcdFx0Ly8gQ2xlYXIgZGF5cyBoaWdobGlnaHRpbmdcclxuXHJcblx0XHRcdHZhciBjc3Nfb2ZfY2FsZW5kYXIgPSAnLndwYmNfb25seV9jYWxlbmRhciAjY2FsZW5kYXJfYm9va2luZycgKyByZXNvdXJjZV9pZDtcclxuXHRcdFx0alF1ZXJ5KCBjc3Nfb2ZfY2FsZW5kYXIgKyAnIC5kYXRlcGljay1kYXlzLWNlbGwsICdcclxuXHRcdFx0XHQgICsgY3NzX29mX2NhbGVuZGFyICsgJyAuZGF0ZXBpY2stZGF5cy1jZWxsIGEnICkuY3NzKCAnY3Vyc29yJywgJ2RlZmF1bHQnICk7XHQvLyBTZXQgY3Vyc29yIHRvIERlZmF1bHRcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHJcblxyXG5cdFx0Ly8gIEQgYSB5IHMgICAgSCBvIHYgZSByIGkgbiBnICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdGlmIChcclxuXHRcdFx0ICAgKCBsb2NhdGlvbi5ocmVmLmluZGV4T2YoICdwYWdlPXdwYmMnICkgPT0gLTEgKVxyXG5cdFx0XHR8fCAoIGxvY2F0aW9uLmhyZWYuaW5kZXhPZiggJ3BhZ2U9d3BiYy1uZXcnICkgPiAwIClcclxuXHRcdFx0fHwgKCBsb2NhdGlvbi5ocmVmLmluZGV4T2YoICdwYWdlPXdwYmMtYXZhaWxhYmlsaXR5JyApID4gMCApXHJcblx0XHQpe1xyXG5cdFx0XHQvLyBUaGUgc2FtZSBhcyBkYXRlcyBzZWxlY3Rpb24sICBidXQgZm9yIGRheXMgaG92ZXJpbmdcclxuXHJcblx0XHRcdGlmICggJ2Z1bmN0aW9uJyA9PSB0eXBlb2YoIHdwYmNfX2NhbGVuZGFyX19kb19kYXlzX2hpZ2hsaWdodF9fYnMgKSApe1xyXG5cdFx0XHRcdHdwYmNfX2NhbGVuZGFyX19kb19kYXlzX2hpZ2hsaWdodF9fYnMoIHNxbF9jbGFzc19kYXksIGRhdGUsIHJlc291cmNlX2lkICk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogU2VsZWN0IGNhbGVuZGFyIGRhdGUgY2VsbHNcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSBkYXRlXHRcdFx0XHRcdFx0XHRcdFx0XHQtICBKYXZhU2NyaXB0IERhdGUgT2JqOiAgXHRcdE1vbiBEZWMgMTEgMjAyMyAwMDowMDowMCBHTVQrMDIwMCAoRWFzdGVybiBFdXJvcGVhbiBTdGFuZGFyZCBUaW1lKVxyXG5cdCAqIEBwYXJhbSBjYWxlbmRhcl9wYXJhbXNfYXJyXHRcdFx0XHRcdFx0LSAgQ2FsZW5kYXIgU2V0dGluZ3MgT2JqZWN0OiAgXHR7XHJcblx0ICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgXHRcdFx0XHRcdFx0XCJyZXNvdXJjZV9pZFwiOiA0XHJcblx0ICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0ICogQHBhcmFtIGRhdGVwaWNrX3RoaXNcdFx0XHRcdFx0XHRcdFx0LSB0aGlzIG9mIGRhdGVwaWNrIE9ialxyXG5cdCAqXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19fY2FsZW5kYXJfX29uX3NlbGVjdF9kYXlzKCBkYXRlLCBjYWxlbmRhcl9wYXJhbXNfYXJyLCBkYXRlcGlja190aGlzICl7XHJcblxyXG5cdFx0dmFyIHJlc291cmNlX2lkID0gKCAndW5kZWZpbmVkJyAhPT0gdHlwZW9mKGNhbGVuZGFyX3BhcmFtc19hcnJbICdyZXNvdXJjZV9pZCcgXSkgKSA/IGNhbGVuZGFyX3BhcmFtc19hcnJbICdyZXNvdXJjZV9pZCcgXSA6ICcxJztcdFx0Ly8gJzEnXHJcblxyXG5cdFx0Ly8gU2V0IHVuc2VsZWN0YWJsZSwgIGlmIG9ubHkgQXZhaWxhYmlsaXR5IENhbGVuZGFyICBoZXJlIChhbmQgd2UgZG8gbm90IGluc2VydCBCb29raW5nIGZvcm0gYnkgbWlzdGFrZSkuXHJcblx0XHR2YXIgaXNfdW5zZWxlY3RhYmxlX2NhbGVuZGFyID0gKCBqUXVlcnkoICcjY2FsZW5kYXJfYm9va2luZ191bnNlbGVjdGFibGUnICsgcmVzb3VyY2VfaWQgKS5sZW5ndGggPiAwKTtcdFx0XHRcdC8vRml4SW46IDguMC4xLjJcclxuXHRcdHZhciBpc19ib29raW5nX2Zvcm1fZXhpc3QgICAgPSAoIGpRdWVyeSggJyNib29raW5nX2Zvcm1fZGl2JyArIHJlc291cmNlX2lkICkubGVuZ3RoID4gMCApO1xyXG5cdFx0aWYgKCAoIGlzX3Vuc2VsZWN0YWJsZV9jYWxlbmRhciApICYmICggISBpc19ib29raW5nX2Zvcm1fZXhpc3QgKSApe1xyXG5cdFx0XHR3cGJjX2NhbGVuZGFyX191bnNlbGVjdF9hbGxfZGF0ZXMoIHJlc291cmNlX2lkICk7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBVbnNlbGVjdCBEYXRlc1xyXG5cdFx0XHRqUXVlcnkoJy53cGJjX29ubHlfY2FsZW5kYXIgLnBvcG92ZXJfY2FsZW5kYXJfaG92ZXInKS5yZW1vdmUoKTsgICAgICAgICAgICAgICAgICAgICAgXHRcdFx0XHRcdFx0XHQvLyBIaWRlIGFsbCBvcGVuZWQgcG9wb3ZlcnNcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdGpRdWVyeSggJyNkYXRlX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS52YWwoIGRhdGUgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIEFkZCBzZWxlY3RlZCBkYXRlcyB0byAgaGlkZGVuIHRleHRhcmVhXHJcblxyXG5cclxuXHRcdGlmICggJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mICh3cGJjX19jYWxlbmRhcl9fZG9fZGF5c19zZWxlY3RfX2JzKSApeyB3cGJjX19jYWxlbmRhcl9fZG9fZGF5c19zZWxlY3RfX2JzKCBkYXRlLCByZXNvdXJjZV9pZCApOyB9XHJcblxyXG5cdFx0d3BiY19kaXNhYmxlX3RpbWVfZmllbGRzX2luX2Jvb2tpbmdfZm9ybSggcmVzb3VyY2VfaWQgKTtcclxuXHJcblx0XHQvLyBIb29rIC0tIHRyaWdnZXIgZGF5IHNlbGVjdGlvbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0dmFyIG1vdXNlX2NsaWNrZWRfZGF0ZXMgPSBkYXRlO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2FuIGJlOiBcIjA1LjEwLjIwMjMgLSAwNy4xMC4yMDIzXCIgIHwgIFwiMTAuMTAuMjAyMyAtIDEwLjEwLjIwMjNcIiAgfFxyXG5cdFx0dmFyIGFsbF9zZWxlY3RlZF9kYXRlc19hcnIgPSB3cGJjX2dldF9fc2VsZWN0ZWRfZGF0ZXNfc3FsX19hc19hcnIoIHJlc291cmNlX2lkICk7XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2FuIGJlOiBbIFwiMjAyMy0xMC0wNVwiLCBcIjIwMjMtMTAtMDZcIiwgXCIyMDIzLTEwLTA3XCIsIOKApiBdXHJcblx0XHRqUXVlcnkoIFwiLmJvb2tpbmdfZm9ybV9kaXZcIiApLnRyaWdnZXIoIFwiZGF0ZV9zZWxlY3RlZFwiLCBbIHJlc291cmNlX2lkLCBtb3VzZV9jbGlja2VkX2RhdGVzLCBhbGxfc2VsZWN0ZWRfZGF0ZXNfYXJyIF0gKTtcclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiAtLSAgVCBpIG0gZSAgICBGIGkgZSBsIGQgcyAgICAgc3RhcnQgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0ICovXHJcblxyXG5cdC8qKlxyXG5cdCAqIERpc2FibGUgdGltZSBzbG90cyBpbiBib29raW5nIGZvcm0gZGVwZW5kIG9uIHNlbGVjdGVkIGRhdGVzIGFuZCBib29rZWQgZGF0ZXMvdGltZXNcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfZGlzYWJsZV90aW1lX2ZpZWxkc19pbl9ib29raW5nX2Zvcm0oIHJlc291cmNlX2lkICl7XHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBcdDEuIEdldCBhbGwgdGltZSBmaWVsZHMgaW4gdGhlIGJvb2tpbmcgZm9ybSBhcyBhcnJheSAgb2Ygb2JqZWN0c1xyXG5cdFx0ICogXHRcdFx0XHRcdFtcclxuXHRcdCAqIFx0XHRcdFx0XHQgXHQgICB7XHRqcXVlcnlfb3B0aW9uOiAgICAgIGpRdWVyeV9PYmplY3Qge31cclxuXHRcdCAqIFx0XHRcdFx0XHRcdFx0XHRuYW1lOiAgICAgICAgICAgICAgICdyYW5nZXRpbWUyW10nXHJcblx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0dGltZXNfYXNfc2Vjb25kczogICBbIDIxNjAwLCAyMzQwMCBdXHJcblx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0dmFsdWVfb3B0aW9uXzI0aDogICAnMDY6MDAgLSAwNjozMCdcclxuXHRcdCAqIFx0XHRcdFx0XHQgICAgIH1cclxuXHRcdCAqIFx0XHRcdFx0XHQgIC4uLlxyXG5cdFx0ICogXHRcdFx0XHRcdFx0ICAge1x0anF1ZXJ5X29wdGlvbjogICAgICBqUXVlcnlfT2JqZWN0IHt9XHJcblx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0bmFtZTogICAgICAgICAgICAgICAnc3RhcnR0aW1lMltdJ1xyXG5cdFx0ICogXHRcdFx0XHRcdFx0XHRcdHRpbWVzX2FzX3NlY29uZHM6ICAgWyAyMTYwMCBdXHJcblx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0dmFsdWVfb3B0aW9uXzI0aDogICAnMDY6MDAnXHJcblx0XHQgKiAgXHRcdFx0XHRcdCAgICB9XHJcblx0XHQgKiBcdFx0XHRcdFx0IF1cclxuXHRcdCAqL1xyXG5cdFx0dmFyIHRpbWVfZmllbGRzX29ial9hcnIgPSB3cGJjX2dldF9fdGltZV9maWVsZHNfX2luX2Jvb2tpbmdfZm9ybV9fYXNfYXJyKCByZXNvdXJjZV9pZCApO1xyXG5cclxuXHRcdC8vIDIuIEdldCBhbGwgc2VsZWN0ZWQgZGF0ZXMgaW4gIFNRTCBmb3JtYXQgIGxpa2UgdGhpcyBbIFwiMjAyMy0wOC0yM1wiLCBcIjIwMjMtMDgtMjRcIiwgXCIyMDIzLTA4LTI1XCIsIC4uLiBdXHJcblx0XHR2YXIgc2VsZWN0ZWRfZGF0ZXNfYXJyID0gd3BiY19nZXRfX3NlbGVjdGVkX2RhdGVzX3NxbF9fYXNfYXJyKCByZXNvdXJjZV9pZCApO1xyXG5cclxuXHRcdC8vIDMuIEdldCBjaGlsZCBib29raW5nIHJlc291cmNlcyAgb3Igc2luZ2xlIGJvb2tpbmcgcmVzb3VyY2UgIHRoYXQgIGV4aXN0ICBpbiBkYXRlc1xyXG5cdFx0dmFyIGNoaWxkX3Jlc291cmNlc19hcnIgPSB3cGJjX2Nsb25lX29iaiggX3dwYmMuYm9va2luZ19fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ3Jlc291cmNlc19pZF9hcnJfX2luX2RhdGVzJyApICk7XHJcblxyXG5cdFx0dmFyIHNxbF9kYXRlO1xyXG5cdFx0dmFyIGNoaWxkX3Jlc291cmNlX2lkO1xyXG5cdFx0dmFyIG1lcmdlZF9zZWNvbmRzO1xyXG5cdFx0dmFyIHRpbWVfZmllbGRzX29iajtcclxuXHRcdHZhciBpc19pbnRlcnNlY3Q7XHJcblx0XHR2YXIgaXNfY2hlY2tfaW47XHJcblxyXG5cdFx0Ly8gNC4gTG9vcCAgYWxsICB0aW1lIEZpZWxkcyBvcHRpb25zXHJcblx0XHRmb3IgKCB2YXIgZmllbGRfa2V5IGluIHRpbWVfZmllbGRzX29ial9hcnIgKXtcclxuXHJcblx0XHRcdHRpbWVfZmllbGRzX29ial9hcnJbIGZpZWxkX2tleSBdLmRpc2FibGVkID0gMDsgICAgICAgICAgLy8gQnkgZGVmYXVsdCB0aGlzIHRpbWUgZmllbGQgaXMgbm90IGRpc2FibGVkXHJcblxyXG5cdFx0XHR0aW1lX2ZpZWxkc19vYmogPSB0aW1lX2ZpZWxkc19vYmpfYXJyWyBmaWVsZF9rZXkgXTtcdFx0Ly8geyB0aW1lc19hc19zZWNvbmRzOiBbIDIxNjAwLCAyMzQwMCBdLCB2YWx1ZV9vcHRpb25fMjRoOiAnMDY6MDAgLSAwNjozMCcsIG5hbWU6ICdyYW5nZXRpbWUyW10nLCBqcXVlcnlfb3B0aW9uOiBqUXVlcnlfT2JqZWN0IHt9fVxyXG5cclxuXHRcdFx0Ly8gTG9vcCAgYWxsICBzZWxlY3RlZCBkYXRlc1xyXG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBzZWxlY3RlZF9kYXRlc19hcnIubGVuZ3RoOyBpKysgKXtcclxuXHJcblx0XHRcdFx0Ly8gR2V0IERhdGU6ICcyMDIzLTA4LTE4J1xyXG5cdFx0XHRcdHNxbF9kYXRlID0gc2VsZWN0ZWRfZGF0ZXNfYXJyWyBpIF07XHJcblxyXG5cclxuXHRcdFx0XHR2YXIgaG93X21hbnlfcmVzb3VyY2VzX2ludGVyc2VjdGVkID0gMDtcclxuXHRcdFx0XHQvLyBMb29wIGFsbCByZXNvdXJjZXMgSURcclxuXHRcdFx0XHRmb3IgKCB2YXIgcmVzX2tleSBpbiBjaGlsZF9yZXNvdXJjZXNfYXJyICl7XHJcblxyXG5cdFx0XHRcdFx0Y2hpbGRfcmVzb3VyY2VfaWQgPSBjaGlsZF9yZXNvdXJjZXNfYXJyWyByZXNfa2V5IF07XHJcblxyXG5cdFx0XHRcdFx0Ly8gX3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX2dldF9mb3JfZGF0ZSgyLCcyMDIzLTA4LTIxJylbMTJdLmJvb2tlZF90aW1lX3Nsb3RzLm1lcmdlZF9zZWNvbmRzXHRcdD0gWyBcIjA3OjAwOjExIC0gMDc6MzA6MDJcIiwgXCIxMDowMDoxMSAtIDAwOjAwOjAwXCIgXVxyXG5cdFx0XHRcdFx0Ly8gX3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX2dldF9mb3JfZGF0ZSgyLCcyMDIzLTA4LTIxJylbMl0uYm9va2VkX3RpbWVfc2xvdHMubWVyZ2VkX3NlY29uZHNcdFx0XHQ9IFsgIFsgMjUyMTEsIDI3MDAyIF0sIFsgMzYwMTEsIDg2NDAwIF0gIF1cclxuXHJcblx0XHRcdFx0XHRpZiAoIGZhbHNlICE9PSBfd3BiYy5ib29raW5nc19pbl9jYWxlbmRhcl9fZ2V0X2Zvcl9kYXRlKCByZXNvdXJjZV9pZCwgc3FsX2RhdGUgKSApe1xyXG5cdFx0XHRcdFx0XHRtZXJnZWRfc2Vjb25kcyA9IF93cGJjLmJvb2tpbmdzX2luX2NhbGVuZGFyX19nZXRfZm9yX2RhdGUoIHJlc291cmNlX2lkLCBzcWxfZGF0ZSApWyBjaGlsZF9yZXNvdXJjZV9pZCBdLmJvb2tlZF90aW1lX3Nsb3RzLm1lcmdlZF9zZWNvbmRzO1x0XHQvLyBbICBbIDI1MjExLCAyNzAwMiBdLCBbIDM2MDExLCA4NjQwMCBdICBdXHJcblx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRtZXJnZWRfc2Vjb25kcyA9IFtdO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0aWYgKCB0aW1lX2ZpZWxkc19vYmoudGltZXNfYXNfc2Vjb25kcy5sZW5ndGggPiAxICl7XHJcblx0XHRcdFx0XHRcdGlzX2ludGVyc2VjdCA9IHdwYmNfaXNfaW50ZXJzZWN0X19yYW5nZV90aW1lX2ludGVydmFsKCAgW1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRbXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KCBwYXJzZUludCggdGltZV9maWVsZHNfb2JqLnRpbWVzX2FzX3NlY29uZHNbMF0gKSArIDIwICksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KCBwYXJzZUludCggdGltZV9maWVsZHNfb2JqLnRpbWVzX2FzX3NlY29uZHNbMV0gKSAtIDIwIClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0LCBtZXJnZWRfc2Vjb25kcyApO1xyXG5cdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0aXNfY2hlY2tfaW4gPSAoLTEgIT09IHRpbWVfZmllbGRzX29iai5uYW1lLmluZGV4T2YoICdzdGFydCcgKSk7XHJcblx0XHRcdFx0XHRcdGlzX2ludGVyc2VjdCA9IHdwYmNfaXNfaW50ZXJzZWN0X19vbmVfdGltZV9pbnRlcnZhbChcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCggKCBpc19jaGVja19pbiApXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgID8gcGFyc2VJbnQoIHRpbWVfZmllbGRzX29iai50aW1lc19hc19zZWNvbmRzICkgKyAyMFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICA6IHBhcnNlSW50KCB0aW1lX2ZpZWxkc19vYmoudGltZXNfYXNfc2Vjb25kcyApIC0gMjBcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCwgbWVyZ2VkX3NlY29uZHMgKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmIChpc19pbnRlcnNlY3Qpe1xyXG5cdFx0XHRcdFx0XHRob3dfbWFueV9yZXNvdXJjZXNfaW50ZXJzZWN0ZWQrKztcdFx0XHQvLyBJbmNyZWFzZVxyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdGlmICggY2hpbGRfcmVzb3VyY2VzX2Fyci5sZW5ndGggPT0gaG93X21hbnlfcmVzb3VyY2VzX2ludGVyc2VjdGVkICkge1xyXG5cdFx0XHRcdFx0Ly8gQWxsIHJlc291cmNlcyBpbnRlcnNlY3RlZCwgIHRoZW4gIGl0J3MgbWVhbnMgdGhhdCB0aGlzIHRpbWUtc2xvdCBvciB0aW1lIG11c3QgIGJlICBEaXNhYmxlZCwgYW5kIHdlIGNhbiAgZXhpc3QgIGZyb20gICBzZWxlY3RlZF9kYXRlc19hcnIgTE9PUFxyXG5cclxuXHRcdFx0XHRcdHRpbWVfZmllbGRzX29ial9hcnJbIGZpZWxkX2tleSBdLmRpc2FibGVkID0gMTtcclxuXHRcdFx0XHRcdGJyZWFrO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBleGlzdCAgZnJvbSAgIERhdGVzIExPT1BcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblxyXG5cdFx0Ly8gNS4gTm93IHdlIGNhbiBkaXNhYmxlIHRpbWUgc2xvdCBpbiBIVE1MIGJ5ICB1c2luZyAgKCBmaWVsZC5kaXNhYmxlZCA9PSAxICkgcHJvcGVydHlcclxuXHRcdHdwYmNfX2h0bWxfX3RpbWVfZmllbGRfb3B0aW9uc19fc2V0X2Rpc2FibGVkKCB0aW1lX2ZpZWxkc19vYmpfYXJyICk7XHJcblxyXG5cdFx0alF1ZXJ5KCBcIi5ib29raW5nX2Zvcm1fZGl2XCIgKS50cmlnZ2VyKCAnd3BiY19ob29rX3RpbWVzbG90c19kaXNhYmxlZCcsIFtyZXNvdXJjZV9pZCwgc2VsZWN0ZWRfZGF0ZXNfYXJyXSApO1x0XHRcdFx0XHQvLyBUcmlnZ2VyIGhvb2sgb24gZGlzYWJsaW5nIHRpbWVzbG90cy5cdFx0VXNhZ2U6IFx0alF1ZXJ5KCBcIi5ib29raW5nX2Zvcm1fZGl2XCIgKS5vbiggJ3dwYmNfaG9va190aW1lc2xvdHNfZGlzYWJsZWQnLCBmdW5jdGlvbiAoIGV2ZW50LCBia190eXBlLCBhbGxfZGF0ZXMgKXsgLi4uIH0gKTtcdFx0Ly9GaXhJbjogOC43LjExLjlcclxuXHR9XHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBJcyBudW1iZXIgaW5zaWRlIC9pbnRlcnNlY3QgIG9mIGFycmF5IG9mIGludGVydmFscyA/XHJcblx0XHQgKlxyXG5cdFx0ICogQHBhcmFtIHRpbWVfQVx0XHQgICAgIFx0LSAyNTgwMFxyXG5cdFx0ICogQHBhcmFtIHRpbWVfaW50ZXJ2YWxfQlx0XHQtIFsgIFsgMjUyMTEsIDI3MDAyIF0sIFsgMzYwMTEsIDg2NDAwIF0gIF1cclxuXHRcdCAqIEByZXR1cm5zIHtib29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRmdW5jdGlvbiB3cGJjX2lzX2ludGVyc2VjdF9fb25lX3RpbWVfaW50ZXJ2YWwoIHRpbWVfQSwgdGltZV9pbnRlcnZhbF9CICl7XHJcblxyXG5cdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCB0aW1lX2ludGVydmFsX0IubGVuZ3RoOyBqKysgKXtcclxuXHJcblx0XHRcdFx0aWYgKCAocGFyc2VJbnQoIHRpbWVfQSApID4gcGFyc2VJbnQoIHRpbWVfaW50ZXJ2YWxfQlsgaiBdWyAwIF0gKSkgJiYgKHBhcnNlSW50KCB0aW1lX0EgKSA8IHBhcnNlSW50KCB0aW1lX2ludGVydmFsX0JbIGogXVsgMSBdICkpICl7XHJcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0Ly8gaWYgKCAoIHBhcnNlSW50KCB0aW1lX0EgKSA9PSBwYXJzZUludCggdGltZV9pbnRlcnZhbF9CWyBqIF1bIDAgXSApICkgfHwgKCBwYXJzZUludCggdGltZV9BICkgPT0gcGFyc2VJbnQoIHRpbWVfaW50ZXJ2YWxfQlsgaiBdWyAxIF0gKSApICkge1xyXG5cdFx0XHRcdC8vIFx0XHRcdC8vIFRpbWUgQSBqdXN0ICBhdCAgdGhlIGJvcmRlciBvZiBpbnRlcnZhbFxyXG5cdFx0XHRcdC8vIH1cclxuXHRcdFx0fVxyXG5cclxuXHRcdCAgICByZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBJcyB0aGVzZSBhcnJheSBvZiBpbnRlcnZhbHMgaW50ZXJzZWN0ZWQgP1xyXG5cdFx0ICpcclxuXHRcdCAqIEBwYXJhbSB0aW1lX2ludGVydmFsX0FcdFx0LSBbIFsgMjE2MDAsIDIzNDAwIF0gXVxyXG5cdFx0ICogQHBhcmFtIHRpbWVfaW50ZXJ2YWxfQlx0XHQtIFsgIFsgMjUyMTEsIDI3MDAyIF0sIFsgMzYwMTEsIDg2NDAwIF0gIF1cclxuXHRcdCAqIEByZXR1cm5zIHtib29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRmdW5jdGlvbiB3cGJjX2lzX2ludGVyc2VjdF9fcmFuZ2VfdGltZV9pbnRlcnZhbCggdGltZV9pbnRlcnZhbF9BLCB0aW1lX2ludGVydmFsX0IgKXtcclxuXHJcblx0XHRcdHZhciBpc19pbnRlcnNlY3Q7XHJcblxyXG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCB0aW1lX2ludGVydmFsX0EubGVuZ3RoOyBpKysgKXtcclxuXHJcblx0XHRcdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgdGltZV9pbnRlcnZhbF9CLmxlbmd0aDsgaisrICl7XHJcblxyXG5cdFx0XHRcdFx0aXNfaW50ZXJzZWN0ID0gd3BiY19pbnRlcnZhbHNfX2lzX2ludGVyc2VjdGVkKCB0aW1lX2ludGVydmFsX0FbIGkgXSwgdGltZV9pbnRlcnZhbF9CWyBqIF0gKTtcclxuXHJcblx0XHRcdFx0XHRpZiAoIGlzX2ludGVyc2VjdCApe1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIEdldCBhbGwgdGltZSBmaWVsZHMgaW4gdGhlIGJvb2tpbmcgZm9ybSBhcyBhcnJheSAgb2Ygb2JqZWN0c1xyXG5cdFx0ICpcclxuXHRcdCAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG5cdFx0ICogQHJldHVybnMgW11cclxuXHRcdCAqXHJcblx0XHQgKiBcdFx0RXhhbXBsZTpcclxuXHRcdCAqIFx0XHRcdFx0XHRbXHJcblx0XHQgKiBcdFx0XHRcdFx0IFx0ICAge1xyXG5cdFx0ICogXHRcdFx0XHRcdFx0XHRcdHZhbHVlX29wdGlvbl8yNGg6ICAgJzA2OjAwIC0gMDY6MzAnXHJcblx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0dGltZXNfYXNfc2Vjb25kczogICBbIDIxNjAwLCAyMzQwMCBdXHJcblx0XHQgKiBcdFx0XHRcdFx0IFx0ICAgXHRcdGpxdWVyeV9vcHRpb246ICAgICAgalF1ZXJ5X09iamVjdCB7fVxyXG5cdFx0ICogXHRcdFx0XHRcdFx0XHRcdG5hbWU6ICAgICAgICAgICAgICAgJ3JhbmdldGltZTJbXSdcclxuXHRcdCAqIFx0XHRcdFx0XHQgICAgIH1cclxuXHRcdCAqIFx0XHRcdFx0XHQgIC4uLlxyXG5cdFx0ICogXHRcdFx0XHRcdFx0ICAge1xyXG5cdFx0ICogXHRcdFx0XHRcdFx0XHRcdHZhbHVlX29wdGlvbl8yNGg6ICAgJzA2OjAwJ1xyXG5cdFx0ICogXHRcdFx0XHRcdFx0XHRcdHRpbWVzX2FzX3NlY29uZHM6ICAgWyAyMTYwMCBdXHJcblx0XHQgKiBcdFx0XHRcdFx0XHQgICBcdFx0anF1ZXJ5X29wdGlvbjogICAgICBqUXVlcnlfT2JqZWN0IHt9XHJcblx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0bmFtZTogICAgICAgICAgICAgICAnc3RhcnR0aW1lMltdJ1xyXG5cdFx0ICogIFx0XHRcdFx0XHQgICAgfVxyXG5cdFx0ICogXHRcdFx0XHRcdCBdXHJcblx0XHQgKi9cclxuXHRcdGZ1bmN0aW9uIHdwYmNfZ2V0X190aW1lX2ZpZWxkc19faW5fYm9va2luZ19mb3JtX19hc19hcnIoIHJlc291cmNlX2lkICl7XHJcblx0XHQgICAgLyoqXHJcblx0XHRcdCAqIEZpZWxkcyB3aXRoICBbXSAgbGlrZSB0aGlzICAgc2VsZWN0W25hbWU9XCJyYW5nZXRpbWUxW11cIl1cclxuXHRcdFx0ICogaXQncyB3aGVuIHdlIGhhdmUgJ211bHRpcGxlJyBpbiBzaG9ydGNvZGU6ICAgW3NlbGVjdCogcmFuZ2V0aW1lIG11bHRpcGxlICBcIjA2OjAwIC0gMDY6MzBcIiAuLi4gXVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dmFyIHRpbWVfZmllbGRzX2Fycj1bXHJcblx0XHRcdFx0XHRcdFx0XHRcdCdzZWxlY3RbbmFtZT1cInJhbmdldGltZScgKyByZXNvdXJjZV9pZCArICdcIl0nLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHQnc2VsZWN0W25hbWU9XCJyYW5nZXRpbWUnICsgcmVzb3VyY2VfaWQgKyAnW11cIl0nLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHQnc2VsZWN0W25hbWU9XCJzdGFydHRpbWUnICsgcmVzb3VyY2VfaWQgKyAnXCJdJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0J3NlbGVjdFtuYW1lPVwic3RhcnR0aW1lJyArIHJlc291cmNlX2lkICsgJ1tdXCJdJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0J3NlbGVjdFtuYW1lPVwiZW5kdGltZScgKyByZXNvdXJjZV9pZCArICdcIl0nLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHQnc2VsZWN0W25hbWU9XCJlbmR0aW1lJyArIHJlc291cmNlX2lkICsgJ1tdXCJdJ1xyXG5cdFx0XHRcdFx0XHRcdFx0XTtcclxuXHJcblx0XHRcdHZhciB0aW1lX2ZpZWxkc19vYmpfYXJyID0gW107XHJcblxyXG5cdFx0XHQvLyBMb29wIGFsbCBUaW1lIEZpZWxkc1xyXG5cdFx0XHRmb3IgKCB2YXIgY3RmPSAwOyBjdGYgPCB0aW1lX2ZpZWxkc19hcnIubGVuZ3RoOyBjdGYrKyApe1xyXG5cclxuXHRcdFx0XHR2YXIgdGltZV9maWVsZCA9IHRpbWVfZmllbGRzX2FyclsgY3RmIF07XHJcblx0XHRcdFx0dmFyIHRpbWVfb3B0aW9uID0galF1ZXJ5KCB0aW1lX2ZpZWxkICsgJyBvcHRpb24nICk7XHJcblxyXG5cdFx0XHRcdC8vIExvb3AgYWxsIG9wdGlvbnMgaW4gdGltZSBmaWVsZFxyXG5cdFx0XHRcdGZvciAoIHZhciBqID0gMDsgaiA8IHRpbWVfb3B0aW9uLmxlbmd0aDsgaisrICl7XHJcblxyXG5cdFx0XHRcdFx0dmFyIGpxdWVyeV9vcHRpb24gPSBqUXVlcnkoIHRpbWVfZmllbGQgKyAnIG9wdGlvbjplcSgnICsgaiArICcpJyApO1xyXG5cdFx0XHRcdFx0dmFyIHZhbHVlX29wdGlvbl9zZWNvbmRzX2FyciA9IGpxdWVyeV9vcHRpb24udmFsKCkuc3BsaXQoICctJyApO1xyXG5cdFx0XHRcdFx0dmFyIHRpbWVzX2FzX3NlY29uZHMgPSBbXTtcclxuXHJcblx0XHRcdFx0XHQvLyBHZXQgdGltZSBhcyBzZWNvbmRzXHJcblx0XHRcdFx0XHRpZiAoIHZhbHVlX29wdGlvbl9zZWNvbmRzX2Fyci5sZW5ndGggKXtcdFx0XHRcdFx0Ly9GaXhJbjogOS44LjEwLjFcclxuXHRcdFx0XHRcdFx0Zm9yICggdmFyIGkgaW4gdmFsdWVfb3B0aW9uX3NlY29uZHNfYXJyICl7XHJcblxyXG5cdFx0XHRcdFx0XHRcdC8vIHZhbHVlX29wdGlvbl9zZWNvbmRzX2FycltpXSA9ICcxNDowMCAnICB8ICcgMTY6MDAnICAgKGlmIGZyb20gJ3JhbmdldGltZScpIGFuZCAnMTY6MDAnICBpZiAoc3RhcnQvZW5kIHRpbWUpXHJcblxyXG5cdFx0XHRcdFx0XHRcdHZhciBzdGFydF9lbmRfdGltZXNfYXJyID0gdmFsdWVfb3B0aW9uX3NlY29uZHNfYXJyWyBpIF0udHJpbSgpLnNwbGl0KCAnOicgKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0dmFyIHRpbWVfaW5fc2Vjb25kcyA9IHBhcnNlSW50KCBzdGFydF9lbmRfdGltZXNfYXJyWyAwIF0gKSAqIDYwICogNjAgKyBwYXJzZUludCggc3RhcnRfZW5kX3RpbWVzX2FyclsgMSBdICkgKiA2MDtcclxuXHJcblx0XHRcdFx0XHRcdFx0dGltZXNfYXNfc2Vjb25kcy5wdXNoKCB0aW1lX2luX3NlY29uZHMgKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdHRpbWVfZmllbGRzX29ial9hcnIucHVzaCgge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnbmFtZScgICAgICAgICAgICA6IGpRdWVyeSggdGltZV9maWVsZCApLmF0dHIoICduYW1lJyApLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndmFsdWVfb3B0aW9uXzI0aCc6IGpxdWVyeV9vcHRpb24udmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdqcXVlcnlfb3B0aW9uJyAgIDoganF1ZXJ5X29wdGlvbixcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3RpbWVzX2FzX3NlY29uZHMnOiB0aW1lc19hc19zZWNvbmRzXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9ICk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRyZXR1cm4gdGltZV9maWVsZHNfb2JqX2FycjtcclxuXHRcdH1cclxuXHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiBEaXNhYmxlIEhUTUwgb3B0aW9ucyBhbmQgYWRkIGJvb2tlZCBDU1MgY2xhc3NcclxuXHRcdFx0ICpcclxuXHRcdFx0ICogQHBhcmFtIHRpbWVfZmllbGRzX29ial9hcnIgICAgICAtIHRoaXMgdmFsdWUgaXMgZnJvbSAgdGhlIGZ1bmM6ICBcdHdwYmNfZ2V0X190aW1lX2ZpZWxkc19faW5fYm9va2luZ19mb3JtX19hc19hcnIoIHJlc291cmNlX2lkIClcclxuXHRcdFx0ICogXHRcdFx0XHRcdFtcclxuXHRcdFx0ICogXHRcdFx0XHRcdCBcdCAgIHtcdGpxdWVyeV9vcHRpb246ICAgICAgalF1ZXJ5X09iamVjdCB7fVxyXG5cdFx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0bmFtZTogICAgICAgICAgICAgICAncmFuZ2V0aW1lMltdJ1xyXG5cdFx0XHQgKiBcdFx0XHRcdFx0XHRcdFx0dGltZXNfYXNfc2Vjb25kczogICBbIDIxNjAwLCAyMzQwMCBdXHJcblx0XHRcdCAqIFx0XHRcdFx0XHRcdFx0XHR2YWx1ZV9vcHRpb25fMjRoOiAgICcwNjowMCAtIDA2OjMwJ1xyXG5cdFx0XHQgKiBcdCAgXHRcdFx0XHRcdFx0ICAgIGRpc2FibGVkID0gMVxyXG5cdFx0XHQgKiBcdFx0XHRcdFx0ICAgICB9XHJcblx0XHRcdCAqIFx0XHRcdFx0XHQgIC4uLlxyXG5cdFx0XHQgKiBcdFx0XHRcdFx0XHQgICB7XHRqcXVlcnlfb3B0aW9uOiAgICAgIGpRdWVyeV9PYmplY3Qge31cclxuXHRcdFx0ICogXHRcdFx0XHRcdFx0XHRcdG5hbWU6ICAgICAgICAgICAgICAgJ3N0YXJ0dGltZTJbXSdcclxuXHRcdFx0ICogXHRcdFx0XHRcdFx0XHRcdHRpbWVzX2FzX3NlY29uZHM6ICAgWyAyMTYwMCBdXHJcblx0XHRcdCAqIFx0XHRcdFx0XHRcdFx0XHR2YWx1ZV9vcHRpb25fMjRoOiAgICcwNjowMCdcclxuXHRcdFx0ICogICBcdFx0XHRcdFx0XHRcdGRpc2FibGVkID0gMFxyXG5cdFx0XHQgKiAgXHRcdFx0XHRcdCAgICB9XHJcblx0XHRcdCAqIFx0XHRcdFx0XHQgXVxyXG5cdFx0XHQgKlxyXG5cdFx0XHQgKi9cclxuXHRcdFx0ZnVuY3Rpb24gd3BiY19faHRtbF9fdGltZV9maWVsZF9vcHRpb25zX19zZXRfZGlzYWJsZWQoIHRpbWVfZmllbGRzX29ial9hcnIgKXtcclxuXHJcblx0XHRcdFx0dmFyIGpxdWVyeV9vcHRpb247XHJcblxyXG5cdFx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHRpbWVfZmllbGRzX29ial9hcnIubGVuZ3RoOyBpKysgKXtcclxuXHJcblx0XHRcdFx0XHR2YXIganF1ZXJ5X29wdGlvbiA9IHRpbWVfZmllbGRzX29ial9hcnJbIGkgXS5qcXVlcnlfb3B0aW9uO1xyXG5cclxuXHRcdFx0XHRcdGlmICggMSA9PSB0aW1lX2ZpZWxkc19vYmpfYXJyWyBpIF0uZGlzYWJsZWQgKXtcclxuXHRcdFx0XHRcdFx0anF1ZXJ5X29wdGlvbi5wcm9wKCAnZGlzYWJsZWQnLCB0cnVlICk7IFx0XHQvLyBNYWtlIGRpc2FibGUgc29tZSBvcHRpb25zXHJcblx0XHRcdFx0XHRcdGpxdWVyeV9vcHRpb24uYWRkQ2xhc3MoICdib29rZWQnICk7ICAgICAgICAgICBcdC8vIEFkZCBcImJvb2tlZFwiIENTUyBjbGFzc1xyXG5cclxuXHRcdFx0XHRcdFx0Ly8gaWYgdGhpcyBib29rZWQgZWxlbWVudCBzZWxlY3RlZCAtLT4gdGhlbiBkZXNlbGVjdCAgaXRcclxuXHRcdFx0XHRcdFx0aWYgKCBqcXVlcnlfb3B0aW9uLnByb3AoICdzZWxlY3RlZCcgKSApe1xyXG5cdFx0XHRcdFx0XHRcdGpxdWVyeV9vcHRpb24ucHJvcCggJ3NlbGVjdGVkJywgZmFsc2UgKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0anF1ZXJ5X29wdGlvbi5wYXJlbnQoKS5maW5kKCAnb3B0aW9uOm5vdChbZGlzYWJsZWRdKTpmaXJzdCcgKS5wcm9wKCAnc2VsZWN0ZWQnLCB0cnVlICkudHJpZ2dlciggXCJjaGFuZ2VcIiApO1xyXG5cdFx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0anF1ZXJ5X29wdGlvbi5wcm9wKCAnZGlzYWJsZWQnLCBmYWxzZSApOyAgXHRcdC8vIE1ha2UgYWN0aXZlIGFsbCB0aW1lc1xyXG5cdFx0XHRcdFx0XHRqcXVlcnlfb3B0aW9uLnJlbW92ZUNsYXNzKCAnYm9va2VkJyApOyAgIFx0XHQvLyBSZW1vdmUgY2xhc3MgXCJib29rZWRcIlxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdH1cclxuXHJcblx0LyoqXHJcblx0ICogQ2hlY2sgaWYgdGhpcyB0aW1lX3JhbmdlIHwgVGltZV9TbG90IGlzIEZ1bGwgRGF5ICBib29rZWRcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB0aW1lc2xvdF9hcnJfaW5fc2Vjb25kc1x0XHQtIFsgMzYwMTEsIDg2NDAwIF1cclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2lzX3RoaXNfdGltZXNsb3RfX2Z1bGxfZGF5X2Jvb2tlZCggdGltZXNsb3RfYXJyX2luX3NlY29uZHMgKXtcclxuXHJcblx0XHRpZiAoXHJcblx0XHRcdFx0KCB0aW1lc2xvdF9hcnJfaW5fc2Vjb25kcy5sZW5ndGggPiAxIClcclxuXHRcdFx0JiYgKCBwYXJzZUludCggdGltZXNsb3RfYXJyX2luX3NlY29uZHNbIDAgXSApIDwgMzAgKVxyXG5cdFx0XHQmJiAoIHBhcnNlSW50KCB0aW1lc2xvdF9hcnJfaW5fc2Vjb25kc1sgMSBdICkgPiAgKCAoMjQgKiA2MCAqIDYwKSAtIDMwKSApXHJcblx0XHQpe1xyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gZmFsc2U7XHJcblx0fVxyXG5cclxuXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBTIGUgbCBlIGMgdCBlIGQgICAgRCBhIHQgZSBzICAvICBUIGkgbSBlIC0gRiBpIGUgbCBkIHNcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHQvKipcclxuXHQgKiAgR2V0IGFsbCBzZWxlY3RlZCBkYXRlcyBpbiBTUUwgZm9ybWF0IGxpa2UgdGhpcyBbIFwiMjAyMy0wOC0yM1wiLCBcIjIwMjMtMDgtMjRcIiAsIC4uLiBdXHJcblx0ICpcclxuXHQgKiBAcGFyYW0gcmVzb3VyY2VfaWRcclxuXHQgKiBAcmV0dXJucyB7W119XHRcdFx0WyBcIjIwMjMtMDgtMjNcIiwgXCIyMDIzLTA4LTI0XCIsIFwiMjAyMy0wOC0yNVwiLCBcIjIwMjMtMDgtMjZcIiwgXCIyMDIzLTA4LTI3XCIsIFwiMjAyMy0wOC0yOFwiLCBcIjIwMjMtMDgtMjlcIiBdXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19nZXRfX3NlbGVjdGVkX2RhdGVzX3NxbF9fYXNfYXJyKCByZXNvdXJjZV9pZCApe1xyXG5cclxuXHRcdHZhciBzZWxlY3RlZF9kYXRlc19hcnIgPSBbXTtcclxuXHRcdHNlbGVjdGVkX2RhdGVzX2FyciA9IGpRdWVyeSggJyNkYXRlX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS52YWwoKS5zcGxpdCgnLCcpO1xyXG5cclxuXHRcdGlmICggc2VsZWN0ZWRfZGF0ZXNfYXJyLmxlbmd0aCApe1x0XHRcdFx0XHQvL0ZpeEluOiA5LjguMTAuMVxyXG5cdFx0XHRmb3IgKCB2YXIgaSBpbiBzZWxlY3RlZF9kYXRlc19hcnIgKXtcclxuXHRcdFx0XHRzZWxlY3RlZF9kYXRlc19hcnJbIGkgXSA9IHNlbGVjdGVkX2RhdGVzX2FyclsgaSBdLnRyaW0oKTtcclxuXHRcdFx0XHRzZWxlY3RlZF9kYXRlc19hcnJbIGkgXSA9IHNlbGVjdGVkX2RhdGVzX2FyclsgaSBdLnNwbGl0KCAnLicgKTtcclxuXHRcdFx0XHRpZiAoIHNlbGVjdGVkX2RhdGVzX2FyclsgaSBdLmxlbmd0aCA+IDEgKXtcclxuXHRcdFx0XHRcdHNlbGVjdGVkX2RhdGVzX2FyclsgaSBdID0gc2VsZWN0ZWRfZGF0ZXNfYXJyWyBpIF1bIDIgXSArICctJyArIHNlbGVjdGVkX2RhdGVzX2FyclsgaSBdWyAxIF0gKyAnLScgKyBzZWxlY3RlZF9kYXRlc19hcnJbIGkgXVsgMCBdO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFJlbW92ZSBlbXB0eSBlbGVtZW50cyBmcm9tIGFuIGFycmF5XHJcblx0XHRzZWxlY3RlZF9kYXRlc19hcnIgPSBzZWxlY3RlZF9kYXRlc19hcnIuZmlsdGVyKCBmdW5jdGlvbiAoIG4gKXsgcmV0dXJuIHBhcnNlSW50KG4pOyB9ICk7XHJcblxyXG5cdFx0c2VsZWN0ZWRfZGF0ZXNfYXJyLnNvcnQoKTtcclxuXHJcblx0XHRyZXR1cm4gc2VsZWN0ZWRfZGF0ZXNfYXJyO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBhbGwgdGltZSBmaWVsZHMgaW4gdGhlIGJvb2tpbmcgZm9ybSBhcyBhcnJheSAgb2Ygb2JqZWN0c1xyXG5cdCAqXHJcblx0ICogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0ICogQHBhcmFtIGlzX29ubHlfc2VsZWN0ZWRfdGltZVxyXG5cdCAqIEByZXR1cm5zIFtdXHJcblx0ICpcclxuXHQgKiBcdFx0RXhhbXBsZTpcclxuXHQgKiBcdFx0XHRcdFx0W1xyXG5cdCAqIFx0XHRcdFx0XHQgXHQgICB7XHJcblx0ICogXHRcdFx0XHRcdFx0XHRcdHZhbHVlX29wdGlvbl8yNGg6ICAgJzA2OjAwIC0gMDY6MzAnXHJcblx0ICogXHRcdFx0XHRcdFx0XHRcdHRpbWVzX2FzX3NlY29uZHM6ICAgWyAyMTYwMCwgMjM0MDAgXVxyXG5cdCAqIFx0XHRcdFx0XHQgXHQgICBcdFx0anF1ZXJ5X29wdGlvbjogICAgICBqUXVlcnlfT2JqZWN0IHt9XHJcblx0ICogXHRcdFx0XHRcdFx0XHRcdG5hbWU6ICAgICAgICAgICAgICAgJ3JhbmdldGltZTJbXSdcclxuXHQgKiBcdFx0XHRcdFx0ICAgICB9XHJcblx0ICogXHRcdFx0XHRcdCAgLi4uXHJcblx0ICogXHRcdFx0XHRcdFx0ICAge1xyXG5cdCAqIFx0XHRcdFx0XHRcdFx0XHR2YWx1ZV9vcHRpb25fMjRoOiAgICcwNjowMCdcclxuXHQgKiBcdFx0XHRcdFx0XHRcdFx0dGltZXNfYXNfc2Vjb25kczogICBbIDIxNjAwIF1cclxuXHQgKiBcdFx0XHRcdFx0XHQgICBcdFx0anF1ZXJ5X29wdGlvbjogICAgICBqUXVlcnlfT2JqZWN0IHt9XHJcblx0ICogXHRcdFx0XHRcdFx0XHRcdG5hbWU6ICAgICAgICAgICAgICAgJ3N0YXJ0dGltZTJbXSdcclxuXHQgKiAgXHRcdFx0XHRcdCAgICB9XHJcblx0ICogXHRcdFx0XHRcdCBdXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19nZXRfX3NlbGVjdGVkX3RpbWVfZmllbGRzX19pbl9ib29raW5nX2Zvcm1fX2FzX2FyciggcmVzb3VyY2VfaWQsIGlzX29ubHlfc2VsZWN0ZWRfdGltZSA9IHRydWUgKXtcclxuXHRcdC8qKlxyXG5cdFx0ICogRmllbGRzIHdpdGggIFtdICBsaWtlIHRoaXMgICBzZWxlY3RbbmFtZT1cInJhbmdldGltZTFbXVwiXVxyXG5cdFx0ICogaXQncyB3aGVuIHdlIGhhdmUgJ211bHRpcGxlJyBpbiBzaG9ydGNvZGU6ICAgW3NlbGVjdCogcmFuZ2V0aW1lIG11bHRpcGxlICBcIjA2OjAwIC0gMDY6MzBcIiAuLi4gXVxyXG5cdFx0ICovXHJcblx0XHR2YXIgdGltZV9maWVsZHNfYXJyPVtcclxuXHRcdFx0XHRcdFx0XHRcdCdzZWxlY3RbbmFtZT1cInJhbmdldGltZScgKyByZXNvdXJjZV9pZCArICdcIl0nLFxyXG5cdFx0XHRcdFx0XHRcdFx0J3NlbGVjdFtuYW1lPVwicmFuZ2V0aW1lJyArIHJlc291cmNlX2lkICsgJ1tdXCJdJyxcclxuXHRcdFx0XHRcdFx0XHRcdCdzZWxlY3RbbmFtZT1cInN0YXJ0dGltZScgKyByZXNvdXJjZV9pZCArICdcIl0nLFxyXG5cdFx0XHRcdFx0XHRcdFx0J3NlbGVjdFtuYW1lPVwic3RhcnR0aW1lJyArIHJlc291cmNlX2lkICsgJ1tdXCJdJyxcclxuXHRcdFx0XHRcdFx0XHRcdCdzZWxlY3RbbmFtZT1cImVuZHRpbWUnICsgcmVzb3VyY2VfaWQgKyAnXCJdJyxcclxuXHRcdFx0XHRcdFx0XHRcdCdzZWxlY3RbbmFtZT1cImVuZHRpbWUnICsgcmVzb3VyY2VfaWQgKyAnW11cIl0nLFxyXG5cdFx0XHRcdFx0XHRcdFx0J3NlbGVjdFtuYW1lPVwiZHVyYXRpb250aW1lJyArIHJlc291cmNlX2lkICsgJ1wiXScsXHJcblx0XHRcdFx0XHRcdFx0XHQnc2VsZWN0W25hbWU9XCJkdXJhdGlvbnRpbWUnICsgcmVzb3VyY2VfaWQgKyAnW11cIl0nXHJcblx0XHRcdFx0XHRcdFx0XTtcclxuXHJcblx0XHR2YXIgdGltZV9maWVsZHNfb2JqX2FyciA9IFtdO1xyXG5cclxuXHRcdC8vIExvb3AgYWxsIFRpbWUgRmllbGRzXHJcblx0XHRmb3IgKCB2YXIgY3RmPSAwOyBjdGYgPCB0aW1lX2ZpZWxkc19hcnIubGVuZ3RoOyBjdGYrKyApe1xyXG5cclxuXHRcdFx0dmFyIHRpbWVfZmllbGQgPSB0aW1lX2ZpZWxkc19hcnJbIGN0ZiBdO1xyXG5cclxuXHRcdFx0dmFyIHRpbWVfb3B0aW9uO1xyXG5cdFx0XHRpZiAoIGlzX29ubHlfc2VsZWN0ZWRfdGltZSApe1xyXG5cdFx0XHRcdHRpbWVfb3B0aW9uID0galF1ZXJ5KCAnI2Jvb2tpbmdfZm9ybScgKyByZXNvdXJjZV9pZCArICcgJyArIHRpbWVfZmllbGQgKyAnIG9wdGlvbjpzZWxlY3RlZCcgKTtcdFx0XHQvLyBFeGNsdWRlIGNvbmRpdGlvbmFsICBmaWVsZHMsICBiZWNhdXNlIG9mIHVzaW5nICcjYm9va2luZ19mb3JtMyAuLi4nXHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGltZV9vcHRpb24gPSBqUXVlcnkoICcjYm9va2luZ19mb3JtJyArIHJlc291cmNlX2lkICsgJyAnICsgdGltZV9maWVsZCArICcgb3B0aW9uJyApO1x0XHRcdFx0Ly8gQWxsICB0aW1lIGZpZWxkc1xyXG5cdFx0XHR9XHJcblxyXG5cclxuXHRcdFx0Ly8gTG9vcCBhbGwgb3B0aW9ucyBpbiB0aW1lIGZpZWxkXHJcblx0XHRcdGZvciAoIHZhciBqID0gMDsgaiA8IHRpbWVfb3B0aW9uLmxlbmd0aDsgaisrICl7XHJcblxyXG5cdFx0XHRcdHZhciBqcXVlcnlfb3B0aW9uID0galF1ZXJ5KCB0aW1lX29wdGlvblsgaiBdICk7XHRcdC8vIEdldCBvbmx5ICBzZWxlY3RlZCBvcHRpb25zIFx0Ly9qUXVlcnkoIHRpbWVfZmllbGQgKyAnIG9wdGlvbjplcSgnICsgaiArICcpJyApO1xyXG5cdFx0XHRcdHZhciB2YWx1ZV9vcHRpb25fc2Vjb25kc19hcnIgPSBqcXVlcnlfb3B0aW9uLnZhbCgpLnNwbGl0KCAnLScgKTtcclxuXHRcdFx0XHR2YXIgdGltZXNfYXNfc2Vjb25kcyA9IFtdO1xyXG5cclxuXHRcdFx0XHQvLyBHZXQgdGltZSBhcyBzZWNvbmRzXHJcblx0XHRcdFx0aWYgKCB2YWx1ZV9vcHRpb25fc2Vjb25kc19hcnIubGVuZ3RoICl7XHRcdFx0XHQgXHQvL0ZpeEluOiA5LjguMTAuMVxyXG5cdFx0XHRcdFx0Zm9yICggdmFyIGkgaW4gdmFsdWVfb3B0aW9uX3NlY29uZHNfYXJyICl7XHJcblxyXG5cdFx0XHRcdFx0XHQvLyB2YWx1ZV9vcHRpb25fc2Vjb25kc19hcnJbaV0gPSAnMTQ6MDAgJyAgfCAnIDE2OjAwJyAgIChpZiBmcm9tICdyYW5nZXRpbWUnKSBhbmQgJzE2OjAwJyAgaWYgKHN0YXJ0L2VuZCB0aW1lKVxyXG5cclxuXHRcdFx0XHRcdFx0dmFyIHN0YXJ0X2VuZF90aW1lc19hcnIgPSB2YWx1ZV9vcHRpb25fc2Vjb25kc19hcnJbIGkgXS50cmltKCkuc3BsaXQoICc6JyApO1xyXG5cclxuXHRcdFx0XHRcdFx0dmFyIHRpbWVfaW5fc2Vjb25kcyA9IHBhcnNlSW50KCBzdGFydF9lbmRfdGltZXNfYXJyWyAwIF0gKSAqIDYwICogNjAgKyBwYXJzZUludCggc3RhcnRfZW5kX3RpbWVzX2FyclsgMSBdICkgKiA2MDtcclxuXHJcblx0XHRcdFx0XHRcdHRpbWVzX2FzX3NlY29uZHMucHVzaCggdGltZV9pbl9zZWNvbmRzICk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHR0aW1lX2ZpZWxkc19vYmpfYXJyLnB1c2goIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCduYW1lJyAgICAgICAgICAgIDogalF1ZXJ5KCAnI2Jvb2tpbmdfZm9ybScgKyByZXNvdXJjZV9pZCArICcgJyArIHRpbWVfZmllbGQgKS5hdHRyKCAnbmFtZScgKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd2YWx1ZV9vcHRpb25fMjRoJzoganF1ZXJ5X29wdGlvbi52YWwoKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdqcXVlcnlfb3B0aW9uJyAgIDoganF1ZXJ5X29wdGlvbixcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd0aW1lc19hc19zZWNvbmRzJzogdGltZXNfYXNfc2Vjb25kc1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFRleHQ6ICAgW3N0YXJ0dGltZV0gLSBbZW5kdGltZV0gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblx0XHR2YXIgdGV4dF90aW1lX2ZpZWxkc19hcnI9W1xyXG5cdFx0XHRcdFx0XHRcdFx0XHQnaW5wdXRbbmFtZT1cInN0YXJ0dGltZScgKyByZXNvdXJjZV9pZCArICdcIl0nLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHQnaW5wdXRbbmFtZT1cImVuZHRpbWUnICsgcmVzb3VyY2VfaWQgKyAnXCJdJyxcclxuXHRcdFx0XHRcdFx0XHRcdF07XHJcblx0XHRmb3IgKCB2YXIgdGY9IDA7IHRmIDwgdGV4dF90aW1lX2ZpZWxkc19hcnIubGVuZ3RoOyB0ZisrICl7XHJcblxyXG5cdFx0XHR2YXIgdGV4dF9qcXVlcnkgPSBqUXVlcnkoICcjYm9va2luZ19mb3JtJyArIHJlc291cmNlX2lkICsgJyAnICsgdGV4dF90aW1lX2ZpZWxkc19hcnJbIHRmIF0gKTtcdFx0XHRcdFx0XHRcdFx0Ly8gRXhjbHVkZSBjb25kaXRpb25hbCAgZmllbGRzLCAgYmVjYXVzZSBvZiB1c2luZyAnI2Jvb2tpbmdfZm9ybTMgLi4uJ1xyXG5cdFx0XHRpZiAoIHRleHRfanF1ZXJ5Lmxlbmd0aCA+IDAgKXtcclxuXHJcblx0XHRcdFx0dmFyIHRpbWVfX2hfbV9fYXJyID0gdGV4dF9qcXVlcnkudmFsKCkudHJpbSgpLnNwbGl0KCAnOicgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gJzE0OjAwJ1xyXG5cdFx0XHRcdGlmICggMCA9PSB0aW1lX19oX21fX2Fyci5sZW5ndGggKXtcclxuXHRcdFx0XHRcdGNvbnRpbnVlO1x0XHRcdFx0XHRcdFx0XHRcdC8vIE5vdCBlbnRlcmVkIHRpbWUgdmFsdWUgaW4gYSBmaWVsZFxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZiAoIDEgPT0gdGltZV9faF9tX19hcnIubGVuZ3RoICl7XHJcblx0XHRcdFx0XHRpZiAoICcnID09PSB0aW1lX19oX21fX2FyclsgMCBdICl7XHJcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1x0XHRcdFx0XHRcdFx0XHQvLyBOb3QgZW50ZXJlZCB0aW1lIHZhbHVlIGluIGEgZmllbGRcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdHRpbWVfX2hfbV9fYXJyWyAxIF0gPSAwO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHR2YXIgdGV4dF90aW1lX2luX3NlY29uZHMgPSBwYXJzZUludCggdGltZV9faF9tX19hcnJbIDAgXSApICogNjAgKiA2MCArIHBhcnNlSW50KCB0aW1lX19oX21fX2FyclsgMSBdICkgKiA2MDtcclxuXHJcblx0XHRcdFx0dmFyIHRleHRfdGltZXNfYXNfc2Vjb25kcyA9IFtdO1xyXG5cdFx0XHRcdHRleHRfdGltZXNfYXNfc2Vjb25kcy5wdXNoKCB0ZXh0X3RpbWVfaW5fc2Vjb25kcyApO1xyXG5cclxuXHRcdFx0XHR0aW1lX2ZpZWxkc19vYmpfYXJyLnB1c2goIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCduYW1lJyAgICAgICAgICAgIDogdGV4dF9qcXVlcnkuYXR0ciggJ25hbWUnICksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndmFsdWVfb3B0aW9uXzI0aCc6IHRleHRfanF1ZXJ5LnZhbCgpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2pxdWVyeV9vcHRpb24nICAgOiB0ZXh0X2pxdWVyeSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd0aW1lc19hc19zZWNvbmRzJzogdGV4dF90aW1lc19hc19zZWNvbmRzXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRpbWVfZmllbGRzX29ial9hcnI7XHJcblx0fVxyXG5cclxuXHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuLy8gUyBVIFAgUCBPIFIgVCAgICBmb3IgICAgQyBBIEwgRSBOIEQgQSBSXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgQ2FsZW5kYXIgZGF0ZXBpY2sgIEluc3RhbmNlXHJcblx0ICogQHBhcmFtIHJlc291cmNlX2lkICBvZiBib29raW5nIHJlc291cmNlXHJcblx0ICogQHJldHVybnMgeyp8bnVsbH1cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2NhbGVuZGFyX19nZXRfaW5zdCggcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0XHRpZiAoICd1bmRlZmluZWQnID09PSB0eXBlb2YgKHJlc291cmNlX2lkKSApe1xyXG5cdFx0XHRyZXNvdXJjZV9pZCA9ICcxJztcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIGpRdWVyeSggJyNjYWxlbmRhcl9ib29raW5nJyArIHJlc291cmNlX2lkICkubGVuZ3RoID4gMCApe1xyXG5cdFx0XHRyZXR1cm4galF1ZXJ5LmRhdGVwaWNrLl9nZXRJbnN0KCBqUXVlcnkoICcjY2FsZW5kYXJfYm9va2luZycgKyByZXNvdXJjZV9pZCApLmdldCggMCApICk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIG51bGw7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBVbnNlbGVjdCAgYWxsIGRhdGVzIGluIGNhbGVuZGFyIGFuZCB2aXN1YWxseSB1cGRhdGUgdGhpcyBjYWxlbmRhclxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHJlc291cmNlX2lkXHRcdElEIG9mIGJvb2tpbmcgcmVzb3VyY2VcclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cdFx0dHJ1ZSBvbiBzdWNjZXNzIHwgZmFsc2UsICBpZiBubyBzdWNoICBjYWxlbmRhclxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfY2FsZW5kYXJfX3Vuc2VsZWN0X2FsbF9kYXRlcyggcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0XHRpZiAoICd1bmRlZmluZWQnID09PSB0eXBlb2YgKHJlc291cmNlX2lkKSApe1xyXG5cdFx0XHRyZXNvdXJjZV9pZCA9ICcxJztcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgaW5zdCA9IHdwYmNfY2FsZW5kYXJfX2dldF9pbnN0KCByZXNvdXJjZV9pZCApXHJcblxyXG5cdFx0aWYgKCBudWxsICE9PSBpbnN0ICl7XHJcblxyXG5cdFx0XHQvLyBVbnNlbGVjdCBhbGwgZGF0ZXMgYW5kIHNldCAgcHJvcGVydGllcyBvZiBEYXRlcGlja1xyXG5cdFx0XHRqUXVlcnkoICcjZGF0ZV9ib29raW5nJyArIHJlc291cmNlX2lkICkudmFsKCAnJyApOyAgICAgIC8vRml4SW46IDUuNC4zXHJcblx0XHRcdGluc3Quc3RheU9wZW4gPSBmYWxzZTtcclxuXHRcdFx0aW5zdC5kYXRlcyA9IFtdO1xyXG5cdFx0XHRqUXVlcnkuZGF0ZXBpY2suX3VwZGF0ZURhdGVwaWNrKCBpbnN0ICk7XHJcblxyXG5cdFx0XHRyZXR1cm4gdHJ1ZVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBDbGVhciBkYXlzIGhpZ2hsaWdodGluZyBpbiBBbGwgb3Igc3BlY2lmaWMgQ2FsZW5kYXJzXHJcblx0ICpcclxuICAgICAqIEBwYXJhbSByZXNvdXJjZV9pZCAgLSBjYW4gYmUgc2tpcGVkIHRvICBjbGVhciBoaWdobGlnaHRpbmcgaW4gYWxsIGNhbGVuZGFyc1xyXG4gICAgICovXHJcblx0ZnVuY3Rpb24gd3BiY19jYWxlbmRhcnNfX2NsZWFyX2RheXNfaGlnaGxpZ2h0aW5nKCByZXNvdXJjZV9pZCApe1xyXG5cclxuXHRcdGlmICggJ3VuZGVmaW5lZCcgIT09IHR5cGVvZiAoIHJlc291cmNlX2lkICkgKXtcclxuXHJcblx0XHRcdGpRdWVyeSggJyNjYWxlbmRhcl9ib29raW5nJyArIHJlc291cmNlX2lkICsgJyAuZGF0ZXBpY2stZGF5cy1jZWxsLW92ZXInICkucmVtb3ZlQ2xhc3MoICdkYXRlcGljay1kYXlzLWNlbGwtb3ZlcicgKTtcdFx0Ly8gQ2xlYXIgaW4gc3BlY2lmaWMgY2FsZW5kYXJcclxuXHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRqUXVlcnkoICcuZGF0ZXBpY2stZGF5cy1jZWxsLW92ZXInICkucmVtb3ZlQ2xhc3MoICdkYXRlcGljay1kYXlzLWNlbGwtb3ZlcicgKTtcdFx0XHRcdFx0XHRcdFx0Ly8gQ2xlYXIgaW4gYWxsIGNhbGVuZGFyc1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogU2Nyb2xsIHRvIHNwZWNpZmljIG1vbnRoIGluIGNhbGVuZGFyXHJcblx0ICpcclxuXHQgKiBAcGFyYW0gcmVzb3VyY2VfaWRcdFx0SUQgb2YgcmVzb3VyY2VcclxuXHQgKiBAcGFyYW0geWVhclx0XHRcdFx0LSByZWFsIHllYXIgIC0gMjAyM1xyXG5cdCAqIEBwYXJhbSBtb250aFx0XHRcdFx0LSByZWFsIG1vbnRoIC0gMTJcclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2NhbGVuZGFyX19zY3JvbGxfdG8oIHJlc291cmNlX2lkLCB5ZWFyLCBtb250aCApe1xyXG5cclxuXHRcdGlmICggJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiAocmVzb3VyY2VfaWQpICl7IHJlc291cmNlX2lkID0gJzEnOyB9XHJcblx0XHR2YXIgaW5zdCA9IHdwYmNfY2FsZW5kYXJfX2dldF9pbnN0KCByZXNvdXJjZV9pZCApXHJcblx0XHRpZiAoIG51bGwgIT09IGluc3QgKXtcclxuXHJcblx0XHRcdHllYXIgID0gcGFyc2VJbnQoIHllYXIgKTtcclxuXHRcdFx0bW9udGggPSBwYXJzZUludCggbW9udGggKSAtIDE7XHRcdC8vIEluIEpTIGRhdGUsICBtb250aCAtMVxyXG5cclxuXHRcdFx0aW5zdC5jdXJzb3JEYXRlID0gbmV3IERhdGUoKTtcclxuXHRcdFx0Ly8gSW4gc29tZSBjYXNlcywgIHRoZSBzZXRGdWxsWWVhciBjYW4gIHNldCAgb25seSBZZWFyLCAgYW5kIG5vdCB0aGUgTW9udGggYW5kIGRheSAgICAgIC8vRml4SW46Ni4yLjMuNVxyXG5cdFx0XHRpbnN0LmN1cnNvckRhdGUuc2V0RnVsbFllYXIoIHllYXIsIG1vbnRoLCAxICk7XHJcblx0XHRcdGluc3QuY3Vyc29yRGF0ZS5zZXRNb250aCggbW9udGggKTtcclxuXHRcdFx0aW5zdC5jdXJzb3JEYXRlLnNldERhdGUoIDEgKTtcclxuXHJcblx0XHRcdGluc3QuZHJhd01vbnRoID0gaW5zdC5jdXJzb3JEYXRlLmdldE1vbnRoKCk7XHJcblx0XHRcdGluc3QuZHJhd1llYXIgPSBpbnN0LmN1cnNvckRhdGUuZ2V0RnVsbFllYXIoKTtcclxuXHJcblx0XHRcdGpRdWVyeS5kYXRlcGljay5fbm90aWZ5Q2hhbmdlKCBpbnN0ICk7XHJcblx0XHRcdGpRdWVyeS5kYXRlcGljay5fYWRqdXN0SW5zdERhdGUoIGluc3QgKTtcclxuXHRcdFx0alF1ZXJ5LmRhdGVwaWNrLl9zaG93RGF0ZSggaW5zdCApO1xyXG5cdFx0XHRqUXVlcnkuZGF0ZXBpY2suX3VwZGF0ZURhdGVwaWNrKCBpbnN0ICk7XHJcblxyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIElzIHRoaXMgZGF0ZSBzZWxlY3RhYmxlIGluIGNhbGVuZGFyIChtYWlubHkgaXQncyBtZWFucyBBVkFJTEFCTEUgZGF0ZSlcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7aW50fHN0cmluZ30gcmVzb3VyY2VfaWRcdFx0MVxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzcWxfY2xhc3NfZGF5XHRcdCcyMDIzLTA4LTExJ1xyXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVx0XHRcdFx0XHR0cnVlIHwgZmFsc2VcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2lzX3RoaXNfZGF5X3NlbGVjdGFibGUoIHJlc291cmNlX2lkLCBzcWxfY2xhc3NfZGF5ICl7XHJcblxyXG5cdFx0Ly8gR2V0IERhdGEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdHZhciBkYXRlX2Jvb2tpbmdzX29iaiA9IF93cGJjLmJvb2tpbmdzX2luX2NhbGVuZGFyX19nZXRfZm9yX2RhdGUoIHJlc291cmNlX2lkLCBzcWxfY2xhc3NfZGF5ICk7XHJcblxyXG5cdFx0dmFyIGlzX2RheV9zZWxlY3RhYmxlID0gKCBwYXJzZUludCggZGF0ZV9ib29raW5nc19vYmpbICdkYXlfYXZhaWxhYmlsaXR5JyBdICkgPiAwICk7XHJcblxyXG5cdFx0aWYgKCAnYXZhaWxhYmxlJyAhPSBkYXRlX2Jvb2tpbmdzX29ialsgJ3N1bW1hcnknXVsnc3RhdHVzX2Zvcl9kYXknIF0gKXtcclxuXHJcblx0XHRcdHZhciBpc19zZXRfcGVuZGluZ19kYXlzX3NlbGVjdGFibGUgPSBfd3BiYy5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ3BlbmRpbmdfZGF5c19zZWxlY3RhYmxlJyApO1x0XHQvLyBzZXQgcGVuZGluZyBkYXlzIHNlbGVjdGFibGUgICAgICAgICAgLy9GaXhJbjogOC42LjEuMThcclxuXHJcblx0XHRcdHN3aXRjaCAoIGRhdGVfYm9va2luZ3Nfb2JqWyAnc3VtbWFyeSddWydzdGF0dXNfZm9yX2Jvb2tpbmdzJyBdICl7XHJcblx0XHRcdFx0Y2FzZSAncGVuZGluZyc6XHJcblx0XHRcdFx0Ly8gU2l0dWF0aW9ucyBmb3IgXCJjaGFuZ2Utb3ZlclwiIGRheXM6XHJcblx0XHRcdFx0Y2FzZSAncGVuZGluZ19wZW5kaW5nJzpcclxuXHRcdFx0XHRjYXNlICdwZW5kaW5nX2FwcHJvdmVkJzpcclxuXHRcdFx0XHRjYXNlICdhcHByb3ZlZF9wZW5kaW5nJzpcclxuXHRcdFx0XHRcdGlzX2RheV9zZWxlY3RhYmxlID0gKGlzX2RheV9zZWxlY3RhYmxlKSA/IHRydWUgOiBpc19zZXRfcGVuZGluZ19kYXlzX3NlbGVjdGFibGU7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRkZWZhdWx0OlxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGlzX2RheV9zZWxlY3RhYmxlO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogSXMgZGF0ZSB0byBjaGVjayBJTiBhcnJheSBvZiBzZWxlY3RlZCBkYXRlc1xyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtkYXRlfWpzX2RhdGVfdG9fY2hlY2tcdFx0LSBKUyBEYXRlXHRcdFx0LSBzaW1wbGUgIEphdmFTY3JpcHQgRGF0ZSBvYmplY3RcclxuXHQgKiBAcGFyYW0ge1tdfSBqc19kYXRlc19hcnJcdFx0XHQtIFsgSlNEYXRlLCAuLi4gXSAgIC0gYXJyYXkgIG9mIEpTIGRhdGVzXHJcblx0ICogQHJldHVybnMge2Jvb2xlYW59XHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19pc190aGlzX2RheV9hbW9uZ19zZWxlY3RlZF9kYXlzKCBqc19kYXRlX3RvX2NoZWNrLCBqc19kYXRlc19hcnIgKXtcclxuXHJcblx0XHRmb3IgKCB2YXIgZGF0ZV9pbmRleCA9IDA7IGRhdGVfaW5kZXggPCBqc19kYXRlc19hcnIubGVuZ3RoIDsgZGF0ZV9pbmRleCsrICl7ICAgICBcdFx0XHRcdFx0XHRcdFx0XHQvL0ZpeEluOiA4LjQuNS4xNlxyXG5cdFx0XHRpZiAoICgganNfZGF0ZXNfYXJyWyBkYXRlX2luZGV4IF0uZ2V0RnVsbFllYXIoKSA9PT0ganNfZGF0ZV90b19jaGVjay5nZXRGdWxsWWVhcigpICkgJiZcclxuXHRcdFx0XHQgKCBqc19kYXRlc19hcnJbIGRhdGVfaW5kZXggXS5nZXRNb250aCgpID09PSBqc19kYXRlX3RvX2NoZWNrLmdldE1vbnRoKCkgKSAmJlxyXG5cdFx0XHRcdCAoIGpzX2RhdGVzX2FyclsgZGF0ZV9pbmRleCBdLmdldERhdGUoKSA9PT0ganNfZGF0ZV90b19jaGVjay5nZXREYXRlKCkgKSApIHtcclxuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuICBmYWxzZTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBTUUwgQ2xhc3MgRGF0ZSAnMjAyMy0wOC0wMScgZnJvbSAgSlMgRGF0ZVxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGRhdGVcdFx0XHRcdEpTIERhdGVcclxuXHQgKiBAcmV0dXJucyB7c3RyaW5nfVx0XHQnMjAyMy0wOC0xMidcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX19nZXRfX3NxbF9jbGFzc19kYXRlKCBkYXRlICl7XHJcblxyXG5cdFx0dmFyIHNxbF9jbGFzc19kYXkgPSBkYXRlLmdldEZ1bGxZZWFyKCkgKyAnLSc7XHJcblx0XHRcdHNxbF9jbGFzc19kYXkgKz0gKCAoIGRhdGUuZ2V0TW9udGgoKSArIDEgKSA8IDEwICkgPyAnMCcgOiAnJztcclxuXHRcdFx0c3FsX2NsYXNzX2RheSArPSAoIGRhdGUuZ2V0TW9udGgoKSArIDEgKSArICctJ1xyXG5cdFx0XHRzcWxfY2xhc3NfZGF5ICs9ICggZGF0ZS5nZXREYXRlKCkgPCAxMCApID8gJzAnIDogJyc7XHJcblx0XHRcdHNxbF9jbGFzc19kYXkgKz0gZGF0ZS5nZXREYXRlKCk7XHJcblxyXG5cdFx0XHRyZXR1cm4gc3FsX2NsYXNzX2RheTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBURCBDbGFzcyBEYXRlICcxLTMxLTIwMjMnIGZyb20gIEpTIERhdGVcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSBkYXRlXHRcdFx0XHRKUyBEYXRlXHJcblx0ICogQHJldHVybnMge3N0cmluZ31cdFx0JzEtMzEtMjAyMydcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX19nZXRfX3RkX2NsYXNzX2RhdGUoIGRhdGUgKXtcclxuXHJcblx0XHR2YXIgdGRfY2xhc3NfZGF5ID0gKGRhdGUuZ2V0TW9udGgoKSArIDEpICsgJy0nICsgZGF0ZS5nZXREYXRlKCkgKyAnLScgKyBkYXRlLmdldEZ1bGxZZWFyKCk7XHRcdFx0XHRcdFx0XHRcdC8vICcxLTktMjAyMydcclxuXHJcblx0XHRyZXR1cm4gdGRfY2xhc3NfZGF5O1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IGRhdGUgcGFyYW1zIGZyb20gIHN0cmluZyBkYXRlXHJcblx0ICpcclxuXHQgKiBAcGFyYW0gZGF0ZVx0XHRcdHN0cmluZyBkYXRlIGxpa2UgJzMxLjUuMjAyMydcclxuXHQgKiBAcGFyYW0gc2VwYXJhdG9yXHRcdGRlZmF1bHQgJy4nICBjYW4gYmUgc2tpcHBlZC5cclxuXHQgKiBAcmV0dXJucyB7ICB7ZGF0ZTogbnVtYmVyLCBtb250aDogbnVtYmVyLCB5ZWFyOiBudW1iZXJ9ICB9XHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19fZ2V0X19kYXRlX3BhcmFtc19fZnJvbV9zdHJpbmdfZGF0ZSggZGF0ZSAsIHNlcGFyYXRvcil7XHJcblxyXG5cdFx0c2VwYXJhdG9yID0gKCAndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChzZXBhcmF0b3IpICkgPyBzZXBhcmF0b3IgOiAnLic7XHJcblxyXG5cdFx0dmFyIGRhdGVfYXJyID0gZGF0ZS5zcGxpdCggc2VwYXJhdG9yICk7XHJcblx0XHR2YXIgZGF0ZV9vYmogPSB7XHJcblx0XHRcdCd5ZWFyJyA6ICBwYXJzZUludCggZGF0ZV9hcnJbIDIgXSApLFxyXG5cdFx0XHQnbW9udGgnOiAocGFyc2VJbnQoIGRhdGVfYXJyWyAxIF0gKSAtIDEpLFxyXG5cdFx0XHQnZGF0ZScgOiAgcGFyc2VJbnQoIGRhdGVfYXJyWyAwIF0gKVxyXG5cdFx0fTtcclxuXHRcdHJldHVybiBkYXRlX29iajtcdFx0Ly8gZm9yIFx0XHQgPSBuZXcgRGF0ZSggZGF0ZV9vYmoueWVhciAsIGRhdGVfb2JqLm1vbnRoICwgZGF0ZV9vYmouZGF0ZSApO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQWRkIFNwaW4gTG9hZGVyIHRvICBjYWxlbmRhclxyXG5cdCAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfY2FsZW5kYXJfX2xvYWRpbmdfX3N0YXJ0KCByZXNvdXJjZV9pZCApe1xyXG5cdFx0aWYgKCAhIGpRdWVyeSggJyNjYWxlbmRhcl9ib29raW5nJyArIHJlc291cmNlX2lkICkubmV4dCgpLmhhc0NsYXNzKCAnd3BiY19zcGluc19sb2FkZXJfd3JhcHBlcicgKSApe1xyXG5cdFx0XHRqUXVlcnkoICcjY2FsZW5kYXJfYm9va2luZycgKyByZXNvdXJjZV9pZCApLmFmdGVyKCAnPGRpdiBjbGFzcz1cIndwYmNfc3BpbnNfbG9hZGVyX3dyYXBwZXJcIj48ZGl2IGNsYXNzPVwid3BiY19zcGluc19sb2FkZXJcIj48L2Rpdj48L2Rpdj4nICk7XHJcblx0XHR9XHJcblx0XHRpZiAoICEgalF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS5oYXNDbGFzcyggJ3dwYmNfY2FsZW5kYXJfYmx1cl9zbWFsbCcgKSApe1xyXG5cdFx0XHRqUXVlcnkoICcjY2FsZW5kYXJfYm9va2luZycgKyByZXNvdXJjZV9pZCApLmFkZENsYXNzKCAnd3BiY19jYWxlbmRhcl9ibHVyX3NtYWxsJyApO1xyXG5cdFx0fVxyXG5cdFx0d3BiY19jYWxlbmRhcl9fYmx1cl9fc3RhcnQoIHJlc291cmNlX2lkICk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBSZW1vdmUgU3BpbiBMb2FkZXIgdG8gIGNhbGVuZGFyXHJcblx0ICogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19jYWxlbmRhcl9fbG9hZGluZ19fc3RvcCggcmVzb3VyY2VfaWQgKXtcclxuXHRcdGpRdWVyeSggJyNjYWxlbmRhcl9ib29raW5nJyArIHJlc291cmNlX2lkICsgJyArIC53cGJjX3NwaW5zX2xvYWRlcl93cmFwcGVyJyApLnJlbW92ZSgpO1xyXG5cdFx0alF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS5yZW1vdmVDbGFzcyggJ3dwYmNfY2FsZW5kYXJfYmx1cl9zbWFsbCcgKTtcclxuXHRcdHdwYmNfY2FsZW5kYXJfX2JsdXJfX3N0b3AoIHJlc291cmNlX2lkICk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBBZGQgQmx1ciB0byAgY2FsZW5kYXJcclxuXHQgKiBAcGFyYW0gcmVzb3VyY2VfaWRcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2NhbGVuZGFyX19ibHVyX19zdGFydCggcmVzb3VyY2VfaWQgKXtcclxuXHRcdGlmICggISBqUXVlcnkoICcjY2FsZW5kYXJfYm9va2luZycgKyByZXNvdXJjZV9pZCApLmhhc0NsYXNzKCAnd3BiY19jYWxlbmRhcl9ibHVyJyApICl7XHJcblx0XHRcdGpRdWVyeSggJyNjYWxlbmRhcl9ib29raW5nJyArIHJlc291cmNlX2lkICkuYWRkQ2xhc3MoICd3cGJjX2NhbGVuZGFyX2JsdXInICk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBSZW1vdmUgQmx1ciBpbiAgY2FsZW5kYXJcclxuXHQgKiBAcGFyYW0gcmVzb3VyY2VfaWRcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2NhbGVuZGFyX19ibHVyX19zdG9wKCByZXNvdXJjZV9pZCApe1xyXG5cdFx0alF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS5yZW1vdmVDbGFzcyggJ3dwYmNfY2FsZW5kYXJfYmx1cicgKTtcclxuXHR9XHJcblxyXG5cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFVwZGF0ZSBMb29rICBvZiBjYWxlbmRhclxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19jYWxlbmRhcl9fdXBkYXRlX2xvb2soIHJlc291cmNlX2lkICl7XHJcblxyXG5cdFx0dmFyIGluc3QgPSB3cGJjX2NhbGVuZGFyX19nZXRfaW5zdCggcmVzb3VyY2VfaWQgKTtcclxuXHJcblx0XHRqUXVlcnkuZGF0ZXBpY2suX3VwZGF0ZURhdGVwaWNrKCBpbnN0ICk7XHJcblx0fVxyXG5cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4vLyBTIFUgUCBQIE8gUiBUICAgIE0gQSBUIEhcclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBNZXJnZSBzZXZlcmFsICBpbnRlcnNlY3RlZCBpbnRlcnZhbHMgb3IgcmV0dXJuIG5vdCBpbnRlcnNlY3RlZDogICAgICAgICAgICAgICAgICAgICAgICBbWzEsM10sWzIsNl0sWzgsMTBdLFsxNSwxOF1dICAtPiAgIFtbMSw2XSxbOCwxMF0sWzE1LDE4XV1cclxuXHRcdCAqXHJcblx0XHQgKiBAcGFyYW0gW10gaW50ZXJ2YWxzXHRcdFx0IFsgWzEsM10sWzIsNF0sWzYsOF0sWzksMTBdLFszLDddIF1cclxuXHRcdCAqIEByZXR1cm5zIFtdXHRcdFx0XHRcdCBbIFsxLDhdLFs5LDEwXSBdXHJcblx0XHQgKlxyXG5cdFx0ICogRXhtYW1wbGU6IHdwYmNfaW50ZXJ2YWxzX19tZXJnZV9pbmVyc2VjdGVkKCAgWyBbMSwzXSxbMiw0XSxbNiw4XSxbOSwxMF0sWzMsN10gXSAgKTtcclxuXHRcdCAqL1xyXG5cdFx0ZnVuY3Rpb24gd3BiY19pbnRlcnZhbHNfX21lcmdlX2luZXJzZWN0ZWQoIGludGVydmFscyApe1xyXG5cclxuXHRcdFx0aWYgKCAhIGludGVydmFscyB8fCBpbnRlcnZhbHMubGVuZ3RoID09PSAwICl7XHJcblx0XHRcdFx0cmV0dXJuIFtdO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR2YXIgbWVyZ2VkID0gW107XHJcblx0XHRcdGludGVydmFscy5zb3J0KCBmdW5jdGlvbiAoIGEsIGIgKXtcclxuXHRcdFx0XHRyZXR1cm4gYVsgMCBdIC0gYlsgMCBdO1xyXG5cdFx0XHR9ICk7XHJcblxyXG5cdFx0XHR2YXIgbWVyZ2VkSW50ZXJ2YWwgPSBpbnRlcnZhbHNbIDAgXTtcclxuXHJcblx0XHRcdGZvciAoIHZhciBpID0gMTsgaSA8IGludGVydmFscy5sZW5ndGg7IGkrKyApe1xyXG5cdFx0XHRcdHZhciBpbnRlcnZhbCA9IGludGVydmFsc1sgaSBdO1xyXG5cclxuXHRcdFx0XHRpZiAoIGludGVydmFsWyAwIF0gPD0gbWVyZ2VkSW50ZXJ2YWxbIDEgXSApe1xyXG5cdFx0XHRcdFx0bWVyZ2VkSW50ZXJ2YWxbIDEgXSA9IE1hdGgubWF4KCBtZXJnZWRJbnRlcnZhbFsgMSBdLCBpbnRlcnZhbFsgMSBdICk7XHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdG1lcmdlZC5wdXNoKCBtZXJnZWRJbnRlcnZhbCApO1xyXG5cdFx0XHRcdFx0bWVyZ2VkSW50ZXJ2YWwgPSBpbnRlcnZhbDtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdG1lcmdlZC5wdXNoKCBtZXJnZWRJbnRlcnZhbCApO1xyXG5cdFx0XHRyZXR1cm4gbWVyZ2VkO1xyXG5cdFx0fVxyXG5cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIElzIDIgaW50ZXJ2YWxzIGludGVyc2VjdGVkOiAgICAgICBbMzYwMTEsIDg2MzkyXSAgICA8PT4gICAgWzEsIDQzMTkyXSAgPT4gIHRydWUgICAgICAoIGludGVyc2VjdGVkIClcclxuXHRcdCAqXHJcblx0XHQgKiBHb29kIGV4cGxhbmF0aW9uICBoZXJlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMyNjk0MzQvd2hhdHMtdGhlLW1vc3QtZWZmaWNpZW50LXdheS10by10ZXN0LWlmLXR3by1yYW5nZXMtb3ZlcmxhcFxyXG5cdFx0ICpcclxuXHRcdCAqIEBwYXJhbSAgaW50ZXJ2YWxfQSAgIC0gWyAzNjAxMSwgODYzOTIgXVxyXG5cdFx0ICogQHBhcmFtICBpbnRlcnZhbF9CICAgLSBbICAgICAxLCA0MzE5MiBdXHJcblx0XHQgKlxyXG5cdFx0ICogQHJldHVybiBib29sXHJcblx0XHQgKi9cclxuXHRcdGZ1bmN0aW9uIHdwYmNfaW50ZXJ2YWxzX19pc19pbnRlcnNlY3RlZCggaW50ZXJ2YWxfQSwgaW50ZXJ2YWxfQiApIHtcclxuXHJcblx0XHRcdGlmIChcclxuXHRcdFx0XHRcdCggMCA9PSBpbnRlcnZhbF9BLmxlbmd0aCApXHJcblx0XHRcdFx0IHx8ICggMCA9PSBpbnRlcnZhbF9CLmxlbmd0aCApXHJcblx0XHRcdCl7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpbnRlcnZhbF9BWyAwIF0gPSBwYXJzZUludCggaW50ZXJ2YWxfQVsgMCBdICk7XHJcblx0XHRcdGludGVydmFsX0FbIDEgXSA9IHBhcnNlSW50KCBpbnRlcnZhbF9BWyAxIF0gKTtcclxuXHRcdFx0aW50ZXJ2YWxfQlsgMCBdID0gcGFyc2VJbnQoIGludGVydmFsX0JbIDAgXSApO1xyXG5cdFx0XHRpbnRlcnZhbF9CWyAxIF0gPSBwYXJzZUludCggaW50ZXJ2YWxfQlsgMSBdICk7XHJcblxyXG5cdFx0XHR2YXIgaXNfaW50ZXJzZWN0ZWQgPSBNYXRoLm1heCggaW50ZXJ2YWxfQVsgMCBdLCBpbnRlcnZhbF9CWyAwIF0gKSAtIE1hdGgubWluKCBpbnRlcnZhbF9BWyAxIF0sIGludGVydmFsX0JbIDEgXSApO1xyXG5cclxuXHRcdFx0Ly8gaWYgKCAwID09IGlzX2ludGVyc2VjdGVkICkge1xyXG5cdFx0XHQvL1x0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjaCByYW5nZXMgZ29pbmcgb25lIGFmdGVyIG90aGVyLCBlLmcuOiBbIDEyLCAxNSBdIGFuZCBbIDE1LCAyMSBdXHJcblx0XHRcdC8vIH1cclxuXHJcblx0XHRcdGlmICggaXNfaW50ZXJzZWN0ZWQgPCAwICkge1xyXG5cdFx0XHRcdHJldHVybiB0cnVlOyAgICAgICAgICAgICAgICAgICAgIC8vIElOVEVSU0VDVEVEXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHJldHVybiBmYWxzZTsgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vdCBpbnRlcnNlY3RlZFxyXG5cdFx0fVxyXG5cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIEdldCB0aGUgY2xvc2V0cyBBQlMgdmFsdWUgb2YgZWxlbWVudCBpbiBhcnJheSB0byB0aGUgY3VycmVudCBteVZhbHVlXHJcblx0XHQgKlxyXG5cdFx0ICogQHBhcmFtIG15VmFsdWUgXHQtIGludCBlbGVtZW50IHRvIHNlYXJjaCBjbG9zZXQgXHRcdFx0NFxyXG5cdFx0ICogQHBhcmFtIG15QXJyYXlcdC0gYXJyYXkgb2YgZWxlbWVudHMgd2hlcmUgdG8gc2VhcmNoIFx0WzUsOCwxLDddXHJcblx0XHQgKiBAcmV0dXJucyBpbnRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ1XHJcblx0XHQgKi9cclxuXHRcdGZ1bmN0aW9uIHdwYmNfZ2V0X2Fic19jbG9zZXN0X3ZhbHVlX2luX2FyciggbXlWYWx1ZSwgbXlBcnJheSApe1xyXG5cclxuXHRcdFx0aWYgKCBteUFycmF5Lmxlbmd0aCA9PSAwICl7IFx0XHRcdFx0XHRcdFx0XHQvLyBJZiB0aGUgYXJyYXkgaXMgZW1wdHkgLT4gcmV0dXJuICB0aGUgbXlWYWx1ZVxyXG5cdFx0XHRcdHJldHVybiBteVZhbHVlO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR2YXIgb2JqID0gbXlBcnJheVsgMCBdO1xyXG5cdFx0XHR2YXIgZGlmZiA9IE1hdGguYWJzKCBteVZhbHVlIC0gb2JqICk7ICAgICAgICAgICAgIFx0Ly8gR2V0IGRpc3RhbmNlIGJldHdlZW4gIDFzdCBlbGVtZW50XHJcblx0XHRcdHZhciBjbG9zZXRWYWx1ZSA9IG15QXJyYXlbIDAgXTsgICAgICAgICAgICAgICAgICAgXHRcdFx0Ly8gU2F2ZSAxc3QgZWxlbWVudFxyXG5cclxuXHRcdFx0Zm9yICggdmFyIGkgPSAxOyBpIDwgbXlBcnJheS5sZW5ndGg7IGkrKyApe1xyXG5cdFx0XHRcdG9iaiA9IG15QXJyYXlbIGkgXTtcclxuXHJcblx0XHRcdFx0aWYgKCBNYXRoLmFicyggbXlWYWx1ZSAtIG9iaiApIDwgZGlmZiApeyAgICAgXHRcdFx0Ly8gd2UgZm91bmQgY2xvc2VyIHZhbHVlIC0+IHNhdmUgaXRcclxuXHRcdFx0XHRcdGRpZmYgPSBNYXRoLmFicyggbXlWYWx1ZSAtIG9iaiApO1xyXG5cdFx0XHRcdFx0Y2xvc2V0VmFsdWUgPSBvYmo7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRyZXR1cm4gY2xvc2V0VmFsdWU7XHJcblx0XHR9XHJcblxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbi8vICBUIE8gTyBMIFQgSSBQIFNcclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5cdC8qKlxyXG5cdCAqIERlZmluZSB0b29sdGlwIHRvIHNob3csICB3aGVuICBtb3VzZSBvdmVyIERhdGUgaW4gQ2FsZW5kYXJcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSAgdG9vbHRpcF90ZXh0XHRcdFx0LSBUZXh0IHRvIHNob3dcdFx0XHRcdCdCb29rZWQgdGltZTogMTI6MDAgLSAxMzowMDxicj5Db3N0OiAkMjAuMDAnXHJcblx0ICogQHBhcmFtICByZXNvdXJjZV9pZFx0XHRcdC0gSUQgb2YgYm9va2luZyByZXNvdXJjZVx0JzEnXHJcblx0ICogQHBhcmFtICB0ZF9jbGFzc1x0XHRcdFx0LSBTUUwgY2xhc3NcdFx0XHRcdFx0JzEtOS0yMDIzJ1xyXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVx0XHRcdFx0XHQtIGRlZmluZWQgdG8gc2hvdyBvciBub3RcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX3NldF90b29sdGlwX19fZm9yX19jYWxlbmRhcl9kYXRlKCB0b29sdGlwX3RleHQsIHJlc291cmNlX2lkLCB0ZF9jbGFzcyApe1xyXG5cclxuXHRcdC8vVE9ETzogbWFrZSBlc2NhcGluZyBvZiB0ZXh0IGZvciBxdW90IHN5bWJvbHMsICBhbmQgSlMvSFRNTC4uLlxyXG5cclxuXHRcdGpRdWVyeSggJyNjYWxlbmRhcl9ib29raW5nJyArIHJlc291cmNlX2lkICsgJyB0ZC5jYWw0ZGF0ZS0nICsgdGRfY2xhc3MgKS5hdHRyKCAnZGF0YS1jb250ZW50JywgdG9vbHRpcF90ZXh0ICk7XHJcblxyXG5cdFx0dmFyIHRkX2VsID0galF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKyAnIHRkLmNhbDRkYXRlLScgKyB0ZF9jbGFzcyApLmdldCggMCApO1x0XHRcdFx0XHQvL0ZpeEluOiA5LjAuMS4xXHJcblxyXG5cdFx0aWYgKFxyXG5cdFx0XHQgICAoICd1bmRlZmluZWQnICE9PSB0eXBlb2YodGRfZWwpIClcclxuXHRcdFx0JiYgKCB1bmRlZmluZWQgPT0gdGRfZWwuX3RpcHB5IClcclxuXHRcdFx0JiYgKCAnJyAhPT0gdG9vbHRpcF90ZXh0IClcclxuXHRcdCl7XHJcblxyXG5cdFx0XHR3cGJjX3RpcHB5KCB0ZF9lbCAsIHtcclxuXHRcdFx0XHRcdGNvbnRlbnQoIHJlZmVyZW5jZSApe1xyXG5cclxuXHRcdFx0XHRcdFx0dmFyIHBvcG92ZXJfY29udGVudCA9IHJlZmVyZW5jZS5nZXRBdHRyaWJ1dGUoICdkYXRhLWNvbnRlbnQnICk7XHJcblxyXG5cdFx0XHRcdFx0XHRyZXR1cm4gJzxkaXYgY2xhc3M9XCJwb3BvdmVyIHBvcG92ZXJfdGlwcHlcIj4nXHJcblx0XHRcdFx0XHRcdFx0XHRcdCsgJzxkaXYgY2xhc3M9XCJwb3BvdmVyLWNvbnRlbnRcIj4nXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0KyBwb3BvdmVyX2NvbnRlbnRcclxuXHRcdFx0XHRcdFx0XHRcdFx0KyAnPC9kaXY+J1xyXG5cdFx0XHRcdFx0XHRcdCArICc8L2Rpdj4nO1xyXG5cdFx0XHRcdFx0fSxcclxuXHRcdFx0XHRcdGFsbG93SFRNTCAgICAgICAgOiB0cnVlLFxyXG5cdFx0XHRcdFx0dHJpZ2dlclx0XHRcdCA6ICdtb3VzZWVudGVyIGZvY3VzJyxcclxuXHRcdFx0XHRcdGludGVyYWN0aXZlICAgICAgOiBmYWxzZSxcclxuXHRcdFx0XHRcdGhpZGVPbkNsaWNrICAgICAgOiB0cnVlLFxyXG5cdFx0XHRcdFx0aW50ZXJhY3RpdmVCb3JkZXI6IDEwLFxyXG5cdFx0XHRcdFx0bWF4V2lkdGggICAgICAgICA6IDU1MCxcclxuXHRcdFx0XHRcdHRoZW1lICAgICAgICAgICAgOiAnd3BiYy10aXBweS10aW1lcycsXHJcblx0XHRcdFx0XHRwbGFjZW1lbnQgICAgICAgIDogJ3RvcCcsXHJcblx0XHRcdFx0XHRkZWxheVx0XHRcdCA6IFs0MDAsIDBdLFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vRml4SW46IDkuNC4yLjJcclxuXHRcdFx0XHRcdC8vZGVsYXlcdFx0XHQgOiBbMCwgOTk5OTk5OTk5OV0sXHRcdFx0XHRcdFx0Ly8gRGVidWdlICB0b29sdGlwXHJcblx0XHRcdFx0XHRpZ25vcmVBdHRyaWJ1dGVzIDogdHJ1ZSxcclxuXHRcdFx0XHRcdHRvdWNoXHRcdFx0IDogdHJ1ZSxcdFx0XHRcdFx0XHRcdFx0Ly9bJ2hvbGQnLCA1MDBdLCAvLyA1MDBtcyBkZWxheVx0XHRcdFx0Ly9GaXhJbjogOS4yLjEuNVxyXG5cdFx0XHRcdFx0YXBwZW5kVG86ICgpID0+IGRvY3VtZW50LmJvZHksXHJcblx0XHRcdH0pO1xyXG5cclxuXHRcdFx0cmV0dXJuICB0cnVlO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiAgZmFsc2U7XHJcblx0fVxyXG4iLCIvKipcclxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICpcdGluY2x1ZGVzL19fanMvY2FsL2RheXNfc2VsZWN0X2N1c3RvbS5qc1xyXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gKi9cclxuXHJcbi8vRml4SW46IDkuOC45LjJcclxuXHJcbi8qKlxyXG4gKiBSZS1Jbml0IENhbGVuZGFyIGFuZCBSZS1SZW5kZXIgaXQuXHJcbiAqXHJcbiAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jYWxfX3JlX2luaXQoIHJlc291cmNlX2lkICl7XHJcblxyXG5cdC8vIFJlbW92ZSBDTEFTUyAgZm9yIGFiaWxpdHkgdG8gcmUtcmVuZGVyIGFuZCByZWluaXQgY2FsZW5kYXIuXHJcblx0alF1ZXJ5KCAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS5yZW1vdmVDbGFzcyggJ2hhc0RhdGVwaWNrJyApO1xyXG5cdHdwYmNfY2FsZW5kYXJfc2hvdyggcmVzb3VyY2VfaWQgKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBSZS1Jbml0IHByZXZpb3VzbHkgIHNhdmVkIGRheXMgc2VsZWN0aW9uICB2YXJpYWJsZXMuXHJcbiAqXHJcbiAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jYWxfZGF5c19zZWxlY3RfX3JlX2luaXQoIHJlc291cmNlX2lkICl7XHJcblxyXG5cdF93cGJjLmNhbGVuZGFyX19zZXRfcGFyYW1fdmFsdWUoIHJlc291cmNlX2lkLCAnc2F2ZWRfdmFyaWFibGVfX19kYXlzX3NlbGVjdF9pbml0aWFsJ1xyXG5cdFx0LCB7XHJcblx0XHRcdCdkeW5hbWljX19kYXlzX21pbicgICAgICAgIDogX3dwYmMuY2FsZW5kYXJfX2dldF9wYXJhbV92YWx1ZSggcmVzb3VyY2VfaWQsICdkeW5hbWljX19kYXlzX21pbicgKSxcclxuXHRcdFx0J2R5bmFtaWNfX2RheXNfbWF4JyAgICAgICAgOiBfd3BiYy5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ2R5bmFtaWNfX2RheXNfbWF4JyApLFxyXG5cdFx0XHQnZHluYW1pY19fZGF5c19zcGVjaWZpYycgICA6IF93cGJjLmNhbGVuZGFyX19nZXRfcGFyYW1fdmFsdWUoIHJlc291cmNlX2lkLCAnZHluYW1pY19fZGF5c19zcGVjaWZpYycgKSxcclxuXHRcdFx0J2R5bmFtaWNfX3dlZWtfZGF5c19fc3RhcnQnOiBfd3BiYy5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ2R5bmFtaWNfX3dlZWtfZGF5c19fc3RhcnQnICksXHJcblx0XHRcdCdmaXhlZF9fZGF5c19udW0nICAgICAgICAgIDogX3dwYmMuY2FsZW5kYXJfX2dldF9wYXJhbV92YWx1ZSggcmVzb3VyY2VfaWQsICdmaXhlZF9fZGF5c19udW0nICksXHJcblx0XHRcdCdmaXhlZF9fd2Vla19kYXlzX19zdGFydCcgIDogX3dwYmMuY2FsZW5kYXJfX2dldF9wYXJhbV92YWx1ZSggcmVzb3VyY2VfaWQsICdmaXhlZF9fd2Vla19kYXlzX19zdGFydCcgKVxyXG5cdFx0fVxyXG5cdCk7XHJcbn1cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIFNldCBTaW5nbGUgRGF5IHNlbGVjdGlvbiAtIGFmdGVyIHBhZ2UgbG9hZFxyXG4gKlxyXG4gKiBAcGFyYW0gcmVzb3VyY2VfaWRcdFx0SUQgb2YgYm9va2luZyByZXNvdXJjZVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jYWxfcmVhZHlfZGF5c19zZWxlY3RfX3NpbmdsZSggcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0Ly8gUmUtZGVmaW5lIHNlbGVjdGlvbiwgb25seSBhZnRlciBwYWdlIGxvYWRlZCB3aXRoIGFsbCBpbml0IHZhcnNcclxuXHRqUXVlcnkoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCl7XHJcblxyXG5cdFx0Ly8gV2FpdCAxIHNlY29uZCwganVzdCB0byAgYmUgc3VyZSwgdGhhdCBhbGwgaW5pdCB2YXJzIGRlZmluZWRcclxuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcclxuXHJcblx0XHRcdHdwYmNfY2FsX2RheXNfc2VsZWN0X19zaW5nbGUoIHJlc291cmNlX2lkICk7XHJcblxyXG5cdFx0fSwgMTAwMCk7XHJcblx0fSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXQgU2luZ2xlIERheSBzZWxlY3Rpb25cclxuICogQ2FuIGJlIHJ1biBhdCBhbnkgIHRpbWUsICB3aGVuICBjYWxlbmRhciBkZWZpbmVkIC0gdXNlZnVsIGZvciBjb25zb2xlIHJ1bi5cclxuICpcclxuICogQHBhcmFtIHJlc291cmNlX2lkXHRcdElEIG9mIGJvb2tpbmcgcmVzb3VyY2VcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfY2FsX2RheXNfc2VsZWN0X19zaW5nbGUoIHJlc291cmNlX2lkICl7XHJcblxyXG5cdF93cGJjLmNhbGVuZGFyX19zZXRfcGFyYW1ldGVycyggcmVzb3VyY2VfaWQsIHsnZGF5c19zZWxlY3RfbW9kZSc6ICdzaW5nbGUnfSApO1xyXG5cclxuXHR3cGJjX2NhbF9kYXlzX3NlbGVjdF9fcmVfaW5pdCggcmVzb3VyY2VfaWQgKTtcclxuXHR3cGJjX2NhbF9fcmVfaW5pdCggcmVzb3VyY2VfaWQgKTtcclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4vKipcclxuICogU2V0IE11bHRpcGxlIERheXMgc2VsZWN0aW9uICAtIGFmdGVyIHBhZ2UgbG9hZFxyXG4gKlxyXG4gKiBAcGFyYW0gcmVzb3VyY2VfaWRcdFx0SUQgb2YgYm9va2luZyByZXNvdXJjZVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jYWxfcmVhZHlfZGF5c19zZWxlY3RfX211bHRpcGxlKCByZXNvdXJjZV9pZCApe1xyXG5cclxuXHQvLyBSZS1kZWZpbmUgc2VsZWN0aW9uLCBvbmx5IGFmdGVyIHBhZ2UgbG9hZGVkIHdpdGggYWxsIGluaXQgdmFyc1xyXG5cdGpRdWVyeShkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKXtcclxuXHJcblx0XHQvLyBXYWl0IDEgc2Vjb25kLCBqdXN0IHRvICBiZSBzdXJlLCB0aGF0IGFsbCBpbml0IHZhcnMgZGVmaW5lZFxyXG5cdFx0c2V0VGltZW91dChmdW5jdGlvbigpe1xyXG5cclxuXHRcdFx0d3BiY19jYWxfZGF5c19zZWxlY3RfX211bHRpcGxlKCByZXNvdXJjZV9pZCApO1xyXG5cclxuXHRcdH0sIDEwMDApO1xyXG5cdH0pO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIFNldCBNdWx0aXBsZSBEYXlzIHNlbGVjdGlvblxyXG4gKiBDYW4gYmUgcnVuIGF0IGFueSAgdGltZSwgIHdoZW4gIGNhbGVuZGFyIGRlZmluZWQgLSB1c2VmdWwgZm9yIGNvbnNvbGUgcnVuLlxyXG4gKlxyXG4gKiBAcGFyYW0gcmVzb3VyY2VfaWRcdFx0SUQgb2YgYm9va2luZyByZXNvdXJjZVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jYWxfZGF5c19zZWxlY3RfX211bHRpcGxlKCByZXNvdXJjZV9pZCApe1xyXG5cclxuXHRfd3BiYy5jYWxlbmRhcl9fc2V0X3BhcmFtZXRlcnMoIHJlc291cmNlX2lkLCB7J2RheXNfc2VsZWN0X21vZGUnOiAnbXVsdGlwbGUnfSApO1xyXG5cclxuXHR3cGJjX2NhbF9kYXlzX3NlbGVjdF9fcmVfaW5pdCggcmVzb3VyY2VfaWQgKTtcclxuXHR3cGJjX2NhbF9fcmVfaW5pdCggcmVzb3VyY2VfaWQgKTtcclxufVxyXG5cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIFNldCBGaXhlZCBEYXlzIHNlbGVjdGlvbiB3aXRoICAxIG1vdXNlIGNsaWNrICAtIGFmdGVyIHBhZ2UgbG9hZFxyXG4gKlxyXG4gKiBAaW50ZWdlciByZXNvdXJjZV9pZFx0XHRcdC0gMVx0XHRcdFx0ICAgLS0gSUQgb2YgYm9va2luZyByZXNvdXJjZSAoY2FsZW5kYXIpIC1cclxuICogQGludGVnZXIgZGF5c19udW1iZXJcdFx0XHQtIDNcdFx0XHRcdCAgIC0tIG51bWJlciBvZiBkYXlzIHRvICBzZWxlY3RcdC1cclxuICogQGFycmF5IHdlZWtfZGF5c19fc3RhcnRcdC0gWy0xXSB8IFsgMSwgNV0gICAtLSAgeyAtMSAtIEFueSB8IDAgLSBTdSwgIDEgLSBNbywgIDIgLSBUdSwgMyAtIFdlLCA0IC0gVGgsIDUgLSBGciwgNiAtIFNhdCB9XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2NhbF9yZWFkeV9kYXlzX3NlbGVjdF9fZml4ZWQoIHJlc291cmNlX2lkLCBkYXlzX251bWJlciwgd2Vla19kYXlzX19zdGFydCA9IFstMV0gKXtcclxuXHJcblx0Ly8gUmUtZGVmaW5lIHNlbGVjdGlvbiwgb25seSBhZnRlciBwYWdlIGxvYWRlZCB3aXRoIGFsbCBpbml0IHZhcnNcclxuXHRqUXVlcnkoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCl7XHJcblxyXG5cdFx0Ly8gV2FpdCAxIHNlY29uZCwganVzdCB0byAgYmUgc3VyZSwgdGhhdCBhbGwgaW5pdCB2YXJzIGRlZmluZWRcclxuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcclxuXHJcblx0XHRcdHdwYmNfY2FsX2RheXNfc2VsZWN0X19maXhlZCggcmVzb3VyY2VfaWQsIGRheXNfbnVtYmVyLCB3ZWVrX2RheXNfX3N0YXJ0ICk7XHJcblxyXG5cdFx0fSwgMTAwMCk7XHJcblx0fSk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogU2V0IEZpeGVkIERheXMgc2VsZWN0aW9uIHdpdGggIDEgbW91c2UgY2xpY2tcclxuICogQ2FuIGJlIHJ1biBhdCBhbnkgIHRpbWUsICB3aGVuICBjYWxlbmRhciBkZWZpbmVkIC0gdXNlZnVsIGZvciBjb25zb2xlIHJ1bi5cclxuICpcclxuICogQGludGVnZXIgcmVzb3VyY2VfaWRcdFx0XHQtIDFcdFx0XHRcdCAgIC0tIElEIG9mIGJvb2tpbmcgcmVzb3VyY2UgKGNhbGVuZGFyKSAtXHJcbiAqIEBpbnRlZ2VyIGRheXNfbnVtYmVyXHRcdFx0LSAzXHRcdFx0XHQgICAtLSBudW1iZXIgb2YgZGF5cyB0byAgc2VsZWN0XHQtXHJcbiAqIEBhcnJheSB3ZWVrX2RheXNfX3N0YXJ0XHQtIFstMV0gfCBbIDEsIDVdICAgLS0gIHsgLTEgLSBBbnkgfCAwIC0gU3UsICAxIC0gTW8sICAyIC0gVHUsIDMgLSBXZSwgNCAtIFRoLCA1IC0gRnIsIDYgLSBTYXQgfVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jYWxfZGF5c19zZWxlY3RfX2ZpeGVkKCByZXNvdXJjZV9pZCwgZGF5c19udW1iZXIsIHdlZWtfZGF5c19fc3RhcnQgPSBbLTFdICl7XHJcblxyXG5cdF93cGJjLmNhbGVuZGFyX19zZXRfcGFyYW1ldGVycyggcmVzb3VyY2VfaWQsIHsnZGF5c19zZWxlY3RfbW9kZSc6ICdmaXhlZCd9ICk7XHJcblxyXG5cdF93cGJjLmNhbGVuZGFyX19zZXRfcGFyYW1ldGVycyggcmVzb3VyY2VfaWQsIHsnZml4ZWRfX2RheXNfbnVtJzogcGFyc2VJbnQoIGRheXNfbnVtYmVyICl9ICk7XHRcdFx0Ly8gTnVtYmVyIG9mIGRheXMgc2VsZWN0aW9uIHdpdGggMSBtb3VzZSBjbGlja1xyXG5cdF93cGJjLmNhbGVuZGFyX19zZXRfcGFyYW1ldGVycyggcmVzb3VyY2VfaWQsIHsnZml4ZWRfX3dlZWtfZGF5c19fc3RhcnQnOiB3ZWVrX2RheXNfX3N0YXJ0fSApOyBcdC8vIHsgLTEgLSBBbnkgfCAwIC0gU3UsICAxIC0gTW8sICAyIC0gVHUsIDMgLSBXZSwgNCAtIFRoLCA1IC0gRnIsIDYgLSBTYXQgfVxyXG5cclxuXHR3cGJjX2NhbF9kYXlzX3NlbGVjdF9fcmVfaW5pdCggcmVzb3VyY2VfaWQgKTtcclxuXHR3cGJjX2NhbF9fcmVfaW5pdCggcmVzb3VyY2VfaWQgKTtcclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4vKipcclxuICogU2V0IFJhbmdlIERheXMgc2VsZWN0aW9uICB3aXRoICAyIG1vdXNlIGNsaWNrcyAgLSBhZnRlciBwYWdlIGxvYWRcclxuICpcclxuICogQGludGVnZXIgcmVzb3VyY2VfaWRcdFx0XHQtIDFcdFx0XHRcdCAgIFx0XHQtLSBJRCBvZiBib29raW5nIHJlc291cmNlIChjYWxlbmRhcilcclxuICogQGludGVnZXIgZGF5c19taW5cdFx0XHQtIDdcdFx0XHRcdCAgIFx0XHQtLSBNaW4gbnVtYmVyIG9mIGRheXMgdG8gc2VsZWN0XHJcbiAqIEBpbnRlZ2VyIGRheXNfbWF4XHRcdFx0LSAzMFx0XHRcdCAgIFx0XHQtLSBNYXggbnVtYmVyIG9mIGRheXMgdG8gc2VsZWN0XHJcbiAqIEBhcnJheSBkYXlzX3NwZWNpZmljXHRcdFx0LSBbXSB8IFs3LDE0LDIxLDI4XVx0XHQtLSBSZXN0cmljdGlvbiBmb3IgU3BlY2lmaWMgbnVtYmVyIG9mIGRheXMgc2VsZWN0aW9uXHJcbiAqIEBhcnJheSB3ZWVrX2RheXNfX3N0YXJ0XHRcdC0gWy0xXSB8IFsgMSwgNV0gICBcdFx0LS0gIHsgLTEgLSBBbnkgfCAwIC0gU3UsICAxIC0gTW8sICAyIC0gVHUsIDMgLSBXZSwgNCAtIFRoLCA1IC0gRnIsIDYgLSBTYXQgfVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jYWxfcmVhZHlfZGF5c19zZWxlY3RfX3JhbmdlKCByZXNvdXJjZV9pZCwgZGF5c19taW4sIGRheXNfbWF4LCBkYXlzX3NwZWNpZmljID0gW10sIHdlZWtfZGF5c19fc3RhcnQgPSBbLTFdICl7XHJcblxyXG5cdC8vIFJlLWRlZmluZSBzZWxlY3Rpb24sIG9ubHkgYWZ0ZXIgcGFnZSBsb2FkZWQgd2l0aCBhbGwgaW5pdCB2YXJzXHJcblx0alF1ZXJ5KGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpe1xyXG5cclxuXHRcdC8vIFdhaXQgMSBzZWNvbmQsIGp1c3QgdG8gIGJlIHN1cmUsIHRoYXQgYWxsIGluaXQgdmFycyBkZWZpbmVkXHJcblx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XHJcblxyXG5cdFx0XHR3cGJjX2NhbF9kYXlzX3NlbGVjdF9fcmFuZ2UoIHJlc291cmNlX2lkLCBkYXlzX21pbiwgZGF5c19tYXgsIGRheXNfc3BlY2lmaWMsIHdlZWtfZGF5c19fc3RhcnQgKTtcclxuXHRcdH0sIDEwMDApO1xyXG5cdH0pO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0IFJhbmdlIERheXMgc2VsZWN0aW9uICB3aXRoICAyIG1vdXNlIGNsaWNrc1xyXG4gKiBDYW4gYmUgcnVuIGF0IGFueSAgdGltZSwgIHdoZW4gIGNhbGVuZGFyIGRlZmluZWQgLSB1c2VmdWwgZm9yIGNvbnNvbGUgcnVuLlxyXG4gKlxyXG4gKiBAaW50ZWdlciByZXNvdXJjZV9pZFx0XHRcdC0gMVx0XHRcdFx0ICAgXHRcdC0tIElEIG9mIGJvb2tpbmcgcmVzb3VyY2UgKGNhbGVuZGFyKVxyXG4gKiBAaW50ZWdlciBkYXlzX21pblx0XHRcdC0gN1x0XHRcdFx0ICAgXHRcdC0tIE1pbiBudW1iZXIgb2YgZGF5cyB0byBzZWxlY3RcclxuICogQGludGVnZXIgZGF5c19tYXhcdFx0XHQtIDMwXHRcdFx0ICAgXHRcdC0tIE1heCBudW1iZXIgb2YgZGF5cyB0byBzZWxlY3RcclxuICogQGFycmF5IGRheXNfc3BlY2lmaWNcdFx0XHQtIFtdIHwgWzcsMTQsMjEsMjhdXHRcdC0tIFJlc3RyaWN0aW9uIGZvciBTcGVjaWZpYyBudW1iZXIgb2YgZGF5cyBzZWxlY3Rpb25cclxuICogQGFycmF5IHdlZWtfZGF5c19fc3RhcnRcdFx0LSBbLTFdIHwgWyAxLCA1XSAgIFx0XHQtLSAgeyAtMSAtIEFueSB8IDAgLSBTdSwgIDEgLSBNbywgIDIgLSBUdSwgMyAtIFdlLCA0IC0gVGgsIDUgLSBGciwgNiAtIFNhdCB9XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2NhbF9kYXlzX3NlbGVjdF9fcmFuZ2UoIHJlc291cmNlX2lkLCBkYXlzX21pbiwgZGF5c19tYXgsIGRheXNfc3BlY2lmaWMgPSBbXSwgd2Vla19kYXlzX19zdGFydCA9IFstMV0gKXtcclxuXHJcblx0X3dwYmMuY2FsZW5kYXJfX3NldF9wYXJhbWV0ZXJzKCAgcmVzb3VyY2VfaWQsIHsnZGF5c19zZWxlY3RfbW9kZSc6ICdkeW5hbWljJ30gICk7XHJcblx0X3dwYmMuY2FsZW5kYXJfX3NldF9wYXJhbV92YWx1ZSggcmVzb3VyY2VfaWQsICdkeW5hbWljX19kYXlzX21pbicgICAgICAgICAsIHBhcnNlSW50KCBkYXlzX21pbiApICApOyAgICAgICAgICAgXHRcdC8vIE1pbi4gTnVtYmVyIG9mIGRheXMgc2VsZWN0aW9uIHdpdGggMiBtb3VzZSBjbGlja3NcclxuXHRfd3BiYy5jYWxlbmRhcl9fc2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ2R5bmFtaWNfX2RheXNfbWF4JyAgICAgICAgICwgcGFyc2VJbnQoIGRheXNfbWF4ICkgICk7ICAgICAgICAgIFx0XHQvLyBNYXguIE51bWJlciBvZiBkYXlzIHNlbGVjdGlvbiB3aXRoIDIgbW91c2UgY2xpY2tzXHJcblx0X3dwYmMuY2FsZW5kYXJfX3NldF9wYXJhbV92YWx1ZSggcmVzb3VyY2VfaWQsICdkeW5hbWljX19kYXlzX3NwZWNpZmljJyAgICAsIGRheXNfc3BlY2lmaWMgICk7XHQgICAgICBcdFx0XHRcdC8vIEV4YW1wbGUgWzUsN11cclxuXHRfd3BiYy5jYWxlbmRhcl9fc2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ2R5bmFtaWNfX3dlZWtfZGF5c19fc3RhcnQnICwgd2Vla19kYXlzX19zdGFydCAgKTsgIFx0XHRcdFx0XHQvLyB7IC0xIC0gQW55IHwgMCAtIFN1LCAgMSAtIE1vLCAgMiAtIFR1LCAzIC0gV2UsIDQgLSBUaCwgNSAtIEZyLCA2IC0gU2F0IH1cclxuXHJcblx0d3BiY19jYWxfZGF5c19zZWxlY3RfX3JlX2luaXQoIHJlc291cmNlX2lkICk7XHJcblx0d3BiY19jYWxfX3JlX2luaXQoIHJlc291cmNlX2lkICk7XHJcbn1cclxuIiwiLyoqXHJcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAqXHRpbmNsdWRlcy9fX2pzL2NhbF9hanhfbG9hZC93cGJjX2NhbF9hanguanNcclxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICovXHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuLy8gIEEgaiBhIHggICAgTCBvIGEgZCAgICBDIGEgbCBlIG4gZCBhIHIgICAgRCBhIHQgYVxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbmZ1bmN0aW9uIHdwYmNfY2FsZW5kYXJfX2xvYWRfZGF0YV9fYWp4KCBwYXJhbXMgKXtcclxuXHJcblx0Ly9GaXhJbjogOS44LjYuMlxyXG5cdHdwYmNfY2FsZW5kYXJfX2xvYWRpbmdfX3N0YXJ0KCBwYXJhbXNbJ3Jlc291cmNlX2lkJ10gKTtcclxuXHRpZiAoIHdwYmNfYmFsYW5jZXJfX2lzX3dhaXQoIHBhcmFtcyAsICd3cGJjX2NhbGVuZGFyX19sb2FkX2RhdGFfX2FqeCcgKSApe1xyXG5cdFx0cmV0dXJuIGZhbHNlO1xyXG5cdH1cclxuXHJcblx0Ly9GaXhJbjogOS44LjYuMlxyXG5cdHdwYmNfY2FsZW5kYXJfX2JsdXJfX3N0b3AoIHBhcmFtc1sncmVzb3VyY2VfaWQnXSApO1xyXG5cclxuXHJcbi8vIGNvbnNvbGUuZ3JvdXBFbmQoKTsgY29uc29sZS50aW1lKCdyZXNvdXJjZV9pZF8nICsgcGFyYW1zWydyZXNvdXJjZV9pZCddKTtcclxuY29uc29sZS5ncm91cENvbGxhcHNlZCggJ1dQQkNfQUpYX0NBTEVOREFSX0xPQUQnICk7IGNvbnNvbGUubG9nKCAnID09IEJlZm9yZSBBamF4IFNlbmQgLSBjYWxlbmRhcnNfYWxsX19nZXQoKSA9PSAnICwgX3dwYmMuY2FsZW5kYXJzX2FsbF9fZ2V0KCkgKTtcclxuXHJcblx0Ly8gU3RhcnQgQWpheFxyXG5cdGpRdWVyeS5wb3N0KCB3cGJjX2dsb2JhbDEud3BiY19hamF4dXJsLFxyXG5cdFx0XHRcdHtcclxuXHRcdFx0XHRcdGFjdGlvbiAgICAgICAgICA6ICdXUEJDX0FKWF9DQUxFTkRBUl9MT0FEJyxcclxuXHRcdFx0XHRcdHdwYmNfYWp4X3VzZXJfaWQ6IF93cGJjLmdldF9zZWN1cmVfcGFyYW0oICd1c2VyX2lkJyApLFxyXG5cdFx0XHRcdFx0bm9uY2UgICAgICAgICAgIDogX3dwYmMuZ2V0X3NlY3VyZV9wYXJhbSggJ25vbmNlJyApLFxyXG5cdFx0XHRcdFx0d3BiY19hanhfbG9jYWxlIDogX3dwYmMuZ2V0X3NlY3VyZV9wYXJhbSggJ2xvY2FsZScgKSxcclxuXHJcblx0XHRcdFx0XHRjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtcyA6IHBhcmFtcyBcdFx0XHRcdFx0XHQvLyBVc3VhbGx5IGxpa2U6IHsgJ3Jlc291cmNlX2lkJzogMSwgJ21heF9kYXlzX2NvdW50JzogMzY1IH1cclxuXHRcdFx0XHR9LFxyXG5cclxuXHRcdFx0XHQvKipcclxuXHRcdFx0XHQgKiBTIHUgYyBjIGUgcyBzXHJcblx0XHRcdFx0ICpcclxuXHRcdFx0XHQgKiBAcGFyYW0gcmVzcG9uc2VfZGF0YVx0XHQtXHRpdHMgb2JqZWN0IHJldHVybmVkIGZyb20gIEFqYXggLSBjbGFzcy1saXZlLXNlYXJjaC5waHBcclxuXHRcdFx0XHQgKiBAcGFyYW0gdGV4dFN0YXR1c1x0XHQtXHQnc3VjY2VzcydcclxuXHRcdFx0XHQgKiBAcGFyYW0ganFYSFJcdFx0XHRcdC1cdE9iamVjdFxyXG5cdFx0XHRcdCAqL1xyXG5cdFx0XHRcdGZ1bmN0aW9uICggcmVzcG9uc2VfZGF0YSwgdGV4dFN0YXR1cywganFYSFIgKSB7XHJcbi8vIGNvbnNvbGUudGltZUVuZCgncmVzb3VyY2VfaWRfJyArIHJlc3BvbnNlX2RhdGFbJ3Jlc291cmNlX2lkJ10pO1xyXG5jb25zb2xlLmxvZyggJyA9PSBSZXNwb25zZSBXUEJDX0FKWF9DQUxFTkRBUl9MT0FEID09ICcsIHJlc3BvbnNlX2RhdGEgKTsgY29uc29sZS5ncm91cEVuZCgpO1xyXG5cclxuXHRcdFx0XHRcdC8vRml4SW46IDkuOC42LjJcclxuXHRcdFx0XHRcdHZhciBhanhfcG9zdF9kYXRhX19yZXNvdXJjZV9pZCA9IHdwYmNfZ2V0X3Jlc291cmNlX2lkX19mcm9tX2FqeF9wb3N0X2RhdGFfdXJsKCB0aGlzLmRhdGEgKTtcclxuXHRcdFx0XHRcdHdwYmNfYmFsYW5jZXJfX2NvbXBsZXRlZCggYWp4X3Bvc3RfZGF0YV9fcmVzb3VyY2VfaWQgLCAnd3BiY19jYWxlbmRhcl9fbG9hZF9kYXRhX19hangnICk7XHJcblxyXG5cdFx0XHRcdFx0Ly8gUHJvYmFibHkgRXJyb3JcclxuXHRcdFx0XHRcdGlmICggKHR5cGVvZiByZXNwb25zZV9kYXRhICE9PSAnb2JqZWN0JykgfHwgKHJlc3BvbnNlX2RhdGEgPT09IG51bGwpICl7XHJcblxyXG5cdFx0XHRcdFx0XHR2YXIganFfbm9kZSAgPSB3cGJjX2dldF9jYWxlbmRhcl9fanFfbm9kZV9fZm9yX21lc3NhZ2VzKCB0aGlzLmRhdGEgKTtcclxuXHRcdFx0XHRcdFx0dmFyIG1lc3NhZ2VfdHlwZSA9ICdpbmZvJztcclxuXHJcblx0XHRcdFx0XHRcdGlmICggJycgPT09IHJlc3BvbnNlX2RhdGEgKXtcclxuXHRcdFx0XHRcdFx0XHRyZXNwb25zZV9kYXRhID0gJ1RoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhbiBlbXB0eSBzdHJpbmcuIFRoZSBzZXJ2ZXIgcHJvYmFibHkgc3RvcHBlZCB3b3JraW5nIHVuZXhwZWN0ZWRseS4gPGJyPlBsZWFzZSBjaGVjayB5b3VyIDxzdHJvbmc+ZXJyb3IubG9nPC9zdHJvbmc+IGluIHlvdXIgc2VydmVyIGNvbmZpZ3VyYXRpb24gZm9yIHJlbGF0aXZlIGVycm9ycy4nO1xyXG5cdFx0XHRcdFx0XHRcdG1lc3NhZ2VfdHlwZSA9ICd3YXJuaW5nJztcclxuXHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdFx0Ly8gU2hvdyBNZXNzYWdlXHJcblx0XHRcdFx0XHRcdHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoIHJlc3BvbnNlX2RhdGEgLCB7ICd0eXBlJyAgICAgOiBtZXNzYWdlX3R5cGUsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzaG93X2hlcmUnOiB7J2pxX25vZGUnOiBqcV9ub2RlLCAnd2hlcmUnOiAnYWZ0ZXInfSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2lzX2FwcGVuZCc6IHRydWUsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzdHlsZScgICAgOiAndGV4dC1hbGlnbjpsZWZ0OycsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdkZWxheScgICAgOiAwXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9ICk7XHJcblx0XHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHQvLyBTaG93IENhbGVuZGFyXHJcblx0XHRcdFx0XHR3cGJjX2NhbGVuZGFyX19sb2FkaW5nX19zdG9wKCByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF0gKTtcclxuXHJcblx0XHRcdFx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHRcdFx0XHQvLyBCb29raW5ncyAtIERhdGVzXHJcblx0XHRcdFx0XHRfd3BiYy5ib29raW5nc19pbl9jYWxlbmRhcl9fc2V0X2RhdGVzKCAgcmVzcG9uc2VfZGF0YVsgJ3Jlc291cmNlX2lkJyBdLCByZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bJ2RhdGVzJ10gICk7XHJcblxyXG5cdFx0XHRcdFx0Ly8gQm9va2luZ3MgLSBDaGlsZCBvciBvbmx5IHNpbmdsZSBib29raW5nIHJlc291cmNlIGluIGRhdGVzXHJcblx0XHRcdFx0XHRfd3BiYy5ib29raW5nX19zZXRfcGFyYW1fdmFsdWUoIHJlc3BvbnNlX2RhdGFbICdyZXNvdXJjZV9pZCcgXSwgJ3Jlc291cmNlc19pZF9hcnJfX2luX2RhdGVzJywgcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAncmVzb3VyY2VzX2lkX2Fycl9faW5fZGF0ZXMnIF0gKTtcclxuXHJcblx0XHRcdFx0XHQvLyBBZ2dyZWdhdGUgYm9va2luZyByZXNvdXJjZXMsICBpZiBhbnkgP1xyXG5cdFx0XHRcdFx0X3dwYmMuYm9va2luZ19fc2V0X3BhcmFtX3ZhbHVlKCByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF0sICdhZ2dyZWdhdGVfcmVzb3VyY2VfaWRfYXJyJywgcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnYWdncmVnYXRlX3Jlc291cmNlX2lkX2FycicgXSApO1xyXG5cdFx0XHRcdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHRcdFx0XHRcdC8vIFVwZGF0ZSBjYWxlbmRhclxyXG5cdFx0XHRcdFx0d3BiY19jYWxlbmRhcl9fdXBkYXRlX2xvb2soIHJlc3BvbnNlX2RhdGFbICdyZXNvdXJjZV9pZCcgXSApO1xyXG5cclxuXHJcblx0XHRcdFx0XHRpZiAoXHJcblx0XHRcdFx0XHRcdFx0KCAndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdhanhfYWZ0ZXJfYWN0aW9uX21lc3NhZ2UnIF0pIClcclxuXHRcdFx0XHRcdFx0ICYmICggJycgIT0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnYWp4X2FmdGVyX2FjdGlvbl9tZXNzYWdlJyBdLnJlcGxhY2UoIC9cXG4vZywgXCI8YnIgLz5cIiApIClcclxuXHRcdFx0XHRcdCl7XHJcblxyXG5cdFx0XHRcdFx0XHR2YXIganFfbm9kZSAgPSB3cGJjX2dldF9jYWxlbmRhcl9fanFfbm9kZV9fZm9yX21lc3NhZ2VzKCB0aGlzLmRhdGEgKTtcclxuXHJcblx0XHRcdFx0XHRcdC8vIFNob3cgTWVzc2FnZVxyXG5cdFx0XHRcdFx0XHR3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlKCByZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdhanhfYWZ0ZXJfYWN0aW9uX21lc3NhZ2UnIF0ucmVwbGFjZSggL1xcbi9nLCBcIjxiciAvPlwiICksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR7ICAgJ3R5cGUnICAgICA6ICggJ3VuZGVmaW5lZCcgIT09IHR5cGVvZiggcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnYWp4X2FmdGVyX2FjdGlvbl9tZXNzYWdlX3N0YXR1cycgXSApIClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICA/IHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZV9zdGF0dXMnIF0gOiAnaW5mbycsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzaG93X2hlcmUnOiB7J2pxX25vZGUnOiBqcV9ub2RlLCAnd2hlcmUnOiAnYWZ0ZXInfSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2lzX2FwcGVuZCc6IHRydWUsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzdHlsZScgICAgOiAndGV4dC1hbGlnbjpsZWZ0OycsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdkZWxheScgICAgOiAxMDAwMFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdC8valF1ZXJ5KCAnI2FqYXhfcmVzcG9uZCcgKS5odG1sKCByZXNwb25zZV9kYXRhICk7XHRcdC8vIEZvciBhYmlsaXR5IHRvIHNob3cgcmVzcG9uc2UsIGFkZCBzdWNoIERJViBlbGVtZW50IHRvIHBhZ2VcclxuXHRcdFx0XHR9XHJcblx0XHRcdCAgKS5mYWlsKCBmdW5jdGlvbiAoIGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93biApIHsgICAgaWYgKCB3aW5kb3cuY29uc29sZSAmJiB3aW5kb3cuY29uc29sZS5sb2cgKXsgY29uc29sZS5sb2coICdBamF4X0Vycm9yJywganFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duICk7IH1cclxuXHJcblx0XHRcdFx0XHR2YXIgYWp4X3Bvc3RfZGF0YV9fcmVzb3VyY2VfaWQgPSB3cGJjX2dldF9yZXNvdXJjZV9pZF9fZnJvbV9hanhfcG9zdF9kYXRhX3VybCggdGhpcy5kYXRhICk7XHJcblx0XHRcdFx0XHR3cGJjX2JhbGFuY2VyX19jb21wbGV0ZWQoIGFqeF9wb3N0X2RhdGFfX3Jlc291cmNlX2lkICwgJ3dwYmNfY2FsZW5kYXJfX2xvYWRfZGF0YV9fYWp4JyApO1xyXG5cclxuXHRcdFx0XHRcdC8vIEdldCBDb250ZW50IG9mIEVycm9yIE1lc3NhZ2VcclxuXHRcdFx0XHRcdHZhciBlcnJvcl9tZXNzYWdlID0gJzxzdHJvbmc+JyArICdFcnJvciEnICsgJzwvc3Ryb25nPiAnICsgZXJyb3JUaHJvd24gO1xyXG5cdFx0XHRcdFx0aWYgKCBqcVhIUi5zdGF0dXMgKXtcclxuXHRcdFx0XHRcdFx0ZXJyb3JfbWVzc2FnZSArPSAnICg8Yj4nICsganFYSFIuc3RhdHVzICsgJzwvYj4pJztcclxuXHRcdFx0XHRcdFx0aWYgKDQwMyA9PSBqcVhIUi5zdGF0dXMgKXtcclxuXHRcdFx0XHRcdFx0XHRlcnJvcl9tZXNzYWdlICs9ICc8YnI+IFByb2JhYmx5IG5vbmNlIGZvciB0aGlzIHBhZ2UgaGFzIGJlZW4gZXhwaXJlZC4gUGxlYXNlIDxhIGhyZWY9XCJqYXZhc2NyaXB0OnZvaWQoMClcIiBvbmNsaWNrPVwiamF2YXNjcmlwdDpsb2NhdGlvbi5yZWxvYWQoKTtcIj5yZWxvYWQgdGhlIHBhZ2U8L2E+Lic7XHJcblx0XHRcdFx0XHRcdFx0ZXJyb3JfbWVzc2FnZSArPSAnPGJyPiBPdGhlcndpc2UsIHBsZWFzZSBjaGVjayB0aGlzIDxhIHN0eWxlPVwiZm9udC13ZWlnaHQ6IDYwMDtcIiBocmVmPVwiaHR0cHM6Ly93cGJvb2tpbmdjYWxlbmRhci5jb20vZmFxL3JlcXVlc3QtZG8tbm90LXBhc3Mtc2VjdXJpdHktY2hlY2svXCI+dHJvdWJsZXNob290aW5nIGluc3RydWN0aW9uPC9hPi48YnI+J1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR2YXIgbWVzc2FnZV9zaG93X2RlbGF5ID0gMzAwMDtcclxuXHRcdFx0XHRcdGlmICgganFYSFIucmVzcG9uc2VUZXh0ICl7XHJcblx0XHRcdFx0XHRcdGVycm9yX21lc3NhZ2UgKz0gJyAnICsganFYSFIucmVzcG9uc2VUZXh0O1xyXG5cdFx0XHRcdFx0XHRtZXNzYWdlX3Nob3dfZGVsYXkgPSAxMDtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVycm9yX21lc3NhZ2UgPSBlcnJvcl9tZXNzYWdlLnJlcGxhY2UoIC9cXG4vZywgXCI8YnIgLz5cIiApO1xyXG5cclxuXHRcdFx0XHRcdHZhciBqcV9ub2RlICA9IHdwYmNfZ2V0X2NhbGVuZGFyX19qcV9ub2RlX19mb3JfbWVzc2FnZXMoIHRoaXMuZGF0YSApO1xyXG5cclxuXHRcdFx0XHRcdC8qKlxyXG5cdFx0XHRcdFx0ICogSWYgd2UgbWFrZSBmYXN0IGNsaWNraW5nIG9uIGRpZmZlcmVudCBwYWdlcyxcclxuXHRcdFx0XHRcdCAqIHRoZW4gdW5kZXIgY2FsZW5kYXIgd2lsbCBzaG93IGVycm9yIG1lc3NhZ2Ugd2l0aCAgZW1wdHkgIHRleHQsIGJlY2F1c2UgYWpheCB3YXMgbm90IHJlY2VpdmVkLlxyXG5cdFx0XHRcdFx0ICogVG8gIG5vdCBzaG93IHN1Y2ggd2FybmluZ3Mgd2UgYXJlIHNldCBkZWxheSAgaW4gMyBzZWNvbmRzLiAgdmFyIG1lc3NhZ2Vfc2hvd19kZWxheSA9IDMwMDA7XHJcblx0XHRcdFx0XHQgKi9cclxuXHRcdFx0XHRcdHZhciBjbG9zZWRfdGltZXIgPSBzZXRUaW1lb3V0KCBmdW5jdGlvbiAoKXtcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gU2hvdyBNZXNzYWdlXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0d3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZSggZXJyb3JfbWVzc2FnZSAsIHsgJ3R5cGUnICAgICA6ICdlcnJvcicsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3Nob3dfaGVyZSc6IHsnanFfbm9kZSc6IGpxX25vZGUsICd3aGVyZSc6ICdhZnRlcid9LFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdpc19hcHBlbmQnOiB0cnVlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzdHlsZScgICAgOiAndGV4dC1hbGlnbjpsZWZ0OycsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2Nzc19jbGFzcyc6J3dwYmNfZmVfbWVzc2FnZV9hbHQnLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdkZWxheScgICAgOiAwXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgIH0gLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICAgcGFyc2VJbnQoIG1lc3NhZ2Vfc2hvd19kZWxheSApICAgKTtcclxuXHJcblx0XHRcdCAgfSlcclxuXHQgICAgICAgICAgLy8gLmRvbmUoICAgZnVuY3Rpb24gKCBkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUiApIHsgICBpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLmxvZyApeyBjb25zb2xlLmxvZyggJ3NlY29uZCBzdWNjZXNzJywgZGF0YSwgdGV4dFN0YXR1cywganFYSFIgKTsgfSAgICB9KVxyXG5cdFx0XHQgIC8vIC5hbHdheXMoIGZ1bmN0aW9uICggZGF0YV9qcVhIUiwgdGV4dFN0YXR1cywganFYSFJfZXJyb3JUaHJvd24gKSB7ICAgaWYgKCB3aW5kb3cuY29uc29sZSAmJiB3aW5kb3cuY29uc29sZS5sb2cgKXsgY29uc29sZS5sb2coICdhbHdheXMgZmluaXNoZWQnLCBkYXRhX2pxWEhSLCB0ZXh0U3RhdHVzLCBqcVhIUl9lcnJvclRocm93biApOyB9ICAgICB9KVxyXG5cdFx0XHQgIDsgIC8vIEVuZCBBamF4XHJcbn1cclxuXHJcblxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbi8vIFN1cHBvcnRcclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBDYWxlbmRhciBqUXVlcnkgbm9kZSBmb3Igc2hvd2luZyBtZXNzYWdlcyBkdXJpbmcgQWpheFxyXG5cdCAqIFRoaXMgcGFyYW1ldGVyOiAgIGNhbGVuZGFyX3JlcXVlc3RfcGFyYW1zW3Jlc291cmNlX2lkXSAgIHBhcnNlZCBmcm9tIHRoaXMuZGF0YSBBamF4IHBvc3QgIGRhdGFcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSBhanhfcG9zdF9kYXRhX3VybF9wYXJhbXNcdFx0ICdhY3Rpb249V1BCQ19BSlhfQ0FMRU5EQVJfTE9BRC4uLiZjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtcyU1QnJlc291cmNlX2lkJTVEPTImY2FsZW5kYXJfcmVxdWVzdF9wYXJhbXMlNUJib29raW5nX2hhc2glNUQ9JmNhbGVuZGFyX3JlcXVlc3RfcGFyYW1zJ1xyXG5cdCAqIEByZXR1cm5zIHtzdHJpbmd9XHQnJyNjYWxlbmRhcl9ib29raW5nMScgIHwgICAnLmJvb2tpbmdfZm9ybV9kaXYnIC4uLlxyXG5cdCAqXHJcblx0ICogRXhhbXBsZSAgICB2YXIganFfbm9kZSAgPSB3cGJjX2dldF9jYWxlbmRhcl9fanFfbm9kZV9fZm9yX21lc3NhZ2VzKCB0aGlzLmRhdGEgKTtcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2dldF9jYWxlbmRhcl9fanFfbm9kZV9fZm9yX21lc3NhZ2VzKCBhanhfcG9zdF9kYXRhX3VybF9wYXJhbXMgKXtcclxuXHJcblx0XHR2YXIganFfbm9kZSA9ICcuYm9va2luZ19mb3JtX2Rpdic7XHJcblxyXG5cdFx0dmFyIGNhbGVuZGFyX3Jlc291cmNlX2lkID0gd3BiY19nZXRfcmVzb3VyY2VfaWRfX2Zyb21fYWp4X3Bvc3RfZGF0YV91cmwoIGFqeF9wb3N0X2RhdGFfdXJsX3BhcmFtcyApO1xyXG5cclxuXHRcdGlmICggY2FsZW5kYXJfcmVzb3VyY2VfaWQgPiAwICl7XHJcblx0XHRcdGpxX25vZGUgPSAnI2NhbGVuZGFyX2Jvb2tpbmcnICsgY2FsZW5kYXJfcmVzb3VyY2VfaWQ7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGpxX25vZGU7XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHJlc291cmNlIElEIGZyb20gYWp4IHBvc3QgZGF0YSB1cmwgICB1c3VhbGx5ICBmcm9tICB0aGlzLmRhdGEgID0gJ2FjdGlvbj1XUEJDX0FKWF9DQUxFTkRBUl9MT0FELi4uJmNhbGVuZGFyX3JlcXVlc3RfcGFyYW1zJTVCcmVzb3VyY2VfaWQlNUQ9MiZjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtcyU1QmJvb2tpbmdfaGFzaCU1RD0mY2FsZW5kYXJfcmVxdWVzdF9wYXJhbXMnXHJcblx0ICpcclxuXHQgKiBAcGFyYW0gYWp4X3Bvc3RfZGF0YV91cmxfcGFyYW1zXHRcdCAnYWN0aW9uPVdQQkNfQUpYX0NBTEVOREFSX0xPQUQuLi4mY2FsZW5kYXJfcmVxdWVzdF9wYXJhbXMlNUJyZXNvdXJjZV9pZCU1RD0yJmNhbGVuZGFyX3JlcXVlc3RfcGFyYW1zJTVCYm9va2luZ19oYXNoJTVEPSZjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtcydcclxuXHQgKiBAcmV0dXJucyB7aW50fVx0XHRcdFx0XHRcdCAxIHwgMCAgKGlmIGVycnJvciB0aGVuICAwKVxyXG5cdCAqXHJcblx0ICogRXhhbXBsZSAgICB2YXIganFfbm9kZSAgPSB3cGJjX2dldF9jYWxlbmRhcl9fanFfbm9kZV9fZm9yX21lc3NhZ2VzKCB0aGlzLmRhdGEgKTtcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2dldF9yZXNvdXJjZV9pZF9fZnJvbV9hanhfcG9zdF9kYXRhX3VybCggYWp4X3Bvc3RfZGF0YV91cmxfcGFyYW1zICl7XHJcblxyXG5cdFx0Ly8gR2V0IGJvb2tpbmcgcmVzb3VyY2UgSUQgZnJvbSBBamF4IFBvc3QgUmVxdWVzdCAgLT4gdGhpcy5kYXRhID0gJ2FjdGlvbj1XUEJDX0FKWF9DQUxFTkRBUl9MT0FELi4uJmNhbGVuZGFyX3JlcXVlc3RfcGFyYW1zJTVCcmVzb3VyY2VfaWQlNUQ9MiZjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtcyU1QmJvb2tpbmdfaGFzaCU1RD0mY2FsZW5kYXJfcmVxdWVzdF9wYXJhbXMnXHJcblx0XHR2YXIgY2FsZW5kYXJfcmVzb3VyY2VfaWQgPSB3cGJjX2dldF91cmlfcGFyYW1fYnlfbmFtZSggJ2NhbGVuZGFyX3JlcXVlc3RfcGFyYW1zW3Jlc291cmNlX2lkXScsIGFqeF9wb3N0X2RhdGFfdXJsX3BhcmFtcyApO1xyXG5cdFx0aWYgKCAobnVsbCAhPT0gY2FsZW5kYXJfcmVzb3VyY2VfaWQpICYmICgnJyAhPT0gY2FsZW5kYXJfcmVzb3VyY2VfaWQpICl7XHJcblx0XHRcdGNhbGVuZGFyX3Jlc291cmNlX2lkID0gcGFyc2VJbnQoIGNhbGVuZGFyX3Jlc291cmNlX2lkICk7XHJcblx0XHRcdGlmICggY2FsZW5kYXJfcmVzb3VyY2VfaWQgPiAwICl7XHJcblx0XHRcdFx0cmV0dXJuIGNhbGVuZGFyX3Jlc291cmNlX2lkO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gMDtcclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgcGFyYW1ldGVyIGZyb20gVVJMICAtICBwYXJzZSBVUkwgcGFyYW1ldGVycywgIGxpa2UgdGhpczogYWN0aW9uPVdQQkNfQUpYX0NBTEVOREFSX0xPQUQuLi4mY2FsZW5kYXJfcmVxdWVzdF9wYXJhbXMlNUJyZXNvdXJjZV9pZCU1RD0yJmNhbGVuZGFyX3JlcXVlc3RfcGFyYW1zJTVCYm9va2luZ19oYXNoJTVEPSZjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtc1xyXG5cdCAqIEBwYXJhbSBuYW1lICBwYXJhbWV0ZXIgIG5hbWUsICBsaWtlICdjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtc1tyZXNvdXJjZV9pZF0nXHJcblx0ICogQHBhcmFtIHVybFx0J3BhcmFtZXRlciAgc3RyaW5nIFVSTCdcclxuXHQgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9ICAgcGFyYW1ldGVyIHZhbHVlXHJcblx0ICpcclxuXHQgKiBFeGFtcGxlOiBcdFx0d3BiY19nZXRfdXJpX3BhcmFtX2J5X25hbWUoICdjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtc1tyZXNvdXJjZV9pZF0nLCB0aGlzLmRhdGEgKTsgIC0+ICcyJ1xyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfZ2V0X3VyaV9wYXJhbV9ieV9uYW1lKCBuYW1lLCB1cmwgKXtcclxuXHJcblx0XHR1cmwgPSBkZWNvZGVVUklDb21wb25lbnQoIHVybCApO1xyXG5cclxuXHRcdG5hbWUgPSBuYW1lLnJlcGxhY2UoIC9bXFxbXFxdXS9nLCAnXFxcXCQmJyApO1xyXG5cdFx0dmFyIHJlZ2V4ID0gbmV3IFJlZ0V4cCggJ1s/Jl0nICsgbmFtZSArICcoPShbXiYjXSopfCZ8I3wkKScgKSxcclxuXHRcdFx0cmVzdWx0cyA9IHJlZ2V4LmV4ZWMoIHVybCApO1xyXG5cdFx0aWYgKCAhcmVzdWx0cyApIHJldHVybiBudWxsO1xyXG5cdFx0aWYgKCAhcmVzdWx0c1sgMiBdICkgcmV0dXJuICcnO1xyXG5cdFx0cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCggcmVzdWx0c1sgMiBdLnJlcGxhY2UoIC9cXCsvZywgJyAnICkgKTtcclxuXHR9XHJcblxyXG5cclxuLy9UT0RPOiByZW1vdmUgdmFyczogICAgICAgYmtfMmNsaWNrc19tb2RlX2RheXNfc3RhcnQsIGJrXzFjbGlja19tb2RlX2RheXNfc3RhcnQgICAgIGRhdGUyYXBwcm92ZSAgIGRhdGVfYXBwcm92ZWQiLCIvKipcclxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAqXHRpbmNsdWRlcy9fX2pzL2Zyb250X2VuZF9tZXNzYWdlcy93cGJjX2ZlX21lc3NhZ2VzLmpzXHJcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gKi9cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4vLyBTaG93IE1lc3NhZ2VzIGF0IEZyb250LUVkbiBzaWRlXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIFNob3cgbWVzc2FnZSBpbiBjb250ZW50XHJcbiAqXHJcbiAqIEBwYXJhbSBtZXNzYWdlXHRcdFx0XHRNZXNzYWdlIEhUTUxcclxuICogQHBhcmFtIHBhcmFtcyA9IHtcclxuICpcdFx0XHRcdFx0XHRcdFx0J3R5cGUnICAgICA6ICd3YXJuaW5nJyxcdFx0XHRcdFx0XHRcdC8vICdlcnJvcicgfCAnd2FybmluZycgfCAnaW5mbycgfCAnc3VjY2VzcydcclxuICpcdFx0XHRcdFx0XHRcdFx0J3Nob3dfaGVyZScgOiB7XHJcbiAqXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnanFfbm9kZScgOiAnJyxcdFx0XHRcdC8vIGFueSBqUXVlcnkgbm9kZSBkZWZpbml0aW9uXHJcbiAqXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnd2hlcmUnICAgOiAnaW5zaWRlJ1x0XHQvLyAnaW5zaWRlJyB8ICdiZWZvcmUnIHwgJ2FmdGVyJyB8ICdyaWdodCcgfCAnbGVmdCdcclxuICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICB9LFxyXG4gKlx0XHRcdFx0XHRcdFx0XHQnaXNfYXBwZW5kJzogdHJ1ZSxcdFx0XHRcdFx0XHRcdFx0Ly8gQXBwbHkgIG9ubHkgaWYgXHQnd2hlcmUnICAgOiAnaW5zaWRlJ1xyXG4gKlx0XHRcdFx0XHRcdFx0XHQnc3R5bGUnICAgIDogJ3RleHQtYWxpZ246bGVmdDsnLFx0XHRcdFx0Ly8gc3R5bGVzLCBpZiBuZWVkZWRcclxuICpcdFx0XHRcdFx0XHRcdCAgICAnY3NzX2NsYXNzJzogJycsXHRcdFx0XHRcdFx0XHRcdC8vIEZvciBleGFtcGxlIGNhbiAgYmU6ICd3cGJjX2ZlX21lc3NhZ2VfYWx0J1xyXG4gKlx0XHRcdFx0XHRcdFx0XHQnZGVsYXknICAgIDogMCxcdFx0XHRcdFx0XHRcdFx0XHQvLyBob3cgbWFueSBtaWNyb3NlY29uZCB0byAgc2hvdywgIGlmIDAgIHRoZW4gIHNob3cgZm9yZXZlclxyXG4gKlx0XHRcdFx0XHRcdFx0XHQnaWZfdmlzaWJsZV9ub3Rfc2hvdyc6IGZhbHNlXHRcdFx0XHRcdC8vIGlmIHRydWUsICB0aGVuIGRvIG5vdCBzaG93IG1lc3NhZ2UsICBpZiBwcmV2aW9zIG1lc3NhZ2Ugd2FzIG5vdCBoaWRlZCAobm90IGFwcGx5IGlmICd3aGVyZScgICA6ICdpbnNpZGUnIClcclxuICpcdFx0XHRcdH07XHJcbiAqIEV4YW1wbGVzOlxyXG4gKiBcdFx0XHR2YXIgaHRtbF9pZCA9IHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoICdZb3UgY2FuIHRlc3QgZGF5cyBzZWxlY3Rpb24gaW4gY2FsZW5kYXInLCB7fSApO1xyXG4gKlxyXG4gKlx0XHRcdHZhciBub3RpY2VfbWVzc2FnZV9pZCA9IHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoIG1lc3NhZ2VfdmVyaWZfcmVxdXJlZCwgeyAndHlwZSc6ICd3YXJuaW5nJywgJ2RlbGF5JzogMTAwMDAsICdpZl92aXNpYmxlX25vdF9zaG93JzogdHJ1ZSxcclxuICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgJ3Nob3dfaGVyZSc6IHsnd2hlcmUnOiAncmlnaHQnLCAnanFfbm9kZSc6IGVsLH0gfSApO1xyXG4gKlxyXG4gKlx0XHRcdHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoIHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZScgXS5yZXBsYWNlKCAvXFxuL2csIFwiPGJyIC8+XCIgKSxcclxuICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0eyAgICd0eXBlJyAgICAgOiAoICd1bmRlZmluZWQnICE9PSB0eXBlb2YoIHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZV9zdGF0dXMnIF0gKSApXHJcbiAqXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICA/IHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZV9zdGF0dXMnIF0gOiAnaW5mbycsXHJcbiAqXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3Nob3dfaGVyZSc6IHsnanFfbm9kZSc6IGpxX25vZGUsICd3aGVyZSc6ICdhZnRlcid9LFxyXG4gKlx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdjc3NfY2xhc3MnOid3cGJjX2ZlX21lc3NhZ2VfYWx0JyxcclxuICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnZGVsYXknICAgIDogMTAwMDBcclxuICpcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG4gKlxyXG4gKlxyXG4gKiBAcmV0dXJucyBzdHJpbmcgIC0gSFRNTCBJRFx0XHRvciAwIGlmIG5vdCBzaG93aW5nIGR1cmluZyB0aGlzIHRpbWUuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlKCBtZXNzYWdlLCBwYXJhbXMgPSB7fSApe1xyXG5cclxuXHR2YXIgcGFyYW1zX2RlZmF1bHQgPSB7XHJcblx0XHRcdFx0XHRcdFx0XHQndHlwZScgICAgIDogJ3dhcm5pbmcnLFx0XHRcdFx0XHRcdFx0Ly8gJ2Vycm9yJyB8ICd3YXJuaW5nJyB8ICdpbmZvJyB8ICdzdWNjZXNzJ1xyXG5cdFx0XHRcdFx0XHRcdFx0J3Nob3dfaGVyZScgOiB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2pxX25vZGUnIDogJycsXHRcdFx0XHQvLyBhbnkgalF1ZXJ5IG5vZGUgZGVmaW5pdGlvblxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd3aGVyZScgICA6ICdpbnNpZGUnXHRcdC8vICdpbnNpZGUnIHwgJ2JlZm9yZScgfCAnYWZ0ZXInIHwgJ3JpZ2h0JyB8ICdsZWZ0J1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICB9LFxyXG5cdFx0XHRcdFx0XHRcdFx0J2lzX2FwcGVuZCc6IHRydWUsXHRcdFx0XHRcdFx0XHRcdC8vIEFwcGx5ICBvbmx5IGlmIFx0J3doZXJlJyAgIDogJ2luc2lkZSdcclxuXHRcdFx0XHRcdFx0XHRcdCdzdHlsZScgICAgOiAndGV4dC1hbGlnbjpsZWZ0OycsXHRcdFx0XHQvLyBzdHlsZXMsIGlmIG5lZWRlZFxyXG5cdFx0XHRcdFx0XHRcdCAgICAnY3NzX2NsYXNzJzogJycsXHRcdFx0XHRcdFx0XHRcdC8vIEZvciBleGFtcGxlIGNhbiAgYmU6ICd3cGJjX2ZlX21lc3NhZ2VfYWx0J1xyXG5cdFx0XHRcdFx0XHRcdFx0J2RlbGF5JyAgICA6IDAsXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaG93IG1hbnkgbWljcm9zZWNvbmQgdG8gIHNob3csICBpZiAwICB0aGVuICBzaG93IGZvcmV2ZXJcclxuXHRcdFx0XHRcdFx0XHRcdCdpZl92aXNpYmxlX25vdF9zaG93JzogZmFsc2UsXHRcdFx0XHRcdC8vIGlmIHRydWUsICB0aGVuIGRvIG5vdCBzaG93IG1lc3NhZ2UsICBpZiBwcmV2aW9zIG1lc3NhZ2Ugd2FzIG5vdCBoaWRlZCAobm90IGFwcGx5IGlmICd3aGVyZScgICA6ICdpbnNpZGUnIClcclxuXHRcdFx0XHRcdFx0XHRcdCdpc19zY3JvbGwnOiB0cnVlXHRcdFx0XHRcdFx0XHRcdC8vIGlzIHNjcm9sbCAgdG8gIHRoaXMgZWxlbWVudFxyXG5cdFx0XHRcdFx0XHR9O1xyXG5cdGZvciAoIHZhciBwX2tleSBpbiBwYXJhbXMgKXtcclxuXHRcdHBhcmFtc19kZWZhdWx0WyBwX2tleSBdID0gcGFyYW1zWyBwX2tleSBdO1xyXG5cdH1cclxuXHRwYXJhbXMgPSBwYXJhbXNfZGVmYXVsdDtcclxuXHJcbiAgICB2YXIgdW5pcXVlX2Rpdl9pZCA9IG5ldyBEYXRlKCk7XHJcbiAgICB1bmlxdWVfZGl2X2lkID0gJ3dwYmNfbm90aWNlXycgKyB1bmlxdWVfZGl2X2lkLmdldFRpbWUoKTtcclxuXHJcblx0cGFyYW1zWydjc3NfY2xhc3MnXSArPSAnIHdwYmNfZmVfbWVzc2FnZSc7XHJcblx0aWYgKCBwYXJhbXNbJ3R5cGUnXSA9PSAnZXJyb3InICl7XHJcblx0XHRwYXJhbXNbJ2Nzc19jbGFzcyddICs9ICcgd3BiY19mZV9tZXNzYWdlX2Vycm9yJztcclxuXHRcdG1lc3NhZ2UgPSAnPGkgY2xhc3M9XCJtZW51X2ljb24gaWNvbi0xeCB3cGJjX2ljbl9yZXBvcnRfZ21haWxlcnJvcnJlZFwiPjwvaT4nICsgbWVzc2FnZTtcclxuXHR9XHJcblx0aWYgKCBwYXJhbXNbJ3R5cGUnXSA9PSAnd2FybmluZycgKXtcclxuXHRcdHBhcmFtc1snY3NzX2NsYXNzJ10gKz0gJyB3cGJjX2ZlX21lc3NhZ2Vfd2FybmluZyc7XHJcblx0XHRtZXNzYWdlID0gJzxpIGNsYXNzPVwibWVudV9pY29uIGljb24tMXggd3BiY19pY25fd2FybmluZ1wiPjwvaT4nICsgbWVzc2FnZTtcclxuXHR9XHJcblx0aWYgKCBwYXJhbXNbJ3R5cGUnXSA9PSAnaW5mbycgKXtcclxuXHRcdHBhcmFtc1snY3NzX2NsYXNzJ10gKz0gJyB3cGJjX2ZlX21lc3NhZ2VfaW5mbyc7XHJcblx0fVxyXG5cdGlmICggcGFyYW1zWyd0eXBlJ10gPT0gJ3N1Y2Nlc3MnICl7XHJcblx0XHRwYXJhbXNbJ2Nzc19jbGFzcyddICs9ICcgd3BiY19mZV9tZXNzYWdlX3N1Y2Nlc3MnO1xyXG5cdFx0bWVzc2FnZSA9ICc8aSBjbGFzcz1cIm1lbnVfaWNvbiBpY29uLTF4IHdwYmNfaWNuX2RvbmVfb3V0bGluZVwiPjwvaT4nICsgbWVzc2FnZTtcclxuXHR9XHJcblxyXG5cdHZhciBzY3JvbGxfdG9fZWxlbWVudCA9ICc8ZGl2IGlkPVwiJyArIHVuaXF1ZV9kaXZfaWQgKyAnX3Njcm9sbFwiIHN0eWxlPVwiZGlzcGxheTpub25lO1wiPjwvZGl2Pic7XHJcblx0bWVzc2FnZSA9ICc8ZGl2IGlkPVwiJyArIHVuaXF1ZV9kaXZfaWQgKyAnXCIgY2xhc3M9XCJ3cGJjX2Zyb250X2VuZF9fbWVzc2FnZSAnICsgcGFyYW1zWydjc3NfY2xhc3MnXSArICdcIiBzdHlsZT1cIicgKyBwYXJhbXNbICdzdHlsZScgXSArICdcIj4nICsgbWVzc2FnZSArICc8L2Rpdj4nO1xyXG5cclxuXHJcblx0dmFyIGpxX2VsX21lc3NhZ2UgPSBmYWxzZTtcclxuXHR2YXIgaXNfc2hvd19tZXNzYWdlID0gdHJ1ZTtcclxuXHJcblx0aWYgKCAnaW5zaWRlJyA9PT0gcGFyYW1zWyAnc2hvd19oZXJlJyBdWyAnd2hlcmUnIF0gKXtcclxuXHJcblx0XHRpZiAoIHBhcmFtc1sgJ2lzX2FwcGVuZCcgXSApe1xyXG5cdFx0XHRqUXVlcnkoIHBhcmFtc1sgJ3Nob3dfaGVyZScgXVsgJ2pxX25vZGUnIF0gKS5hcHBlbmQoIHNjcm9sbF90b19lbGVtZW50ICk7XHJcblx0XHRcdGpRdWVyeSggcGFyYW1zWyAnc2hvd19oZXJlJyBdWyAnanFfbm9kZScgXSApLmFwcGVuZCggbWVzc2FnZSApO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0alF1ZXJ5KCBwYXJhbXNbICdzaG93X2hlcmUnIF1bICdqcV9ub2RlJyBdICkuaHRtbCggc2Nyb2xsX3RvX2VsZW1lbnQgKyBtZXNzYWdlICk7XHJcblx0XHR9XHJcblxyXG5cdH0gZWxzZSBpZiAoICdiZWZvcmUnID09PSBwYXJhbXNbICdzaG93X2hlcmUnIF1bICd3aGVyZScgXSApe1xyXG5cclxuXHRcdGpxX2VsX21lc3NhZ2UgPSBqUXVlcnkoIHBhcmFtc1sgJ3Nob3dfaGVyZScgXVsgJ2pxX25vZGUnIF0gKS5zaWJsaW5ncyggJ1tpZF49XCJ3cGJjX25vdGljZV9cIl0nICk7XHJcblx0XHRpZiAoIChwYXJhbXNbICdpZl92aXNpYmxlX25vdF9zaG93JyBdKSAmJiAoanFfZWxfbWVzc2FnZS5pcyggJzp2aXNpYmxlJyApKSApe1xyXG5cdFx0XHRpc19zaG93X21lc3NhZ2UgPSBmYWxzZTtcclxuXHRcdFx0dW5pcXVlX2Rpdl9pZCA9IGpRdWVyeSgganFfZWxfbWVzc2FnZS5nZXQoIDAgKSApLmF0dHIoICdpZCcgKTtcclxuXHRcdH1cclxuXHRcdGlmICggaXNfc2hvd19tZXNzYWdlICl7XHJcblx0XHRcdGpRdWVyeSggcGFyYW1zWyAnc2hvd19oZXJlJyBdWyAnanFfbm9kZScgXSApLmJlZm9yZSggc2Nyb2xsX3RvX2VsZW1lbnQgKTtcclxuXHRcdFx0alF1ZXJ5KCBwYXJhbXNbICdzaG93X2hlcmUnIF1bICdqcV9ub2RlJyBdICkuYmVmb3JlKCBtZXNzYWdlICk7XHJcblx0XHR9XHJcblxyXG5cdH0gZWxzZSBpZiAoICdhZnRlcicgPT09IHBhcmFtc1sgJ3Nob3dfaGVyZScgXVsgJ3doZXJlJyBdICl7XHJcblxyXG5cdFx0anFfZWxfbWVzc2FnZSA9IGpRdWVyeSggcGFyYW1zWyAnc2hvd19oZXJlJyBdWyAnanFfbm9kZScgXSApLm5leHRBbGwoICdbaWRePVwid3BiY19ub3RpY2VfXCJdJyApO1xyXG5cdFx0aWYgKCAocGFyYW1zWyAnaWZfdmlzaWJsZV9ub3Rfc2hvdycgXSkgJiYgKGpxX2VsX21lc3NhZ2UuaXMoICc6dmlzaWJsZScgKSkgKXtcclxuXHRcdFx0aXNfc2hvd19tZXNzYWdlID0gZmFsc2U7XHJcblx0XHRcdHVuaXF1ZV9kaXZfaWQgPSBqUXVlcnkoIGpxX2VsX21lc3NhZ2UuZ2V0KCAwICkgKS5hdHRyKCAnaWQnICk7XHJcblx0XHR9XHJcblx0XHRpZiAoIGlzX3Nob3dfbWVzc2FnZSApe1xyXG5cdFx0XHRqUXVlcnkoIHBhcmFtc1sgJ3Nob3dfaGVyZScgXVsgJ2pxX25vZGUnIF0gKS5iZWZvcmUoIHNjcm9sbF90b19lbGVtZW50ICk7XHRcdC8vIFdlIG5lZWQgdG8gIHNldCAgaGVyZSBiZWZvcmUoZm9yIGhhbmR5IHNjcm9sbClcclxuXHRcdFx0alF1ZXJ5KCBwYXJhbXNbICdzaG93X2hlcmUnIF1bICdqcV9ub2RlJyBdICkuYWZ0ZXIoIG1lc3NhZ2UgKTtcclxuXHRcdH1cclxuXHJcblx0fSBlbHNlIGlmICggJ3JpZ2h0JyA9PT0gcGFyYW1zWyAnc2hvd19oZXJlJyBdWyAnd2hlcmUnIF0gKXtcclxuXHJcblx0XHRqcV9lbF9tZXNzYWdlID0galF1ZXJ5KCBwYXJhbXNbICdzaG93X2hlcmUnIF1bICdqcV9ub2RlJyBdICkubmV4dEFsbCggJy53cGJjX2Zyb250X2VuZF9fbWVzc2FnZV9jb250YWluZXJfcmlnaHQnICkuZmluZCggJ1tpZF49XCJ3cGJjX25vdGljZV9cIl0nICk7XHJcblx0XHRpZiAoIChwYXJhbXNbICdpZl92aXNpYmxlX25vdF9zaG93JyBdKSAmJiAoanFfZWxfbWVzc2FnZS5pcyggJzp2aXNpYmxlJyApKSApe1xyXG5cdFx0XHRpc19zaG93X21lc3NhZ2UgPSBmYWxzZTtcclxuXHRcdFx0dW5pcXVlX2Rpdl9pZCA9IGpRdWVyeSgganFfZWxfbWVzc2FnZS5nZXQoIDAgKSApLmF0dHIoICdpZCcgKTtcclxuXHRcdH1cclxuXHRcdGlmICggaXNfc2hvd19tZXNzYWdlICl7XHJcblx0XHRcdGpRdWVyeSggcGFyYW1zWyAnc2hvd19oZXJlJyBdWyAnanFfbm9kZScgXSApLmJlZm9yZSggc2Nyb2xsX3RvX2VsZW1lbnQgKTtcdFx0Ly8gV2UgbmVlZCB0byAgc2V0ICBoZXJlIGJlZm9yZShmb3IgaGFuZHkgc2Nyb2xsKVxyXG5cdFx0XHRqUXVlcnkoIHBhcmFtc1sgJ3Nob3dfaGVyZScgXVsgJ2pxX25vZGUnIF0gKS5hZnRlciggJzxkaXYgY2xhc3M9XCJ3cGJjX2Zyb250X2VuZF9fbWVzc2FnZV9jb250YWluZXJfcmlnaHRcIj4nICsgbWVzc2FnZSArICc8L2Rpdj4nICk7XHJcblx0XHR9XHJcblx0fSBlbHNlIGlmICggJ2xlZnQnID09PSBwYXJhbXNbICdzaG93X2hlcmUnIF1bICd3aGVyZScgXSApe1xyXG5cclxuXHRcdGpxX2VsX21lc3NhZ2UgPSBqUXVlcnkoIHBhcmFtc1sgJ3Nob3dfaGVyZScgXVsgJ2pxX25vZGUnIF0gKS5zaWJsaW5ncyggJy53cGJjX2Zyb250X2VuZF9fbWVzc2FnZV9jb250YWluZXJfbGVmdCcgKS5maW5kKCAnW2lkXj1cIndwYmNfbm90aWNlX1wiXScgKTtcclxuXHRcdGlmICggKHBhcmFtc1sgJ2lmX3Zpc2libGVfbm90X3Nob3cnIF0pICYmIChqcV9lbF9tZXNzYWdlLmlzKCAnOnZpc2libGUnICkpICl7XHJcblx0XHRcdGlzX3Nob3dfbWVzc2FnZSA9IGZhbHNlO1xyXG5cdFx0XHR1bmlxdWVfZGl2X2lkID0galF1ZXJ5KCBqcV9lbF9tZXNzYWdlLmdldCggMCApICkuYXR0ciggJ2lkJyApO1xyXG5cdFx0fVxyXG5cdFx0aWYgKCBpc19zaG93X21lc3NhZ2UgKXtcclxuXHRcdFx0alF1ZXJ5KCBwYXJhbXNbICdzaG93X2hlcmUnIF1bICdqcV9ub2RlJyBdICkuYmVmb3JlKCBzY3JvbGxfdG9fZWxlbWVudCApO1x0XHQvLyBXZSBuZWVkIHRvICBzZXQgIGhlcmUgYmVmb3JlKGZvciBoYW5keSBzY3JvbGwpXHJcblx0XHRcdGpRdWVyeSggcGFyYW1zWyAnc2hvd19oZXJlJyBdWyAnanFfbm9kZScgXSApLmJlZm9yZSggJzxkaXYgY2xhc3M9XCJ3cGJjX2Zyb250X2VuZF9fbWVzc2FnZV9jb250YWluZXJfbGVmdFwiPicgKyBtZXNzYWdlICsgJzwvZGl2PicgKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGlmICggICAoIGlzX3Nob3dfbWVzc2FnZSApICAmJiAgKCBwYXJzZUludCggcGFyYW1zWyAnZGVsYXknIF0gKSA+IDAgKSAgICl7XHJcblx0XHR2YXIgY2xvc2VkX3RpbWVyID0gc2V0VGltZW91dCggZnVuY3Rpb24gKCl7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0alF1ZXJ5KCAnIycgKyB1bmlxdWVfZGl2X2lkICkuZmFkZU91dCggMTUwMCApO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0gLCBwYXJzZUludCggcGFyYW1zWyAnZGVsYXknIF0gKSAgICk7XHJcblxyXG5cdFx0dmFyIGNsb3NlZF90aW1lcjIgPSBzZXRUaW1lb3V0KCBmdW5jdGlvbiAoKXtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGpRdWVyeSggJyMnICsgdW5pcXVlX2Rpdl9pZCApLnRyaWdnZXIoICdoaWRlJyApO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0sICggcGFyc2VJbnQoIHBhcmFtc1sgJ2RlbGF5JyBdICkgKyAxNTAxICkgKTtcclxuXHR9XHJcblxyXG5cdC8vIENoZWNrICBpZiBzaG93ZWQgbWVzc2FnZSBpbiBzb21lIGhpZGRlbiBwYXJlbnQgc2VjdGlvbiBhbmQgc2hvdyBpdC4gQnV0IGl0IG11c3QgIGJlIGxvd2VyIHRoYW4gJy53cGJjX2NvbnRhaW5lcidcclxuXHR2YXIgcGFyZW50X2VscyA9IGpRdWVyeSggJyMnICsgdW5pcXVlX2Rpdl9pZCApLnBhcmVudHMoKS5tYXAoIGZ1bmN0aW9uICgpe1xyXG5cdFx0aWYgKCAoIWpRdWVyeSggdGhpcyApLmlzKCAndmlzaWJsZScgKSkgJiYgKGpRdWVyeSggJy53cGJjX2NvbnRhaW5lcicgKS5oYXMoIHRoaXMgKSkgKXtcclxuXHRcdFx0alF1ZXJ5KCB0aGlzICkuc2hvdygpO1xyXG5cdFx0fVxyXG5cdH0gKTtcclxuXHJcblx0aWYgKCBwYXJhbXNbICdpc19zY3JvbGwnIF0gKXtcclxuXHRcdHdwYmNfZG9fc2Nyb2xsKCAnIycgKyB1bmlxdWVfZGl2X2lkICsgJ19zY3JvbGwnICk7XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gdW5pcXVlX2Rpdl9pZDtcclxufVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogRXJyb3IgbWVzc2FnZS4gXHRQcmVzZXQgb2YgcGFyYW1ldGVycyBmb3IgcmVhbCBtZXNzYWdlIGZ1bmN0aW9uLlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGVsXHRcdC0gYW55IGpRdWVyeSBub2RlIGRlZmluaXRpb25cclxuXHQgKiBAcGFyYW0gbWVzc2FnZVx0LSBNZXNzYWdlIEhUTUxcclxuXHQgKiBAcmV0dXJucyBzdHJpbmcgIC0gSFRNTCBJRFx0XHRvciAwIGlmIG5vdCBzaG93aW5nIGR1cmluZyB0aGlzIHRpbWUuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZV9fZXJyb3IoIGpxX25vZGUsIG1lc3NhZ2UgKXtcclxuXHJcblx0XHR2YXIgbm90aWNlX21lc3NhZ2VfaWQgPSB3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlKFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1lc3NhZ2UsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0e1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3R5cGUnICAgICAgICAgICAgICAgOiAnZXJyb3InLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2RlbGF5JyAgICAgICAgICAgICAgOiAxMDAwMCxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdpZl92aXNpYmxlX25vdF9zaG93JzogdHJ1ZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzaG93X2hlcmUnICAgICAgICAgIDoge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doZXJlJyAgOiAncmlnaHQnLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2pxX25vZGUnOiBqcV9ub2RlXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICAgfVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XHJcblx0XHRyZXR1cm4gbm90aWNlX21lc3NhZ2VfaWQ7XHJcblx0fVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogRXJyb3IgbWVzc2FnZSBVTkRFUiBlbGVtZW50LiBcdFByZXNldCBvZiBwYXJhbWV0ZXJzIGZvciByZWFsIG1lc3NhZ2UgZnVuY3Rpb24uXHJcblx0ICpcclxuXHQgKiBAcGFyYW0gZWxcdFx0LSBhbnkgalF1ZXJ5IG5vZGUgZGVmaW5pdGlvblxyXG5cdCAqIEBwYXJhbSBtZXNzYWdlXHQtIE1lc3NhZ2UgSFRNTFxyXG5cdCAqIEByZXR1cm5zIHN0cmluZyAgLSBIVE1MIElEXHRcdG9yIDAgaWYgbm90IHNob3dpbmcgZHVyaW5nIHRoaXMgdGltZS5cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlX19lcnJvcl91bmRlcl9lbGVtZW50KCBqcV9ub2RlLCBtZXNzYWdlLCBtZXNzYWdlX2RlbGF5ICl7XHJcblxyXG5cdFx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIChtZXNzYWdlX2RlbGF5KSApe1xyXG5cdFx0XHRtZXNzYWdlX2RlbGF5ID0gMFxyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBub3RpY2VfbWVzc2FnZV9pZCA9IHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0bWVzc2FnZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndHlwZScgICAgICAgICAgICAgICA6ICdlcnJvcicsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnZGVsYXknICAgICAgICAgICAgICA6IG1lc3NhZ2VfZGVsYXksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnaWZfdmlzaWJsZV9ub3Rfc2hvdyc6IHRydWUsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc2hvd19oZXJlJyAgICAgICAgICA6IHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd3aGVyZScgIDogJ2FmdGVyJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdqcV9ub2RlJzoganFfbm9kZVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQpO1xyXG5cdFx0cmV0dXJuIG5vdGljZV9tZXNzYWdlX2lkO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIEVycm9yIG1lc3NhZ2UgVU5ERVIgZWxlbWVudC4gXHRQcmVzZXQgb2YgcGFyYW1ldGVycyBmb3IgcmVhbCBtZXNzYWdlIGZ1bmN0aW9uLlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGVsXHRcdC0gYW55IGpRdWVyeSBub2RlIGRlZmluaXRpb25cclxuXHQgKiBAcGFyYW0gbWVzc2FnZVx0LSBNZXNzYWdlIEhUTUxcclxuXHQgKiBAcmV0dXJucyBzdHJpbmcgIC0gSFRNTCBJRFx0XHRvciAwIGlmIG5vdCBzaG93aW5nIGR1cmluZyB0aGlzIHRpbWUuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZV9fZXJyb3JfYWJvdmVfZWxlbWVudCgganFfbm9kZSwgbWVzc2FnZSwgbWVzc2FnZV9kZWxheSApe1xyXG5cclxuXHRcdGlmICggJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiAobWVzc2FnZV9kZWxheSkgKXtcclxuXHRcdFx0bWVzc2FnZV9kZWxheSA9IDEwMDAwXHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIG5vdGljZV9tZXNzYWdlX2lkID0gd3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZShcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRtZXNzYWdlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd0eXBlJyAgICAgICAgICAgICAgIDogJ2Vycm9yJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdkZWxheScgICAgICAgICAgICAgIDogbWVzc2FnZV9kZWxheSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdpZl92aXNpYmxlX25vdF9zaG93JzogdHJ1ZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzaG93X2hlcmUnICAgICAgICAgIDoge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doZXJlJyAgOiAnYmVmb3JlJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdqcV9ub2RlJzoganFfbm9kZVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQpO1xyXG5cdFx0cmV0dXJuIG5vdGljZV9tZXNzYWdlX2lkO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFdhcm5pbmcgbWVzc2FnZS4gXHRQcmVzZXQgb2YgcGFyYW1ldGVycyBmb3IgcmVhbCBtZXNzYWdlIGZ1bmN0aW9uLlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGVsXHRcdC0gYW55IGpRdWVyeSBub2RlIGRlZmluaXRpb25cclxuXHQgKiBAcGFyYW0gbWVzc2FnZVx0LSBNZXNzYWdlIEhUTUxcclxuXHQgKiBAcmV0dXJucyBzdHJpbmcgIC0gSFRNTCBJRFx0XHRvciAwIGlmIG5vdCBzaG93aW5nIGR1cmluZyB0aGlzIHRpbWUuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZV9fd2FybmluZygganFfbm9kZSwgbWVzc2FnZSApe1xyXG5cclxuXHRcdHZhciBub3RpY2VfbWVzc2FnZV9pZCA9IHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0bWVzc2FnZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndHlwZScgICAgICAgICAgICAgICA6ICd3YXJuaW5nJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdkZWxheScgICAgICAgICAgICAgIDogMTAwMDAsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnaWZfdmlzaWJsZV9ub3Rfc2hvdyc6IHRydWUsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc2hvd19oZXJlJyAgICAgICAgICA6IHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd3aGVyZScgIDogJ3JpZ2h0JyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdqcV9ub2RlJzoganFfbm9kZVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQpO1xyXG5cdFx0cmV0dXJuIG5vdGljZV9tZXNzYWdlX2lkO1xyXG5cdH1cclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIFdhcm5pbmcgbWVzc2FnZSBVTkRFUiBlbGVtZW50LiBcdFByZXNldCBvZiBwYXJhbWV0ZXJzIGZvciByZWFsIG1lc3NhZ2UgZnVuY3Rpb24uXHJcblx0ICpcclxuXHQgKiBAcGFyYW0gZWxcdFx0LSBhbnkgalF1ZXJ5IG5vZGUgZGVmaW5pdGlvblxyXG5cdCAqIEBwYXJhbSBtZXNzYWdlXHQtIE1lc3NhZ2UgSFRNTFxyXG5cdCAqIEByZXR1cm5zIHN0cmluZyAgLSBIVE1MIElEXHRcdG9yIDAgaWYgbm90IHNob3dpbmcgZHVyaW5nIHRoaXMgdGltZS5cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlX193YXJuaW5nX3VuZGVyX2VsZW1lbnQoIGpxX25vZGUsIG1lc3NhZ2UgKXtcclxuXHJcblx0XHR2YXIgbm90aWNlX21lc3NhZ2VfaWQgPSB3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlKFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1lc3NhZ2UsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0e1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3R5cGUnICAgICAgICAgICAgICAgOiAnd2FybmluZycsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnZGVsYXknICAgICAgICAgICAgICA6IDEwMDAwLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2lmX3Zpc2libGVfbm90X3Nob3cnOiB0cnVlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3Nob3dfaGVyZScgICAgICAgICAgOiB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnd2hlcmUnICA6ICdhZnRlcicsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnanFfbm9kZSc6IGpxX25vZGVcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgICB9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcclxuXHRcdHJldHVybiBub3RpY2VfbWVzc2FnZV9pZDtcclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBXYXJuaW5nIG1lc3NhZ2UgQUJPVkUgZWxlbWVudC4gXHRQcmVzZXQgb2YgcGFyYW1ldGVycyBmb3IgcmVhbCBtZXNzYWdlIGZ1bmN0aW9uLlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGVsXHRcdC0gYW55IGpRdWVyeSBub2RlIGRlZmluaXRpb25cclxuXHQgKiBAcGFyYW0gbWVzc2FnZVx0LSBNZXNzYWdlIEhUTUxcclxuXHQgKiBAcmV0dXJucyBzdHJpbmcgIC0gSFRNTCBJRFx0XHRvciAwIGlmIG5vdCBzaG93aW5nIGR1cmluZyB0aGlzIHRpbWUuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZV9fd2FybmluZ19hYm92ZV9lbGVtZW50KCBqcV9ub2RlLCBtZXNzYWdlICl7XHJcblxyXG5cdFx0dmFyIG5vdGljZV9tZXNzYWdlX2lkID0gd3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZShcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRtZXNzYWdlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd0eXBlJyAgICAgICAgICAgICAgIDogJ3dhcm5pbmcnLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2RlbGF5JyAgICAgICAgICAgICAgOiAxMDAwMCxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdpZl92aXNpYmxlX25vdF9zaG93JzogdHJ1ZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzaG93X2hlcmUnICAgICAgICAgIDoge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doZXJlJyAgOiAnYmVmb3JlJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdqcV9ub2RlJzoganFfbm9kZVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgIH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQpO1xyXG5cdFx0cmV0dXJuIG5vdGljZV9tZXNzYWdlX2lkO1xyXG5cdH1cclxuXHJcblxyXG4vKipcclxuICogU2Nyb2xsIHRvIHNwZWNpZmljIGVsZW1lbnRcclxuICpcclxuICogQHBhcmFtIGpxX25vZGVcdFx0XHRcdFx0c3RyaW5nIG9yIGpRdWVyeSBlbGVtZW50LCAgd2hlcmUgc2Nyb2xsICB0b1xyXG4gKiBAcGFyYW0gZXh0cmFfc2hpZnRfb2Zmc2V0XHRcdGludCBzaGlmdCBvZmZzZXQgZnJvbSAganFfbm9kZVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19kb19zY3JvbGwoIGpxX25vZGUgLCBleHRyYV9zaGlmdF9vZmZzZXQgPSAwICl7XHJcblxyXG5cdGlmICggIWpRdWVyeSgganFfbm9kZSApLmxlbmd0aCApe1xyXG5cdFx0cmV0dXJuO1xyXG5cdH1cclxuXHR2YXIgdGFyZ2V0T2Zmc2V0ID0galF1ZXJ5KCBqcV9ub2RlICkub2Zmc2V0KCkudG9wO1xyXG5cclxuXHRpZiAoIHRhcmdldE9mZnNldCA8PSAwICl7XHJcblx0XHRpZiAoIDAgIT0galF1ZXJ5KCBqcV9ub2RlICkubmV4dEFsbCggJzp2aXNpYmxlJyApLmxlbmd0aCApe1xyXG5cdFx0XHR0YXJnZXRPZmZzZXQgPSBqUXVlcnkoIGpxX25vZGUgKS5uZXh0QWxsKCAnOnZpc2libGUnICkuZmlyc3QoKS5vZmZzZXQoKS50b3A7XHJcblx0XHR9IGVsc2UgaWYgKCAwICE9IGpRdWVyeSgganFfbm9kZSApLnBhcmVudCgpLm5leHRBbGwoICc6dmlzaWJsZScgKS5sZW5ndGggKXtcclxuXHRcdFx0dGFyZ2V0T2Zmc2V0ID0galF1ZXJ5KCBqcV9ub2RlICkucGFyZW50KCkubmV4dEFsbCggJzp2aXNpYmxlJyApLmZpcnN0KCkub2Zmc2V0KCkudG9wO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0aWYgKCBqUXVlcnkoICcjd3BhZG1pbmJhcicgKS5sZW5ndGggPiAwICl7XHJcblx0XHR0YXJnZXRPZmZzZXQgPSB0YXJnZXRPZmZzZXQgLSA1MCAtIDUwO1xyXG5cdH0gZWxzZSB7XHJcblx0XHR0YXJnZXRPZmZzZXQgPSB0YXJnZXRPZmZzZXQgLSAyMCAtIDUwO1xyXG5cdH1cclxuXHR0YXJnZXRPZmZzZXQgKz0gZXh0cmFfc2hpZnRfb2Zmc2V0O1xyXG5cclxuXHQvLyBTY3JvbGwgb25seSAgaWYgd2UgZGlkIG5vdCBzY3JvbGwgYmVmb3JlXHJcblx0aWYgKCAhIGpRdWVyeSggJ2h0bWwsYm9keScgKS5pcyggJzphbmltYXRlZCcgKSApe1xyXG5cdFx0alF1ZXJ5KCAnaHRtbCxib2R5JyApLmFuaW1hdGUoIHtzY3JvbGxUb3A6IHRhcmdldE9mZnNldH0sIDUwMCApO1xyXG5cdH1cclxufVxyXG5cclxuIl0sImZpbGUiOiJfZGlzdC9hbGwvX291dC93cGJjX2FsbC5qcyJ9;
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/js/client.js?ver=9.8.12 
var date_approved = [];
var date2approve = [];


////////////////////////////////////////////////////////////////////////////
// Days Selections - support functions
////////////////////////////////////////////////////////////////////////////

/**
 * Get first day of selection
 *
 * @param dates
 * @returns {string|*}
 */
function get_first_day_of_selection(dates) {

    // Multiple days selections
    if ( dates.indexOf( ',' ) != -1 ){
        var dates_array = dates.split( /,\s*/ );
        var length = dates_array.length;
        var element = null;
        var new_dates_array = [];

        for ( var i = 0; i < length; i++ ){

            element = dates_array[ i ].split( /\./ );

            new_dates_array[ new_dates_array.length ] = element[ 2 ] + '.' + element[ 1 ] + '.' + element[ 0 ];       //2013.12.20
        }
        new_dates_array.sort();

        element = new_dates_array[ 0 ].split( /\./ );

        return element[ 2 ] + '.' + element[ 1 ] + '.' + element[ 0 ];                    //20.12.2013
    }

    // Range days selection
    if ( dates.indexOf( ' - ' ) != -1 ){
        var start_end_date = dates.split( " - " );
        return start_end_date[ 0 ];
    }

    // Single day selection
    return dates;                                                               //20.12.2013
}

// Get last day of selection
function get_last_day_of_selection(dates) {

    // Multiple days selections
    if ( dates.indexOf(',') != -1 ){
        var dates_array =dates.split(/,\s*/);
        var length = dates_array.length;
        var element = null;
        var new_dates_array = [];

        for (var i = 0; i < length; i++) {

          element = dates_array[i].split(/\./);

          new_dates_array[new_dates_array.length] = element[2]+'.' + element[1]+'.' + element[0];       //2013.12.20
        }
        new_dates_array.sort();

        element = new_dates_array[(new_dates_array.length-1)].split(/\./);

        return element[2]+'.' + element[1]+'.' + element[0];                    //20.12.2013
    }

    // Range days selection
    if ( dates.indexOf(' - ') != -1 ){
        var start_end_date = dates.split(" - ");
        return start_end_date[(start_end_date.length-1)];
    }

    // Single day selection
    return dates;                                                               //20.12.2013
}


/**
 * Check ID of selected additional calendars
 *
 * @param int bk_type
 * @returns array
 */
function wpbc_get_arr_of_selected_additional_calendars( bk_type ){                                                      //FixIn: 8.5.2.26

    var selected_additionl_calendars = [];

    // Checking according additional calendars
    if ( document.getElementById( 'additional_calendars' + bk_type ) != null ){

        var id_additional_str = document.getElementById( 'additional_calendars' + bk_type ).value;
        var id_additional_arr = id_additional_str.split( ',' );

        var is_all_additional_days_unselected = true;

        for ( var ia = 0; ia < id_additional_arr.length; ia++ ){
            if ( document.getElementById( 'date_booking' + id_additional_arr[ ia ] ).value != '' ){
                selected_additionl_calendars.push( id_additional_arr[ ia ] );
            }
        }
    }
    return selected_additionl_calendars;
}

////////////////////////////////////////////////////////////////////////////
// Submit Booking Data
////////////////////////////////////////////////////////////////////////////

// Check fields at form and then send request
function mybooking_submit( submit_form , bk_type, wpdev_active_locale){

    var target_elm = jQuery( ".booking_form_div" ).trigger( "booking_form_submit_click", [bk_type, submit_form, wpdev_active_locale] );     //FixIn: 8.8.3.13
    if  (
            ( jQuery( target_elm ).find( 'input[name="booking_form_show_summary"]' ).length > 0 )
         && ( 'pause_submit' === jQuery( target_elm ).find( 'input[name="booking_form_show_summary"]' ).val() )
        )
    {
        return false;
    }

    //FixIn: 8.4.0.2
    var is_error = wpbc_check_errors_in_booking_form( bk_type );
    if ( is_error ) { return false; }

    // Show message if no selected days in Calendar(s)
    if (document.getElementById('date_booking' + bk_type).value == '')  {

        var arr_of_selected_additional_calendars = wpbc_get_arr_of_selected_additional_calendars( bk_type );            //FixIn: 8.5.2.26

        if ( arr_of_selected_additional_calendars.length == 0 ) {
            wpbc_front_end__show_message__error_under_element( '#booking_form_div' + bk_type + ' .bk_calendar_frame', message_verif_selectdts, 3000 );
            return;
        }
    }

    var count = submit_form.elements.length;
    var formdata = '';
    var inp_value;
    var element;
    var el_type;


        //FixIn:6.1.1.3
    if( typeof( wpbc_is_this_time_selection_not_available ) == 'function' ) {

        if ( document.getElementById('date_booking' + bk_type).value == '' )  {         // Primary calendar not selected.

            if ( document.getElementById('additional_calendars' + bk_type ) != null ) { // Checking additional calendars.

                var id_additional_str = document.getElementById('additional_calendars' + bk_type).value; //Loop have to be here based on , sign
                var id_additional_arr = id_additional_str.split(',');
                var is_times_dates_ok = false;
                for ( var ia=0;ia<id_additional_arr.length;ia++ ) {
                    if (
                            ( document.getElementById('date_booking' + id_additional_arr[ia] ).value != '' )
                         && ( ! wpbc_is_this_time_selection_not_available( id_additional_arr[ia], submit_form.elements ) )
                       ){
                        is_times_dates_ok = true;
                    }
                }
                if ( ! is_times_dates_ok ) return;
            }
        } else {                                                                        //Primary calendar selected.
            if ( wpbc_is_this_time_selection_not_available( bk_type, submit_form.elements ) )
                return;
        }
    }



    // Serialize form here
    for ( var i = 0; i < count; i++ ){  //FixIn: 9.1.5.1
        element = submit_form.elements[i];

        if ( jQuery( element ).closest( '.booking_form_garbage' ).length ) {
            continue;       // Skip elements from garbage                                           //FixIn: 7.1.2.14
        }

        if (
               ( element.type !== 'button' )
            && ( element.type !== 'hidden' )
            && ( element.name !== ( 'date_booking' + bk_type ) )
            // && ( jQuery( element ).is( ':visible' ) )                                            //FixIn: 7.2.1.12.2 // Its prevent of saving hints,  and some other hidden element
        ) {           // Skip buttons and hidden element - type                                     //FixIn: 7.2.1.12


            // Get Element Value
            if ( element.type == 'checkbox' ){

                if (element.value == '') {
                    inp_value = element.checked;
                } else {
                    if (element.checked) inp_value = element.value;
                    else inp_value = '';
                }

            } else if ( element.type == 'radio' ) {

                if (element.checked) {
                    inp_value = element.value;
                } else {
                        // Check  if this radio required,  and if it does not check,  then show warning, otherwise if it is not required or some other option checked skip this loop
                        // We need to  check  it here, because radio have the several  options with  same name and type, and otherwise we will save several options with  selected and empty values.
                    if (                                                        //FixIn: 7.0.1.62
                           ( element.className.indexOf('wpdev-validates-as-required') !== -1 )
                        && ( jQuery( element ).is( ':visible' ) )                                            //FixIn: 7.2.1.12.2 // Its prevent of saving hints,  and some other hidden element
                        && ( ! jQuery(':radio[name="'+element.name+'"]', submit_form).is(":checked") ) ) {
                        wpbc_front_end__show_message__warning( element, message_verif_requred_for_radio_box );   		//FixIn: 8.5.1.3
                        return;
                    }
                    continue;
                }
            } else {
                inp_value = element.value;
            }

            // Get value in selectbox of multiple selection
            if (element.type =='select-multiple') {
                inp_value = jQuery('[name="'+element.name+'"]').val() ;
                if (( inp_value == null ) || (inp_value.toString() == '' ))
                    inp_value='';
            }

            // Make validation  only  for visible elements
            if ( jQuery( element ).is( ':visible' ) ) {                                             //FixIn: 7.2.1.12.2


                // Recheck for max num. available visitors selection
                if ( typeof (wpbc__is_less_than_required__of_max_available_slots__bl) == 'function' ){
                    if ( wpbc__is_less_than_required__of_max_available_slots__bl( bk_type, element ) ){
                        return;
                    }
                }


                // Phone validation
                /*if ( element.name == ('phone'+bk_type) ) {
                    // we validate a phone number of 10 digits with no comma, no spaces, no punctuation and there will be no + sign in front the number - See more at: http://www.w3resource.com/javascript/form/phone-no-validation.php#sthash.U9FHwcdW.dpuf
                    var reg =  /^\d{10}$/;
                    var message_verif_phone = "Please enter correctly phone number";
                    if ( inp_value != '' )
                        if(reg.test(inp_value) == false) {wpbc_front_end__show_message__warning( element , message_verif_phone );return;}
                }*/

                // Validation Check --- Requred fields
                if ( element.className.indexOf('wpdev-validates-as-required') !== -1 ){
                    if  ((element.type =='checkbox') && ( element.checked === false)) {
                        if ( ! jQuery(':checkbox[name="'+element.name+'"]', submit_form).is(":checked") ) {
                            wpbc_front_end__show_message__warning( element , message_verif_requred_for_check_box );   		//FixIn: 8.5.1.3
                            return;
                        }
                    }
                    if  (element.type =='radio') {
                        if ( ! jQuery(':radio[name="'+element.name+'"]', submit_form).is(":checked") ) {
                            wpbc_front_end__show_message__warning( element , message_verif_requred_for_radio_box );   		//FixIn: 8.5.1.3
                            return;
                        }
                    }

                    if (  (element.type != 'checkbox') && (element.type != 'radio') && ( '' === wpbc_trim( inp_value ) )  ){       //FixIn: 8.8.1.3   //FixIn:7.0.1.39       //FixIn: 8.7.11.12
                        wpbc_front_end__show_message__warning( element , message_verif_requred );   		//FixIn: 8.5.1.3
                        return;
                    }
                }

                // Validation Check --- Email correct filling field
                if ( element.className.indexOf('wpdev-validates-as-email') !== -1 ){
                    inp_value = inp_value.replace(/^\s+|\s+$/gm,'');                // Trim  white space //FixIn: 5.4.5
                    var reg = /^([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,})$/;
                    if ( inp_value != '' )
                        if(reg.test(inp_value) == false) {
                            wpbc_front_end__show_message__warning( element , message_verif_emeil );   		//FixIn: 8.5.1.3
                            return;
                        }
                }

                // Validation Check --- Same Email Field
                if ( ( element.className.indexOf('wpdev-validates-as-email') !== -1 ) && ( element.className.indexOf('same_as_') !== -1 ) ) {

                    // Get  the name of Primary Email field from the "same_as_NAME" class
                    var primary_email_name = element.className.match(/same_as_([^\s])+/gi);
                    if (primary_email_name != null) { // We found
                        primary_email_name = primary_email_name[0].substr(8);

                        // Recehck if such primary email field exist in the booking form
                        if (jQuery('[name="' + primary_email_name + bk_type + '"]').length > 0) {

                            // Recheck the values of the both emails, if they do  not equla show warning
                            if ( jQuery('[name="' + primary_email_name + bk_type + '"]').val() !== inp_value ) {
                                wpbc_front_end__show_message__warning( element , message_verif_same_emeil  );   		//FixIn: 8.5.1.3
                                return;
                            }
                        }
                    }
                    // Skip one loop for the email veryfication field
                    continue;                                                                                           //FixIn: 8.1.2.15
                }

            }

            // Get Form Data
            if ( element.name !== ('captcha_input' + bk_type) ) {
                if (formdata !=='') formdata +=  '~';                                                // next field element

                el_type = element.type;
                if ( element.className.indexOf('wpdev-validates-as-email') !== -1 )  el_type='email';
                if ( element.className.indexOf('wpdev-validates-as-coupon') !== -1 ) el_type='coupon';

                inp_value = inp_value + '';
                inp_value = inp_value.replace(new RegExp("\\^",'g'), '&#94;'); // replace registered characters
                inp_value = inp_value.replace(new RegExp("~",'g'), '&#126;'); // replace registered characters

                inp_value = inp_value.replace(/"/g, '&#34;'); // replace double quot
                inp_value = inp_value.replace(/'/g, '&#39;'); // replace single quot

                formdata += el_type + '^' + element.name + '^' + inp_value ;                    // element attr
            }
        }

    }  // End Fields Loop


    // TODO: here was function  for 'Check if visitor finish  dates selection.


    // Cpatch  verify
    var captcha = document.getElementById('wpdev_captcha_challenge_' + bk_type);

    //Disable Submit button
    if (captcha != null)  form_submit_send( bk_type, formdata, captcha.value, document.getElementById('captcha_input' + bk_type).value ,wpdev_active_locale);
    else                  form_submit_send( bk_type, formdata, '',            '' ,                                                      wpdev_active_locale);
    return;
}


// Gathering params for sending Ajax request and then send it
function form_submit_send( bk_type, formdata, captcha_chalange, user_captcha ,wpdev_active_locale){

    //document.getElementById('submiting' + bk_type).innerHTML = '<div style="height:20px;width:100%;text-align:center;margin:15px auto;"><img style="vertical-align:middle;box-shadow:none;width:14px;" src="'+wpdev_bk_plugin_url+'/assets/img/ajax-loader.gif"><//div>';

    var my_booking_form = '';
    var my_booking_hash = '';
    if (document.getElementById('booking_form_type' + bk_type) != undefined)
        my_booking_form =document.getElementById('booking_form_type' + bk_type).value;

    if ( wpdev_bk_edit_id_hash != '' ) my_booking_hash = wpdev_bk_edit_id_hash;

    var is_send_emeils = 1;
    if ( jQuery('#is_send_email_for_pending').length ) {
        is_send_emeils = jQuery( '#is_send_email_for_pending' ).is( ':checked' );       //FixIn: 8.7.9.5
        if ( false === is_send_emeils ) { is_send_emeils = 0; }
        else                            { is_send_emeils = 1; }
    }

    if ( document.getElementById('date_booking' + bk_type).value != '' )        //FixIn:6.1.1.3
        send_ajax_submit(bk_type,formdata,captcha_chalange,user_captcha,is_send_emeils,my_booking_hash,my_booking_form,wpdev_active_locale   ); // Ajax sending request
    else {
        jQuery('#booking_form_div' + bk_type ).hide();
        jQuery('#submiting' + bk_type ).hide();
    }

    var formdata_additional_arr;
    var formdata_additional;
    var my_form_field;
    var id_additional;
    var id_additional_str;
    var id_additional_arr;
    if (document.getElementById('additional_calendars' + bk_type) != null ) {

        id_additional_str = document.getElementById('additional_calendars' + bk_type).value; //Loop have to be here based on , sign
        id_additional_arr = id_additional_str.split(',');


        //TODO: remove this spinner and add the new !!!
        //FixIn: 8.5.2.26
        if ( ! jQuery( '#booking_form_div' + bk_type ).is( ':visible' ) ) {
            jQuery( '#booking_form_div' + bk_type ).after(
                '<div class="wpbc_submit_spinner" style="height:20px;width:100%;text-align:center;margin:15px auto;"><img style="vertical-align:middle;box-shadow:none;width:14px;" src="'+wpdev_bk_plugin_url+'/assets/img/ajax-loader.gif"></div>'
            );
        }



        for (var ia=0;ia<id_additional_arr.length;ia++) {
            formdata_additional_arr = formdata;
            formdata_additional = '';
            id_additional = id_additional_arr[ia];


            formdata_additional_arr = formdata_additional_arr.split('~');
            for (var j=0;j<formdata_additional_arr.length;j++) {
                my_form_field = formdata_additional_arr[j].split('^');
                if (formdata_additional !=='') formdata_additional +=  '~';

                if (my_form_field[1].substr( (my_form_field[1].length -2),2)=='[]')
                  my_form_field[1] = my_form_field[1].substr(0, (my_form_field[1].length - (''+bk_type).length ) - 2 ) + id_additional + '[]';
                else
                  my_form_field[1] = my_form_field[1].substr(0, (my_form_field[1].length - (''+bk_type).length ) ) + id_additional ;


                formdata_additional += my_form_field[0] + '^' + my_form_field[1] + '^' + my_form_field[2];
            }

            if ( jQuery('#gateway_payment_forms' + bk_type).length > 0 ) {         // If Payment form  for main  booking resources is showing then append payment form  for additional  calendars.
                jQuery('#gateway_payment_forms' + bk_type).after('<div id="gateway_payment_forms'+id_additional+'"></div>');
                jQuery('#gateway_payment_forms' + bk_type).after('<div id="ajax_respond_insert'+id_additional+'" style="display:none;"></div>');
            }
            //FixIn: 8.5.2.17
            send_ajax_submit( id_additional ,formdata_additional,captcha_chalange,user_captcha,is_send_emeils,my_booking_hash,my_booking_form ,wpdev_active_locale  );  // Submit
        }
    }
}


//<![CDATA[
function send_ajax_submit( resource_id, formdata, captcha_chalange, user_captcha, is_send_emeils, my_booking_hash, my_booking_form, wpdev_active_locale ){

    // Disable Submit | Show spin loader
    wpbc_booking_form__on_submit__ui_elements_disable( resource_id )


    var is_exit = wpbc_ajx_booking__create( {
                                'resource_id'              : resource_id,
                                'dates_ddmmyy_csv'         : document.getElementById( 'date_booking' + resource_id ).value,
                                'formdata'                 : formdata,
                                'booking_hash'             : my_booking_hash,
                                'custom_form'              : my_booking_form,
                                'aggregate_resource_id_arr': ( ( null !== _wpbc.booking__get_param_value( resource_id, 'aggregate_resource_id_arr' ))
                                                                        ? _wpbc.booking__get_param_value( resource_id, 'aggregate_resource_id_arr' ).join( ',' ) : ''),


                                'captcha_chalange'   : captcha_chalange,
                                'captcha_user_input' : user_captcha,

                                'is_emails_send'     : is_send_emeils,
                                'active_locale'      : wpdev_active_locale
                            } );
    if ( true === is_exit ){
        return;
    }
}
//]]>

////////////////////////////////////////////////////////////////////////////


// Hint labels inside of input boxes
jQuery(document).ready( function(){

    jQuery('div.inside_hint').on( 'click', function(){                   //FixIn: 8.7.11.12
            jQuery(this).css('visibility', 'hidden').siblings('.has-inside-hint').trigger( 'focus' );   //FixIn: 8.7.11.12
    });

    jQuery('input.has-inside-hint').on( 'blur', function(){                   //FixIn: 8.7.11.12
        if ( this.value == '' )
            jQuery(this).siblings('.inside_hint').css('visibility', '');
    }).on( 'focus', function(){                                                 //FixIn: 8.7.11.12
            jQuery(this).siblings('.inside_hint').css('visibility', 'hidden');
    });

    jQuery('.booking_form_div input[type=button]').prop("disabled", false);
});



// Support Functions

//FixIn: 8.8.1.3
/**
 * Trim  strings and array joined with  (,)
 *
 * @param string_to_trim   string / array
 * @returns string
 */
function wpbc_trim( string_to_trim ){

    if ( Array.isArray( string_to_trim ) ){
        string_to_trim = string_to_trim.join( ',' );
    }

    if ( 'string' == typeof (string_to_trim) ){
        string_to_trim = string_to_trim.trim();
    }

    return string_to_trim;
}


function wpdev_in_array (array_here, p_val) {
   for(var i = 0, l = array_here.length; i < l; i++) {
       if(array_here[i] == p_val) {
           return true;
       }
   }
   return false;
}


function days_between(date1, date2) {

    // The number of milliseconds in one day
    var ONE_DAY = 1000 * 60 * 60 * 24;

    // Convert both dates to milliseconds
    var date1_ms = date1.getTime();
    var date2_ms = date2.getTime();

    // Calculate the difference in milliseconds
    var difference_ms =  date1_ms - date2_ms;

    // Convert back to days and return
    return Math.round(difference_ms/ONE_DAY);

}





//FixIn: 8.4.0.2
/**
 * Check errors in booking form  fields, and show warnings if some errors exist.
 * Check  errors,  like not selected dates or not filled requred form  fields, or not correct entering email or phone fields,  etc...
 *
 * @param bk_type  int (ID of booking resource)
 */
function wpbc_check_errors_in_booking_form( bk_type ) {

    var is_error_in_field = false;  // By default all  is good - no error

    var my_form = jQuery( '#booking_form' + bk_type );

    if ( my_form.length ) {

        var fields_with_errors_arr = [];

        // Pseudo-selector that get form elements <input , <textarea , <select, <button...
        my_form.find( ':input' ).each( function( index, el ) {

            // Skip some elements
            var skip_elements = [ 'hidden', 'button' ];

            if (  -1 == skip_elements.indexOf( jQuery( el ).attr( 'type' ) )  ){

				// Check Calendar Dates Selection
                if ( ( 'date_booking' + bk_type ) == jQuery( el ).attr( 'name' ) ) {

                    // Show Warning only  if the calendar visible ( we are at step with  calendar)
                    if (
                            (  ( jQuery( '#calendar_booking' + bk_type ).is( ':visible' )  ) && ( '' == jQuery( el ).val() )  )
                         && ( wpbc_get_arr_of_selected_additional_calendars( bk_type ).length == 0 )                    //FixIn: 8.5.2.26
                    ){            //FixIn: 8.4.4.5

                        var notice_message_id = wpbc_front_end__show_message__error_under_element( '#booking_form_div' + bk_type + ' .bk_calendar_frame', message_verif_selectdts , 3000 );

						//wpbc_do_scroll('#calendar_booking' + bk_type);            // Scroll to the calendar    		//FixIn: 8.5.1.3
						is_error_in_field = true;    // Error
                    }
                }

                // Check only visible elements at this step
                if ( jQuery( el ).is( ':visible' )  ){
// console.log( '|id, type, val, visible|::', jQuery( el ).attr( 'name' ), '|' + jQuery( el ).attr( 'type' ) + '|', jQuery( el ).val(), jQuery( el ).is( ':visible' ) );

					// Is Required
					if ( jQuery( el ).hasClass( 'wpdev-validates-as-required' ) ){

						// Checkboxes
						if ( 'checkbox' == jQuery( el ).attr( 'type' ) ){

                            if (
                                    ( ! jQuery( el ).is( ':checked' ))
                                 && ( ! jQuery( ':checkbox[name="' + el.name + '"]', my_form ).is( ":checked" ) )       //FixIn: 8.5.2.12
                            ){
                                var checkbox_parent_element;

                                if ( jQuery( el ).parents( '.wpdev-form-control-wrap' ).length > 0 ){

                                    checkbox_parent_element = jQuery( el ).parents( '.wpdev-form-control-wrap' );

                                } else if ( jQuery( el ).parents( '.controls' ).length > 0 ){

                                    checkbox_parent_element = jQuery( el ).parents( '.controls' );

                                } else {

                                    checkbox_parent_element = jQuery( el );
                                }
                                var notice_message_id = wpbc_front_end__show_message__warning( checkbox_parent_element, message_verif_requred_for_check_box );

                                fields_with_errors_arr.push( el );
								is_error_in_field = true;    // Error
							}

							// Radio boxes
						} else if ( 'radio' == jQuery( el ).attr( 'type' ) ){

							if ( !jQuery( ':radio[name="' + jQuery( el ).attr( 'name' ) + '"]', my_form ).is( ':checked' ) ){
                                var notice_message_id = wpbc_front_end__show_message__warning( jQuery( el ).parents('.wpdev-form-control-wrap'), message_verif_requred_for_radio_box );
                                fields_with_errors_arr.push( el );
								is_error_in_field = true;    // Error
							}

							// Other elements
						} else {

							var inp_value = jQuery( el ).val();

                            if ( '' === wpbc_trim( inp_value ) ){                                                       //FixIn: 8.8.1.3        //FixIn: 8.7.11.12

                                var notice_message_id = wpbc_front_end__show_message__warning( el, message_verif_requred );

                                fields_with_errors_arr.push( el );
								is_error_in_field = true;    // Error
							}
						}
					}

					// Validate Email
					if ( jQuery( el ).hasClass( 'wpdev-validates-as-email' ) ){
						var inp_value = jQuery( el ).val();
						inp_value = inp_value.replace( /^\s+|\s+$/gm, '' );                // Trim  white space //FixIn: 5.4.5
						var reg = /^([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,})$/;
						if ( (inp_value != '') && (reg.test( inp_value ) == false) ){

                            var notice_message_id = wpbc_front_end__show_message__warning( el, message_verif_emeil );
                            fields_with_errors_arr.push( el );
							is_error_in_field = true;    // Error
						}
					}

					// Validate For digit entering - for example for - Phone
					// <p>Digit Field:<br />[text* dig_field class:validate_as_digit] </p>
					// <p>Phone:<br />[text* phone class:validate_digit_8] </p>

					var classList = jQuery( el ).attr( 'class' );

					if ( classList ){

						classList = classList.split( /\s+/ );

                        jQuery.each( classList, function ( cl_index, cl_item ){

                            ////////////////////////////////////////////////////////////////////////////////////////////

                            // Validate field value as "Date"   [CSS class - 'validate_as_digit']
                            if ( 'validate_as_date' === cl_item ) {

                                // Valid values: 09-25-2018, 09/25/2018, 09-25-2018,  31-9-1918  ---   m/d/Y, m.d.Y, m-d-Y, d/m/Y, d.m.Y, d-m-Y
                                var regex = new RegExp( '^[0-3]?\\d{1}[\\/\\.\\-]+[0-3]?\\d{1}[\\/\\.\\-]+[0-2]+\\d{3}$' );       // Check for Date 09/25/2018
                                var message_verif_phone = 'This field must be valid date like this ' + '09/25/2018';
                                var inp_value = jQuery( el ).val();

                                if (  ( inp_value != '' ) && ( regex.test( inp_value ) == false )  ){
                                    wpbc_front_end__show_message__warning( el, message_verif_phone );
                                    fields_with_errors_arr.push( el );
                                    is_error_in_field = true;    // Error
                                }
                            }

                            ////////////////////////////////////////////////////////////////////////////////////////////

                            // Validate field value as "DIGIT"   [CSS class - 'validate_as_digit']
                            if ( 'validate_as_digit' === cl_item ) {

                                var regex = new RegExp( '^[0-9]+\\.?[0-9]*$' );       // Check for digits
                                var message_verif_phone = 'This field must contain only digits';
                                var inp_value = jQuery( el ).val();

                                if (  ( inp_value != '' ) && ( regex.test( inp_value ) == false )  ){
                                    wpbc_front_end__show_message__warning( el, message_verif_phone );
                                    fields_with_errors_arr.push( el );
                                    is_error_in_field = true;    // Error
                                }
                            }

                            ////////////////////////////////////////////////////////////////////////////////////////////

                            // Validate field value as "Phone" number or any other valid number wth specific number of digits [CSS class - 'validate_digit_8' || 'validate_digit_10' ]
                            var is_validate_digit = cl_item.substring( 0, 15 );

                            // Check  if class start  with 'validate_digit_'
                            if ( 'validate_digit_' === is_validate_digit ){

                                // Get  number of digit in class: validate_digit_8 => 8 or validate_digit_10 => 10
                                var digits_to_check = parseInt( cl_item.substring( 15 ) );

                                // Check  about any errors in
                                if ( !isNaN( digits_to_check ) ){

                                    var regex = new RegExp( '^\\d{' + digits_to_check + '}$' );       // We was valid it as parseInt - only integer variable - digits_to_check
                                    var message_verif_phone = 'This field must contain ' + digits_to_check + ' digits';
                                    var inp_value = jQuery( el ).val();

									if (  ( inp_value != '' ) && ( regex.test( inp_value ) == false )  ){
                                        wpbc_front_end__show_message__warning( el, message_verif_phone );
                                        fields_with_errors_arr.push( el );
                                        is_error_in_field = true;    // Error
                                    }
                                }
                            }

                            ////////////////////////////////////////////////////////////////////////////////////////////

                        });
    				}
                }
			}
        } );

        if ( fields_with_errors_arr.length > 0 ){
            jQuery( fields_with_errors_arr[ 0 ] ).trigger( 'focus' );    //FixIn: 9.3.1.9
        }
	}

    return is_error_in_field;
}


//FixIn: 8.4.4.4
function bk_calendar_step_click( el ){
    var br_id = jQuery( el ).closest( 'form' ).find( 'input[name^="bk_type"]' ).val();
    var is_error = wpbc_check_errors_in_booking_form( br_id );
    if ( is_error ){
        return false;
    }
    if ( br_id != undefined ){
        jQuery( "#booking_form" + br_id + " .bk_calendar_step" ).css( {"display": "none"} );
        jQuery( "#booking_form" + br_id + " .bk_form_step" ).css( {"display": "block"} );
    } else {
        jQuery( ".bk_calendar_step" ).css( {"display": "none"} );
        jQuery( ".bk_form_step" ).css( {"display": "block"} );
    }
}

function bk_form_step_click( el ){
    var br_id = jQuery( el ).closest( 'form' ).find( 'input[name^="bk_type"]' ).val();
    var is_error = false; // wpbc_check_errors_in_booking_form( br_id );          //FixIn: 8.4.5.6
    if ( is_error ){
        return false;
    }
    if ( br_id != undefined ){
        jQuery( "#booking_form" + br_id + " .bk_calendar_step" ).css( {"display": "block"} );
        jQuery( "#booking_form" + br_id + " .bk_form_step" ).css( {"display": "none"} );
        wpbc_do_scroll( "#bklnk" + br_id );
    } else {
        jQuery( ".bk_calendar_step" ).css( {"display": "block"} );
        jQuery( ".bk_form_step" ).css( {"display": "none"} );
    }
}

//FixIn: 8.6.1.15
/**
 * Go to next  specific step in Wizard style booking form, with
 * check all required elements specific step, otherwise show warning message!
 *
 * @param el
 * @param step_num
 * @returns {boolean}
 */
function wpbc_wizard_step( el, step_num, step_from ){
    var br_id = jQuery( el ).closest( 'form' ).find( 'input[name^="bk_type"]' ).val();

    //FixIn: 8.8.1.5
    if ( ( undefined == step_from ) || ( step_num > step_from ) ){
        if ( 1 != step_num ){                                                                       //FixIn: 8.7.7.8
            var is_error = wpbc_check_errors_in_booking_form( br_id );
            if ( is_error ){
                return false;
            }
        }
    }

    if ( wpbc_is_some_elements_visible( br_id, ['rangetime', 'durationtime', 'starttime', 'endtime'] ) ){
        if ( wpbc_is_this_time_selection_not_available( br_id, document.getElementById( 'booking_form' + br_id ) ) ){
            return false;
        }
    }

    if ( br_id != undefined ){
        jQuery( "#booking_form" + br_id + " .wpbc_wizard_step" ).css( {"display": "none"} );
        jQuery( "#booking_form" + br_id + " .wpbc_wizard_step" + step_num ).css( {"display": "block"} );
    }
}


//FixIn: 8.6.1.15
/**
 * Check if at least  one element from  array  of  elements names in booking form  visible  or not.
 * Usage Example:   if ( wpbc_is_some_elements_visible( br_id, ['rangetime', 'durationtime', 'starttime', 'endtime'] ) ){ ... }
 *
 * @param bk_type
 * @param elements_names
 * @returns {boolean}
 */
function wpbc_is_some_elements_visible( bk_type, elements_names ){

    var is_some_elements_visible = false;

    var my_form = jQuery( '#booking_form' + bk_type );

    if ( my_form.length ){

        // Pseudo-selector that get form elements <input , <textarea , <select, <button...
        my_form.find( ':input' ).each( function ( index, el ){

            // Skip some elements
            var skip_elements = ['hidden', 'button'];

            if ( -1 == skip_elements.indexOf( jQuery( el ).attr( 'type' ) ) ){

                for ( var ei = 0; ei < ( elements_names.length - 1) ; ei++ ){

                    // Check Calendar Dates Selection
                    if ( (elements_names[ ei ] + bk_type) == jQuery( el ).attr( 'name' ) ){

                        if ( jQuery( el ).is( ':visible' ) ){
                            is_some_elements_visible = true;
                        }
                    }
                }
            }
        } );
    }
    return is_some_elements_visible;
}

//FixIn: 9.2.3.4
/**
 * Select dates in calendar
 *
 * @param int       resource_id             1
 * @param array     selected_dates          [ [ 2022, "09", 20 ], [ 2022, "09", 21 ], ... ]
 */
function wpbc_select_days_in_calendar( resource_id, selected_dates ){

    //clearTimeout( timeout_DSwindow );

    var inst = jQuery.datepick._getInst( document.getElementById( 'calendar_booking' + resource_id ) );
    inst.dates = [];
    var original_array = [];
    var date;

    var bk_inputing = document.getElementById( 'date_booking' + resource_id );
    var bk_distinct_dates = [];

    if ( 0 ){                                                                   // Select  one additional day in calendar, during editing of booking  //FixIn: 6.2.3.6
        var last_selected_date = new Date();
        last_selected_date.setFullYear( parseInt( selected_dates[ selected_dates.length - 1 ][ 0 ] ) );
        last_selected_date.setMonth( parseInt( selected_dates[ selected_dates.length - 1 ][ 1 ] - 1 ) );
        last_selected_date.setDate( parseInt( selected_dates[ selected_dates.length - 1 ][ 2 ] ) );
        last_selected_date.setHours( 0 );
        last_selected_date.setMinutes( 0 );
        last_selected_date.setSeconds( 0 );
        var last_selected_next_date = new Date( last_selected_date.getTime() + 1000 * 60 * 60 * 24 );
        selected_dates.push( new Array( last_selected_next_date.getFullYear(), (last_selected_next_date.getMonth() + 1), last_selected_next_date.getDate() ) );
    }

    for ( var i = 0; i < selected_dates.length; i++ ){

        var dta = selected_dates[ i ];

        date = new Date();
        date.setFullYear( dta[ 0 ], (dta[ 1 ] - 1), dta[ 2 ] );    // get date
        original_array.push( jQuery.datepick._restrictMinMax( inst, jQuery.datepick._determineDate( inst, date, null ) ) ); //add date

        // Add leading 0 for number from 1 to 9                                                                 //FixIn: 8.0.2.2
        dta[ 2 ] = parseInt( dta[ 2 ] );
        if ( dta[ 2 ] < 10 ){
            dta[ 2 ] = '0' + dta[ 2 ];
        }
        dta[ 1 ] = parseInt( dta[ 1 ] );
        if ( dta[ 1 ] < 10 ){
            dta[ 1 ] = '0' + dta[ 1 ];
        }
        if ( !wpdev_in_array( bk_distinct_dates, dta[ 2 ] + '.' + dta[ 1 ] + '.' + dta[ 0 ] ) )
            bk_distinct_dates.push( dta[ 2 ] + '.' + dta[ 1 ] + '.' + dta[ 0 ] );
    }

    for ( var j = 0; j < original_array.length; j++ ){       //loop array of dates
        if ( original_array[ j ] != -1 ) inst.dates.push( original_array[ j ] );
    }
    var dateStr = (inst.dates.length == 0 ? '' : jQuery.datepick._formatDate( inst, inst.dates[ 0 ] )); // Get first date
    for ( i = 1; i < inst.dates.length; i++ )
        dateStr += jQuery.datepick._get( inst, 'multiSeparator' ) + jQuery.datepick._formatDate( inst, inst.dates[ i ] );  // Gathering all dates
    jQuery( '#date_booking' + resource_id ).val( dateStr ); // Fill the input box

    if ( original_array.length > 0 ){ // Set showing of start month
        inst.cursorDate = original_array[ 0 ];
        inst.drawMonth = inst.cursorDate.getMonth();
        inst.drawYear = inst.cursorDate.getFullYear();
    }

    // Update calendar
    jQuery.datepick._notifyChange( inst );
    jQuery.datepick._adjustInstDate( inst );
        jQuery.datepick._showDate( inst );
    jQuery.datepick._updateDatepick( inst );

    if ( bk_inputing != null )
        bk_inputing.value = bk_distinct_dates.join( ', ' );


    if ( typeof (check_condition_sections_in_bkform) == 'function' ){
        check_condition_sections_in_bkform( jQuery( '#date_booking' + resource_id ).val(), resource_id );
    }


    if ( typeof (showCostHintInsideBkForm) == 'function' ){
        showCostHintInsideBkForm( resource_id );
    }
};
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/includes/_capacity/_out/create_booking.js?ver=9.8.12 
"use strict"; // ---------------------------------------------------------------------------------------------------------------------
//  A j a x    A d d    N e w    B o o k i n g
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Submit new booking
 *
 * @param params   =     {
                                'resource_id'        : resource_id,
                                'dates_ddmmyy_csv'   : document.getElementById( 'date_booking' + resource_id ).value,
                                'formdata'           : formdata,
                                'booking_hash'       : my_booking_hash,
                                'custom_form'        : my_booking_form,

                                'captcha_chalange'   : captcha_chalange,
                                'captcha_user_input' : user_captcha,

                                'is_emails_send'     : is_send_emeils,
                                'active_locale'      : wpdev_active_locale
						}
 *
 */

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }

function wpbc_ajx_booking__create(params) {
  console.groupCollapsed('WPBC_AJX_BOOKING__CREATE');
  console.groupCollapsed('== Before Ajax Send ==');
  console.log(params);
  console.groupEnd();
  params = wpbc_captcha__simple__maybe_remove_in_ajx_params(params); // Start Ajax

  jQuery.post(wpbc_global1.wpbc_ajaxurl, {
    action: 'WPBC_AJX_BOOKING__CREATE',
    wpbc_ajx_user_id: _wpbc.get_secure_param('user_id'),
    nonce: _wpbc.get_secure_param('nonce'),
    wpbc_ajx_locale: _wpbc.get_secure_param('locale'),
    calendar_request_params: params
    /**
     *  Usually  params = { 'resource_id'        : resource_id,
     *						'dates_ddmmyy_csv'   : document.getElementById( 'date_booking' + resource_id ).value,
     *						'formdata'           : formdata,
     *						'booking_hash'       : my_booking_hash,
     *						'custom_form'        : my_booking_form,
     *
     *						'captcha_chalange'   : captcha_chalange,
     *						'user_captcha'       : user_captcha,
     *
     *						'is_emails_send'     : is_send_emeils,
     *						'active_locale'      : wpdev_active_locale
     *				}
     */

  },
  /**
   * S u c c e s s
   *
   * @param response_data		-	its object returned from  Ajax - class-live-searcg.php
   * @param textStatus		-	'success'
   * @param jqXHR				-	Object
   */
  function (response_data, textStatus, jqXHR) {
    console.log(' == Response WPBC_AJX_BOOKING__CREATE == ');

    for (var obj_key in response_data) {
      console.groupCollapsed('==' + obj_key + '==');
      console.log(' : ' + obj_key + ' : ', response_data[obj_key]);
      console.groupEnd();
    }

    console.groupEnd(); // <editor-fold     defaultstate="collapsed"     desc=" = Error Message! Server response with String.  ->  E_X_I_T  "  >
    // -------------------------------------------------------------------------------------------------
    // This section execute,  when server response with  String instead of Object -- Usually  it's because of mistake in code !
    // -------------------------------------------------------------------------------------------------

    if (_typeof(response_data) !== 'object' || response_data === null) {
      var calendar_id = wpbc_get_resource_id__from_ajx_post_data_url(this.data);
      var jq_node = '#booking_form' + calendar_id;

      if ('' == response_data) {
        response_data = '<strong>' + 'Error! Server respond with empty string!' + '</strong> ';
      } // Show Message


      wpbc_front_end__show_message(response_data, {
        'type': 'error',
        'show_here': {
          'jq_node': jq_node,
          'where': 'after'
        },
        'is_append': true,
        'style': 'text-align:left;',
        'delay': 0
      }); // Enable Submit | Hide spin loader

      wpbc_booking_form__on_response__ui_elements_enable(calendar_id);
      return;
    } // </editor-fold>
    // <editor-fold     defaultstate="collapsed"     desc="  ==  This section execute,  when we have KNOWN errors from Booking Calendar.  ->  E_X_I_T  "  >
    // -------------------------------------------------------------------------------------------------
    // This section execute,  when we have KNOWN errors from Booking Calendar
    // -------------------------------------------------------------------------------------------------


    if ('ok' != response_data['ajx_data']['status']) {
      switch (response_data['ajx_data']['status_error']) {
        case 'captcha_simple_wrong':
          wpbc_captcha__simple__update({
            'resource_id': response_data['resource_id'],
            'url': response_data['ajx_data']['captcha__simple']['url'],
            'challenge': response_data['ajx_data']['captcha__simple']['challenge'],
            'message': response_data['ajx_data']['ajx_after_action_message'].replace(/\n/g, "<br />")
          });
          break;

        case 'resource_id_incorrect':
          // Show Error Message - incorrect  booking resource ID during submit of booking.
          var message_id = wpbc_front_end__show_message(response_data['ajx_data']['ajx_after_action_message'].replace(/\n/g, "<br />"), {
            'type': 'undefined' !== typeof response_data['ajx_data']['ajx_after_action_message_status'] ? response_data['ajx_data']['ajx_after_action_message_status'] : 'warning',
            'delay': 0,
            'show_here': {
              'where': 'after',
              'jq_node': '#booking_form' + params['resource_id']
            }
          });
          break;

        case 'booking_can_not_save':
          // We can not save booking, because dates are booked or can not save in same booking resource all the dates
          var message_id = wpbc_front_end__show_message(response_data['ajx_data']['ajx_after_action_message'].replace(/\n/g, "<br />"), {
            'type': 'undefined' !== typeof response_data['ajx_data']['ajx_after_action_message_status'] ? response_data['ajx_data']['ajx_after_action_message_status'] : 'warning',
            'delay': 0,
            'show_here': {
              'where': 'after',
              'jq_node': '#booking_form' + params['resource_id']
            }
          }); // Enable Submit | Hide spin loader

          wpbc_booking_form__on_response__ui_elements_enable(response_data['resource_id']);
          break;

        default:
          // <editor-fold     defaultstate="collapsed"                        desc=" = For debug only ? --  Show Message under the form = "  >
          // --------------------------------------------------------------------------------------------------------------------------------
          if ('undefined' !== typeof response_data['ajx_data']['ajx_after_action_message'] && '' != response_data['ajx_data']['ajx_after_action_message'].replace(/\n/g, "<br />")) {
            var calendar_id = wpbc_get_resource_id__from_ajx_post_data_url(this.data);
            var jq_node = '#booking_form' + calendar_id;
            var ajx_after_booking_message = response_data['ajx_data']['ajx_after_action_message'].replace(/\n/g, "<br />");
            console.log(ajx_after_booking_message);
            /**
             * // Show Message
            	var ajx_after_action_message_id = wpbc_front_end__show_message( ajx_after_booking_message,
            								{
            									'type' : ('undefined' !== typeof (response_data[ 'ajx_data' ][ 'ajx_after_action_message_status' ]))
            											? response_data[ 'ajx_data' ][ 'ajx_after_action_message_status' ] : 'info',
            									'delay'    : 10000,
            									'show_here': {
            													'jq_node': jq_node,
            													'where'  : 'after'
            												 }
            								} );
             */
          }

        // </editor-fold>
      } // -------------------------------------------------------------------------------------------------
      // Reactivate calendar again ?
      // -------------------------------------------------------------------------------------------------
      // Enable Submit | Hide spin loader


      wpbc_booking_form__on_response__ui_elements_enable(response_data['resource_id']); // Unselect  dates

      wpbc_calendar__unselect_all_dates(response_data['resource_id']); // 'resource_id'    => $params['resource_id'],
      // 'booking_hash'   => $booking_hash,
      // 'request_uri'    => $_SERVER['REQUEST_URI'],                                            // Is it the same as window.location.href or
      // 'custom_form'    => $params['custom_form'],                                             // Optional.
      // 'aggregate_resource_id_str' => implode( ',', $params['aggregate_resource_id_arr'] )     // Optional. Resource ID   from  aggregate parameter in shortcode.
      // Load new data in calendar.

      wpbc_calendar__load_data__ajx({
        'resource_id': response_data['resource_id'] // It's from response ...AJX_BOOKING__CREATE of initial sent resource_id
        ,
        'booking_hash': response_data['ajx_cleaned_params']['booking_hash'] // ?? we can not use it,  because HASH chnaged in any  case!
        ,
        'request_uri': response_data['ajx_cleaned_params']['request_uri'],
        'custom_form': response_data['ajx_cleaned_params']['custom_form'] // Aggregate booking resources,  if any ?
        ,
        'aggregate_resource_id_str': _wpbc.booking__get_param_value(response_data['resource_id'], 'aggregate_resource_id_arr').join(',')
      }); // Exit

      return;
    } // </editor-fold>

    /*
    	// Show Calendar
    	wpbc_calendar__loading__stop( response_data[ 'resource_id' ] );
    
    	// -------------------------------------------------------------------------------------------------
    	// Bookings - Dates
    	_wpbc.bookings_in_calendar__set_dates(  response_data[ 'resource_id' ], response_data[ 'ajx_data' ]['dates']  );
    
    	// Bookings - Child or only single booking resource in dates
    	_wpbc.booking__set_param_value( response_data[ 'resource_id' ], 'resources_id_arr__in_dates', response_data[ 'ajx_data' ][ 'resources_id_arr__in_dates' ] );
    	// -------------------------------------------------------------------------------------------------
    
    	// Update calendar
    	wpbc_calendar__update_look( response_data[ 'resource_id' ] );
    */
    // Hide spin loader


    wpbc_booking_form__spin_loader__hide(response_data['resource_id']); // Hide booking form

    wpbc_booking_form__animated__hide(response_data['resource_id']); // Show Confirmation | Payment section

    wpbc_show_thank_you_message_after_booking(response_data);
    setTimeout(function () {
      wpbc_do_scroll('#wpbc_scroll_point_' + response_data['resource_id'], 10);
    }, 500);
  }).fail( // <editor-fold     defaultstate="collapsed"                        desc=" = This section execute,  when  NONCE field was not passed or some error happened at  server! = "  >
  function (jqXHR, textStatus, errorThrown) {
    if (window.console && window.console.log) {
      console.log('Ajax_Error', jqXHR, textStatus, errorThrown);
    } // -------------------------------------------------------------------------------------------------
    // This section execute,  when  NONCE field was not passed or some error happened at  server!
    // -------------------------------------------------------------------------------------------------
    // Get Content of Error Message


    var error_message = '<strong>' + 'Error!' + '</strong> ' + errorThrown;

    if (jqXHR.status) {
      error_message += ' (<b>' + jqXHR.status + '</b>)';

      if (403 == jqXHR.status) {
        error_message += '<br> Probably nonce for this page has been expired. Please <a href="javascript:void(0)" onclick="javascript:location.reload();">reload the page</a>.';
        error_message += '<br> Otherwise, please check this <a style="font-weight: 600;" href="https://wpbookingcalendar.com/faq/request-do-not-pass-security-check/">troubleshooting instruction</a>.<br>';
      }
    }

    if (jqXHR.responseText) {
      // Escape tags in Error message
      error_message += '<br><strong>Response</strong><div style="padding: 0 10px;margin: 0 0 10px;border-radius:3px; box-shadow:0px 0px 1px #a3a3a3;">' + jqXHR.responseText.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;") + '</div>';
    }

    error_message = error_message.replace(/\n/g, "<br />");
    var calendar_id = wpbc_get_resource_id__from_ajx_post_data_url(this.data);
    var jq_node = '#booking_form' + calendar_id; // Show Message

    wpbc_front_end__show_message(error_message, {
      'type': 'error',
      'show_here': {
        'jq_node': jq_node,
        'where': 'after'
      },
      'is_append': true,
      'style': 'text-align:left;',
      'delay': 0
    }); // Enable Submit | Hide spin loader

    wpbc_booking_form__on_response__ui_elements_enable(calendar_id);
  } // </editor-fold>
  ) // .done(   function ( data, textStatus, jqXHR ) {   if ( window.console && window.console.log ){ console.log( 'second success', data, textStatus, jqXHR ); }    })
  // .always( function ( data_jqXHR, textStatus, jqXHR_errorThrown ) {   if ( window.console && window.console.log ){ console.log( 'always finished', data_jqXHR, textStatus, jqXHR_errorThrown ); }     })
  ; // End Ajax

  return true;
} // <editor-fold     defaultstate="collapsed"                        desc="  ==  CAPTCHA ==  "  >

/**
 * Update image in captcha and show warning message
 *
 * @param params
 *
 * Example of 'params' : {
 *							'resource_id': response_data[ 'resource_id' ],
 *							'url'        : response_data[ 'ajx_data' ][ 'captcha__simple' ][ 'url' ],
 *							'challenge'  : response_data[ 'ajx_data' ][ 'captcha__simple' ][ 'challenge' ],
 *							'message'    : response_data[ 'ajx_data' ][ 'ajx_after_action_message' ].replace( /\n/g, "<br />" )
 *						}
 */


function wpbc_captcha__simple__update(params) {
  document.getElementById('captcha_input' + params['resource_id']).value = '';
  document.getElementById('captcha_img' + params['resource_id']).src = params['url'];
  document.getElementById('wpdev_captcha_challenge_' + params['resource_id']).value = params['challenge']; // Show warning 		After CAPTCHA Img

  var message_id = wpbc_front_end__show_message__warning('#captcha_input' + params['resource_id'] + ' + img', params['message']); // Animate

  jQuery('#' + message_id + ', ' + '#captcha_input' + params['resource_id']).fadeOut(350).fadeIn(300).fadeOut(350).fadeIn(400).animate({
    opacity: 1
  }, 4000); // Focus text  field

  jQuery('#captcha_input' + params['resource_id']).trigger('focus'); //FixIn: 8.7.11.12
  // Enable Submit | Hide spin loader

  wpbc_booking_form__on_response__ui_elements_enable(params['resource_id']);
}
/**
 * If the captcha elements not exist  in the booking form,  then  remove parameters relative captcha
 * @param params
 * @returns obj
 */


function wpbc_captcha__simple__maybe_remove_in_ajx_params(params) {
  if (!wpbc_captcha__simple__is_exist_in_form(params['resource_id'])) {
    delete params['captcha_chalange'];
    delete params['captcha_user_input'];
  }

  return params;
}
/**
 * Check if CAPTCHA exist in the booking form
 * @param resource_id
 * @returns {boolean}
 */


function wpbc_captcha__simple__is_exist_in_form(resource_id) {
  return 0 !== jQuery('#wpdev_captcha_challenge_' + resource_id).length || 0 !== jQuery('#captcha_input' + resource_id).length;
} // </editor-fold>
// <editor-fold     defaultstate="collapsed"                        desc="  ==  Send Button | Form Spin Loader  ==  "  >

/**
 * Disable Send button  |  Show Spin Loader
 *
 * @param resource_id
 */


function wpbc_booking_form__on_submit__ui_elements_disable(resource_id) {
  // Disable Submit
  wpbc_booking_form__send_button__disable(resource_id); // Show Spin loader in booking form

  wpbc_booking_form__spin_loader__show(resource_id);
}
/**
 * Enable Send button  |   Hide Spin Loader
 *
 * @param resource_id
 */


function wpbc_booking_form__on_response__ui_elements_enable(resource_id) {
  // Enable Submit
  wpbc_booking_form__send_button__enable(resource_id); // Hide Spin loader in booking form

  wpbc_booking_form__spin_loader__hide(resource_id);
}
/**
 * Enable Submit button
 * @param resource_id
 */


function wpbc_booking_form__send_button__enable(resource_id) {
  // Activate Send button
  jQuery('#booking_form_div' + resource_id + ' input[type=button]').prop("disabled", false);
  jQuery('#booking_form_div' + resource_id + ' button').prop("disabled", false);
}
/**
 * Disable Submit button  and show  spin
 *
 * @param resource_id
 */


function wpbc_booking_form__send_button__disable(resource_id) {
  // Disable Send button
  jQuery('#booking_form_div' + resource_id + ' input[type=button]').prop("disabled", true);
  jQuery('#booking_form_div' + resource_id + ' button').prop("disabled", true);
}
/**
 * Show booking form  Spin Loader
 * @param resource_id
 */


function wpbc_booking_form__spin_loader__show(resource_id) {
  // Show Spin Loader
  jQuery('#booking_form' + resource_id).after('<div id="wpbc_booking_form_spin_loader' + resource_id + '" class="wpbc_booking_form_spin_loader" style="position: relative;"><div class="wpbc_spins_loader_wrapper"><div class="wpbc_spins_loader_mini"></div></div></div>');
}
/**
 * Remove / Hide booking form  Spin Loader
 * @param resource_id
 */


function wpbc_booking_form__spin_loader__hide(resource_id) {
  // Remove Spin Loader
  jQuery('#wpbc_booking_form_spin_loader' + resource_id).remove();
}
/**
 * Hide booking form wth animation
 *
 * @param resource_id
 */


function wpbc_booking_form__animated__hide(resource_id) {
  // jQuery( '#booking_form' + resource_id ).slideUp(  1000
  // 												, function (){
  //
  // 														// if ( document.getElementById( 'gateway_payment_forms' + response_data[ 'resource_id' ] ) != null ){
  // 														// 	wpbc_do_scroll( '#submiting' + resource_id );
  // 														// } else
  // 														if ( jQuery( '#booking_form' + resource_id ).parent().find( '.submiting_content' ).length > 0 ){
  // 															//wpbc_do_scroll( '#booking_form' + resource_id + ' + .submiting_content' );
  //
  // 															 var hideTimeout = setTimeout(function () {
  // 																				  wpbc_do_scroll( jQuery( '#booking_form' + resource_id ).parent().find( '.submiting_content' ).get( 0 ) );
  // 																				}, 100);
  //
  // 														}
  // 												  }
  // 										);
  jQuery('#booking_form' + resource_id).hide(); // var hideTimeout = setTimeout( function (){
  //
  // 	if ( jQuery( '#booking_form' + resource_id ).parent().find( '.submiting_content' ).length > 0 ){
  // 		var random_id = Math.floor( (Math.random() * 10000) + 1 );
  // 		jQuery( '#booking_form' + resource_id ).parent().before( '<div id="scroll_to' + random_id + '"></div>' );
  // 		console.log( jQuery( '#scroll_to' + random_id ) );
  //
  // 		wpbc_do_scroll( '#scroll_to' + random_id );
  // 		//wpbc_do_scroll( jQuery( '#booking_form' + resource_id ).parent().get( 0 ) );
  // 	}
  // }, 500 );
} // </editor-fold>
//TODO: what  about showing only  Thank you. message without payment forms.

/**
 * Show 'Thank you'. message and payment forms
 *
 * @param response_data
 */


function wpbc_show_thank_you_message_after_booking(response_data) {
  if ('undefined' !== typeof response_data['ajx_confirmation']['ty_is_redirect'] && 'undefined' !== typeof response_data['ajx_confirmation']['ty_url'] && 'page' == response_data['ajx_confirmation']['ty_is_redirect'] && '' != response_data['ajx_confirmation']['ty_url']) {
    window.location.href = response_data['ajx_confirmation']['ty_url'];
    return;
  }

  var resource_id = response_data['resource_id'];
  var confirm_content = '';

  if ('undefined' === typeof response_data['ajx_confirmation']['ty_message']) {
    response_data['ajx_confirmation']['ty_message'] = '';
  }

  if ('undefined' === typeof response_data['ajx_confirmation']['ty_payment_payment_description']) {
    response_data['ajx_confirmation']['ty_payment_payment_description'] = '';
  }

  if ('undefined' === typeof response_data['ajx_confirmation']['payment_cost']) {
    response_data['ajx_confirmation']['payment_cost'] = '';
  }

  if ('undefined' === typeof response_data['ajx_confirmation']['ty_payment_gateways']) {
    response_data['ajx_confirmation']['ty_payment_gateways'] = '';
  }

  var ty_message_hide = '' == response_data['ajx_confirmation']['ty_message'] ? 'wpbc_ty_hide' : '';
  var ty_payment_payment_description_hide = '' == response_data['ajx_confirmation']['ty_payment_payment_description'].replace(/\\n/g, '') ? 'wpbc_ty_hide' : '';
  var ty_booking_costs_hide = '' == response_data['ajx_confirmation']['payment_cost'] ? 'wpbc_ty_hide' : '';
  var ty_payment_gateways_hide = '' == response_data['ajx_confirmation']['ty_payment_gateways'].replace(/\\n/g, '') ? 'wpbc_ty_hide' : '';

  if ('wpbc_ty_hide' != ty_payment_gateways_hide) {
    jQuery('.wpbc_ty__content_text.wpbc_ty__content_gateways').html(''); // Reset  all  other possible gateways before showing new one.
  }

  confirm_content += "<div id=\"wpbc_scroll_point_".concat(resource_id, "\"></div>");
  confirm_content += "  <div class=\"wpbc_after_booking_thank_you_section\">";
  confirm_content += "    <div class=\"wpbc_ty__message ".concat(ty_message_hide, "\">").concat(response_data['ajx_confirmation']['ty_message'], "</div>");
  confirm_content += "    <div class=\"wpbc_ty__container\">";
  confirm_content += "      <div class=\"wpbc_ty__header\">".concat(response_data['ajx_confirmation']['ty_message_booking_id'], "</div>");
  confirm_content += "      <div class=\"wpbc_ty__content\">";
  confirm_content += "        <div class=\"wpbc_ty__content_text wpbc_ty__payment_description ".concat(ty_payment_payment_description_hide, "\">").concat(response_data['ajx_confirmation']['ty_payment_payment_description'].replace(/\\n/g, ''), "</div>");
  confirm_content += "      \t<div class=\"wpbc_ty__content_text wpbc_cols_2\">".concat(response_data['ajx_confirmation']['ty_customer_details'], "</div>");
  confirm_content += "      \t<div class=\"wpbc_ty__content_text wpbc_cols_2\">".concat(response_data['ajx_confirmation']['ty_booking_details'], "</div>");
  confirm_content += "        <div class=\"wpbc_ty__content_text wpbc_ty__content_costs ".concat(ty_booking_costs_hide, "\">").concat(response_data['ajx_confirmation']['ty_booking_costs'], "</div>");
  confirm_content += "        <div class=\"wpbc_ty__content_text wpbc_ty__content_gateways ".concat(ty_payment_gateways_hide, "\">").concat(response_data['ajx_confirmation']['ty_payment_gateways'].replace(/\\n/g, '').replace(/ajax_script/gi, 'script'), "</div>");
  confirm_content += "      </div>";
  confirm_content += "    </div>";
  confirm_content += "</div>";
  jQuery('#booking_form' + resource_id).after(confirm_content);
}
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluY2x1ZGVzL19jYXBhY2l0eS9fc3JjL2NyZWF0ZV9ib29raW5nLmpzIl0sIm5hbWVzIjpbIndwYmNfYWp4X2Jvb2tpbmdfX2NyZWF0ZSIsInBhcmFtcyIsImNvbnNvbGUiLCJncm91cENvbGxhcHNlZCIsImxvZyIsImdyb3VwRW5kIiwid3BiY19jYXB0Y2hhX19zaW1wbGVfX21heWJlX3JlbW92ZV9pbl9hanhfcGFyYW1zIiwialF1ZXJ5IiwicG9zdCIsIndwYmNfZ2xvYmFsMSIsIndwYmNfYWpheHVybCIsImFjdGlvbiIsIndwYmNfYWp4X3VzZXJfaWQiLCJfd3BiYyIsImdldF9zZWN1cmVfcGFyYW0iLCJub25jZSIsIndwYmNfYWp4X2xvY2FsZSIsImNhbGVuZGFyX3JlcXVlc3RfcGFyYW1zIiwicmVzcG9uc2VfZGF0YSIsInRleHRTdGF0dXMiLCJqcVhIUiIsIm9ial9rZXkiLCJjYWxlbmRhcl9pZCIsIndwYmNfZ2V0X3Jlc291cmNlX2lkX19mcm9tX2FqeF9wb3N0X2RhdGFfdXJsIiwiZGF0YSIsImpxX25vZGUiLCJ3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlIiwid3BiY19ib29raW5nX2Zvcm1fX29uX3Jlc3BvbnNlX191aV9lbGVtZW50c19lbmFibGUiLCJ3cGJjX2NhcHRjaGFfX3NpbXBsZV9fdXBkYXRlIiwicmVwbGFjZSIsIm1lc3NhZ2VfaWQiLCJhanhfYWZ0ZXJfYm9va2luZ19tZXNzYWdlIiwid3BiY19jYWxlbmRhcl9fdW5zZWxlY3RfYWxsX2RhdGVzIiwid3BiY19jYWxlbmRhcl9fbG9hZF9kYXRhX19hangiLCJib29raW5nX19nZXRfcGFyYW1fdmFsdWUiLCJqb2luIiwid3BiY19ib29raW5nX2Zvcm1fX3NwaW5fbG9hZGVyX19oaWRlIiwid3BiY19ib29raW5nX2Zvcm1fX2FuaW1hdGVkX19oaWRlIiwid3BiY19zaG93X3RoYW5rX3lvdV9tZXNzYWdlX2FmdGVyX2Jvb2tpbmciLCJzZXRUaW1lb3V0Iiwid3BiY19kb19zY3JvbGwiLCJmYWlsIiwiZXJyb3JUaHJvd24iLCJ3aW5kb3ciLCJlcnJvcl9tZXNzYWdlIiwic3RhdHVzIiwicmVzcG9uc2VUZXh0IiwiZG9jdW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsInZhbHVlIiwic3JjIiwid3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZV9fd2FybmluZyIsImZhZGVPdXQiLCJmYWRlSW4iLCJhbmltYXRlIiwib3BhY2l0eSIsInRyaWdnZXIiLCJ3cGJjX2NhcHRjaGFfX3NpbXBsZV9faXNfZXhpc3RfaW5fZm9ybSIsInJlc291cmNlX2lkIiwibGVuZ3RoIiwid3BiY19ib29raW5nX2Zvcm1fX29uX3N1Ym1pdF9fdWlfZWxlbWVudHNfZGlzYWJsZSIsIndwYmNfYm9va2luZ19mb3JtX19zZW5kX2J1dHRvbl9fZGlzYWJsZSIsIndwYmNfYm9va2luZ19mb3JtX19zcGluX2xvYWRlcl9fc2hvdyIsIndwYmNfYm9va2luZ19mb3JtX19zZW5kX2J1dHRvbl9fZW5hYmxlIiwicHJvcCIsImFmdGVyIiwicmVtb3ZlIiwiaGlkZSIsImxvY2F0aW9uIiwiaHJlZiIsImNvbmZpcm1fY29udGVudCIsInR5X21lc3NhZ2VfaGlkZSIsInR5X3BheW1lbnRfcGF5bWVudF9kZXNjcmlwdGlvbl9oaWRlIiwidHlfYm9va2luZ19jb3N0c19oaWRlIiwidHlfcGF5bWVudF9nYXRld2F5c19oaWRlIiwiaHRtbCJdLCJtYXBwaW5ncyI6IkFBQUEsYSxDQUVBO0FBQ0E7QUFDQTs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFDQSxTQUFTQSx3QkFBVCxDQUFtQ0MsTUFBbkMsRUFBMkM7QUFFM0NDLEVBQUFBLE9BQU8sQ0FBQ0MsY0FBUixDQUF3QiwwQkFBeEI7QUFDQUQsRUFBQUEsT0FBTyxDQUFDQyxjQUFSLENBQXdCLHdCQUF4QjtBQUNBRCxFQUFBQSxPQUFPLENBQUNFLEdBQVIsQ0FBYUgsTUFBYjtBQUNBQyxFQUFBQSxPQUFPLENBQUNHLFFBQVI7QUFFQ0osRUFBQUEsTUFBTSxHQUFHSyxnREFBZ0QsQ0FBRUwsTUFBRixDQUF6RCxDQVAwQyxDQVMxQzs7QUFDQU0sRUFBQUEsTUFBTSxDQUFDQyxJQUFQLENBQWFDLFlBQVksQ0FBQ0MsWUFBMUIsRUFDRztBQUNDQyxJQUFBQSxNQUFNLEVBQVksMEJBRG5CO0FBRUNDLElBQUFBLGdCQUFnQixFQUFFQyxLQUFLLENBQUNDLGdCQUFOLENBQXdCLFNBQXhCLENBRm5CO0FBR0NDLElBQUFBLEtBQUssRUFBYUYsS0FBSyxDQUFDQyxnQkFBTixDQUF3QixPQUF4QixDQUhuQjtBQUlDRSxJQUFBQSxlQUFlLEVBQUdILEtBQUssQ0FBQ0MsZ0JBQU4sQ0FBd0IsUUFBeEIsQ0FKbkI7QUFNQ0csSUFBQUEsdUJBQXVCLEVBQUdoQjtBQUUxQjtBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQXJCSSxHQURIO0FBeUJHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0ksWUFBV2lCLGFBQVgsRUFBMEJDLFVBQTFCLEVBQXNDQyxLQUF0QyxFQUE4QztBQUNsRGxCLElBQUFBLE9BQU8sQ0FBQ0UsR0FBUixDQUFhLDJDQUFiOztBQUNBLFNBQU0sSUFBSWlCLE9BQVYsSUFBcUJILGFBQXJCLEVBQW9DO0FBQ25DaEIsTUFBQUEsT0FBTyxDQUFDQyxjQUFSLENBQXdCLE9BQU9rQixPQUFQLEdBQWlCLElBQXpDO0FBQ0FuQixNQUFBQSxPQUFPLENBQUNFLEdBQVIsQ0FBYSxRQUFRaUIsT0FBUixHQUFrQixLQUEvQixFQUFzQ0gsYUFBYSxDQUFFRyxPQUFGLENBQW5EO0FBQ0FuQixNQUFBQSxPQUFPLENBQUNHLFFBQVI7QUFDQTs7QUFDREgsSUFBQUEsT0FBTyxDQUFDRyxRQUFSLEdBUGtELENBVTdDO0FBQ0E7QUFDQTtBQUNBOztBQUNBLFFBQU0sUUFBT2EsYUFBUCxNQUF5QixRQUExQixJQUF3Q0EsYUFBYSxLQUFLLElBQS9ELEVBQXNFO0FBRXJFLFVBQUlJLFdBQVcsR0FBR0MsNENBQTRDLENBQUUsS0FBS0MsSUFBUCxDQUE5RDtBQUNBLFVBQUlDLE9BQU8sR0FBRyxrQkFBa0JILFdBQWhDOztBQUVBLFVBQUssTUFBTUosYUFBWCxFQUEwQjtBQUN6QkEsUUFBQUEsYUFBYSxHQUFHLGFBQWEsMENBQWIsR0FBMEQsWUFBMUU7QUFDQSxPQVBvRSxDQVFyRTs7O0FBQ0FRLE1BQUFBLDRCQUE0QixDQUFFUixhQUFGLEVBQWtCO0FBQUUsZ0JBQWEsT0FBZjtBQUNsQyxxQkFBYTtBQUFDLHFCQUFXTyxPQUFaO0FBQXFCLG1CQUFTO0FBQTlCLFNBRHFCO0FBRWxDLHFCQUFhLElBRnFCO0FBR2xDLGlCQUFhLGtCQUhxQjtBQUlsQyxpQkFBYTtBQUpxQixPQUFsQixDQUE1QixDQVRxRSxDQWVyRTs7QUFDQUUsTUFBQUEsa0RBQWtELENBQUVMLFdBQUYsQ0FBbEQ7QUFDQTtBQUNBLEtBaEM0QyxDQWlDN0M7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7O0FBRUEsUUFBSyxRQUFRSixhQUFhLENBQUUsVUFBRixDQUFiLENBQTZCLFFBQTdCLENBQWIsRUFBdUQ7QUFFdEQsY0FBU0EsYUFBYSxDQUFFLFVBQUYsQ0FBYixDQUE2QixjQUE3QixDQUFUO0FBRUMsYUFBSyxzQkFBTDtBQUNDVSxVQUFBQSw0QkFBNEIsQ0FBRTtBQUN0QiwyQkFBZVYsYUFBYSxDQUFFLGFBQUYsQ0FETjtBQUV0QixtQkFBZUEsYUFBYSxDQUFFLFVBQUYsQ0FBYixDQUE2QixpQkFBN0IsRUFBa0QsS0FBbEQsQ0FGTztBQUd0Qix5QkFBZUEsYUFBYSxDQUFFLFVBQUYsQ0FBYixDQUE2QixpQkFBN0IsRUFBa0QsV0FBbEQsQ0FITztBQUl0Qix1QkFBZUEsYUFBYSxDQUFFLFVBQUYsQ0FBYixDQUE2QiwwQkFBN0IsRUFBMERXLE9BQTFELENBQW1FLEtBQW5FLEVBQTBFLFFBQTFFO0FBSk8sV0FBRixDQUE1QjtBQU9BOztBQUVELGFBQUssdUJBQUw7QUFBNkM7QUFDNUMsY0FBSUMsVUFBVSxHQUFHSiw0QkFBNEIsQ0FBRVIsYUFBYSxDQUFFLFVBQUYsQ0FBYixDQUE2QiwwQkFBN0IsRUFBMERXLE9BQTFELENBQW1FLEtBQW5FLEVBQTBFLFFBQTFFLENBQUYsRUFDckM7QUFDQyxvQkFBVSxnQkFBZ0IsT0FBUVgsYUFBYSxDQUFFLFVBQUYsQ0FBYixDQUE2QixpQ0FBN0IsQ0FBekIsR0FDTEEsYUFBYSxDQUFFLFVBQUYsQ0FBYixDQUE2QixpQ0FBN0IsQ0FESyxHQUM4RCxTQUZ4RTtBQUdDLHFCQUFhLENBSGQ7QUFJQyx5QkFBYTtBQUFFLHVCQUFTLE9BQVg7QUFBb0IseUJBQVcsa0JBQWtCakIsTUFBTSxDQUFFLGFBQUY7QUFBdkQ7QUFKZCxXQURxQyxDQUE3QztBQU9BOztBQUVELGFBQUssc0JBQUw7QUFBNEM7QUFDM0MsY0FBSTZCLFVBQVUsR0FBR0osNEJBQTRCLENBQUVSLGFBQWEsQ0FBRSxVQUFGLENBQWIsQ0FBNkIsMEJBQTdCLEVBQTBEVyxPQUExRCxDQUFtRSxLQUFuRSxFQUEwRSxRQUExRSxDQUFGLEVBQ3JDO0FBQ0Msb0JBQVUsZ0JBQWdCLE9BQVFYLGFBQWEsQ0FBRSxVQUFGLENBQWIsQ0FBNkIsaUNBQTdCLENBQXpCLEdBQ0xBLGFBQWEsQ0FBRSxVQUFGLENBQWIsQ0FBNkIsaUNBQTdCLENBREssR0FDOEQsU0FGeEU7QUFHQyxxQkFBYSxDQUhkO0FBSUMseUJBQWE7QUFBRSx1QkFBUyxPQUFYO0FBQW9CLHlCQUFXLGtCQUFrQmpCLE1BQU0sQ0FBRSxhQUFGO0FBQXZEO0FBSmQsV0FEcUMsQ0FBN0MsQ0FERCxDQVNDOztBQUNBMEIsVUFBQUEsa0RBQWtELENBQUVULGFBQWEsQ0FBRSxhQUFGLENBQWYsQ0FBbEQ7QUFFQTs7QUFHRDtBQUVDO0FBQ0E7QUFDQSxjQUNJLGdCQUFnQixPQUFRQSxhQUFhLENBQUUsVUFBRixDQUFiLENBQTZCLDBCQUE3QixDQUExQixJQUNLLE1BQU1BLGFBQWEsQ0FBRSxVQUFGLENBQWIsQ0FBNkIsMEJBQTdCLEVBQTBEVyxPQUExRCxDQUFtRSxLQUFuRSxFQUEwRSxRQUExRSxDQUZiLEVBR0M7QUFFQSxnQkFBSVAsV0FBVyxHQUFHQyw0Q0FBNEMsQ0FBRSxLQUFLQyxJQUFQLENBQTlEO0FBQ0EsZ0JBQUlDLE9BQU8sR0FBRyxrQkFBa0JILFdBQWhDO0FBRUEsZ0JBQUlTLHlCQUF5QixHQUFHYixhQUFhLENBQUUsVUFBRixDQUFiLENBQTZCLDBCQUE3QixFQUEwRFcsT0FBMUQsQ0FBbUUsS0FBbkUsRUFBMEUsUUFBMUUsQ0FBaEM7QUFFQTNCLFlBQUFBLE9BQU8sQ0FBQ0UsR0FBUixDQUFhMkIseUJBQWI7QUFFQTtBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNTOztBQUNEO0FBbkVGLE9BRnNELENBeUV0RDtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0FKLE1BQUFBLGtEQUFrRCxDQUFFVCxhQUFhLENBQUUsYUFBRixDQUFmLENBQWxELENBN0VzRCxDQStFdEQ7O0FBQ0FjLE1BQUFBLGlDQUFpQyxDQUFFZCxhQUFhLENBQUUsYUFBRixDQUFmLENBQWpDLENBaEZzRCxDQWtGdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUNBZSxNQUFBQSw2QkFBNkIsQ0FBRTtBQUN4Qix1QkFBZ0JmLGFBQWEsQ0FBRSxhQUFGLENBREwsQ0FDNkI7QUFEN0I7QUFFeEIsd0JBQWdCQSxhQUFhLENBQUUsb0JBQUYsQ0FBYixDQUFzQyxjQUF0QyxDQUZRLENBRStDO0FBRi9DO0FBR3hCLHVCQUFnQkEsYUFBYSxDQUFFLG9CQUFGLENBQWIsQ0FBc0MsYUFBdEMsQ0FIUTtBQUl4Qix1QkFBZ0JBLGFBQWEsQ0FBRSxvQkFBRixDQUFiLENBQXNDLGFBQXRDLENBSlEsQ0FLbEI7QUFMa0I7QUFNeEIscUNBQThCTCxLQUFLLENBQUNxQix3QkFBTixDQUFnQ2hCLGFBQWEsQ0FBRSxhQUFGLENBQTdDLEVBQWdFLDJCQUFoRSxFQUE4RmlCLElBQTlGLENBQW1HLEdBQW5HO0FBTk4sT0FBRixDQUE3QixDQXpGc0QsQ0FrR3REOztBQUNBO0FBQ0EsS0E3STRDLENBK0k3Qzs7QUFHTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFSzs7O0FBQ0FDLElBQUFBLG9DQUFvQyxDQUFFbEIsYUFBYSxDQUFFLGFBQUYsQ0FBZixDQUFwQyxDQW5LNkMsQ0FxSzdDOztBQUNBbUIsSUFBQUEsaUNBQWlDLENBQUVuQixhQUFhLENBQUUsYUFBRixDQUFmLENBQWpDLENBdEs2QyxDQXdLN0M7O0FBQ0FvQixJQUFBQSx5Q0FBeUMsQ0FBRXBCLGFBQUYsQ0FBekM7QUFFQXFCLElBQUFBLFVBQVUsQ0FBRSxZQUFXO0FBQ3RCQyxNQUFBQSxjQUFjLENBQUUsd0JBQXdCdEIsYUFBYSxDQUFFLGFBQUYsQ0FBdkMsRUFBMEQsRUFBMUQsQ0FBZDtBQUNBLEtBRlMsRUFFUCxHQUZPLENBQVY7QUFNQSxHQWpOSixFQWtOTXVCLElBbE5OLEVBbU5LO0FBQ0EsWUFBV3JCLEtBQVgsRUFBa0JELFVBQWxCLEVBQThCdUIsV0FBOUIsRUFBNEM7QUFBSyxRQUFLQyxNQUFNLENBQUN6QyxPQUFQLElBQWtCeUMsTUFBTSxDQUFDekMsT0FBUCxDQUFlRSxHQUF0QyxFQUEyQztBQUFFRixNQUFBQSxPQUFPLENBQUNFLEdBQVIsQ0FBYSxZQUFiLEVBQTJCZ0IsS0FBM0IsRUFBa0NELFVBQWxDLEVBQThDdUIsV0FBOUM7QUFBOEQsS0FBaEgsQ0FFN0M7QUFDQTtBQUNBO0FBRUE7OztBQUNBLFFBQUlFLGFBQWEsR0FBRyxhQUFhLFFBQWIsR0FBd0IsWUFBeEIsR0FBdUNGLFdBQTNEOztBQUNBLFFBQUt0QixLQUFLLENBQUN5QixNQUFYLEVBQW1CO0FBQ2xCRCxNQUFBQSxhQUFhLElBQUksVUFBVXhCLEtBQUssQ0FBQ3lCLE1BQWhCLEdBQXlCLE9BQTFDOztBQUNBLFVBQUksT0FBT3pCLEtBQUssQ0FBQ3lCLE1BQWpCLEVBQXlCO0FBQ3hCRCxRQUFBQSxhQUFhLElBQUksc0pBQWpCO0FBQ0FBLFFBQUFBLGFBQWEsSUFBSSxrTEFBakI7QUFDQTtBQUNEOztBQUNELFFBQUt4QixLQUFLLENBQUMwQixZQUFYLEVBQXlCO0FBQ3hCO0FBQ0FGLE1BQUFBLGFBQWEsSUFBSSxtSUFBbUl4QixLQUFLLENBQUMwQixZQUFOLENBQW1CakIsT0FBbkIsQ0FBMkIsSUFBM0IsRUFBaUMsT0FBakMsRUFDeElBLE9BRHdJLENBQ2hJLElBRGdJLEVBQzFILE1BRDBILEVBRXhJQSxPQUZ3SSxDQUVoSSxJQUZnSSxFQUUxSCxNQUYwSCxFQUd4SUEsT0FId0ksQ0FHaEksSUFIZ0ksRUFHMUgsUUFIMEgsRUFJeElBLE9BSndJLENBSWhJLElBSmdJLEVBSTFILE9BSjBILENBQW5JLEdBS1osUUFMTDtBQU1BOztBQUNEZSxJQUFBQSxhQUFhLEdBQUdBLGFBQWEsQ0FBQ2YsT0FBZCxDQUF1QixLQUF2QixFQUE4QixRQUE5QixDQUFoQjtBQUVBLFFBQUlQLFdBQVcsR0FBR0MsNENBQTRDLENBQUUsS0FBS0MsSUFBUCxDQUE5RDtBQUNBLFFBQUlDLE9BQU8sR0FBRyxrQkFBa0JILFdBQWhDLENBM0I2QyxDQTZCN0M7O0FBQ0FJLElBQUFBLDRCQUE0QixDQUFFa0IsYUFBRixFQUFrQjtBQUFFLGNBQWEsT0FBZjtBQUNsQyxtQkFBYTtBQUFDLG1CQUFXbkIsT0FBWjtBQUFxQixpQkFBUztBQUE5QixPQURxQjtBQUVsQyxtQkFBYSxJQUZxQjtBQUdsQyxlQUFhLGtCQUhxQjtBQUlsQyxlQUFhO0FBSnFCLEtBQWxCLENBQTVCLENBOUI2QyxDQW9DN0M7O0FBQ0FFLElBQUFBLGtEQUFrRCxDQUFFTCxXQUFGLENBQWxEO0FBQ0csR0ExUFAsQ0EyUEk7QUEzUEosSUE2UFU7QUFDTjtBQTlQSixHQVYwQyxDQXlRbkM7O0FBRVAsU0FBTyxJQUFQO0FBQ0EsQyxDQUdBOztBQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0MsU0FBU00sNEJBQVQsQ0FBdUMzQixNQUF2QyxFQUErQztBQUU5QzhDLEVBQUFBLFFBQVEsQ0FBQ0MsY0FBVCxDQUF5QixrQkFBa0IvQyxNQUFNLENBQUUsYUFBRixDQUFqRCxFQUFxRWdELEtBQXJFLEdBQTZFLEVBQTdFO0FBQ0FGLEVBQUFBLFFBQVEsQ0FBQ0MsY0FBVCxDQUF5QixnQkFBZ0IvQyxNQUFNLENBQUUsYUFBRixDQUEvQyxFQUFtRWlELEdBQW5FLEdBQXlFakQsTUFBTSxDQUFFLEtBQUYsQ0FBL0U7QUFDQThDLEVBQUFBLFFBQVEsQ0FBQ0MsY0FBVCxDQUF5Qiw2QkFBNkIvQyxNQUFNLENBQUUsYUFBRixDQUE1RCxFQUFnRmdELEtBQWhGLEdBQXdGaEQsTUFBTSxDQUFFLFdBQUYsQ0FBOUYsQ0FKOEMsQ0FNOUM7O0FBQ0EsTUFBSTZCLFVBQVUsR0FBR3FCLHFDQUFxQyxDQUFFLG1CQUFtQmxELE1BQU0sQ0FBRSxhQUFGLENBQXpCLEdBQTZDLFFBQS9DLEVBQXlEQSxNQUFNLENBQUUsU0FBRixDQUEvRCxDQUF0RCxDQVA4QyxDQVM5Qzs7QUFDQU0sRUFBQUEsTUFBTSxDQUFFLE1BQU11QixVQUFOLEdBQW1CLElBQW5CLEdBQTBCLGdCQUExQixHQUE2QzdCLE1BQU0sQ0FBRSxhQUFGLENBQXJELENBQU4sQ0FBK0VtRCxPQUEvRSxDQUF3RixHQUF4RixFQUE4RkMsTUFBOUYsQ0FBc0csR0FBdEcsRUFBNEdELE9BQTVHLENBQXFILEdBQXJILEVBQTJIQyxNQUEzSCxDQUFtSSxHQUFuSSxFQUF5SUMsT0FBekksQ0FBa0o7QUFBQ0MsSUFBQUEsT0FBTyxFQUFFO0FBQVYsR0FBbEosRUFBZ0ssSUFBaEssRUFWOEMsQ0FXOUM7O0FBQ0FoRCxFQUFBQSxNQUFNLENBQUUsbUJBQW1CTixNQUFNLENBQUUsYUFBRixDQUEzQixDQUFOLENBQXFEdUQsT0FBckQsQ0FBOEQsT0FBOUQsRUFaOEMsQ0FZdUM7QUFHckY7O0FBQ0E3QixFQUFBQSxrREFBa0QsQ0FBRTFCLE1BQU0sQ0FBRSxhQUFGLENBQVIsQ0FBbEQ7QUFDQTtBQUdEO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7OztBQUNDLFNBQVNLLGdEQUFULENBQTJETCxNQUEzRCxFQUFtRTtBQUVsRSxNQUFLLENBQUV3RCxzQ0FBc0MsQ0FBRXhELE1BQU0sQ0FBRSxhQUFGLENBQVIsQ0FBN0MsRUFBMEU7QUFDekUsV0FBT0EsTUFBTSxDQUFFLGtCQUFGLENBQWI7QUFDQSxXQUFPQSxNQUFNLENBQUUsb0JBQUYsQ0FBYjtBQUNBOztBQUNELFNBQU9BLE1BQVA7QUFDQTtBQUdEO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7OztBQUNDLFNBQVN3RCxzQ0FBVCxDQUFpREMsV0FBakQsRUFBOEQ7QUFFN0QsU0FDSyxNQUFNbkQsTUFBTSxDQUFFLDhCQUE4Qm1ELFdBQWhDLENBQU4sQ0FBb0RDLE1BQTNELElBQ0ksTUFBTXBELE1BQU0sQ0FBRSxtQkFBbUJtRCxXQUFyQixDQUFOLENBQXlDQyxNQUZ2RDtBQUlBLEMsQ0FFRDtBQUdBOztBQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7OztBQUNDLFNBQVNDLGlEQUFULENBQTRERixXQUE1RCxFQUF5RTtBQUV4RTtBQUNBRyxFQUFBQSx1Q0FBdUMsQ0FBRUgsV0FBRixDQUF2QyxDQUh3RSxDQUt4RTs7QUFDQUksRUFBQUEsb0NBQW9DLENBQUVKLFdBQUYsQ0FBcEM7QUFDQTtBQUVEO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7OztBQUNDLFNBQVMvQixrREFBVCxDQUE0RCtCLFdBQTVELEVBQXdFO0FBRXZFO0FBQ0FLLEVBQUFBLHNDQUFzQyxDQUFFTCxXQUFGLENBQXRDLENBSHVFLENBS3ZFOztBQUNBdEIsRUFBQUEsb0NBQW9DLENBQUVzQixXQUFGLENBQXBDO0FBQ0E7QUFFQTtBQUNGO0FBQ0E7QUFDQTs7O0FBQ0UsU0FBU0ssc0NBQVQsQ0FBaURMLFdBQWpELEVBQThEO0FBRTdEO0FBQ0FuRCxFQUFBQSxNQUFNLENBQUUsc0JBQXNCbUQsV0FBdEIsR0FBb0MscUJBQXRDLENBQU4sQ0FBb0VNLElBQXBFLENBQTBFLFVBQTFFLEVBQXNGLEtBQXRGO0FBQ0F6RCxFQUFBQSxNQUFNLENBQUUsc0JBQXNCbUQsV0FBdEIsR0FBb0MsU0FBdEMsQ0FBTixDQUF3RE0sSUFBeEQsQ0FBOEQsVUFBOUQsRUFBMEUsS0FBMUU7QUFDQTtBQUVEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7OztBQUNFLFNBQVNILHVDQUFULENBQWtESCxXQUFsRCxFQUErRDtBQUU5RDtBQUNBbkQsRUFBQUEsTUFBTSxDQUFFLHNCQUFzQm1ELFdBQXRCLEdBQW9DLHFCQUF0QyxDQUFOLENBQW9FTSxJQUFwRSxDQUEwRSxVQUExRSxFQUFzRixJQUF0RjtBQUNBekQsRUFBQUEsTUFBTSxDQUFFLHNCQUFzQm1ELFdBQXRCLEdBQW9DLFNBQXRDLENBQU4sQ0FBd0RNLElBQXhELENBQThELFVBQTlELEVBQTBFLElBQTFFO0FBQ0E7QUFFRDtBQUNGO0FBQ0E7QUFDQTs7O0FBQ0UsU0FBU0Ysb0NBQVQsQ0FBK0NKLFdBQS9DLEVBQTREO0FBRTNEO0FBQ0FuRCxFQUFBQSxNQUFNLENBQUUsa0JBQWtCbUQsV0FBcEIsQ0FBTixDQUF3Q08sS0FBeEMsQ0FDQywyQ0FBMkNQLFdBQTNDLEdBQXlELG1LQUQxRDtBQUdBO0FBRUQ7QUFDRjtBQUNBO0FBQ0E7OztBQUNFLFNBQVN0QixvQ0FBVCxDQUErQ3NCLFdBQS9DLEVBQTREO0FBRTNEO0FBQ0FuRCxFQUFBQSxNQUFNLENBQUUsbUNBQW1DbUQsV0FBckMsQ0FBTixDQUF5RFEsTUFBekQ7QUFDQTtBQUdEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7OztBQUNFLFNBQVM3QixpQ0FBVCxDQUE0Q3FCLFdBQTVDLEVBQXlEO0FBRXhEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUFuRCxFQUFBQSxNQUFNLENBQUUsa0JBQWtCbUQsV0FBcEIsQ0FBTixDQUF3Q1MsSUFBeEMsR0FuQndELENBcUJ4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQyxDQUNGO0FBR0Q7O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBUzdCLHlDQUFULENBQW9EcEIsYUFBcEQsRUFBbUU7QUFFbEUsTUFDTSxnQkFBZ0IsT0FBUUEsYUFBYSxDQUFFLGtCQUFGLENBQWIsQ0FBcUMsZ0JBQXJDLENBQXpCLElBQ0EsZ0JBQWdCLE9BQVFBLGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLFFBQXJDLENBRHhCLElBRUEsVUFBVUEsYUFBYSxDQUFFLGtCQUFGLENBQWIsQ0FBcUMsZ0JBQXJDLENBRlYsSUFHQSxNQUFNQSxhQUFhLENBQUUsa0JBQUYsQ0FBYixDQUFxQyxRQUFyQyxDQUpYLEVBS0M7QUFDQXlCLElBQUFBLE1BQU0sQ0FBQ3lCLFFBQVAsQ0FBZ0JDLElBQWhCLEdBQXVCbkQsYUFBYSxDQUFFLGtCQUFGLENBQWIsQ0FBcUMsUUFBckMsQ0FBdkI7QUFDQTtBQUNBOztBQUVELE1BQUl3QyxXQUFXLEdBQUd4QyxhQUFhLENBQUUsYUFBRixDQUEvQjtBQUNBLE1BQUlvRCxlQUFlLEdBQUUsRUFBckI7O0FBRUEsTUFBSyxnQkFBZ0IsT0FBUXBELGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLFlBQXJDLENBQTdCLEVBQW1GO0FBQ3pFQSxJQUFBQSxhQUFhLENBQUUsa0JBQUYsQ0FBYixDQUFxQyxZQUFyQyxJQUFzRCxFQUF0RDtBQUNUOztBQUNELE1BQUssZ0JBQWdCLE9BQVFBLGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLGdDQUFyQyxDQUE3QixFQUF3RztBQUM3RkEsSUFBQUEsYUFBYSxDQUFFLGtCQUFGLENBQWIsQ0FBcUMsZ0NBQXJDLElBQTBFLEVBQTFFO0FBQ1Y7O0FBQ0QsTUFBSyxnQkFBZ0IsT0FBUUEsYUFBYSxDQUFFLGtCQUFGLENBQWIsQ0FBcUMsY0FBckMsQ0FBN0IsRUFBc0Y7QUFDNUVBLElBQUFBLGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLGNBQXJDLElBQXdELEVBQXhEO0FBQ1Q7O0FBQ0QsTUFBSyxnQkFBZ0IsT0FBUUEsYUFBYSxDQUFFLGtCQUFGLENBQWIsQ0FBcUMscUJBQXJDLENBQTdCLEVBQTZGO0FBQ25GQSxJQUFBQSxhQUFhLENBQUUsa0JBQUYsQ0FBYixDQUFxQyxxQkFBckMsSUFBK0QsRUFBL0Q7QUFDVDs7QUFDRCxNQUFJcUQsZUFBZSxHQUFVLE1BQU1yRCxhQUFhLENBQUUsa0JBQUYsQ0FBYixDQUFxQyxZQUFyQyxDQUFQLEdBQThELGNBQTlELEdBQStFLEVBQTNHO0FBQ0EsTUFBSXNELG1DQUFtQyxHQUFLLE1BQU10RCxhQUFhLENBQUUsa0JBQUYsQ0FBYixDQUFxQyxnQ0FBckMsRUFBd0VXLE9BQXhFLENBQWlGLE1BQWpGLEVBQXlGLEVBQXpGLENBQVAsR0FBd0csY0FBeEcsR0FBeUgsRUFBcEs7QUFDQSxNQUFJNEMscUJBQXFCLEdBQVEsTUFBTXZELGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLGNBQXJDLENBQVAsR0FBZ0UsY0FBaEUsR0FBaUYsRUFBakg7QUFDQSxNQUFJd0Qsd0JBQXdCLEdBQU8sTUFBTXhELGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLHFCQUFyQyxFQUE2RFcsT0FBN0QsQ0FBc0UsTUFBdEUsRUFBOEUsRUFBOUUsQ0FBUCxHQUE2RixjQUE3RixHQUE4RyxFQUFoSjs7QUFFQSxNQUFLLGtCQUFrQjZDLHdCQUF2QixFQUFpRDtBQUNoRG5FLElBQUFBLE1BQU0sQ0FBRSxrREFBRixDQUFOLENBQTZEb0UsSUFBN0QsQ0FBbUUsRUFBbkUsRUFEZ0QsQ0FDeUI7QUFDekU7O0FBRURMLEVBQUFBLGVBQWUsMENBQWtDWixXQUFsQyxjQUFmO0FBQ0FZLEVBQUFBLGVBQWUsNERBQWY7QUFDQUEsRUFBQUEsZUFBZSxnREFBd0NDLGVBQXhDLGdCQUE0RHJELGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLFlBQXJDLENBQTVELFdBQWY7QUFDR29ELEVBQUFBLGVBQWUsNENBQWY7QUFDQUEsRUFBQUEsZUFBZSxtREFBMENwRCxhQUFhLENBQUMsa0JBQUQsQ0FBYixDQUFrQyx1QkFBbEMsQ0FBMUMsV0FBZjtBQUNBb0QsRUFBQUEsZUFBZSw0Q0FBZjtBQUNIQSxFQUFBQSxlQUFlLHNGQUE4RUUsbUNBQTlFLGdCQUFzSHRELGFBQWEsQ0FBRSxrQkFBRixDQUFiLENBQXFDLGdDQUFyQyxFQUF3RVcsT0FBeEUsQ0FBaUYsTUFBakYsRUFBeUYsRUFBekYsQ0FBdEgsV0FBZjtBQUNHeUMsRUFBQUEsZUFBZSx1RUFBNkRwRCxhQUFhLENBQUMsa0JBQUQsQ0FBYixDQUFrQyxxQkFBbEMsQ0FBN0QsV0FBZjtBQUNBb0QsRUFBQUEsZUFBZSx1RUFBNkRwRCxhQUFhLENBQUMsa0JBQUQsQ0FBYixDQUFrQyxvQkFBbEMsQ0FBN0QsV0FBZjtBQUNIb0QsRUFBQUEsZUFBZSxnRkFBd0VHLHFCQUF4RSxnQkFBa0d2RCxhQUFhLENBQUUsa0JBQUYsQ0FBYixDQUFxQyxrQkFBckMsQ0FBbEcsV0FBZjtBQUNBb0QsRUFBQUEsZUFBZSxtRkFBMkVJLHdCQUEzRSxnQkFBd0d4RCxhQUFhLENBQUUsa0JBQUYsQ0FBYixDQUFxQyxxQkFBckMsRUFBNkRXLE9BQTdELENBQXNFLE1BQXRFLEVBQThFLEVBQTlFLEVBQW1GQSxPQUFuRixDQUE0RixlQUE1RixFQUE2RyxRQUE3RyxDQUF4RyxXQUFmO0FBQ0d5QyxFQUFBQSxlQUFlLGtCQUFmO0FBQ0FBLEVBQUFBLGVBQWUsZ0JBQWY7QUFDSEEsRUFBQUEsZUFBZSxZQUFmO0FBRUMvRCxFQUFBQSxNQUFNLENBQUUsa0JBQWtCbUQsV0FBcEIsQ0FBTixDQUF3Q08sS0FBeEMsQ0FBK0NLLGVBQS9DO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4vLyAgQSBqIGEgeCAgICBBIGQgZCAgICBOIGUgdyAgICBCIG8gbyBrIGkgbiBnXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHJcbi8qKlxyXG4gKiBTdWJtaXQgbmV3IGJvb2tpbmdcclxuICpcclxuICogQHBhcmFtIHBhcmFtcyAgID0gICAgIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncmVzb3VyY2VfaWQnICAgICAgICA6IHJlc291cmNlX2lkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdkYXRlc19kZG1teXlfY3N2JyAgIDogZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoICdkYXRlX2Jvb2tpbmcnICsgcmVzb3VyY2VfaWQgKS52YWx1ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZm9ybWRhdGEnICAgICAgICAgICA6IGZvcm1kYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdib29raW5nX2hhc2gnICAgICAgIDogbXlfYm9va2luZ19oYXNoLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjdXN0b21fZm9ybScgICAgICAgIDogbXlfYm9va2luZ19mb3JtLFxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY2FwdGNoYV9jaGFsYW5nZScgICA6IGNhcHRjaGFfY2hhbGFuZ2UsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NhcHRjaGFfdXNlcl9pbnB1dCcgOiB1c2VyX2NhcHRjaGEsXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdpc19lbWFpbHNfc2VuZCcgICAgIDogaXNfc2VuZF9lbWVpbHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2FjdGl2ZV9sb2NhbGUnICAgICAgOiB3cGRldl9hY3RpdmVfbG9jYWxlXHJcblx0XHRcdFx0XHRcdH1cclxuICpcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX2NyZWF0ZSggcGFyYW1zICl7XHJcblxyXG5jb25zb2xlLmdyb3VwQ29sbGFwc2VkKCAnV1BCQ19BSlhfQk9PS0lOR19fQ1JFQVRFJyApO1xyXG5jb25zb2xlLmdyb3VwQ29sbGFwc2VkKCAnPT0gQmVmb3JlIEFqYXggU2VuZCA9PScgKTtcclxuY29uc29sZS5sb2coIHBhcmFtcyApO1xyXG5jb25zb2xlLmdyb3VwRW5kKCk7XHJcblxyXG5cdHBhcmFtcyA9IHdwYmNfY2FwdGNoYV9fc2ltcGxlX19tYXliZV9yZW1vdmVfaW5fYWp4X3BhcmFtcyggcGFyYW1zICk7XHJcblxyXG5cdC8vIFN0YXJ0IEFqYXhcclxuXHRqUXVlcnkucG9zdCggd3BiY19nbG9iYWwxLndwYmNfYWpheHVybCxcclxuXHRcdFx0XHR7XHJcblx0XHRcdFx0XHRhY3Rpb24gICAgICAgICAgOiAnV1BCQ19BSlhfQk9PS0lOR19fQ1JFQVRFJyxcclxuXHRcdFx0XHRcdHdwYmNfYWp4X3VzZXJfaWQ6IF93cGJjLmdldF9zZWN1cmVfcGFyYW0oICd1c2VyX2lkJyApLFxyXG5cdFx0XHRcdFx0bm9uY2UgICAgICAgICAgIDogX3dwYmMuZ2V0X3NlY3VyZV9wYXJhbSggJ25vbmNlJyApLFxyXG5cdFx0XHRcdFx0d3BiY19hanhfbG9jYWxlIDogX3dwYmMuZ2V0X3NlY3VyZV9wYXJhbSggJ2xvY2FsZScgKSxcclxuXHJcblx0XHRcdFx0XHRjYWxlbmRhcl9yZXF1ZXN0X3BhcmFtcyA6IHBhcmFtc1xyXG5cclxuXHRcdFx0XHRcdC8qKlxyXG5cdFx0XHRcdFx0ICogIFVzdWFsbHkgIHBhcmFtcyA9IHsgJ3Jlc291cmNlX2lkJyAgICAgICAgOiByZXNvdXJjZV9pZCxcclxuXHRcdFx0XHRcdCAqXHRcdFx0XHRcdFx0J2RhdGVzX2RkbW15eV9jc3YnICAgOiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggJ2RhdGVfYm9va2luZycgKyByZXNvdXJjZV9pZCApLnZhbHVlLFxyXG5cdFx0XHRcdFx0ICpcdFx0XHRcdFx0XHQnZm9ybWRhdGEnICAgICAgICAgICA6IGZvcm1kYXRhLFxyXG5cdFx0XHRcdFx0ICpcdFx0XHRcdFx0XHQnYm9va2luZ19oYXNoJyAgICAgICA6IG15X2Jvb2tpbmdfaGFzaCxcclxuXHRcdFx0XHRcdCAqXHRcdFx0XHRcdFx0J2N1c3RvbV9mb3JtJyAgICAgICAgOiBteV9ib29raW5nX2Zvcm0sXHJcblx0XHRcdFx0XHQgKlxyXG5cdFx0XHRcdFx0ICpcdFx0XHRcdFx0XHQnY2FwdGNoYV9jaGFsYW5nZScgICA6IGNhcHRjaGFfY2hhbGFuZ2UsXHJcblx0XHRcdFx0XHQgKlx0XHRcdFx0XHRcdCd1c2VyX2NhcHRjaGEnICAgICAgIDogdXNlcl9jYXB0Y2hhLFxyXG5cdFx0XHRcdFx0ICpcclxuXHRcdFx0XHRcdCAqXHRcdFx0XHRcdFx0J2lzX2VtYWlsc19zZW5kJyAgICAgOiBpc19zZW5kX2VtZWlscyxcclxuXHRcdFx0XHRcdCAqXHRcdFx0XHRcdFx0J2FjdGl2ZV9sb2NhbGUnICAgICAgOiB3cGRldl9hY3RpdmVfbG9jYWxlXHJcblx0XHRcdFx0XHQgKlx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0fSxcclxuXHJcblx0XHRcdFx0LyoqXHJcblx0XHRcdFx0ICogUyB1IGMgYyBlIHMgc1xyXG5cdFx0XHRcdCAqXHJcblx0XHRcdFx0ICogQHBhcmFtIHJlc3BvbnNlX2RhdGFcdFx0LVx0aXRzIG9iamVjdCByZXR1cm5lZCBmcm9tICBBamF4IC0gY2xhc3MtbGl2ZS1zZWFyY2cucGhwXHJcblx0XHRcdFx0ICogQHBhcmFtIHRleHRTdGF0dXNcdFx0LVx0J3N1Y2Nlc3MnXHJcblx0XHRcdFx0ICogQHBhcmFtIGpxWEhSXHRcdFx0XHQtXHRPYmplY3RcclxuXHRcdFx0XHQgKi9cclxuXHRcdFx0XHRmdW5jdGlvbiAoIHJlc3BvbnNlX2RhdGEsIHRleHRTdGF0dXMsIGpxWEhSICkge1xyXG5jb25zb2xlLmxvZyggJyA9PSBSZXNwb25zZSBXUEJDX0FKWF9CT09LSU5HX19DUkVBVEUgPT0gJyApO1xyXG5mb3IgKCB2YXIgb2JqX2tleSBpbiByZXNwb25zZV9kYXRhICl7XHJcblx0Y29uc29sZS5ncm91cENvbGxhcHNlZCggJz09JyArIG9ial9rZXkgKyAnPT0nICk7XHJcblx0Y29uc29sZS5sb2coICcgOiAnICsgb2JqX2tleSArICcgOiAnLCByZXNwb25zZV9kYXRhWyBvYmpfa2V5IF0gKTtcclxuXHRjb25zb2xlLmdyb3VwRW5kKCk7XHJcbn1cclxuY29uc29sZS5ncm91cEVuZCgpO1xyXG5cclxuXHJcblx0XHRcdFx0XHQvLyA8ZWRpdG9yLWZvbGQgICAgIGRlZmF1bHRzdGF0ZT1cImNvbGxhcHNlZFwiICAgICBkZXNjPVwiID0gRXJyb3IgTWVzc2FnZSEgU2VydmVyIHJlc3BvbnNlIHdpdGggU3RyaW5nLiAgLT4gIEVfWF9JX1QgIFwiICA+XHJcblx0XHRcdFx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHRcdFx0XHQvLyBUaGlzIHNlY3Rpb24gZXhlY3V0ZSwgIHdoZW4gc2VydmVyIHJlc3BvbnNlIHdpdGggIFN0cmluZyBpbnN0ZWFkIG9mIE9iamVjdCAtLSBVc3VhbGx5ICBpdCdzIGJlY2F1c2Ugb2YgbWlzdGFrZSBpbiBjb2RlICFcclxuXHRcdFx0XHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdFx0XHRcdGlmICggKHR5cGVvZiByZXNwb25zZV9kYXRhICE9PSAnb2JqZWN0JykgfHwgKHJlc3BvbnNlX2RhdGEgPT09IG51bGwpICl7XHJcblxyXG5cdFx0XHRcdFx0XHR2YXIgY2FsZW5kYXJfaWQgPSB3cGJjX2dldF9yZXNvdXJjZV9pZF9fZnJvbV9hanhfcG9zdF9kYXRhX3VybCggdGhpcy5kYXRhICk7XHJcblx0XHRcdFx0XHRcdHZhciBqcV9ub2RlID0gJyNib29raW5nX2Zvcm0nICsgY2FsZW5kYXJfaWQ7XHJcblxyXG5cdFx0XHRcdFx0XHRpZiAoICcnID09IHJlc3BvbnNlX2RhdGEgKXtcclxuXHRcdFx0XHRcdFx0XHRyZXNwb25zZV9kYXRhID0gJzxzdHJvbmc+JyArICdFcnJvciEgU2VydmVyIHJlc3BvbmQgd2l0aCBlbXB0eSBzdHJpbmchJyArICc8L3N0cm9uZz4gJyA7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0Ly8gU2hvdyBNZXNzYWdlXHJcblx0XHRcdFx0XHRcdHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoIHJlc3BvbnNlX2RhdGEgLCB7ICd0eXBlJyAgICAgOiAnZXJyb3InLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc2hvd19oZXJlJzogeydqcV9ub2RlJzoganFfbm9kZSwgJ3doZXJlJzogJ2FmdGVyJ30sXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdpc19hcHBlbmQnOiB0cnVlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc3R5bGUnICAgIDogJ3RleHQtYWxpZ246bGVmdDsnLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnZGVsYXknICAgIDogMFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cdFx0XHRcdFx0XHQvLyBFbmFibGUgU3VibWl0IHwgSGlkZSBzcGluIGxvYWRlclxyXG5cdFx0XHRcdFx0XHR3cGJjX2Jvb2tpbmdfZm9ybV9fb25fcmVzcG9uc2VfX3VpX2VsZW1lbnRzX2VuYWJsZSggY2FsZW5kYXJfaWQgKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0Ly8gPC9lZGl0b3ItZm9sZD5cclxuXHJcblxyXG5cdFx0XHRcdFx0Ly8gPGVkaXRvci1mb2xkICAgICBkZWZhdWx0c3RhdGU9XCJjb2xsYXBzZWRcIiAgICAgZGVzYz1cIiAgPT0gIFRoaXMgc2VjdGlvbiBleGVjdXRlLCAgd2hlbiB3ZSBoYXZlIEtOT1dOIGVycm9ycyBmcm9tIEJvb2tpbmcgQ2FsZW5kYXIuICAtPiAgRV9YX0lfVCAgXCIgID5cclxuXHRcdFx0XHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdFx0XHRcdC8vIFRoaXMgc2VjdGlvbiBleGVjdXRlLCAgd2hlbiB3ZSBoYXZlIEtOT1dOIGVycm9ycyBmcm9tIEJvb2tpbmcgQ2FsZW5kYXJcclxuXHRcdFx0XHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblx0XHRcdFx0XHRpZiAoICdvaycgIT0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnc3RhdHVzJyBdICkge1xyXG5cclxuXHRcdFx0XHRcdFx0c3dpdGNoICggcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnc3RhdHVzX2Vycm9yJyBdICl7XHJcblxyXG5cdFx0XHRcdFx0XHRcdGNhc2UgJ2NhcHRjaGFfc2ltcGxlX3dyb25nJzpcclxuXHRcdFx0XHRcdFx0XHRcdHdwYmNfY2FwdGNoYV9fc2ltcGxlX191cGRhdGUoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQncmVzb3VyY2VfaWQnOiByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF0sXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3VybCcgICAgICAgIDogcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnY2FwdGNoYV9fc2ltcGxlJyBdWyAndXJsJyBdLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdjaGFsbGVuZ2UnICA6IHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2NhcHRjaGFfX3NpbXBsZScgXVsgJ2NoYWxsZW5nZScgXSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnbWVzc2FnZScgICAgOiByZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdhanhfYWZ0ZXJfYWN0aW9uX21lc3NhZ2UnIF0ucmVwbGFjZSggL1xcbi9nLCBcIjxiciAvPlwiIClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcclxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0XHRcdFx0XHRjYXNlICdyZXNvdXJjZV9pZF9pbmNvcnJlY3QnOlx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gU2hvdyBFcnJvciBNZXNzYWdlIC0gaW5jb3JyZWN0ICBib29raW5nIHJlc291cmNlIElEIGR1cmluZyBzdWJtaXQgb2YgYm9va2luZy5cclxuXHRcdFx0XHRcdFx0XHRcdHZhciBtZXNzYWdlX2lkID0gd3BiY19mcm9udF9lbmRfX3Nob3dfbWVzc2FnZSggcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnYWp4X2FmdGVyX2FjdGlvbl9tZXNzYWdlJyBdLnJlcGxhY2UoIC9cXG4vZywgXCI8YnIgLz5cIiApLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd0eXBlJyA6ICgndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdhanhfYWZ0ZXJfYWN0aW9uX21lc3NhZ2Vfc3RhdHVzJyBdKSlcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ/IHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZV9zdGF0dXMnIF0gOiAnd2FybmluZycsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnZGVsYXknICAgIDogMCxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzaG93X2hlcmUnOiB7ICd3aGVyZSc6ICdhZnRlcicsICdqcV9ub2RlJzogJyNib29raW5nX2Zvcm0nICsgcGFyYW1zWyAncmVzb3VyY2VfaWQnIF0gfVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0XHRcdFx0XHRjYXNlICdib29raW5nX2Nhbl9ub3Rfc2F2ZSc6XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBXZSBjYW4gbm90IHNhdmUgYm9va2luZywgYmVjYXVzZSBkYXRlcyBhcmUgYm9va2VkIG9yIGNhbiBub3Qgc2F2ZSBpbiBzYW1lIGJvb2tpbmcgcmVzb3VyY2UgYWxsIHRoZSBkYXRlc1xyXG5cdFx0XHRcdFx0XHRcdFx0dmFyIG1lc3NhZ2VfaWQgPSB3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlKCByZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdhanhfYWZ0ZXJfYWN0aW9uX21lc3NhZ2UnIF0ucmVwbGFjZSggL1xcbi9nLCBcIjxiciAvPlwiICksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0e1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3R5cGUnIDogKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgKHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZV9zdGF0dXMnIF0pKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdD8gcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnYWp4X2FmdGVyX2FjdGlvbl9tZXNzYWdlX3N0YXR1cycgXSA6ICd3YXJuaW5nJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdkZWxheScgICAgOiAwLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3Nob3dfaGVyZSc6IHsgJ3doZXJlJzogJ2FmdGVyJywgJ2pxX25vZGUnOiAnI2Jvb2tpbmdfZm9ybScgKyBwYXJhbXNbICdyZXNvdXJjZV9pZCcgXSB9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cclxuXHRcdFx0XHRcdFx0XHRcdC8vIEVuYWJsZSBTdWJtaXQgfCBIaWRlIHNwaW4gbG9hZGVyXHJcblx0XHRcdFx0XHRcdFx0XHR3cGJjX2Jvb2tpbmdfZm9ybV9fb25fcmVzcG9uc2VfX3VpX2VsZW1lbnRzX2VuYWJsZSggcmVzcG9uc2VfZGF0YVsgJ3Jlc291cmNlX2lkJyBdICk7XHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblxyXG5cclxuXHRcdFx0XHRcdFx0XHRkZWZhdWx0OlxyXG5cclxuXHRcdFx0XHRcdFx0XHRcdC8vIDxlZGl0b3ItZm9sZCAgICAgZGVmYXVsdHN0YXRlPVwiY29sbGFwc2VkXCIgICAgICAgICAgICAgICAgICAgICAgICBkZXNjPVwiID0gRm9yIGRlYnVnIG9ubHkgPyAtLSAgU2hvdyBNZXNzYWdlIHVuZGVyIHRoZSBmb3JtID0gXCIgID5cclxuXHRcdFx0XHRcdFx0XHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHRcdFx0XHRcdFx0XHRpZiAoXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0KCAndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdhanhfYWZ0ZXJfYWN0aW9uX21lc3NhZ2UnIF0pIClcclxuXHRcdFx0XHRcdFx0XHRcdFx0ICYmICggJycgIT0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnYWp4X2FmdGVyX2FjdGlvbl9tZXNzYWdlJyBdLnJlcGxhY2UoIC9cXG4vZywgXCI8YnIgLz5cIiApIClcclxuXHRcdFx0XHRcdFx0XHRcdCl7XHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0XHR2YXIgY2FsZW5kYXJfaWQgPSB3cGJjX2dldF9yZXNvdXJjZV9pZF9fZnJvbV9hanhfcG9zdF9kYXRhX3VybCggdGhpcy5kYXRhICk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHZhciBqcV9ub2RlID0gJyNib29raW5nX2Zvcm0nICsgY2FsZW5kYXJfaWQ7XHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0XHR2YXIgYWp4X2FmdGVyX2Jvb2tpbmdfbWVzc2FnZSA9IHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZScgXS5yZXBsYWNlKCAvXFxuL2csIFwiPGJyIC8+XCIgKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKCBhanhfYWZ0ZXJfYm9va2luZ19tZXNzYWdlICk7XHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0XHQvKipcclxuXHRcdFx0XHRcdFx0XHRcdFx0ICogLy8gU2hvdyBNZXNzYWdlXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyIGFqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZV9pZCA9IHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2UoIGFqeF9hZnRlcl9ib29raW5nX21lc3NhZ2UsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd0eXBlJyA6ICgndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdhanhfYWZ0ZXJfYWN0aW9uX21lc3NhZ2Vfc3RhdHVzJyBdKSlcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdD8gcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnYWp4X2FmdGVyX2FjdGlvbl9tZXNzYWdlX3N0YXR1cycgXSA6ICdpbmZvJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2RlbGF5JyAgICA6IDEwMDAwLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc2hvd19oZXJlJzoge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdqcV9ub2RlJzoganFfbm9kZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnd2hlcmUnICA6ICdhZnRlcidcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0IH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHQvLyA8L2VkaXRvci1mb2xkPlxyXG5cdFx0XHRcdFx0XHR9XHJcblxyXG5cclxuXHRcdFx0XHRcdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0XHRcdFx0XHQvLyBSZWFjdGl2YXRlIGNhbGVuZGFyIGFnYWluID9cclxuXHRcdFx0XHRcdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0XHRcdFx0XHQvLyBFbmFibGUgU3VibWl0IHwgSGlkZSBzcGluIGxvYWRlclxyXG5cdFx0XHRcdFx0XHR3cGJjX2Jvb2tpbmdfZm9ybV9fb25fcmVzcG9uc2VfX3VpX2VsZW1lbnRzX2VuYWJsZSggcmVzcG9uc2VfZGF0YVsgJ3Jlc291cmNlX2lkJyBdICk7XHJcblxyXG5cdFx0XHRcdFx0XHQvLyBVbnNlbGVjdCAgZGF0ZXNcclxuXHRcdFx0XHRcdFx0d3BiY19jYWxlbmRhcl9fdW5zZWxlY3RfYWxsX2RhdGVzKCByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF0gKTtcclxuXHJcblx0XHRcdFx0XHRcdC8vICdyZXNvdXJjZV9pZCcgICAgPT4gJHBhcmFtc1sncmVzb3VyY2VfaWQnXSxcclxuXHRcdFx0XHRcdFx0Ly8gJ2Jvb2tpbmdfaGFzaCcgICA9PiAkYm9va2luZ19oYXNoLFxyXG5cdFx0XHRcdFx0XHQvLyAncmVxdWVzdF91cmknICAgID0+ICRfU0VSVkVSWydSRVFVRVNUX1VSSSddLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSXMgaXQgdGhlIHNhbWUgYXMgd2luZG93LmxvY2F0aW9uLmhyZWYgb3JcclxuXHRcdFx0XHRcdFx0Ly8gJ2N1c3RvbV9mb3JtJyAgICA9PiAkcGFyYW1zWydjdXN0b21fZm9ybSddLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wdGlvbmFsLlxyXG5cdFx0XHRcdFx0XHQvLyAnYWdncmVnYXRlX3Jlc291cmNlX2lkX3N0cicgPT4gaW1wbG9kZSggJywnLCAkcGFyYW1zWydhZ2dyZWdhdGVfcmVzb3VyY2VfaWRfYXJyJ10gKSAgICAgLy8gT3B0aW9uYWwuIFJlc291cmNlIElEICAgZnJvbSAgYWdncmVnYXRlIHBhcmFtZXRlciBpbiBzaG9ydGNvZGUuXHJcblxyXG5cdFx0XHRcdFx0XHQvLyBMb2FkIG5ldyBkYXRhIGluIGNhbGVuZGFyLlxyXG5cdFx0XHRcdFx0XHR3cGJjX2NhbGVuZGFyX19sb2FkX2RhdGFfX2FqeCgge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICAncmVzb3VyY2VfaWQnIDogcmVzcG9uc2VfZGF0YVsgJ3Jlc291cmNlX2lkJyBdXHRcdFx0XHRcdFx0XHQvLyBJdCdzIGZyb20gcmVzcG9uc2UgLi4uQUpYX0JPT0tJTkdfX0NSRUFURSBvZiBpbml0aWFsIHNlbnQgcmVzb3VyY2VfaWRcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCwgJ2Jvb2tpbmdfaGFzaCc6IHJlc3BvbnNlX2RhdGFbICdhanhfY2xlYW5lZF9wYXJhbXMnIF1bJ2Jvb2tpbmdfaGFzaCddIFx0Ly8gPz8gd2UgY2FuIG5vdCB1c2UgaXQsICBiZWNhdXNlIEhBU0ggY2huYWdlZCBpbiBhbnkgIGNhc2UhXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsICdyZXF1ZXN0X3VyaScgOiByZXNwb25zZV9kYXRhWyAnYWp4X2NsZWFuZWRfcGFyYW1zJyBdWydyZXF1ZXN0X3VyaSddXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsICdjdXN0b21fZm9ybScgOiByZXNwb25zZV9kYXRhWyAnYWp4X2NsZWFuZWRfcGFyYW1zJyBdWydjdXN0b21fZm9ybSddXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQWdncmVnYXRlIGJvb2tpbmcgcmVzb3VyY2VzLCAgaWYgYW55ID9cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCwgJ2FnZ3JlZ2F0ZV9yZXNvdXJjZV9pZF9zdHInIDogX3dwYmMuYm9va2luZ19fZ2V0X3BhcmFtX3ZhbHVlKCByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF0sICdhZ2dyZWdhdGVfcmVzb3VyY2VfaWRfYXJyJyApLmpvaW4oJywnKVxyXG5cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9ICk7XHJcblx0XHRcdFx0XHRcdC8vIEV4aXRcclxuXHRcdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdC8vIDwvZWRpdG9yLWZvbGQ+XHJcblxyXG5cclxuLypcclxuXHQvLyBTaG93IENhbGVuZGFyXHJcblx0d3BiY19jYWxlbmRhcl9fbG9hZGluZ19fc3RvcCggcmVzcG9uc2VfZGF0YVsgJ3Jlc291cmNlX2lkJyBdICk7XHJcblxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBCb29raW5ncyAtIERhdGVzXHJcblx0X3dwYmMuYm9va2luZ3NfaW5fY2FsZW5kYXJfX3NldF9kYXRlcyggIHJlc3BvbnNlX2RhdGFbICdyZXNvdXJjZV9pZCcgXSwgcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWydkYXRlcyddICApO1xyXG5cclxuXHQvLyBCb29raW5ncyAtIENoaWxkIG9yIG9ubHkgc2luZ2xlIGJvb2tpbmcgcmVzb3VyY2UgaW4gZGF0ZXNcclxuXHRfd3BiYy5ib29raW5nX19zZXRfcGFyYW1fdmFsdWUoIHJlc3BvbnNlX2RhdGFbICdyZXNvdXJjZV9pZCcgXSwgJ3Jlc291cmNlc19pZF9hcnJfX2luX2RhdGVzJywgcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAncmVzb3VyY2VzX2lkX2Fycl9faW5fZGF0ZXMnIF0gKTtcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5cdC8vIFVwZGF0ZSBjYWxlbmRhclxyXG5cdHdwYmNfY2FsZW5kYXJfX3VwZGF0ZV9sb29rKCByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF0gKTtcclxuKi9cclxuXHJcblx0XHRcdFx0XHQvLyBIaWRlIHNwaW4gbG9hZGVyXHJcblx0XHRcdFx0XHR3cGJjX2Jvb2tpbmdfZm9ybV9fc3Bpbl9sb2FkZXJfX2hpZGUoIHJlc3BvbnNlX2RhdGFbICdyZXNvdXJjZV9pZCcgXSApO1xyXG5cclxuXHRcdFx0XHRcdC8vIEhpZGUgYm9va2luZyBmb3JtXHJcblx0XHRcdFx0XHR3cGJjX2Jvb2tpbmdfZm9ybV9fYW5pbWF0ZWRfX2hpZGUoIHJlc3BvbnNlX2RhdGFbICdyZXNvdXJjZV9pZCcgXSApO1xyXG5cclxuXHRcdFx0XHRcdC8vIFNob3cgQ29uZmlybWF0aW9uIHwgUGF5bWVudCBzZWN0aW9uXHJcblx0XHRcdFx0XHR3cGJjX3Nob3dfdGhhbmtfeW91X21lc3NhZ2VfYWZ0ZXJfYm9va2luZyggcmVzcG9uc2VfZGF0YSApO1xyXG5cclxuXHRcdFx0XHRcdHNldFRpbWVvdXQoIGZ1bmN0aW9uICgpe1xyXG5cdFx0XHRcdFx0XHR3cGJjX2RvX3Njcm9sbCggJyN3cGJjX3Njcm9sbF9wb2ludF8nICsgcmVzcG9uc2VfZGF0YVsgJ3Jlc291cmNlX2lkJyBdLCAxMCApO1xyXG5cdFx0XHRcdFx0fSwgNTAwICk7XHJcblxyXG5cclxuXHJcblx0XHRcdFx0fVxyXG5cdFx0XHQgICkuZmFpbChcclxuXHRcdFx0XHQgIC8vIDxlZGl0b3ItZm9sZCAgICAgZGVmYXVsdHN0YXRlPVwiY29sbGFwc2VkXCIgICAgICAgICAgICAgICAgICAgICAgICBkZXNjPVwiID0gVGhpcyBzZWN0aW9uIGV4ZWN1dGUsICB3aGVuICBOT05DRSBmaWVsZCB3YXMgbm90IHBhc3NlZCBvciBzb21lIGVycm9yIGhhcHBlbmVkIGF0ICBzZXJ2ZXIhID0gXCIgID5cclxuXHRcdFx0XHQgIGZ1bmN0aW9uICgganFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duICkgeyAgICBpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLmxvZyApeyBjb25zb2xlLmxvZyggJ0FqYXhfRXJyb3InLCBqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24gKTsgfVxyXG5cclxuXHRcdFx0XHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdFx0XHRcdC8vIFRoaXMgc2VjdGlvbiBleGVjdXRlLCAgd2hlbiAgTk9OQ0UgZmllbGQgd2FzIG5vdCBwYXNzZWQgb3Igc29tZSBlcnJvciBoYXBwZW5lZCBhdCAgc2VydmVyIVxyXG5cdFx0XHRcdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHRcdFx0XHRcdC8vIEdldCBDb250ZW50IG9mIEVycm9yIE1lc3NhZ2VcclxuXHRcdFx0XHRcdHZhciBlcnJvcl9tZXNzYWdlID0gJzxzdHJvbmc+JyArICdFcnJvciEnICsgJzwvc3Ryb25nPiAnICsgZXJyb3JUaHJvd24gO1xyXG5cdFx0XHRcdFx0aWYgKCBqcVhIUi5zdGF0dXMgKXtcclxuXHRcdFx0XHRcdFx0ZXJyb3JfbWVzc2FnZSArPSAnICg8Yj4nICsganFYSFIuc3RhdHVzICsgJzwvYj4pJztcclxuXHRcdFx0XHRcdFx0aWYgKDQwMyA9PSBqcVhIUi5zdGF0dXMgKXtcclxuXHRcdFx0XHRcdFx0XHRlcnJvcl9tZXNzYWdlICs9ICc8YnI+IFByb2JhYmx5IG5vbmNlIGZvciB0aGlzIHBhZ2UgaGFzIGJlZW4gZXhwaXJlZC4gUGxlYXNlIDxhIGhyZWY9XCJqYXZhc2NyaXB0OnZvaWQoMClcIiBvbmNsaWNrPVwiamF2YXNjcmlwdDpsb2NhdGlvbi5yZWxvYWQoKTtcIj5yZWxvYWQgdGhlIHBhZ2U8L2E+Lic7XHJcblx0XHRcdFx0XHRcdFx0ZXJyb3JfbWVzc2FnZSArPSAnPGJyPiBPdGhlcndpc2UsIHBsZWFzZSBjaGVjayB0aGlzIDxhIHN0eWxlPVwiZm9udC13ZWlnaHQ6IDYwMDtcIiBocmVmPVwiaHR0cHM6Ly93cGJvb2tpbmdjYWxlbmRhci5jb20vZmFxL3JlcXVlc3QtZG8tbm90LXBhc3Mtc2VjdXJpdHktY2hlY2svXCI+dHJvdWJsZXNob290aW5nIGluc3RydWN0aW9uPC9hPi48YnI+J1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRpZiAoIGpxWEhSLnJlc3BvbnNlVGV4dCApe1xyXG5cdFx0XHRcdFx0XHQvLyBFc2NhcGUgdGFncyBpbiBFcnJvciBtZXNzYWdlXHJcblx0XHRcdFx0XHRcdGVycm9yX21lc3NhZ2UgKz0gJzxicj48c3Ryb25nPlJlc3BvbnNlPC9zdHJvbmc+PGRpdiBzdHlsZT1cInBhZGRpbmc6IDAgMTBweDttYXJnaW46IDAgMCAxMHB4O2JvcmRlci1yYWRpdXM6M3B4OyBib3gtc2hhZG93OjBweCAwcHggMXB4ICNhM2EzYTM7XCI+JyArIGpxWEhSLnJlc3BvbnNlVGV4dC5yZXBsYWNlKC8mL2csIFwiJmFtcDtcIilcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgLnJlcGxhY2UoLzwvZywgXCImbHQ7XCIpXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0IC5yZXBsYWNlKC8+L2csIFwiJmd0O1wiKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAucmVwbGFjZSgvXCIvZywgXCImcXVvdDtcIilcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgLnJlcGxhY2UoLycvZywgXCImIzM5O1wiKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCsnPC9kaXY+JztcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVycm9yX21lc3NhZ2UgPSBlcnJvcl9tZXNzYWdlLnJlcGxhY2UoIC9cXG4vZywgXCI8YnIgLz5cIiApO1xyXG5cclxuXHRcdFx0XHRcdHZhciBjYWxlbmRhcl9pZCA9IHdwYmNfZ2V0X3Jlc291cmNlX2lkX19mcm9tX2FqeF9wb3N0X2RhdGFfdXJsKCB0aGlzLmRhdGEgKTtcclxuXHRcdFx0XHRcdHZhciBqcV9ub2RlID0gJyNib29raW5nX2Zvcm0nICsgY2FsZW5kYXJfaWQ7XHJcblxyXG5cdFx0XHRcdFx0Ly8gU2hvdyBNZXNzYWdlXHJcblx0XHRcdFx0XHR3cGJjX2Zyb250X2VuZF9fc2hvd19tZXNzYWdlKCBlcnJvcl9tZXNzYWdlICwgeyAndHlwZScgICAgIDogJ2Vycm9yJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdzaG93X2hlcmUnOiB7J2pxX25vZGUnOiBqcV9ub2RlLCAnd2hlcmUnOiAnYWZ0ZXInfSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdpc19hcHBlbmQnOiB0cnVlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3N0eWxlJyAgICA6ICd0ZXh0LWFsaWduOmxlZnQ7JyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdkZWxheScgICAgOiAwXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cdFx0XHRcdFx0Ly8gRW5hYmxlIFN1Ym1pdCB8IEhpZGUgc3BpbiBsb2FkZXJcclxuXHRcdFx0XHRcdHdwYmNfYm9va2luZ19mb3JtX19vbl9yZXNwb25zZV9fdWlfZWxlbWVudHNfZW5hYmxlKCBjYWxlbmRhcl9pZCApO1xyXG5cdFx0XHQgIFx0IH1cclxuXHRcdFx0XHQgLy8gPC9lZGl0b3ItZm9sZD5cclxuXHRcdFx0ICApXHJcblx0ICAgICAgICAgIC8vIC5kb25lKCAgIGZ1bmN0aW9uICggZGF0YSwgdGV4dFN0YXR1cywganFYSFIgKSB7ICAgaWYgKCB3aW5kb3cuY29uc29sZSAmJiB3aW5kb3cuY29uc29sZS5sb2cgKXsgY29uc29sZS5sb2coICdzZWNvbmQgc3VjY2VzcycsIGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSICk7IH0gICAgfSlcclxuXHRcdFx0ICAvLyAuYWx3YXlzKCBmdW5jdGlvbiAoIGRhdGFfanFYSFIsIHRleHRTdGF0dXMsIGpxWEhSX2Vycm9yVGhyb3duICkgeyAgIGlmICggd2luZG93LmNvbnNvbGUgJiYgd2luZG93LmNvbnNvbGUubG9nICl7IGNvbnNvbGUubG9nKCAnYWx3YXlzIGZpbmlzaGVkJywgZGF0YV9qcVhIUiwgdGV4dFN0YXR1cywganFYSFJfZXJyb3JUaHJvd24gKTsgfSAgICAgfSlcclxuXHRcdFx0ICA7ICAvLyBFbmQgQWpheFxyXG5cclxuXHRyZXR1cm4gdHJ1ZTtcclxufVxyXG5cclxuXHJcblx0Ly8gPGVkaXRvci1mb2xkICAgICBkZWZhdWx0c3RhdGU9XCJjb2xsYXBzZWRcIiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2M9XCIgID09ICBDQVBUQ0hBID09ICBcIiAgPlxyXG5cclxuXHQvKipcclxuXHQgKiBVcGRhdGUgaW1hZ2UgaW4gY2FwdGNoYSBhbmQgc2hvdyB3YXJuaW5nIG1lc3NhZ2VcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSBwYXJhbXNcclxuXHQgKlxyXG5cdCAqIEV4YW1wbGUgb2YgJ3BhcmFtcycgOiB7XHJcblx0ICpcdFx0XHRcdFx0XHRcdCdyZXNvdXJjZV9pZCc6IHJlc3BvbnNlX2RhdGFbICdyZXNvdXJjZV9pZCcgXSxcclxuXHQgKlx0XHRcdFx0XHRcdFx0J3VybCcgICAgICAgIDogcmVzcG9uc2VfZGF0YVsgJ2FqeF9kYXRhJyBdWyAnY2FwdGNoYV9fc2ltcGxlJyBdWyAndXJsJyBdLFxyXG5cdCAqXHRcdFx0XHRcdFx0XHQnY2hhbGxlbmdlJyAgOiByZXNwb25zZV9kYXRhWyAnYWp4X2RhdGEnIF1bICdjYXB0Y2hhX19zaW1wbGUnIF1bICdjaGFsbGVuZ2UnIF0sXHJcblx0ICpcdFx0XHRcdFx0XHRcdCdtZXNzYWdlJyAgICA6IHJlc3BvbnNlX2RhdGFbICdhanhfZGF0YScgXVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZScgXS5yZXBsYWNlKCAvXFxuL2csIFwiPGJyIC8+XCIgKVxyXG5cdCAqXHRcdFx0XHRcdFx0fVxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfY2FwdGNoYV9fc2ltcGxlX191cGRhdGUoIHBhcmFtcyApe1xyXG5cclxuXHRcdGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCAnY2FwdGNoYV9pbnB1dCcgKyBwYXJhbXNbICdyZXNvdXJjZV9pZCcgXSApLnZhbHVlID0gJyc7XHJcblx0XHRkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggJ2NhcHRjaGFfaW1nJyArIHBhcmFtc1sgJ3Jlc291cmNlX2lkJyBdICkuc3JjID0gcGFyYW1zWyAndXJsJyBdO1xyXG5cdFx0ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoICd3cGRldl9jYXB0Y2hhX2NoYWxsZW5nZV8nICsgcGFyYW1zWyAncmVzb3VyY2VfaWQnIF0gKS52YWx1ZSA9IHBhcmFtc1sgJ2NoYWxsZW5nZScgXTtcclxuXHJcblx0XHQvLyBTaG93IHdhcm5pbmcgXHRcdEFmdGVyIENBUFRDSEEgSW1nXHJcblx0XHR2YXIgbWVzc2FnZV9pZCA9IHdwYmNfZnJvbnRfZW5kX19zaG93X21lc3NhZ2VfX3dhcm5pbmcoICcjY2FwdGNoYV9pbnB1dCcgKyBwYXJhbXNbICdyZXNvdXJjZV9pZCcgXSArICcgKyBpbWcnLCBwYXJhbXNbICdtZXNzYWdlJyBdICk7XHJcblxyXG5cdFx0Ly8gQW5pbWF0ZVxyXG5cdFx0alF1ZXJ5KCAnIycgKyBtZXNzYWdlX2lkICsgJywgJyArICcjY2FwdGNoYV9pbnB1dCcgKyBwYXJhbXNbICdyZXNvdXJjZV9pZCcgXSApLmZhZGVPdXQoIDM1MCApLmZhZGVJbiggMzAwICkuZmFkZU91dCggMzUwICkuZmFkZUluKCA0MDAgKS5hbmltYXRlKCB7b3BhY2l0eTogMX0sIDQwMDAgKTtcclxuXHRcdC8vIEZvY3VzIHRleHQgIGZpZWxkXHJcblx0XHRqUXVlcnkoICcjY2FwdGNoYV9pbnB1dCcgKyBwYXJhbXNbICdyZXNvdXJjZV9pZCcgXSApLnRyaWdnZXIoICdmb2N1cycgKTsgICAgXHRcdFx0XHRcdFx0XHRcdFx0Ly9GaXhJbjogOC43LjExLjEyXHJcblxyXG5cclxuXHRcdC8vIEVuYWJsZSBTdWJtaXQgfCBIaWRlIHNwaW4gbG9hZGVyXHJcblx0XHR3cGJjX2Jvb2tpbmdfZm9ybV9fb25fcmVzcG9uc2VfX3VpX2VsZW1lbnRzX2VuYWJsZSggcGFyYW1zWyAncmVzb3VyY2VfaWQnIF0gKTtcclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBJZiB0aGUgY2FwdGNoYSBlbGVtZW50cyBub3QgZXhpc3QgIGluIHRoZSBib29raW5nIGZvcm0sICB0aGVuICByZW1vdmUgcGFyYW1ldGVycyByZWxhdGl2ZSBjYXB0Y2hhXHJcblx0ICogQHBhcmFtIHBhcmFtc1xyXG5cdCAqIEByZXR1cm5zIG9ialxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfY2FwdGNoYV9fc2ltcGxlX19tYXliZV9yZW1vdmVfaW5fYWp4X3BhcmFtcyggcGFyYW1zICl7XHJcblxyXG5cdFx0aWYgKCAhIHdwYmNfY2FwdGNoYV9fc2ltcGxlX19pc19leGlzdF9pbl9mb3JtKCBwYXJhbXNbICdyZXNvdXJjZV9pZCcgXSApICl7XHJcblx0XHRcdGRlbGV0ZSBwYXJhbXNbICdjYXB0Y2hhX2NoYWxhbmdlJyBdO1xyXG5cdFx0XHRkZWxldGUgcGFyYW1zWyAnY2FwdGNoYV91c2VyX2lucHV0JyBdO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHBhcmFtcztcclxuXHR9XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBDaGVjayBpZiBDQVBUQ0hBIGV4aXN0IGluIHRoZSBib29raW5nIGZvcm1cclxuXHQgKiBAcGFyYW0gcmVzb3VyY2VfaWRcclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2NhcHRjaGFfX3NpbXBsZV9faXNfZXhpc3RfaW5fZm9ybSggcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0XHRyZXR1cm4gKFxyXG5cdFx0XHRcdFx0XHQoMCAhPT0galF1ZXJ5KCAnI3dwZGV2X2NhcHRjaGFfY2hhbGxlbmdlXycgKyByZXNvdXJjZV9pZCApLmxlbmd0aClcclxuXHRcdFx0XHRcdCB8fCAoMCAhPT0galF1ZXJ5KCAnI2NhcHRjaGFfaW5wdXQnICsgcmVzb3VyY2VfaWQgKS5sZW5ndGgpXHJcblx0XHRcdFx0KTtcclxuXHR9XHJcblxyXG5cdC8vIDwvZWRpdG9yLWZvbGQ+XHJcblxyXG5cclxuXHQvLyA8ZWRpdG9yLWZvbGQgICAgIGRlZmF1bHRzdGF0ZT1cImNvbGxhcHNlZFwiICAgICAgICAgICAgICAgICAgICAgICAgZGVzYz1cIiAgPT0gIFNlbmQgQnV0dG9uIHwgRm9ybSBTcGluIExvYWRlciAgPT0gIFwiICA+XHJcblxyXG5cdC8qKlxyXG5cdCAqIERpc2FibGUgU2VuZCBidXR0b24gIHwgIFNob3cgU3BpbiBMb2FkZXJcclxuXHQgKlxyXG5cdCAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfYm9va2luZ19mb3JtX19vbl9zdWJtaXRfX3VpX2VsZW1lbnRzX2Rpc2FibGUoIHJlc291cmNlX2lkICl7XHJcblxyXG5cdFx0Ly8gRGlzYWJsZSBTdWJtaXRcclxuXHRcdHdwYmNfYm9va2luZ19mb3JtX19zZW5kX2J1dHRvbl9fZGlzYWJsZSggcmVzb3VyY2VfaWQgKTtcclxuXHJcblx0XHQvLyBTaG93IFNwaW4gbG9hZGVyIGluIGJvb2tpbmcgZm9ybVxyXG5cdFx0d3BiY19ib29raW5nX2Zvcm1fX3NwaW5fbG9hZGVyX19zaG93KCByZXNvdXJjZV9pZCApO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogRW5hYmxlIFNlbmQgYnV0dG9uICB8ICAgSGlkZSBTcGluIExvYWRlclxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gd3BiY19ib29raW5nX2Zvcm1fX29uX3Jlc3BvbnNlX191aV9lbGVtZW50c19lbmFibGUocmVzb3VyY2VfaWQpe1xyXG5cclxuXHRcdC8vIEVuYWJsZSBTdWJtaXRcclxuXHRcdHdwYmNfYm9va2luZ19mb3JtX19zZW5kX2J1dHRvbl9fZW5hYmxlKCByZXNvdXJjZV9pZCApO1xyXG5cclxuXHRcdC8vIEhpZGUgU3BpbiBsb2FkZXIgaW4gYm9va2luZyBmb3JtXHJcblx0XHR3cGJjX2Jvb2tpbmdfZm9ybV9fc3Bpbl9sb2FkZXJfX2hpZGUoIHJlc291cmNlX2lkICk7XHJcblx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogRW5hYmxlIFN1Ym1pdCBidXR0b25cclxuXHRcdCAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG5cdFx0ICovXHJcblx0XHRmdW5jdGlvbiB3cGJjX2Jvb2tpbmdfZm9ybV9fc2VuZF9idXR0b25fX2VuYWJsZSggcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0XHRcdC8vIEFjdGl2YXRlIFNlbmQgYnV0dG9uXHJcblx0XHRcdGpRdWVyeSggJyNib29raW5nX2Zvcm1fZGl2JyArIHJlc291cmNlX2lkICsgJyBpbnB1dFt0eXBlPWJ1dHRvbl0nICkucHJvcCggXCJkaXNhYmxlZFwiLCBmYWxzZSApO1xyXG5cdFx0XHRqUXVlcnkoICcjYm9va2luZ19mb3JtX2RpdicgKyByZXNvdXJjZV9pZCArICcgYnV0dG9uJyApLnByb3AoIFwiZGlzYWJsZWRcIiwgZmFsc2UgKTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIERpc2FibGUgU3VibWl0IGJ1dHRvbiAgYW5kIHNob3cgIHNwaW5cclxuXHRcdCAqXHJcblx0XHQgKiBAcGFyYW0gcmVzb3VyY2VfaWRcclxuXHRcdCAqL1xyXG5cdFx0ZnVuY3Rpb24gd3BiY19ib29raW5nX2Zvcm1fX3NlbmRfYnV0dG9uX19kaXNhYmxlKCByZXNvdXJjZV9pZCApe1xyXG5cclxuXHRcdFx0Ly8gRGlzYWJsZSBTZW5kIGJ1dHRvblxyXG5cdFx0XHRqUXVlcnkoICcjYm9va2luZ19mb3JtX2RpdicgKyByZXNvdXJjZV9pZCArICcgaW5wdXRbdHlwZT1idXR0b25dJyApLnByb3AoIFwiZGlzYWJsZWRcIiwgdHJ1ZSApO1xyXG5cdFx0XHRqUXVlcnkoICcjYm9va2luZ19mb3JtX2RpdicgKyByZXNvdXJjZV9pZCArICcgYnV0dG9uJyApLnByb3AoIFwiZGlzYWJsZWRcIiwgdHJ1ZSApO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogU2hvdyBib29raW5nIGZvcm0gIFNwaW4gTG9hZGVyXHJcblx0XHQgKiBAcGFyYW0gcmVzb3VyY2VfaWRcclxuXHRcdCAqL1xyXG5cdFx0ZnVuY3Rpb24gd3BiY19ib29raW5nX2Zvcm1fX3NwaW5fbG9hZGVyX19zaG93KCByZXNvdXJjZV9pZCApe1xyXG5cclxuXHRcdFx0Ly8gU2hvdyBTcGluIExvYWRlclxyXG5cdFx0XHRqUXVlcnkoICcjYm9va2luZ19mb3JtJyArIHJlc291cmNlX2lkICkuYWZ0ZXIoXHJcblx0XHRcdFx0JzxkaXYgaWQ9XCJ3cGJjX2Jvb2tpbmdfZm9ybV9zcGluX2xvYWRlcicgKyByZXNvdXJjZV9pZCArICdcIiBjbGFzcz1cIndwYmNfYm9va2luZ19mb3JtX3NwaW5fbG9hZGVyXCIgc3R5bGU9XCJwb3NpdGlvbjogcmVsYXRpdmU7XCI+PGRpdiBjbGFzcz1cIndwYmNfc3BpbnNfbG9hZGVyX3dyYXBwZXJcIj48ZGl2IGNsYXNzPVwid3BiY19zcGluc19sb2FkZXJfbWluaVwiPjwvZGl2PjwvZGl2PjwvZGl2PidcclxuXHRcdFx0KTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIFJlbW92ZSAvIEhpZGUgYm9va2luZyBmb3JtICBTcGluIExvYWRlclxyXG5cdFx0ICogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0XHQgKi9cclxuXHRcdGZ1bmN0aW9uIHdwYmNfYm9va2luZ19mb3JtX19zcGluX2xvYWRlcl9faGlkZSggcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0XHRcdC8vIFJlbW92ZSBTcGluIExvYWRlclxyXG5cdFx0XHRqUXVlcnkoICcjd3BiY19ib29raW5nX2Zvcm1fc3Bpbl9sb2FkZXInICsgcmVzb3VyY2VfaWQgKS5yZW1vdmUoKTtcclxuXHRcdH1cclxuXHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBIaWRlIGJvb2tpbmcgZm9ybSB3dGggYW5pbWF0aW9uXHJcblx0XHQgKlxyXG5cdFx0ICogQHBhcmFtIHJlc291cmNlX2lkXHJcblx0XHQgKi9cclxuXHRcdGZ1bmN0aW9uIHdwYmNfYm9va2luZ19mb3JtX19hbmltYXRlZF9faGlkZSggcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0XHRcdC8vIGpRdWVyeSggJyNib29raW5nX2Zvcm0nICsgcmVzb3VyY2VfaWQgKS5zbGlkZVVwKCAgMTAwMFxyXG5cdFx0XHQvLyBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsIGZ1bmN0aW9uICgpe1xyXG5cdFx0XHQvL1xyXG5cdFx0XHQvLyBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gaWYgKCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggJ2dhdGV3YXlfcGF5bWVudF9mb3JtcycgKyByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF0gKSAhPSBudWxsICl7XHJcblx0XHRcdC8vIFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBcdHdwYmNfZG9fc2Nyb2xsKCAnI3N1Ym1pdGluZycgKyByZXNvdXJjZV9pZCApO1xyXG5cdFx0XHQvLyBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gfSBlbHNlXHJcblx0XHRcdC8vIFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeSggJyNib29raW5nX2Zvcm0nICsgcmVzb3VyY2VfaWQgKS5wYXJlbnQoKS5maW5kKCAnLnN1Ym1pdGluZ19jb250ZW50JyApLmxlbmd0aCA+IDAgKXtcclxuXHRcdFx0Ly8gXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly93cGJjX2RvX3Njcm9sbCggJyNib29raW5nX2Zvcm0nICsgcmVzb3VyY2VfaWQgKyAnICsgLnN1Ym1pdGluZ19jb250ZW50JyApO1xyXG5cdFx0XHQvL1xyXG5cdFx0XHQvLyBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgdmFyIGhpZGVUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdC8vIFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQgIHdwYmNfZG9fc2Nyb2xsKCBqUXVlcnkoICcjYm9va2luZ19mb3JtJyArIHJlc291cmNlX2lkICkucGFyZW50KCkuZmluZCggJy5zdWJtaXRpbmdfY29udGVudCcgKS5nZXQoIDAgKSApO1xyXG5cdFx0XHQvLyBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSwgMTAwKTtcclxuXHRcdFx0Ly9cclxuXHRcdFx0Ly8gXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0Ly8gXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ICB9XHJcblx0XHRcdC8vIFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcclxuXHJcblx0XHRcdGpRdWVyeSggJyNib29raW5nX2Zvcm0nICsgcmVzb3VyY2VfaWQgKS5oaWRlKCk7XHJcblxyXG5cdFx0XHQvLyB2YXIgaGlkZVRpbWVvdXQgPSBzZXRUaW1lb3V0KCBmdW5jdGlvbiAoKXtcclxuXHRcdFx0Ly9cclxuXHRcdFx0Ly8gXHRpZiAoIGpRdWVyeSggJyNib29raW5nX2Zvcm0nICsgcmVzb3VyY2VfaWQgKS5wYXJlbnQoKS5maW5kKCAnLnN1Ym1pdGluZ19jb250ZW50JyApLmxlbmd0aCA+IDAgKXtcclxuXHRcdFx0Ly8gXHRcdHZhciByYW5kb21faWQgPSBNYXRoLmZsb29yKCAoTWF0aC5yYW5kb20oKSAqIDEwMDAwKSArIDEgKTtcclxuXHRcdFx0Ly8gXHRcdGpRdWVyeSggJyNib29raW5nX2Zvcm0nICsgcmVzb3VyY2VfaWQgKS5wYXJlbnQoKS5iZWZvcmUoICc8ZGl2IGlkPVwic2Nyb2xsX3RvJyArIHJhbmRvbV9pZCArICdcIj48L2Rpdj4nICk7XHJcblx0XHRcdC8vIFx0XHRjb25zb2xlLmxvZyggalF1ZXJ5KCAnI3Njcm9sbF90bycgKyByYW5kb21faWQgKSApO1xyXG5cdFx0XHQvL1xyXG5cdFx0XHQvLyBcdFx0d3BiY19kb19zY3JvbGwoICcjc2Nyb2xsX3RvJyArIHJhbmRvbV9pZCApO1xyXG5cdFx0XHQvLyBcdFx0Ly93cGJjX2RvX3Njcm9sbCggalF1ZXJ5KCAnI2Jvb2tpbmdfZm9ybScgKyByZXNvdXJjZV9pZCApLnBhcmVudCgpLmdldCggMCApICk7XHJcblx0XHRcdC8vIFx0fVxyXG5cdFx0XHQvLyB9LCA1MDAgKTtcclxuXHRcdH1cclxuXHQvLyA8L2VkaXRvci1mb2xkPlxyXG5cclxuXHJcbi8vVE9ETzogd2hhdCAgYWJvdXQgc2hvd2luZyBvbmx5ICBUaGFuayB5b3UuIG1lc3NhZ2Ugd2l0aG91dCBwYXltZW50IGZvcm1zLlxyXG4vKipcclxuICogU2hvdyAnVGhhbmsgeW91Jy4gbWVzc2FnZSBhbmQgcGF5bWVudCBmb3Jtc1xyXG4gKlxyXG4gKiBAcGFyYW0gcmVzcG9uc2VfZGF0YVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19zaG93X3RoYW5rX3lvdV9tZXNzYWdlX2FmdGVyX2Jvb2tpbmcoIHJlc3BvbnNlX2RhdGEgKXtcclxuXHJcblx0aWYgKFxyXG4gXHRcdCAgICgndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X2lzX3JlZGlyZWN0JyBdKSlcclxuXHRcdCYmICgndW5kZWZpbmVkJyAhPT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X3VybCcgXSkpXHJcblx0XHQmJiAoJ3BhZ2UnID09IHJlc3BvbnNlX2RhdGFbICdhanhfY29uZmlybWF0aW9uJyBdWyAndHlfaXNfcmVkaXJlY3QnIF0pXHJcblx0XHQmJiAoJycgIT0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9jb25maXJtYXRpb24nIF1bICd0eV91cmwnIF0pXHJcblx0KXtcclxuXHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9jb25maXJtYXRpb24nIF1bICd0eV91cmwnIF07XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cclxuXHR2YXIgcmVzb3VyY2VfaWQgPSByZXNwb25zZV9kYXRhWyAncmVzb3VyY2VfaWQnIF1cclxuXHR2YXIgY29uZmlybV9jb250ZW50ID0nJztcclxuXHJcblx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X21lc3NhZ2UnIF0pICl7XHJcblx0XHRcdFx0XHQgIFx0XHRcdCByZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X21lc3NhZ2UnIF0gPSAnJztcclxuXHR9XHJcblx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X3BheW1lbnRfcGF5bWVudF9kZXNjcmlwdGlvbicgXSApICl7XHJcblx0XHQgXHRcdFx0ICBcdFx0XHQgcmVzcG9uc2VfZGF0YVsgJ2FqeF9jb25maXJtYXRpb24nIF1bICd0eV9wYXltZW50X3BheW1lbnRfZGVzY3JpcHRpb24nIF0gPSAnJztcclxuXHR9XHJcblx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIChyZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3BheW1lbnRfY29zdCcgXSApICl7XHJcblx0XHRcdFx0XHQgIFx0XHRcdCByZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3BheW1lbnRfY29zdCcgXSA9ICcnO1xyXG5cdH1cclxuXHRpZiAoICd1bmRlZmluZWQnID09PSB0eXBlb2YgKHJlc3BvbnNlX2RhdGFbICdhanhfY29uZmlybWF0aW9uJyBdWyAndHlfcGF5bWVudF9nYXRld2F5cycgXSApICl7XHJcblx0XHRcdFx0XHQgIFx0XHRcdCByZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X3BheW1lbnRfZ2F0ZXdheXMnIF0gPSAnJztcclxuXHR9XHJcblx0dmFyIHR5X21lc3NhZ2VfaGlkZSBcdFx0XHRcdFx0XHQ9ICgnJyA9PSByZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X21lc3NhZ2UnIF0pID8gJ3dwYmNfdHlfaGlkZScgOiAnJztcclxuXHR2YXIgdHlfcGF5bWVudF9wYXltZW50X2Rlc2NyaXB0aW9uX2hpZGUgXHQ9ICgnJyA9PSByZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3R5X3BheW1lbnRfcGF5bWVudF9kZXNjcmlwdGlvbicgXS5yZXBsYWNlKCAvXFxcXG4vZywgJycgKSkgPyAnd3BiY190eV9oaWRlJyA6ICcnO1xyXG5cdHZhciB0eV9ib29raW5nX2Nvc3RzX2hpZGUgXHRcdFx0XHQ9ICgnJyA9PSByZXNwb25zZV9kYXRhWyAnYWp4X2NvbmZpcm1hdGlvbicgXVsgJ3BheW1lbnRfY29zdCcgXSkgPyAnd3BiY190eV9oaWRlJyA6ICcnO1xyXG5cdHZhciB0eV9wYXltZW50X2dhdGV3YXlzX2hpZGUgXHRcdFx0PSAoJycgPT0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9jb25maXJtYXRpb24nIF1bICd0eV9wYXltZW50X2dhdGV3YXlzJyBdLnJlcGxhY2UoIC9cXFxcbi9nLCAnJyApKSA/ICd3cGJjX3R5X2hpZGUnIDogJyc7XHJcblxyXG5cdGlmICggJ3dwYmNfdHlfaGlkZScgIT0gdHlfcGF5bWVudF9nYXRld2F5c19oaWRlICl7XHJcblx0XHRqUXVlcnkoICcud3BiY190eV9fY29udGVudF90ZXh0LndwYmNfdHlfX2NvbnRlbnRfZ2F0ZXdheXMnICkuaHRtbCggJycgKTtcdC8vIFJlc2V0ICBhbGwgIG90aGVyIHBvc3NpYmxlIGdhdGV3YXlzIGJlZm9yZSBzaG93aW5nIG5ldyBvbmUuXHJcblx0fVxyXG5cclxuXHRjb25maXJtX2NvbnRlbnQgKz0gYDxkaXYgaWQ9XCJ3cGJjX3Njcm9sbF9wb2ludF8ke3Jlc291cmNlX2lkfVwiPjwvZGl2PmA7XHJcblx0Y29uZmlybV9jb250ZW50ICs9IGAgIDxkaXYgY2xhc3M9XCJ3cGJjX2FmdGVyX2Jvb2tpbmdfdGhhbmtfeW91X3NlY3Rpb25cIj5gO1xyXG5cdGNvbmZpcm1fY29udGVudCArPSBgICAgIDxkaXYgY2xhc3M9XCJ3cGJjX3R5X19tZXNzYWdlICR7dHlfbWVzc2FnZV9oaWRlfVwiPiR7cmVzcG9uc2VfZGF0YVsgJ2FqeF9jb25maXJtYXRpb24nIF1bICd0eV9tZXNzYWdlJyBdfTwvZGl2PmA7XHJcbiAgICBjb25maXJtX2NvbnRlbnQgKz0gYCAgICA8ZGl2IGNsYXNzPVwid3BiY190eV9fY29udGFpbmVyXCI+YDtcclxuICAgIGNvbmZpcm1fY29udGVudCArPSBgICAgICAgPGRpdiBjbGFzcz1cIndwYmNfdHlfX2hlYWRlclwiPiR7cmVzcG9uc2VfZGF0YVsnYWp4X2NvbmZpcm1hdGlvbiddWyd0eV9tZXNzYWdlX2Jvb2tpbmdfaWQnXX08L2Rpdj5gO1xyXG4gICAgY29uZmlybV9jb250ZW50ICs9IGAgICAgICA8ZGl2IGNsYXNzPVwid3BiY190eV9fY29udGVudFwiPmA7XHJcblx0Y29uZmlybV9jb250ZW50ICs9IGAgICAgICAgIDxkaXYgY2xhc3M9XCJ3cGJjX3R5X19jb250ZW50X3RleHQgd3BiY190eV9fcGF5bWVudF9kZXNjcmlwdGlvbiAke3R5X3BheW1lbnRfcGF5bWVudF9kZXNjcmlwdGlvbl9oaWRlfVwiPiR7cmVzcG9uc2VfZGF0YVsgJ2FqeF9jb25maXJtYXRpb24nIF1bICd0eV9wYXltZW50X3BheW1lbnRfZGVzY3JpcHRpb24nIF0ucmVwbGFjZSggL1xcXFxuL2csICcnICl9PC9kaXY+YDtcclxuICAgIGNvbmZpcm1fY29udGVudCArPSBgICAgICAgXHQ8ZGl2IGNsYXNzPVwid3BiY190eV9fY29udGVudF90ZXh0IHdwYmNfY29sc18yXCI+JHtyZXNwb25zZV9kYXRhWydhanhfY29uZmlybWF0aW9uJ11bJ3R5X2N1c3RvbWVyX2RldGFpbHMnXX08L2Rpdj5gO1xyXG4gICAgY29uZmlybV9jb250ZW50ICs9IGAgICAgICBcdDxkaXYgY2xhc3M9XCJ3cGJjX3R5X19jb250ZW50X3RleHQgd3BiY19jb2xzXzJcIj4ke3Jlc3BvbnNlX2RhdGFbJ2FqeF9jb25maXJtYXRpb24nXVsndHlfYm9va2luZ19kZXRhaWxzJ119PC9kaXY+YDtcclxuXHRjb25maXJtX2NvbnRlbnQgKz0gYCAgICAgICAgPGRpdiBjbGFzcz1cIndwYmNfdHlfX2NvbnRlbnRfdGV4dCB3cGJjX3R5X19jb250ZW50X2Nvc3RzICR7dHlfYm9va2luZ19jb3N0c19oaWRlfVwiPiR7cmVzcG9uc2VfZGF0YVsgJ2FqeF9jb25maXJtYXRpb24nIF1bICd0eV9ib29raW5nX2Nvc3RzJyBdfTwvZGl2PmA7XHJcblx0Y29uZmlybV9jb250ZW50ICs9IGAgICAgICAgIDxkaXYgY2xhc3M9XCJ3cGJjX3R5X19jb250ZW50X3RleHQgd3BiY190eV9fY29udGVudF9nYXRld2F5cyAke3R5X3BheW1lbnRfZ2F0ZXdheXNfaGlkZX1cIj4ke3Jlc3BvbnNlX2RhdGFbICdhanhfY29uZmlybWF0aW9uJyBdWyAndHlfcGF5bWVudF9nYXRld2F5cycgXS5yZXBsYWNlKCAvXFxcXG4vZywgJycgKS5yZXBsYWNlKCAvYWpheF9zY3JpcHQvZ2ksICdzY3JpcHQnICl9PC9kaXY+YDtcclxuICAgIGNvbmZpcm1fY29udGVudCArPSBgICAgICAgPC9kaXY+YDtcclxuICAgIGNvbmZpcm1fY29udGVudCArPSBgICAgIDwvZGl2PmA7XHJcblx0Y29uZmlybV9jb250ZW50ICs9IGA8L2Rpdj5gO1xyXG5cclxuIFx0alF1ZXJ5KCAnI2Jvb2tpbmdfZm9ybScgKyByZXNvdXJjZV9pZCApLmFmdGVyKCBjb25maXJtX2NvbnRlbnQgKTtcclxufVxyXG4iXSwiZmlsZSI6ImluY2x1ZGVzL19jYXBhY2l0eS9fb3V0L2NyZWF0ZV9ib29raW5nLmpzIn0=;
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/js/wpbc_times.js?ver=9.8.12 
var time_buffer_value = 0;					// Customization of bufer time for DAN
var is_check_start_time_gone = false;		// Check  start time or end time for the time, which is gone already TODAY.
var start_time_checking_index;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Get dots for partially  booked dates.
 *    For parent booking resources with  specific capacity,
 *    System do not show partially booked dates,  if at least one child booking resource fully  available
 *    Otherwise it show maximum number of time-slot in one specific child booking resource
 *
 * @param param_calendar_id				ID of booking resource
 * @param my_thisDateTime				timestamp of date
 * @returns {string}
 */
function wpbc_show_date_info_top( param_calendar_id, my_thisDateTime ){

	var resource_id = parseInt( param_calendar_id.replace( "calendar_booking", '' ) );

	// console.log( _wpbc.bookings_in_calendar__get( resource_id ) );		// for debug

	// 1. Get child booking resources  or single booking resource  that  exist  in dates :	[1] | [1,14,15,17]
	var child_resources_arr = wpbc_clone_obj( _wpbc.booking__get_param_value( resource_id, 'resources_id_arr__in_dates' ) );

	// '2023-08-21'
	var sql_date = wpbc__get__sql_class_date( new Date( my_thisDateTime ) );

	var child_resource_id;
	var merged_seconds;
	var dots_count = 0;

	var dots_in__resources = [];

	// Loop all resources ID
	for ( var res_key in child_resources_arr ){

		child_resource_id = child_resources_arr[ res_key ];

		// _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[12].booked_time_slots.merged_seconds		= [ "07:00:11 - 07:30:02", "10:00:11 - 00:00:00" ]
		// _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[2].booked_time_slots.merged_seconds			= [  [ 25211, 27002 ], [ 36011, 86400 ]  ]

		if ( false !== _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date ) ){
			merged_seconds = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date )[ child_resource_id ].booked_time_slots.merged_seconds;		// [  [ 25211, 27002 ], [ 36011, 86400 ]  ]
		} else {
			merged_seconds = [];
		}

		if ( 0 === merged_seconds.length ){
			return ''; 																		// Day available
		}

		for ( var i = 0; i < merged_seconds.length; i++ ){
			if ( ! wpbc_is_this_timeslot__full_day_booked( merged_seconds[i] ) ){			// Check  if this fully  booked date. If yes,  then  do not count it
				dots_count++;
			}
		}

		dots_in__resources.push( dots_count );
		dots_count = 0;
	}

	var dots_count_max = Math.max.apply( Math, dots_in__resources );						// Get maximum value in array [ 1, 5, 3]  ->  5

	var dot_content = '';
	for ( var d = 0; d < dots_count_max; d++ ){
		dot_content += '&centerdot;';
	}

	dot_content = ( '' !== dot_content ) ? '<div class="wpbc_time_dots">' + dot_content + '</div>' : '';

	return dot_content;
}


function wpbc_show_date_info_bottom( param_calendar_id, my_thisDateTime ) {

	if ( typeof( wpbc_show_day_cost_in_date_bottom ) == 'function' ) {

		return wpbc_show_day_cost_in_date_bottom( param_calendar_id, my_thisDateTime );

	} else {
		return '';
	}
}



/**
 * Hide Tippy tooltip on scroll, to prevent issue on mobile touch devices of showing tooltip at top left corner!
 * @param evt
 */
jQuery( window ).on( 'scroll', function ( event ){													//FixIn: 9.2.1.5	//FixIn: 9.4.3.3
	if ( 'function' === typeof( wpbc_tippy ) ){
		wpbc_tippy.hideAll();
	}
} );


/**
 * Check if in booking form  exist  times fields for booking for specific time-slot
 * @param resource_id
 * @param form_elements
 * @returns {boolean}
 */
function wpbc_is_time_field_in_booking_form( resource_id, form_elements ){											//FixIn: 8.2.1.28

	var count = form_elements.length;
	var start_time = false;
	var end_time = false;
	var duration = false;
	var element;

	/**
	 *  Get from booking form  'rangetime', 'durationtime', 'starttime', 'endtime',  if exists.
	 */
	for ( var i = 0; i < count; i++ ){

		element = form_elements[ i ];

		// Skip elements from garbage
		if ( jQuery( element ).closest( '.booking_form_garbage' ).length ){											//FixIn: 7.1.2.14
			continue;
		}

		if (
			   ( element.name != undefined )
			&& ( element.name.indexOf( 'hint' ) !== -1 )				//FixIn: 9.5.5.2
		){
			var my_element = element.name; //.toString();
			if ( my_element.indexOf( 'rangetime' ) !== -1 ){                       	// Range Time

				return true;
			}
			if ( (my_element.indexOf( 'durationtime' ) !== -1) ){                	// Duration
				duration = element.value;
			}
			if ( my_element.indexOf( 'starttime' ) !== -1 ){                     	// Start Time
				start_time = element.value;
			}
			if ( my_element.indexOf( 'endtime' ) !== -1 ){                        	// End Time
				end_time = element.value;
			}
		}
	}

	// Duration get Values
	if ( ( duration !== false ) && ( start_time !== false ) ){  // we have Duration and Start time
		return true;
	}

	if ( ( start_time !== false ) && ( end_time !== false ) ){  // we have End time and Start time
		return true;
	}

	return false;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TODO: Continue Refactoring here 2018-04-21
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


	//PS: This function  from ../booking/inc/js/personal.js
	function wpbc_is_this_time_selection_not_available( resource_id, form_elements ){

		// Skip this checking if we are in the Admin  panel at Add booking page
		if ( location.href.indexOf( 'page=wpbc-new' ) > 0 ) {
			return false;
		}

		var count = form_elements.length;
		var start_time = false;
		var end_time = false;
		var duration = false;
		var element;
		var element_start = false;
		var element_end = false;
		var element_duration = false;
		var element_rangetime = false;

		/**
		 *  Get from booking form  'rangetime', 'durationtime', 'starttime', 'endtime',  if exists.
		 */
		for ( var i = 0; i < count; i++ ){

			element = form_elements[ i ];

			// Skip elements from garbage
			if ( jQuery( element ).closest( '.booking_form_garbage' ).length ){											//FixIn: 7.1.2.14
				continue;
			}

			if (
				   ( element.name != undefined )
				&& ( element.name.indexOf( 'hint' ) === -1 )				//FixIn: 9.5.5.2		//FixIn: 9.6.3.9
			){
				var my_element = element.name; //.toString();
				if ( my_element.indexOf( 'rangetime' ) !== -1 ){                       	// Range Time
					if ( element.value == '' ){                                 										//FixIn: 7.0.Beta.19
					 	var notice_message_id = wpbc_front_end__show_message__warning( element, message_verif_requred );
						return true;
					}
					var my_rangetime = element.value.split( '-' );
					if ( my_rangetime.length > 1 ){
						start_time = my_rangetime[ 0 ].replace( /(^\s+)|(\s+$)/g, "" ); 	// Trim
						end_time = my_rangetime[ 1 ].replace( /(^\s+)|(\s+$)/g, "" );
						element_rangetime = element;
					}
				}
				if ( (my_element.indexOf( 'durationtime' ) !== -1) ){                	// Duration
					duration = element.value;
					element_duration = element;
				}
				if ( my_element.indexOf( 'starttime' ) !== -1 ){                     	// Start Time
					start_time = element.value;
					element_start = element;
				}
				if ( my_element.indexOf( 'endtime' ) !== -1 ){                        	// End Time
					end_time = element.value;
					element_end = element;
				}
			}
		}


		// Duration get Values
		if ( (duration !== false) && (start_time !== false) ){  // we have Duration and Start time so  try to get End time

			var mylocalstarttime = start_time.split( ':' );
			var d = new Date( 1980, 1, 1, mylocalstarttime[ 0 ], mylocalstarttime[ 1 ], 0 );

			var my_duration = duration.split( ':' );
			my_duration = my_duration[ 0 ] * 60 * 60 * 1000 + my_duration[ 1 ] * 60 * 1000;
			d.setTime( d.getTime() + my_duration );

			var my_hours = d.getHours();
			if ( my_hours < 10 ) my_hours = '0' + (my_hours + '');
			var my_minutes = d.getMinutes();
			if ( my_minutes < 10 ) my_minutes = '0' + (my_minutes + '');

			// We are get end time
			end_time = (my_hours + '') + ':' + (my_minutes + '');
			if ( end_time == '00:00' ) end_time = '23:59';
		}


		if ( (start_time === false) || (end_time === false) ){                     // We do not have Start or End time or Both of them, so do not check it

			return false;

		} else {

			var valid_time = true;
			if ( (start_time == '') || (end_time == '') ) valid_time = false;

			if ( !isValidTimeTextField( start_time ) ) valid_time = false;
			if ( !isValidTimeTextField( end_time ) ) valid_time = false;

			if ( valid_time === true )
				if (
					(typeof(checkRecurentTimeInside) == 'function') &&
					(typeof(is_booking_recurrent_time) !== 'undefined') &&
					(is_booking_recurrent_time == true)
				){                                                                // Recheck Time here !!!
					valid_time = checkRecurentTimeInside( [ start_time, end_time ], resource_id );
				} else {

					if ( typeof(checkTimeInside) == 'function' ){
						valid_time = checkTimeInside( start_time, true, resource_id );
					}

					if ( valid_time === true ){
						if ( typeof(checkTimeInside) == 'function' ){
							valid_time = checkTimeInside( end_time, false, resource_id );
						}
					}
				}

			if ( valid_time !== true ){
				//return false;                                                  // do not show warning for setting pending days selectable,  if making booking for time-slot   //FixIn: 7.0.1.23
				if ( (is_booking_used_check_in_out_time) && (element_start !== false) && (element_end !== false) ){      //FixIn:6.1.1.1
					wpbc_front_end__show_message__warning_under_element( '#date_booking' + resource_id, message_checkinouttime_error  );
				}
				if ( element_rangetime !== false ){ wpbc_front_end__show_message__warning_under_element( element_rangetime, message_rangetime_error ); }
				if ( element_duration !== false ){  wpbc_front_end__show_message__warning_under_element( element_duration, message_durationtime_error ); }
				if ( element_start !== false ){ 	wpbc_front_end__show_message__warning_under_element( element_start, message_starttime_error ); }
				if ( element_end !== false ){ 		wpbc_front_end__show_message__warning_under_element( element_end, message_endtime_error ); }

				return true;

			} else {
				return false;
			}

		}


	}


	function isTimeTodayGone( myTime, sort_date_array ){
		var date_to_check = sort_date_array[ 0 ];
		if ( is_check_start_time_gone == false ){
			date_to_check = sort_date_array[ (sort_date_array.length - 1) ];
		}

		if ( parseInt( date_to_check[ 0 ] ) < parseInt( wpbc_today[ 0 ] ) ) return true;
		if ( (parseInt( date_to_check[ 0 ] ) == parseInt( wpbc_today[ 0 ] )) && (parseInt( date_to_check[ 1 ] ) < parseInt( wpbc_today[ 1 ] )) )
			return true;
		if ( (parseInt( date_to_check[ 0 ] ) == parseInt( wpbc_today[ 0 ] )) && (parseInt( date_to_check[ 1 ] ) == parseInt( wpbc_today[ 1 ] )) && (parseInt( date_to_check[ 2 ] ) < parseInt( wpbc_today[ 2 ] )) )
			return true;
		if ( (parseInt( date_to_check[ 0 ] ) == parseInt( wpbc_today[ 0 ] )) &&
			(parseInt( date_to_check[ 1 ] ) == parseInt( wpbc_today[ 1 ] )) &&
			(parseInt( date_to_check[ 2 ] ) == parseInt( wpbc_today[ 2 ] )) ){
			var mytime_value = myTime.split( ":" );
			mytime_value = mytime_value[ 0 ] * 60 + parseInt( mytime_value[ 1 ] );

			var current_time_value = wpbc_today[ 3 ] * 60 + parseInt( wpbc_today[ 4 ] );

			if ( current_time_value > mytime_value ) return true;

		}
		return false;
	}


	function checkTimeInside( mytime, is_start_time, bk_type ){

		var my_dates_str = document.getElementById( 'date_booking' + bk_type ).value;                 // GET DATES From TEXTAREA

		return checkTimeInsideProcess( mytime, is_start_time, bk_type, my_dates_str );

	}


	function checkRecurentTimeInside( my_rangetime, bk_type ){

		var valid_time = true;
		var my_dates_str = document.getElementById( 'date_booking' + bk_type ).value;                 // GET DATES From TEXTAREA
		// recurrent time check for all days in loop

		var date_array = my_dates_str.split( ", " );
		if ( date_array.length == 2 ){ // This recheck is need for editing booking, with single day
			if ( date_array[ 0 ] == date_array[ 1 ] ){
				date_array = [ date_array[ 0 ] ];
			}
		}
		var temp_date_str = '';
		for ( var i = 0; i < date_array.length; i++ ){  // Get SORTED selected days array
			temp_date_str = date_array[ i ];
			if ( checkTimeInsideProcess( my_rangetime[ 0 ], true, bk_type, temp_date_str ) == false ) valid_time = false;
			if ( checkTimeInsideProcess( my_rangetime[ 1 ], false, bk_type, temp_date_str ) == false ) valid_time = false;

		}

		return valid_time;
	}


// Function check start and end time at selected days
	function checkTimeInsideProcess( mytime, is_start_time, bk_type, my_dates_str ){
		var i, h, s, m;	//FixIn: 9.1.5.1

		var date_array = my_dates_str.split( ", " );
		if ( date_array.length == 2 ){ // This recheck is need for editing booking, with single day
			if ( date_array[ 0 ] == date_array[ 1 ] ){
				date_array = [ date_array[ 0 ] ];
			}
		}

		var temp_elemnt;
		var td_class;
		var sort_date_array = [];
		var work_date_array = [];
		var times_array = [];
		var is_check_for_time;

		for ( var i = 0; i < date_array.length; i++ ){  // Get SORTED selected days array
			temp_elemnt = date_array[ i ].split( "." );
			sort_date_array[ i ] = [ temp_elemnt[ 2 ], temp_elemnt[ 1 ] + '', temp_elemnt[ 0 ] + '' ]; // [2009,7,1],...
		}
		sort_date_array.sort();                                                                   // SORT    D a t e s
		for ( i = 0; i < sort_date_array.length; i++ ){                                  // trnasform to integers
			sort_date_array[ i ] = [ parseInt( sort_date_array[ i ][ 0 ] * 1 ), parseInt( sort_date_array[ i ][ 1 ] * 1 ), parseInt( sort_date_array[ i ][ 2 ] * 1 ) ]; // [2009,7,1],...
		}

		if ( ((is_check_start_time_gone) && (is_start_time)) ||
			((!is_check_start_time_gone) && (!is_start_time)) ){

			if ( isTimeTodayGone( mytime, sort_date_array ) ) return false;
		}
		//  CHECK FOR BOOKING INSIDE OF     S E L E C T E D    DAY RANGE AND FOR TOTALLY BOOKED DAYS AT THE START AND END OF RANGE
		work_date_array = sort_date_array;
		for ( var j = 0; j < work_date_array.length; j++ ){
			td_class = work_date_array[ j ][ 1 ] + '-' + work_date_array[ j ][ 2 ] + '-' + work_date_array[ j ][ 0 ];

			if ( (j == 0) || (j == (work_date_array.length - 1)) ) is_check_for_time = true;         // Check for time only start and end time
			else is_check_for_time = false;

			// Get dates and time from pending dates
			if ( typeof(date2approve[ bk_type ]) !== 'undefined' ){
				if ( (typeof(date2approve[ bk_type ][ td_class ]) !== 'undefined') ){
					if ( ! is_check_for_time ){
						return false;
					} // its mean that this date is booked inside of range selected dates
					if ( (date2approve[ bk_type ][ td_class ][ 0 ][ 3 ] != 0) || (date2approve[ bk_type ][ td_class ][ 0 ][ 4 ] != 0) ){
						// Evrything good - some time is booked check later
					} else {
						return false;
					} // its mean that this date tottally booked
				}
			}

			// Get dates and time from pending dates
			if ( typeof(date_approved[ bk_type ]) !== 'undefined' ){
				if ( (typeof(date_approved[ bk_type ][ td_class ]) !== 'undefined') ){
					if ( !is_check_for_time ){
						return false;
					} // its mean that this date is booked inside of range selected dates
					if ( (date_approved[ bk_type ][ td_class ][ 0 ][ 3 ] != 0) || (date_approved[ bk_type ][ td_class ][ 0 ][ 4 ] != 0) ){
						// Evrything good - some time is booked check later
					} else {
						return false;
					} // its mean that this date tottally booked
				}
			}
		}  ///////////////////////////////////////////////////////////////////////////////////////////////////////


		// Check    START   OR    END   time for time no in correct fee range
		if ( is_start_time ) work_date_array = sort_date_array[ 0 ];
		else work_date_array = sort_date_array[ sort_date_array.length - 1 ];

		td_class = work_date_array[ 1 ] + '-' + work_date_array[ 2 ] + '-' + work_date_array[ 0 ];

		// Get dates and time from pending dates
		if ( typeof(date2approve[ bk_type ]) !== 'undefined' )
			if ( typeof(date2approve[ bk_type ][ td_class ]) !== 'undefined' )
				for ( i = 0; i < date2approve[ bk_type ][ td_class ].length; i++ ){
					h = date2approve[ bk_type ][ td_class ][ i ][ 3 ];
					if ( h < 10 ) h = '0' + h;
					if ( h == 0 ) h = '00';
					m = date2approve[ bk_type ][ td_class ][ i ][ 4 ];
					if ( m < 10 ) m = '0' + m;
					if ( m == 0 ) m = '00';
					s = date2approve[ bk_type ][ td_class ][ i ][ 5 ];

//Customization of bufer time for DAN
					if ( s == '02' ){
						m = (m * 1) + time_buffer_value;
						if ( m > 59 ){
							m = m - 60;
							h = (h * 1) + 1;
						}
						if ( m < 10 ) m = '0' + m;
					}

					times_array[ times_array.length ] = [ h, m, s ];
				}

		// Get dates and time from pending dates
		if ( typeof(date_approved[ bk_type ]) !== 'undefined' )
			if ( typeof(date_approved[ bk_type ][ td_class ]) !== 'undefined' )
				for ( i = 0; i < date_approved[ bk_type ][ td_class ].length; i++ ){
					h = date_approved[ bk_type ][ td_class ][ i ][ 3 ];
					if ( h < 10 ) h = '0' + h;
					if ( h == 0 ) h = '00';
					m = date_approved[ bk_type ][ td_class ][ i ][ 4 ];
					if ( m < 10 ) m = '0' + m;
					if ( m == 0 ) m = '00';
					s = date_approved[ bk_type ][ td_class ][ i ][ 5 ];

//Customization of bufer time for DAN
					if ( s == '02' ){
						m = (m * 1) + time_buffer_value;
						if ( m > 59 ){
							m = m - 60;
							h = (h * 1) + 1;
						}
						if ( m < 10 ) m = '0' + m;
					}


					times_array[ times_array.length ] = [ h, m, s ];
				}


		times_array.sort();                     // SORT TIMES

		var times_in_day = [];                  // array with all times
		var times_in_day_interval_marks = [];   // array with time interval marks 1- stsrt time 2 - end time


		for ( i = 0; i < times_array.length; i++ ){
			s = times_array[ i ][ 2 ];         // s = 2 - end time,   s = 1 - start time
			// Start close interval
			if ( (s == 2) && (i == 0) ){
				times_in_day[ times_in_day.length ] = 0;
				times_in_day_interval_marks[ times_in_day_interval_marks.length ] = 1;
			}
			// Normal
			times_in_day[ times_in_day.length ] = times_array[ i ][ 0 ] * 60 + parseInt( times_array[ i ][ 1 ] );
			times_in_day_interval_marks[ times_in_day_interval_marks.length ] = s;
			// End close interval
			if ( (s == 1) && (i == (times_array.length - 1)) ){
				times_in_day[ times_in_day.length ] = (24 * 60);
				times_in_day_interval_marks[ times_in_day_interval_marks.length ] = 2;
			}
		}

		// Get time from entered time
		var mytime_value = mytime.split( ":" );
		mytime_value = mytime_value[ 0 ] * 60 + parseInt( mytime_value[ 1 ] );

//alert('My time:'+ mytime_value + '  List of times: '+ times_in_day + '  Saved indexes: ' + start_time_checking_index + ' Days: ' + sort_date_array ) ;

		var start_i = 0;
		if ( start_time_checking_index != undefined )
			if ( start_time_checking_index[ 0 ] != undefined )
				if ( (!is_start_time) && (sort_date_array.length == 1) ){
					start_i = start_time_checking_index[ 0 ];
					/*start_i++;*/
				}
		i = start_i;

		// Main checking inside a day
		for ( i = start_i; i < times_in_day.length; i++ ){
			times_in_day[ i ] = parseInt( times_in_day[ i ] );
			mytime_value = parseInt( mytime_value );
			if ( is_start_time ){
				if ( mytime_value > times_in_day[ i ] ){
					// Its Ok, lets Loop to next item
				} else if ( mytime_value == times_in_day[ i ] ){
					if ( times_in_day_interval_marks[ i ] == 1 ){
						return false;     //start time is begin with some other interval
					} else {
						if ( (i + 1) <= (times_in_day.length - 1) ){
							if ( times_in_day[ i + 1 ] <= mytime_value ) return false;  //start time  is begin with next elemnt interval
							else {                                                 // start time from end of some other
								if ( sort_date_array.length > 1 )
									if ( (i + 1) <= (times_in_day.length - 1) ) return false;   // Its mean that we make end booking at some other day then this and we have some booking time at this day after start booking  - its wrong
								start_time_checking_index = [ i, td_class, mytime_value ];
								return true;
							}
						}
						if ( sort_date_array.length > 1 )
							if ( (i + 1) <= (times_in_day.length - 1) ) return false;   // Its mean that we make end booking at some other day then this and we have some booking time at this day after start booking  - its wrong
						start_time_checking_index = [ i, td_class, mytime_value ];
						return true;                                            // start time from end of some other
					}
				} else if ( mytime_value < times_in_day[ i ] ){
					if ( times_in_day_interval_marks[ i ] == 2 ){
						return false;     // start time inside of some interval
					} else {
						if ( sort_date_array.length > 1 )
							if ( (i + 1) <= (times_in_day.length - 1) ) return false;   // Its mean that we make end booking at some other day then this and we have some booking time at this day after start booking  - its wrong
						start_time_checking_index = [ i, td_class, mytime_value ];
						return true;
					}
				}
			} else {
				if ( sort_date_array.length == 1 ){

					if ( start_time_checking_index != undefined )
						if ( start_time_checking_index[ 2 ] != undefined )

							if ( (start_time_checking_index[ 2 ] == times_in_day[ i ]) && (times_in_day_interval_marks[ i ] == 2) ){    // Good, because start time = end of some other interval and we need to get next interval for current end time.
							} else if ( times_in_day[ i ] < mytime_value ) return false;                 // some interval begins before end of curent "end time"
							else {
								if ( start_time_checking_index[ 2 ] >= mytime_value ) return false;  // we are select only one day and end time is earlythe starttime its wrong
								return true;                                                    // if we selected only one day so evrything is fine and end time no inside some other intervals
							}
				} else {
					if ( times_in_day[ i ] < mytime_value ) return false;                 // Some other interval start before we make end time in the booking at the end day selection
					else return true;
				}

			}
		}

		if ( is_start_time ) start_time_checking_index = [ i, td_class, mytime_value ];
		else {
			if ( start_time_checking_index != undefined )
				if ( start_time_checking_index[ 2 ] != undefined )
					if ( (sort_date_array.length == 1) && (start_time_checking_index[ 2 ] >= mytime_value) ) return false;  // we are select only one day and end time is earlythe starttime its wrong
		}
		return true;
	}


	//PS: This function  from ../booking/inc/js/personal.js
	function isValidTimeTextField( timeStr ){
		// Checks if time is in HH:MM AM/PM format.
		// The seconds and AM/PM are optional.

		var timePat = /^(\d{1,2}):(\d{2})(\s?(AM|am|PM|pm))?$/;

		var matchArray = timeStr.match( timePat );
		if ( matchArray == null ){
			return false; //("<?php _e('Time is not in a valid format. Use this format HH:MM or HH:MM AM/PM'); ?>");
		}
		var hour = matchArray[ 1 ];
		var minute = matchArray[ 2 ];
		var ampm = matchArray[ 4 ];

		if ( ampm == "" ){
			ampm = null
		}

		if ( hour < 0 || hour > 24 ){		//FixIn: 8.3.1.1
			return false; //("<?php _e('Hour must be between 1 and 12. (or 0 and 23 for military time)'); ?>");
		}
		if ( hour > 12 && ampm != null ){
			return false; //("<?php _e('You can not specify AM or PM for military time.'); ?>");
		}
		if ( minute < 0 || minute > 59 ){
			return false; //("<?php _e('Minute must be between 0 and 59.'); ?>");
		}
		return true;
	};
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/js/meiomask.js?ver=9.8.12 
/**
 * jquery.meio.mask.js
 * @author: fabiomcosta
 * @version: 1.1.14
 * @help: https://github.com/fabiomcosta/jquery-meiomask/wiki
 *
 * Created by Fabio M. Costa on 2008-09-16. Please report any bug at http://www.meiocodigo.com
 *
 * Copyright (c) 2008 Fabio M. Costa http://www.meiocodigo.com
 *
 * The MIT License (http://www.opensource.org/licenses/mit-license.php)
 *
 * 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.
 */

/**
 * //FixIn: 8.7.9.11
 *
 * replaced here .browser to  .browser_is_supported_meio
 */

(function($) {

    // https://github.com/jquery/jquery-migrate/blob/master/src/core.js#L50
    if (!$.browser_is_supported_meio) {
        var uaMatch = function(ua) {
            ua = ua.toLowerCase();

            var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];

            return match[2] || '0';
        };

        $.browser_is_supported_meio = {
            mozilla: /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase()),
            webkit: /webkit/.test(navigator.userAgent.toLowerCase()),
            opera: /opera/.test(navigator.userAgent.toLowerCase()),
            msie: /msie/.test(navigator.userAgent.toLowerCase()),
            android: (navigator.userAgent.toLowerCase().indexOf('mozilla/5.0') > -1 && navigator.userAgent.toLowerCase().indexOf('android ') > -1 && navigator.userAgent.toLowerCase().indexOf('applewebkit') > -1),
            version: uaMatch(navigator.userAgent)
        };
    }

    var isMobile = (window.orientation != null);

    // browsers like firefox2 and before and opera doesnt have the onPaste event, but the paste feature can be done with the onInput event.
    var pasteEvent = (($.browser_is_supported_meio.opera || ($.browser_is_supported_meio.mozilla && parseFloat($.browser_is_supported_meio.version.substr(0, 3)) < 1.9)) ? 'input' : 'paste');

    // the timeout is set because we can't get the value from the input without it
    var pasteHandler = function(e) {
        e = $.event.fix(e || window.event);
        e.type = 'paste';
        var el = e.target;

        setTimeout(function() {
            $.event.dispatch.call(el, e);
        }, 1);
    };

    $.event.special.paste = {
        setup: function() {
            if (this.addEventListener) this.addEventListener(pasteEvent, pasteHandler, false);
            else if (this.attachEvent) this.attachEvent('on' + pasteEvent, pasteHandler);
        },

        teardown: function() {
            if (this.removeEventListener) this.removeEventListener(pasteEvent, pasteHandler, false);
            else if (this.detachEvent) this.detachEvent('on' + pasteEvent, pasteHandler);
        }
    };

    $.extend({
        mask: {

            // the mask rules. You may add yours!
            // number rules will be overwritten
            rules: {
                'z': /[a-z]/,
                'Z': /[A-Z]/,
                'a': /[a-zA-Z]/,
                '*': /[0-9a-zA-Z]/,
                '@': /[0-9a-zA-ZçÇáàãâéèêíìóòôõúùü]/
            },

            // these keys will be ignored by the mask.
            // all these numbers where obtained on the keydown event
            keyRepresentation: {
                8: 'backspace',
                9: 'tab',
                13: 'enter',
                16: 'shift',
                17: 'control',
                18: 'alt',
                27: 'esc',
                33: 'page up',
                34: 'page down',
                35: 'end',
                36: 'home',
                37: 'left',
                38: 'up',
                39: 'right',
                40: 'down',
                45: 'insert',
                46: 'delete',
                116: 'f5',
                123: 'f12',
                224: 'command'
            },

            signals: {
                '+': '',
                '-': '-'
            },

            // default settings for the plugin
            options: {
                attr: 'alt', // an attr to look for the mask name or the mask itself
                mask: null, // the mask to be used on the input
                type: 'fixed', // the mask of this mask
                maxLength: -1, // the maxLength of the mask
                defaultValue: '', // the default value for this input
                signal: false, // this should not be set, to use signal at masks put the signal you want ('-' or '+') at the default value of this mask.
                // See the defined masks for a better understanding.

                textAlign: true, // use false to not use text-align on any mask (at least not by the plugin, you may apply it using css)
                selectCharsOnFocus: true, // select all chars from input on its focus
                autoTab: true, // auto focus the next form element when you type the mask completely
                setSize: false, // sets the input size based on the length of the mask (work with fixed and reverse masks only)
                fixedChars: '[(),.:/ -]', // fixed chars to be used on the masks. You may change it for your needs!

                onInvalid: function() {},
                onValid: function() {},
                onOverflow: function() {},
                onFocus: function(input, evt) {},
                onBlur: function(input, evt) {}
            },

            // masks. You may add yours!
            // Ex: $.fn.setMask.masks.msk = {mask: '999'}
            // and then if the 'attr' options value is 'alt', your input should look like:
            // <input type="text" name="some_name" id="some_name" alt="msk" />
            masks: {
                'phone': {
                    mask: '(99) 9999-9999'
                },
                'phone-us': {
                    mask: '(999) 999-9999'
                },
                'cpf': {
                    mask: '999.999.999-99'
                }, // cadastro nacional de pessoa fisica (kind of a brazillian ssn)
                'cnpj': {
                    mask: '99.999.999/9999-99'
                },
                'date': {
                    mask: '39/19/9999'
                }, // uk date
                'date-us': {
                    mask: '19/39/9999'
                },
                'cep': {
                    mask: '99999-999'
                },
                'time': {
                    mask: '29:59'
                },
                'cc': {
                    mask: '9999 9999 9999 9999'
                }, // credit card
                'integer': {
                    mask: '999.999.999.999',
                    type: 'reverse'
                },
                'decimal': {
                    mask: '99,999.999.999.999',
                    type: 'reverse',
                    defaultValue: '000'
                },
                'decimal-us': {
                    mask: '99.999,999,999,999',
                    type: 'reverse',
                    defaultValue: '000'
                },
                'signed-decimal': {
                    mask: '99,999.999.999.999',
                    type: 'reverse',
                    defaultValue: '+000'
                },
                'signed-decimal-us': {
                    mask: '99,999.999.999.999',
                    type: 'reverse',
                    defaultValue: '+000'
                }
            },

            init: function() {
                // if has not inited...
                if (!this.hasInit) {

                    var self = this,
                        i,
                        keyRep = this.keyRepresentation;

                    this.ignore = false;

                    // constructs number rules
                    for (i = 0; i <= 9; i++) this.rules[i] = new RegExp('[0-' + i + ']');

                    this.keyRep = keyRep;
                    // ignore keys array creation for iphone or the normal ones
                    this.ignoreKeys = [];
                    $.each(keyRep, function(key) {
                        self.ignoreKeys.push(parseInt(key, 10));
                    });

                    this.hasInit = true;
                }
            },

            set: function(el, options) {

                var maskObj = this,
                    $el = $(el),
                    mlStr = 'maxLength';

                options = options || {};
                this.init();

                return $el.each(function() {

                    if (options.attr) maskObj.options.attr = options.attr;

                    var $this = $(this),
                        o = $.extend({}, maskObj.options),
                        attrValue = $this.attr(o.attr),
                        tmpMask = '';

                    // then we look for the 'attr' option
                    tmpMask = (typeof options == 'string') ? options : (attrValue !== '') ? attrValue : null;
                    if (tmpMask) o.mask = tmpMask;

                    // then we see if it's a defined mask
                    if (maskObj.masks[tmpMask]) o = $.extend(o, maskObj.masks[tmpMask]);

                    // then it looks if the options is an object, if it is we will overwrite the actual options
                    if (typeof options == 'object' && options.constructor != Array) o = $.extend(o, options);

                    //then we look for some metadata on the input
                    if ($.metadata) o = $.extend(o, $this.metadata());

                    if (o.mask != null) {

                        // prevents javascript automatic type convertion
                        o.mask += '';

                        if ($this.data('mask')) maskObj.unset($this);

                        var defaultValue = o.defaultValue,
                            reverse = (o.type === 'reverse'),
                            fixedCharsRegG = new RegExp(o.fixedChars, 'g');

                        if (o.maxLength === -1) o.maxLength = $this.attr(mlStr);

                        o = $.extend({}, o, {
                            fixedCharsReg: new RegExp(o.fixedChars),
                            fixedCharsRegG: fixedCharsRegG,
                            maskArray: o.mask.split(''),
                            maskNonFixedCharsArray: o.mask.replace(fixedCharsRegG, '').split('')
                        });

                        // setSize option (this is kept when the mask is removed)
                        if ((o.type == 'fixed' || reverse) && o.setSize && !$this.attr('size')) $this.attr('size', o.mask.length);

                        // sets text-align right for reverse masks
                        if (reverse && o.textAlign) $this.css('text-align', 'right');

                        if (this.value !== '' || defaultValue !== '') {
                            // apply mask to the current value of the input or to the default value
                            var val = maskObj.string((this.value !== '') ? this.value : defaultValue, o);
                            //setting defaultValue fixes the reset button from the form
                            this.defaultValue = val;
                            $this.val(val);
                        }

                        // compatibility patch for infinite mask, that is now repeat
                        if (o.type == 'infinite') o.type = 'repeat';

                        $this.data('mask', o);

                        // removes the maxLength attribute (it will be set again if you use the unset method)
                        $this.removeAttr(mlStr);

                        // setting the input events
                        $this.on('keydown.mask', {
                            func: maskObj._onKeyDown,
                            thisObj: maskObj
                        }, maskObj._onMask)
                            .on('keypress.mask', {
                            func: maskObj._onKeyPress,
                            thisObj: maskObj
                        }, maskObj._onMask)
                            .on('keyup.mask', {
                            func: maskObj._onKeyUp,
                            thisObj: maskObj
                        }, maskObj._onMask)
                            .on('paste.mask', {
                            func: maskObj._onPaste,
                            thisObj: maskObj
                        }, maskObj._onMask)
                            .on('drop.mask', {
                            func: maskObj._onPaste,
                            thisObj: maskObj
                        }, maskObj._onMask)
                            .on('focus.mask', maskObj._onFocus)
                            .on('blur.mask', maskObj._onBlur)
                            .on('change.mask', maskObj._onChange);
                    }
                });
            },

            //unsets the mask from el
            unset: function(el) {
                var $el = $(el);

                return $el.each(function() {
                    var $this = $(this);
                    if ($this.data('mask')) {
                        var maxLength = $this.data('mask').maxLength;
                        if (maxLength != -1) $this.attr('maxLength', maxLength);
                        $this.unbind('.mask')
                            .removeData('mask');
                    }
                });
            },

            //masks a string
            string: function(str, options) {
                this.init();
                var o = {};
                if (typeof str != 'string') str = String(str);
                switch (typeof options) {
                    case 'string':
                        // then we see if it's a defined mask
                        if (this.masks[options]) o = $.extend(o, this.masks[options]);
                        else o.mask = options;
                        break;
                    case 'object':
                        o = options;
                }
                if (!o.fixedChars) o.fixedChars = this.options.fixedChars;

                var fixedCharsReg = new RegExp(o.fixedChars),
                    fixedCharsRegG = new RegExp(o.fixedChars, 'g');

                // insert signal if any
                if ((o.type === 'reverse') && o.defaultValue) {
                    if (typeof this.signals[o.defaultValue.charAt(0)] != 'undefined') {
                        var maybeASignal = str.charAt(0);
                        o.signal = (typeof this.signals[maybeASignal] != 'undefined') ? this.signals[maybeASignal] : this.signals[o.defaultValue.charAt(0)];
                        o.defaultValue = o.defaultValue.substring(1);
                    }
                }

                return this.__maskArray(str.split(''),
                o.mask.replace(fixedCharsRegG, '').split(''),
                o.mask.split(''),
                o.type,
                o.maxLength,
                o.defaultValue,
                fixedCharsReg,
                o.signal);
            },

            // all the 3 events below are here just to fix the change event on reversed masks.
            // It isn't fired in cases that the keypress event returns false (needed).
            _onFocus: function(e) {
                var $this = $(this),
                    dataObj = $this.data('mask');
                dataObj.inputFocusValue = $this.val();
                dataObj.changed = false;
                //if (dataObj.selectCharsOnFocus) $this.select();                //FixIn: 2023-10-31
                if (dataObj.selectCharsOnFocus) $this.trigger( 'select' );       //FixIn: 2023-10-31
                // trigger mask function
                dataObj.onFocus(this, e);
            },

            _onBlur: function(e) {
                var $this = $(this),
                    dataObj = $this.data('mask');
                if (dataObj.inputFocusValue != $this.val() && !dataObj.changed) $this.trigger('change');
                // trigger  mask function
                dataObj.onBlur(this, e);
            },

            _onChange: function(e) {
                $(this).data('mask').changed = true;
            },

            _onMask: function(e) {
                var thisObj = e.data.thisObj,
                    o = {};

                o._this = e.target;
                o.$this = $(o._this);
                o.data = o.$this.data('mask');

                if (o.$this.attr('readonly') || !o.data) {
                    return true;
                }

                o[o.data.type] = true;
                o.value = o.$this.val();
                o.nKey = thisObj.__getKeyNumber(e);
                o.range = thisObj.__getRange(o._this);
                o.valueArray = o.value.split('');
                return e.data.func.call(thisObj, e, o);
            },

            _onKeyDown: function(e, o) {
                // lets say keypress at desktop == keydown at iphone (theres no keypress at iphone)
                this.ignore = $.inArray(o.nKey, this.ignoreKeys) > -1 || ((e.ctrlKey || e.metaKey || e.altKey) && e.key);
                if (this.ignore) {
                    var rep = this.keyRep[o.nKey];
                    o.data.onValid.call(o._this, rep || '', o.nKey);
                }
                return true;
            },

            _onKeyUp: function(e, o) {
                //9=TAB_KEY 16=SHIFT_KEY
                //this is a little bug, when you go to an input with tab key
                //it would remove the range selected by default, and that's not a desired behavior
                if (o.nKey === 9 || o.nKey === 16) return true;

                if (o.repeat) {
                    this.__autoTab(o);
                    return true;
                }

                return this._onPaste(e, o);
            },

            _onPaste: function(e, o) {
                // changes the signal at the data obj from the input
                if (o.reverse) this.__changeSignal(e.type, o);

                var $thisVal = this.__maskArray(
                o.valueArray,
                o.data.maskNonFixedCharsArray,
                o.data.maskArray,
                o.data.type,
                o.data.maxLength,
                o.data.defaultValue,
                o.data.fixedCharsReg,
                o.data.signal);

                o.$this.val($thisVal);
                // this makes the caret stay at first position when
                // the user removes all values in an input and the plugin adds the default value to it (if it haves one).
                if (!o.reverse && o.data.defaultValue.length && (o.range.start === o.range.end)) this.__setRange(o._this, o.range.start, o.range.end);

                //fix so ie's and safari's caret won't go to the end of the input value.
                if (($.browser_is_supported_meio.msie || $.browser_is_supported_meio.safari) && !o.reverse) this.__setRange(o._this, o.range.start, o.range.end);

                if (this.ignore) return true;

                this.__autoTab(o);
                return true;
            },

            _onKeyPress: function(e, o) {

                if (this.ignore) return true;

                // changes the signal at the data obj from the input
                if (o.reverse) this.__changeSignal(e.type, o);

                var c = String.fromCharCode(o.nKey),
                    rangeStart = o.range.start,
                    rawValue = o.value,
                    maskArray = o.data.maskArray;

                if (o.reverse) {
                    // the input value from the range start to the value start
                    var valueStart = rawValue.substr(0, rangeStart),
                        // the input value from the range end to the value end
                        valueEnd = rawValue.substr(o.range.end, rawValue.length);

                    rawValue = valueStart + c + valueEnd;
                    //necessary, if not decremented you will be able to input just the mask.length-1 if signal!=''
                    //ex: mask:99,999.999.999 you will be able to input 99,999.999.99
                    if (o.data.signal && (rangeStart - o.data.signal.length > 0)) {
                        rangeStart -= o.data.signal.length;
                    }
                }

                var valueArray = rawValue.replace(o.data.fixedCharsRegG, '').split(''),
                    // searches for fixed chars begining from the range start position, till it finds a non fixed
                    extraPos = this.__extraPositionsTill(rangeStart, maskArray, o.data.fixedCharsReg);

                o.rsEp = rangeStart + extraPos;

                if (o.repeat) {
                    o.rsEp = 0;
                }

                // if the rule for this character doesnt exist (value.length is bigger than mask.length)
                // added a verification for maxLength in the case of the repeat type mask
                if (!this.rules[maskArray[o.rsEp]] || (o.data.maxLength != -1 && valueArray.length >= o.data.maxLength && o.repeat)) {
                    // auto focus on the next input of the current form
                    o.data.onOverflow.call(o._this, c, o.nKey);
                    return false;
                }

                // if the new character is not obeying the law...
                else if (!this.rules[maskArray[o.rsEp]].test(c)) {
                    o.data.onInvalid.call(o._this, c, o.nKey);
                    return false;
                } else {
                    o.data.onValid.call(o._this, c, o.nKey);
                }

                var $thisVal = this.__maskArray(
                valueArray,
                o.data.maskNonFixedCharsArray,
                maskArray,
                o.data.type,
                o.data.maxLength,
                o.data.defaultValue,
                o.data.fixedCharsReg,
                o.data.signal,
                extraPos);

                if (!o.repeat) {
                    o.$this.val($thisVal);
                }

                return (o.reverse) ? this._keyPressReverse(e, o) : (o.fixed) ? this._keyPressFixed(e, o) : true;
            },

            _keyPressFixed: function(e, o) {

                if (o.range.start == o.range.end) {
                    // the 0 thing is because theres an unwanted behavior when you put a default
                    // value on a fixed mask and you select the value from the input the range would go to the
                    // end of the string when you enter a char. with this it will overwrite the first char wich is a better behavior.
                    // opera fix, cant have range value bigger than value length, i think it loops thought the input value...
                    if ((o.rsEp === 0 && o.value.length === 0) || o.rsEp < o.value.length) this.__setRange(o._this, o.rsEp, o.rsEp + 1);
                } else this.__setRange(o._this, o.range.start, o.range.end);

                return true;
            },

            _keyPressReverse: function(e, o) {
                // fix for ie
                // this bug was pointed by Pedro Martins
                // it fixes a strange behavior that ie was having after a char was inputted in a text input that
                // had its content selected by any range
                if ($.browser_is_supported_meio.msie && ((o.range.start === 0 && o.range.end === 0) || o.range.start != o.range.end)) this.__setRange(o._this, o.value.length);
                return false;
            },

            __autoTab: function(o) {
                if (o.data.autoTab && (
                (
                o.$this.val().length >= o.data.maskArray.length && !o.repeat) || (
                o.data.maxLength != -1 && o.valueArray.length >= o.data.maxLength && o.repeat))) {
                    var nextEl = this.__getNextInput(o._this, o.data.autoTab);
                    if (nextEl) {
                        o.$this.trigger('blur');
                        nextEl.trigger( 'focus' ).trigger( 'select' );      //FixIn: 8.7.11.12
                    }
                }
            },

            // changes the signal at the data obj from the input
            __changeSignal: function(eventType, o) {
                if (o.data.signal !== false) {
                    var inputChar = (eventType === 'paste') ? o.value.charAt(0) : String.fromCharCode(o.nKey);
                    if (this.signals && (typeof this.signals[inputChar] !== 'undefined')) {
                        o.data.signal = this.signals[inputChar];
                    }
                }
            },

            __getKeyNumber: function(e) {
                return (e.charCode || e.keyCode || e.which);
            },

            // this function is totaly specific to be used with this plugin, youll never need it
            // it gets the array representing an unmasked string and masks it depending on the type of the mask
            __maskArray: function(valueArray, maskNonFixedCharsArray, maskArray, type, maxlength, defaultValue, fixedCharsReg, signal, extraPos) {
                if (type === 'reverse') valueArray.reverse();
                valueArray = this.__removeInvalidChars(valueArray, maskNonFixedCharsArray, type === 'repeat' || type === 'infinite');
                if (defaultValue) valueArray = this.__applyDefaultValue.call(valueArray, defaultValue);
                valueArray = this.__applyMask(valueArray, maskArray, extraPos, fixedCharsReg);
                switch (type) {
                    case 'reverse':
                        valueArray.reverse();
                        return (signal || '') + valueArray.join('').substring(valueArray.length - maskArray.length);
                    case 'infinite':
                    case 'repeat':
                        var joinedValue = valueArray.join('');
                        return (maxlength !== -1 && valueArray.length >= maxlength) ? joinedValue.substring(0, maxlength) : joinedValue;
                    default:
                        return valueArray.join('').substring(0, maskArray.length);
                }
                return '';
            },

            // applyes the default value to the result string
            __applyDefaultValue: function(defaultValue) {
                var defLen = defaultValue.length,
                    thisLen = this.length,
                    i;
                //removes the leading chars
                for (i = thisLen - 1; i >= 0; i--) {
                    if (this[i] == defaultValue.charAt(0)) {
                        this.pop();
                    } else break;
                }
                // apply the default value
                for (i = 0; i < defLen; i++) if (!this[i]) {
                    this[i] = defaultValue.charAt(i);
                }

                return this;
            },

            // Removes values that doesnt match the mask from the valueArray
            // Returns the array without the invalid chars.
            __removeInvalidChars: function(valueArray, maskNonFixedCharsArray, repeatType) {
                // removes invalid chars
                for (var i = 0, y = 0; i < valueArray.length; i++) {
                    if (maskNonFixedCharsArray[y] && this.rules[maskNonFixedCharsArray[y]] && !this.rules[maskNonFixedCharsArray[y]].test(valueArray[i])) {
                        valueArray.splice(i, 1);
                        if (!repeatType) y--;
                        i--;
                    }
                    if (!repeatType) y++;
                }
                return valueArray;
            },

            // Apply the current input mask to the valueArray and returns it.
            __applyMask: function(valueArray, maskArray, plus, fixedCharsReg) {
                if (typeof plus == 'undefined') plus = 0;
                // apply the current mask to the array of chars
                for (var i = 0; i < valueArray.length + plus; i++) {
                    if (maskArray[i] && fixedCharsReg.test(maskArray[i])) valueArray.splice(i, 0, maskArray[i]);
                }
                return valueArray;
            },

            // searches for fixed chars begining from the range start position, till it finds a non fixed
            __extraPositionsTill: function(rangeStart, maskArray, fixedCharsReg) {
                var extraPos = 0;
                while (fixedCharsReg.test(maskArray[rangeStart++])) {
                    extraPos++;
                }
                return extraPos;
            },

            __getNextInput: function(input, selector) {
                var form = input.form;

                if (form == null) {
                    return null;
                }

                var formEls = form.elements,
                    initialInputIndex = $.inArray(input, formEls) + 1,
                    len = formEls.length,
                    $input = null,
                    i;

                // look for next input on the form of the pased input
                for (i = initialInputIndex; i < len; i++) {
                    $input = $(formEls[i]);
                    if (this.__isNextInput($input, selector)) {
                        return $input;
                    }
                }

                var forms = document.forms,
                    initialFormIndex = $.inArray(input.form, forms) + 1,
                    y, tmpFormEls, _len = forms.length;
                // look for the next forms for the next input
                for (y = initialFormIndex; y < _len; y++) {
                    tmpFormEls = forms[y].elements;
                    len = tmpFormEls.length;
                    for (i = 0; i < len; i++) {
                        $input = $(tmpFormEls[i]);
                        if (this.__isNextInput($input, selector)) {
                            return $input;
                        }
                    }
                }
                return null;
            },

            __isNextInput: function($formEl, selector) {
                var formEl = $formEl.get(0);
                return formEl && (formEl.offsetWidth > 0 || formEl.offsetHeight > 0) && formEl.nodeName != 'FIELDSET' && (selector === true || (typeof selector == 'string' && $formEl.is(selector)));
            },

            // http://www.bazon.net/mishoo/articles.epl?art_id=1292
            __setRange: function(input, start, end) {
                if (typeof end == 'undefined') {
                    end = start;
                }
                if (input.setSelectionRange) {
                    input.setSelectionRange(start, end);
                } else {
                    // assumed IE
                    var range = input.createTextRange();
                    range.collapse();
                    range.moveStart('character', start);
                    range.moveEnd('character', end - start);
                    range.select();
                }
            },

            // adaptation from http://digitarald.de/project/autocompleter/
            __getRange: function(input) {
                if (!$.browser_is_supported_meio.msie && !$.browser_is_supported_meio.android) return {
                    start: input.selectionStart,
                    end: input.selectionEnd
                };
                var pos = {
                    start: 0,
                    end: 0
                },
                range = document.selection.createRange();
                pos.start = 0 - range.duplicate().moveStart('character', - 100000);
                pos.end = pos.start + range.text.length;
                return pos;
            },

            //deprecated
            unmaskedVal: function(el) {
                return $(el).val().replace($.mask.fixedCharsRegG, '');
            }

        }
    });

    $.fn.extend({
        setMask: function(options) {
            return $.mask.set(this, options);
        },
        unsetMask: function() {
            return $.mask.unset(this);
        },
        //deprecated
        unmaskedVal: function() {
            return $.mask.unmaskedVal(this[0]);
        }
    });
})(jQuery);
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/js/personal.js?ver=9.8.12 
jQuery(document).ready( function(){
   if( jQuery('.wpdev-validates-as-time').length > 0 ) {
       jQuery('.wpdev-validates-as-time').attr('alt','time');
       jQuery('.wpdev-validates-as-time').setMask();
   }
});

// ---------------------------------------------------------------------------------------------------------------------

// Send booking Cancel by visitor
function wpbc_customer_action__booking_cancel( booking_hash, bk_type, wpdev_active_locale ){
    
    if (booking_hash!='') {
        
        document.getElementById('submiting' + bk_type).innerHTML =
            '<div style="height:20px;width:100%;text-align:center;margin:15px auto;"><img  style="vertical-align:middle;box-shadow:none;width:14px;" src="'+wpdev_bk_plugin_url+'/assets/img/ajax-loader.gif"><//div>';

        var wpdev_ajax_path = wpdev_bk_plugin_url+'/' + wpdev_bk_plugin_filename;
        var ajax_type_action='DELETE_BY_VISITOR';

        jQuery.ajax({                                           // Start Ajax Sending
            // url: wpdev_ajax_path,
            url: wpbc_ajaxurl,
            type:'POST',
            success: function (data, textStatus){if( textStatus == 'success')   jQuery('#ajax_respond_insert' + bk_type).html( data ) ;},
            error:function (XMLHttpRequest, textStatus, errorThrown){window.status = 'Ajax sending Error status:'+ textStatus;alert(XMLHttpRequest.status + ' ' + XMLHttpRequest.statusText);if (XMLHttpRequest.status == 500) {alert('Please check at this page according this error:' + ' https://wpbookingcalendar.com/faq/#ajax-sending-error');}},
            // beforeSend: someFunction,
            data:{
                // ajax_action : ajax_type_action,
                action : ajax_type_action,
                booking_hash : booking_hash,
                bk_type : bk_type,
                wpdev_active_locale:wpdev_active_locale,
                wpbc_nonce: document.getElementById('wpbc_nonce_delete'+bk_type).value 
            }
        });
        return false;
    }
    return true;
}

// ---------------------------------------------------------------------------------------------------------------------

/**
 * Set checkbox in booking form Exclusive on click
 *
 * @param element
 */
function wpbc_in_form__make_exclusive_checkbox( element ){

    jQuery( '[name="' + element.name + '"]' ).prop( "checked", false );             // Uncheck  all checkboxes with  this name

    element.checked = true;
}

/**
 * Set select-box with multiple selections - Exclusive
 * @param element
 */
function wpbc_in_form__make_exclusive_selectbox( element ){

    // Get all selected elements.
    var selectedOptions = jQuery.find( '[name="' + element.name + '"] option:selected' );

    // Check if we have more than 1 selection
    if ( selectedOptions.length > 1 ){

        var ind = selectedOptions[ 0 ].index;                                             // Get index of the first  selected element
        jQuery( '[name="' + element.name + '"] option' ).prop( "selected", false );             // Uncheck  all checkboxes with  this name
        jQuery( '[name="' + element.name + '"] option:eq(' + ind + ')' ).prop( "selected", true );  // Set the first element selected
    }
}

// ---------------------------------------------------------------------------------------------------------------------
                                                                                                                        //FixIn: 9.6.3.5

function wpbc_reset__form_configuration(type) {

    var editor_textarea_id = 'booking_form';
    var editor_textarea_content = wpbc_reset__get_form_configuration( type );

    //FixIn: 8.4.7.18
    if  ( (typeof WPBC_CM !== 'undefined') && ( WPBC_CM.is_defined( '#' + editor_textarea_id ) ) ){

        WPBC_CM.set_codemirror_value( '#' + editor_textarea_id , editor_textarea_content );

    } else {

        if ( typeof tinymce != "undefined" ){
            var editor = tinymce.get( editor_textarea_id );
            if ( editor && editor instanceof tinymce.Editor ){
                editor.setContent( editor_textarea_content );
                editor.save( {no_events: true} );
            } else {
                jQuery( '#' + editor_textarea_id ).val( editor_textarea_content );
            }
        } else {
            jQuery( '#' + editor_textarea_id ).val( editor_textarea_content );
        }
    }
}

function wpbc_reset__form_data(type) {

    var editor_textarea_id = 'booking_form_show';
    var editor_textarea_content = wpbc_reset__get_form_data(type);

    //FixIn: 8.4.7.18
    if  ( (typeof WPBC_CM !== 'undefined') && ( WPBC_CM.is_defined( '#' + editor_textarea_id ) ) ){

        WPBC_CM.set_codemirror_value( '#' + editor_textarea_id , editor_textarea_content );
    } else {


        if( typeof tinymce != "undefined" ) {
            var editor = tinymce.get( editor_textarea_id );
            if( editor && editor instanceof tinymce.Editor ) {
                editor.setContent( editor_textarea_content );
                editor.save( { no_events: true } );
            } else {
                jQuery( '#' + editor_textarea_id ).val( editor_textarea_content );
            }
        } else {
            jQuery( '#' + editor_textarea_id ).val( editor_textarea_content );
        }
    }
}

function wpbc_reset__get_form_configuration( form_type ) {
    var form_content = '';
    
    if ( (form_type == 'times') || (form_type == 'times30')  || (form_type == 'times15') ){
        form_content = '';
        form_content +='<!--  Simple HTML shortcodes in the form (check more at "Generate Tag" section): \n';
        form_content +='      Row: <r>...</r> | Columns: <c>...</c> | Labels: <l>...</l> | Spacer: <spacer></spacer> --> \n';
        form_content +='<div class="wpbc__form__div">  \n';
        form_content +='	<r>  \n';
        form_content +='		<c> [calendar]  </c> \n';
        form_content +='		<c>  <l>Select Times (required):</l><br /> \n';
        if ( form_type == 'times' ) {
            form_content +='			[select* rangetime multiple "10:00 AM - 12:00 PM@@10:00 - 12:00" "12:00 PM - 02:00 PM@@12:00 - 14:00" "02:00 PM - 04:00 PM@@14:00 - 16:00" "04:00 PM - 06:00 PM@@16:00 - 18:00" "06:00 PM - 08:00 PM@@18:00 - 20:00"] \n';
        }
        if ( form_type == 'times30' ) {
            form_content +='			[select rangetime "06:00 - 06:30" "06:30 - 07:00" "07:00 - 07:30" "07:30 - 08:00" "08:00 - 08:30" "08:30 - 09:00" "09:00 - 09:30" "09:30 - 10:00" "10:00 - 10:30" "10:30 - 11:00" "11:00 - 11:30" "11:30 - 12:00" "12:00 - 12:30" "12:30 - 13:00" "13:00 - 13:30" "13:30 - 14:00" "14:00 - 14:30" "14:30 - 15:00" "15:00 - 15:30" "15:30 - 16:00" "16:00 - 16:30" "16:30 - 17:00" "17:00 - 17:30" "17:30 - 18:00" "18:00 - 18:30" "18:30 - 19:00" "19:00 - 19:30" "19:30 - 20:00" "20:00 - 20:30" "20:30 - 21:00" "21:00 - 21:30"] \n';
        }
        if ( form_type == 'times15' ) {
            form_content +='			[select rangetime "8:00 AM - 8:15 AM@@08:00 - 08:15" "8:15 AM - 8:30 AM@@08:15 - 08:30" "8:30 AM - 8:45 AM@@08:30 - 08:45" "8:45 AM - 9:00 AM@@08:45 - 09:00" "9:00 AM - 9:15 AM@@09:00 - 09:15" "9:15 AM - 9:30 AM@@09:15 - 09:30" "9:30 AM - 9:45 AM@@09:30 - 09:45" "9:45 AM - 10:00 AM@@09:45 - 10:00" "10:00 AM - 10:15 AM@@10:00 - 10:15" "10:15 AM - 10:30 AM@@10:15 - 10:30" "10:30 AM - 10:45 AM@@10:30 - 10:45" "10:45 AM - 11:00 AM@@10:45 - 11:00" "11:00 AM - 11:15 AM@@11:00 - 11:15" "11:15 AM - 11:30 AM@@11:15 - 11:30" "11:30 AM - 11:45 AM@@11:30 - 11:45" "11:45 AM - 12:00 AM@@11:45 - 12:00" "12:00 AM - 12:15 AM@@12:00 - 12:15" "12:15 AM - 12:30 AM@@12:15 - 12:30" "12:30 AM - 12:45 AM@@12:30 - 12:45" "12:45 AM - 1:00 PM@@12:45 - 13:00" "1:00 PM - 1:15 PM@@13:00 - 13:15" "1:15 PM - 1:30 PM@@13:15 - 13:30" "1:30 PM - 1:45 PM@@13:30 - 13:45" "1:45 PM - 2:00 PM@@13:45 - 14:00" "2:00 PM - 2:15 PM@@14:00 - 14:15" "2:15 PM - 2:30 PM@@14:15 - 14:30" "2:30 PM - 2:45 PM@@14:30 - 14:45" "2:45 PM - 3:00 PM@@14:45 - 15:00" "3:00 PM - 3:15 PM@@15:00 - 15:15" "3:15 PM - 3:30 PM@@15:15 - 15:30" "3:30 PM - 3:45 PM@@15:30 - 15:45" "3:45 PM - 4:00 PM@@15:45 - 16:00" "4:00 PM - 4:15 PM@@16:00 - 16:15" "4:15 PM - 4:30 PM@@16:15 - 16:30" "4:30 PM - 4:45 PM@@16:30 - 16:45" "4:45 PM - 5:00 PM@@16:45 - 17:00" "5:00 PM - 5:15 PM@@17:00 - 17:15" "5:15 PM - 5:30 PM@@17:15 - 17:30" "5:30 PM - 5:45 PM@@17:30 - 17:45" "5:45 PM - 6:00 PM@@17:45 - 18:00" "6:00 PM - 6:15 PM@@18:00 - 18:15" "6:15 PM - 6:30 PM@@18:15 - 18:30" "6:30 PM - 6:45 PM@@18:30 - 18:45" "6:45 PM - 7:00 PM@@18:45 - 19:00" "7:00 PM - 7:15 PM@@19:00 - 19:15" "7:15 PM - 7:30 PM@@19:15 - 19:30" "7:30 PM - 7:45 PM@@19:30 - 19:45" "7:45 PM - 8:00 PM@@19:45 - 20:00" "8:00 PM - 8:15 PM@@20:00 - 20:15" "8:15 PM - 8:30 PM@@20:15 - 20:30" "8:30 PM - 8:45 PM@@20:30 - 20:45" "8:45 PM - 9:00 PM@@20:45 - 21:00" "9:00 PM - 9:15 PM@@21:00 - 21:15" "9:15 PM - 9:30 PM@@21:15 - 21:30" "9:30 PM - 9:45 PM@@21:30 - 21:45"] \n';
        }
        if ( 'function' === typeof( wpbc_update_capacity_hint ) ){                                                      // >= biz_l
            form_content +='		<spacer>height:1em;</spacer> \n';
            form_content +='		<l>Availability:</l><spacer></spacer> \n';
            form_content +='		[capacity_hint] \n';
        }
        form_content +='		</c> \n';
        form_content +='	</r> \n';
        form_content +='	<hr> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>First Name (required):</l><br />[text* name] </c> \n';
        form_content +='		<c> <l>Last Name (required):</l><br />[text* secondname] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Email (required):</l><br />[email* email] </c> \n';
        form_content +='		<c> <l>Phone:</l><br />[text phone] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Adults:</l><br />[select visitors "1" "2" "3" "4" "5"] </c> \n';
        form_content +='		<c> <l>Children:</l><br />[select children "0" "1" "2" "3"] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Details:</l><spacer></spacer> \n';
        form_content +='			[textarea details] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<spacer>height:10px;</spacer> \n';
        form_content +='	<r> \n';
        form_content +='		<c> [checkbox* term_and_condition use_label_element "I Accept term and conditions"] </c> \n';
        form_content +='		<c> [captcha] </c> \n';
        form_content +='	</r> \n';
        if ( 'function' === typeof( wpbc_show_day_cost_in_date_bottom ) ){                                              // >= biz_m
            form_content += '	<r> \n';
            form_content += '		<c><p> \n';
            form_content += '			Dates: <strong>[selected_short_timedates_hint]</strong> \n';
            form_content += '			([nights_number_hint] - night(s))<br> \n';
            form_content += '			Full cost of the booking: <strong>[cost_hint]</strong> <br> \n';
            form_content += '		</p></c> \n';
            form_content += '	</r> \n';
        }
        form_content +='	<hr> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <p>[submit "Send"]</p> </c> \n';
        form_content +='	</r> \n';
        form_content +='</div> \n';
    }

    if (form_type == 'timesweek'){
           form_content = '';
           form_content +='[calendar] \n'; 
           form_content +='<div class="times-form"> \n';
           form_content +='<p> \n';
           form_content +='    [condition name="weekday-condition" type="weekday" value="*"] \n';
           form_content +='        Select Time Slot:<br> [select rangetime multiple "10:00 - 12:00" "12:00 - 14:00" "14:00 - 16:00" "16:00 - 18:00" "18:00 - 20:00"] \n';
           form_content +='    [/condition] \n';
           form_content +='    [condition name="weekday-condition" type="weekday" value="1,2"] \n';
           form_content +='        Select Time Slot available on Monday, Tuesday:<br>    [select rangetime multiple "10:00 - 12:00" "12:00 - 14:00"] \n';
           form_content +='    [/condition] \n';
           form_content +='    [condition name="weekday-condition" type="weekday" value="3,4"] \n';
           form_content +='        Select Time Slot available on Wednesday, Thursday:<br>  [select rangetime multiple "14:00 - 16:00" "16:00 - 18:00" "18:00 - 20:00"] \n';
           form_content +='    [/condition] \n';
           form_content +='    [condition name="weekday-condition" type="weekday" value="5,6,0"] \n';
           form_content +='        Select Time Slot available on Friday, Saturday, Sunday:<br> [select rangetime multiple "12:00 - 14:00" "14:00 - 16:00" "16:00 - 18:00"] \n';
           form_content +='    [/condition] \n';
           form_content +='</p> \n';
           form_content +='     <p>First Name (required):<br />[text* name] </p> \n';
           form_content +='     <p>Last Name (required):<br />[text* secondname] </p> \n';
           form_content +='     <p>Email (required):<br />[email* email] </p>   \n';
           form_content +='     <p>Phone:<br />[text phone] </p> \n';
           form_content +='     <p>Adults:<br />[select visitors "1" "2" "3" "4"]</p> \n';
           form_content +='     <p>Children:<br />[select children "0" "1" "2" "3"]</p> \n';
           form_content +='     <p>Details:<br /> [textarea details] </p> \n';
           form_content +='     <p>[checkbox* term_and_condition use_label_element "I Accept term and conditions"] </p>\n';
           form_content +='     <p>[captcha]</p> \n';
           form_content +='     <p>[submit class:btn "Send"]</p> \n';
           form_content +='</div>';
    }

    if (form_type == 'hints'){
           form_content = '';
           form_content +='[calendar] \n'; 
           form_content +='<div class="standard-form"> \n';
           if ( 'function' === typeof( wpbc_show_day_cost_in_date_bottom ) ){                                              // >= biz_m
               form_content += '     <div class="form-hints"> \n';
               form_content += '          Dates:[selected_short_timedates_hint]  ([nights_number_hint] - night(s))<br><br> \n';
               form_content += '          Full cost of the booking: [cost_hint] <br> \n';
               form_content += '     </div><hr/> \n';
           }
           form_content +='     <p>First Name (required):<br />[text* name] </p> \n';
           form_content +='     <p>Last Name (required):<br />[text* secondname] </p> \n';
           form_content +='     <p>Email (required):<br />[email* email] </p>   \n';
           form_content +='     <p>Phone:<br />[text phone] </p> \n';
           form_content +='     <p>Adults:<br />[select visitors "1" "2" "3" "4"]</p> \n';
           form_content +='     <p>Children:<br />[select children "0" "1" "2" "3"]</p> \n';
           form_content +='     <p>Details:<br /> [textarea details] </p> \n';
           form_content +='     <p>[checkbox* term_and_condition use_label_element "I Accept term and conditions"] </p>\n';
           form_content +='     <p>[captcha]</p> \n';
           form_content +='     <p>[submit class:btn "Send"]</p> \n';
           form_content +='</div>';
    }

    //FixIn: 8.7.3.5
    if ( 'hints-dev' == form_type ){
            form_content = '';
            form_content +='<!--  Simple HTML shortcodes in the form (check more at "Generate Tag" section): \n';
            form_content +='      Row: <r>...</r> | Columns: <c>...</c> | Labels: <l>...</l> | Spacer: <spacer></spacer> --> \n';
            form_content +='[calendar] \n';
            form_content +='<div class="wpbc__form__div"> \n';
            if ( 'function' === typeof( wpbc_update_capacity_hint ) ){                                                      // >= biz_l
                form_content +='	<r> \n';
                form_content +='		<c><l>Availability:</l><spacer></spacer>[capacity_hint]</c> \n';
                form_content +='	</r> \n';
            }
            if ( 'function' === typeof( wpbc_show_day_cost_in_date_bottom ) ){                                              // >= biz_m
                form_content +='	<r> \n';
                form_content +='		<c><p> \n';
                form_content +='			Dates: <strong>[selected_short_timedates_hint]</strong> \n';
                form_content +='			([nights_number_hint] - night(s))<br> \n';
                form_content +='			Full cost of the booking: <strong>[cost_hint]</strong> <br> \n';
                form_content +='		</p></c> \n';
                form_content +='	</r> <hr> \n';
            }
            form_content +='	<r> \n';
            form_content +='		<c> <l>First Name (required):</l><br />[text* name] </c> \n';
            form_content +='		<c> <l>Last Name (required):</l><br />[text* secondname] </c> \n';
            form_content +='	</r> \n';
            form_content +='	<r> \n';
            form_content +='		<c> <l>Email (required):</l><br />[email* email] </c> \n';
            form_content +='		<c> <l>Phone:</l><br />[text phone] </c> \n';
            form_content +='	</r> \n';
            form_content +='	<r> \n';
            form_content +='		<c> <l>Adults:</l><br />[select visitors "1" "2" "3" "4" "5"] </c> \n';
            form_content +='		<c> <l>Children:</l><br />[select children "0" "1" "2" "3"] </c> \n';
            form_content +='	</r> \n';
            form_content +='	<r> \n';
            form_content +='		<c> <l>Details:</l><spacer></spacer> \n';
            form_content +='			[textarea details] </c> \n';
            form_content +='	</r> \n';
            form_content +='	<spacer>height:10px;</spacer> \n';
            form_content +='	<r> \n';
            form_content +='		<c> [checkbox* term_and_condition use_label_element "I Accept term and conditions"] </c> \n';
            form_content +='		<c> [captcha] </c> \n';
            form_content +='	</r> \n';
            if ( 'function' === typeof( wpbc_show_day_cost_in_date_bottom ) ){                                              // >= biz_m
                form_content += '	<r> \n';
                form_content += '		<c><p> \n';
                form_content += '			Dates: <strong>[selected_short_timedates_hint]</strong> \n';
                form_content += '			([nights_number_hint] - night(s))<br> \n';
                form_content += '			Full cost of the booking: <strong>[cost_hint]</strong> <br> \n';
                form_content += '		</p></c> \n';
                form_content += '	</r> \n';
            }
            form_content +='	<hr> \n';
            form_content +='	<r> \n';
            form_content +='		<c> <p>[submit "Send"]</p> </c> \n';
            form_content +='	</r> \n';
            form_content +='</div> \n';
    }

	if ( (form_type == 'payment') || (form_type == 'paymentUS') ){
        form_content = '';
        form_content +='<!--  Simple HTML shortcodes in the form (check more at "Generate Tag" section): \n';
        form_content +='      Row: <r>...</r> | Columns: <c>...</c> | Labels: <l>...</l> | Spacer: <spacer></spacer> --> \n';
        form_content +='[calendar] \n';
        form_content +='<div class="payment-form"> \n';
        form_content +='     <p>First Name (required):<br />[text* name] </p> \n';
        form_content +='     <p>Last Name (required):<br />[text* secondname] </p> \n';
        form_content +='     <p>Email (required):<br />[email* email] </p> \n';
        form_content +='     <p>Phone:<br />[text phone] </p> \n';
        form_content +='     <p>Address (required):<br />  [text* address] </p> \n';
        form_content +='     <p>City (required):<br />  [text* city] </p> \n';
        form_content +='     <p>Post code (required):<br />  [text* postcode] </p> \n';
        if ( form_type == 'paymentUS' ){                                                                                //FixIn: 8.1.1.5
            form_content +='     <p>Country (required):<br />  [country "US"] </p> \n';
            form_content +='     <p>State:<br /> [select state "" "Alabama@@AL" "Alaska@@AK" "Arizona@@AZ" "Arkansas@@AR" "California@@CA" "Colorado@@CO" "Connecticut@@CT" "Delaware@@DE" "Florida@@FL" "Georgia@@GA" "Hawaii@@HI" "Idaho@@ID" "Illinois@@IL" "Indiana@@IN" "Iowa@@IA" "Kansas@@KS" "Kentucky@@KY" "Louisiana@@LA" "Maine@@ME" "Maryland@@MD" "Massachusetts@@MA" "Michigan@@MI" "Minnesota@@MN" "Mississippi@@MS" "Missouri@@MO" "Montana@@MT" "Nebraska@@NE" "Nevada@@NV" "New Hampshire@@NH" "New Jersey@@NJ" "New Mexico@@NM" "New York@@NY" "North Carolina@@NC" "North Dakota@@ND" "Ohio@@OH" "Oklahoma@@OK" "Oregon@@OR" "Pennsylvania@@PA" "Rhode Island@@RI" "South Carolina@@SC" "South Dakota@@SD" "Tennessee@@TN" "Texas@@TX" "Utah@@UT" "Vermont@@VT" "Virginia@@VA" "Washington@@WA" "West Virginia@@WV" "Wisconsin@@WI" "Wyoming@@WY"] </p> \n';
		} else {
			form_content += '     <p>Country (required):<br />  [country] </p> \n';
		}
        form_content +='     <p>Adults:<br />[select visitors "1" "2" "3" "4"]</p> \n';
        form_content +='     <p>Children:<br />[select children "0" "1" "2" "3"]</p> \n';
        form_content +='     <p>Details:<br /> [textarea details] </p> \n';
        form_content +='     <p>[checkbox* term_and_condition use_label_element "I Accept term and conditions"] </p> \n';
        form_content +='     <p>[captcha]</p> \n';
        form_content +='     <p>[submit class:btn "Send"]</p> \n';
        form_content +='</div>';
    }

    if (form_type == 'wizard')  {
        //FixIn: 8.6.1.15
		form_content = '';
        if ( location.href.indexOf( 'wpbookingcalendar.com' ) !== -1 ){
            form_content += '<!-- In our Public Demo, JavaScript is restricted in the form. --> \n';
            form_content += '<!-- As a result, the "Wizard Form Template" is unable to function here. --> \n';
        }
        form_content +='<!--  Simple HTML shortcodes in the form (check more at "Generate Tag" section): \n';
        form_content +='      Row: <r>...</r> | Columns: <c>...</c> | Labels: <l>...</l> | Spacer: <spacer></spacer> --> \n';
        form_content +='<div class="wpbc_wizard_step wpbc__form__div wpbc_wizard_step1"> \n';
        form_content +='		<r> \n';
        form_content +='			<c> [calendar] </c> \n';
        if ( 'function' === typeof( wpbc_show_day_cost_in_date_bottom ) ){                                              // >= biz_m
            form_content += '			<c><p> \n';
            form_content += '				Dates: <strong>[selected_short_timedates_hint]</strong> \n';
            form_content += '				([nights_number_hint] - night(s))<br> \n';
            form_content += '				Full cost of the booking: <strong>[cost_hint]</strong> <br> \n';
            form_content += '			</p></c> \n';
        }
        form_content +='		</r> <hr> \n';
        form_content +='		<r> \n';
        form_content +='			<div class="wpbc__field" style="justify-content: flex-end;"> \n';
        form_content +='     			<a class="wpbc_button_light" href="javascript:void(0);" \n';
        form_content +='				   onclick="javascript:wpbc_wizard_step(this ,2);"> \n';
        form_content +='				Continue to step 2 \n';
        form_content +='				</a> \n';
        form_content +='			</div> \n';
        form_content +='		</r> \n';
        form_content +='</div> \n';
        form_content +='<div class="wpbc_wizard_step wpbc__form__div wpbc_wizard_step2" style="display:none;clear:both;"> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>First Name (required):</l><br />[text* name] </c> \n';
        form_content +='		<c> <l>Last Name (required):</l><br />[text* secondname] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Email (required):</l><br />[email* email] </c> \n';
        form_content +='		<c> <l>Phone:</l><br />[text phone] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Adults:</l><br />[select visitors "1" "2" "3" "4" "5"] </c> \n';
        form_content +='		<c> <l>Children:</l><br />[select children "0" "1" "2" "3"] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Details:</l><spacer></spacer> \n';
        form_content +='			[textarea details] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<spacer>height:10px;</spacer> \n';
        form_content +='	<r> \n';
        form_content +='		<c> [checkbox* term_and_condition use_label_element "I Accept term and conditions"] </c> \n';
        form_content +='		<c> [captcha] </c> \n';
        form_content +='	</r> \n';
        if ( 'function' === typeof( wpbc_show_day_cost_in_date_bottom ) ){                                              // >= biz_m
            form_content += '	<r> \n';
            form_content += '		<c><div class="form-hints"> \n';
            form_content += '			Dates: <strong>[selected_short_timedates_hint]</strong> \n';
            form_content += '			([nights_number_hint] - night(s))<br> \n';
            form_content += '			Full cost of the booking: <strong>[cost_hint]</strong> <br> \n';
            form_content += '		</div></c> \n';
            form_content += '	</r> \n';
        }
        form_content +='	<hr> \n';
        form_content +='	<r> \n';
        form_content +='		<div class="wpbc__field" style="justify-content: flex-end;"> \n';
        form_content +='			<a href="javascript:void(0);" \n';
        form_content +='				  onclick="javascript:wpbc_wizard_step(this, 1);" \n';
        form_content +='				  class="wpbc_button_light">Back to step 1</a>&nbsp;&nbsp;&nbsp; \n';
        form_content +='			[submit "Send"] \n';
        form_content +='		</div> \n';
        form_content +='	</r> \n';
        form_content +='</div> \n';

    }

    if (form_type == '2collumns')  { // calendar next to  form
        form_content = '';

        form_content +='<!--  Simple HTML shortcodes in the form (check more at "Generate Tag" section): \n';
        form_content +='      Row: <r>...</r> | Columns: <c>...</c> | Labels: <l>...</l> | Spacer: <spacer></spacer> --> \n';
        form_content +='<r> \n';
        form_content +='	<c>[calendar]</c> \n';
        form_content +='	<spacer>width:40px;</spacer> \n';
        form_content +='	<c> \n';
        form_content +='		<r><c> <l>First Name (required):</l> <br>[text* name]</c></r> \n';
        form_content +='		<r><c> <l>Last Name (required):</l>  <br>[text* secondname] </c></r> \n';
        form_content +='		<r><c> <l>Email (required):</l>      <br>[email* email] </c></r> \n';
        form_content +='		<r><c> <l>Phone:</l>                 <br>[text phone] </c></r> \n';
        form_content +='		<r><c> <l>Adults:</l>                <br>[select visitors "1" "2" "3" "4"] </c></r> \n';
        form_content +='		<r><c> <l>Children:</l>              <br>[select children "0" "1" "2" "3"] </c></r> \n';
        form_content +='		<r><c> <l>Details:</l><br> [textarea details]</c></r> \n';
        form_content +='		<r> \n';
        form_content +='			<c>[checkbox* term_and_condition use_label_element "I Accept term and conditions"]</c> \n';
        form_content +='			<c>[captcha]</c> \n';
        form_content +='		</r> \n';
        form_content +='		<hr/> \n';
        form_content +='		<r><c>[submit class:btn "Send"]</c></r> \n';
        form_content +='	</c> \n';
        form_content +='</r> \n';


        // form_content +='<r> \n';
        // form_content +='	<c>[calendar]</c> \n';
        // form_content +='	<c> \n';
        // form_content +='		<r><c> <l>First Name (required):</l><br>[text* name]</c></r> \n';
        // form_content +='		<r><c> <l>Last Name (required):</l><br>[text* secondname]</c></r> \n';
        // form_content +='		<r><c> <l>Email (required):</l><br>[email* email]</c></r> \n';
        // form_content +='		<r><c> <l>Phone:</l><br>[text phone]</c></r> \n';
        // form_content +='		<r><c> <l>Adults:</l><br>[select visitors "1" "2" "3" "4"]</c></r> \n';
        // form_content +='		<r><c> <l>Children:</l><br>[select children "0" "1" "2" "3"]</c></r> \n';
        // form_content +='		<r><c> <l>Details:</l><br> [textarea details]</c></r> \n';
        // form_content +='		<r> \n';
        // form_content +='			<c>[checkbox* term_and_condition use_label_element "I Accept term and conditions"]</c> \n';
        // form_content +='			<c>[captcha]</c> \n';
        // form_content +='		</r> \n';
        // form_content +='		<hr/> \n';
        // form_content +='		<r><c>[submit class:btn "Send"]</c></r> \n';
        // form_content +='	</c> \n';
        // form_content +='</r> \n';

        // form_content +='<div class="wpbc_sections"> \n';
        // form_content +='	<div class="wpbc_section_50"> \n';
        // form_content +='		[calendar] \n';
        // form_content +='	</div> \n';
        // form_content +='	<div class="wpbc_section_spacer"></div> \n';
        // form_content +='	<div class="wpbc_section_50"> \n';
        // form_content +='		<p>First Name (required):<br />[text* name] </p> \n';
        // form_content +='		<p>Last Name (required):<br />[text* secondname] </p>  \n';
        // form_content +='		<p>Email (required):<br />[email* email] </p>  \n';
        // form_content +='		<p>Phone:<br />[text phone] </p>  \n';
        // form_content +='		<p>Adults:<br />[select visitors "1" "2" "3" "4"]</p> \n';
        // form_content +='		<p>Children:<br />[select children "0" "1" "2" "3"]</p>  \n';
        // form_content +='	</div> \n';
        // form_content +='	<div class="wpbc_section_100"> \n';
        // form_content +='		<p>Details:<br /> [textarea details]</p>  \n';
        // form_content +='		[captcha] \n';
        // form_content +='		<p>[checkbox* term_and_condition use_label_element "I Accept term and conditions"]</p> \n';
        // form_content +='		<hr/> \n';
        // form_content +='		<p>[submit class:btn "Send"] </p> \n';
        // form_content +='	</div> \n';
        // form_content +='</div> \n';
    }

    //FixIn: 8.7.7.15
    if (form_type == 'fields2columns')  { // 2 columns form
        form_content = '';
        form_content +='<!--  Simple HTML shortcodes in the form (check more at "Generate Tag" section): \n';
        form_content +='      Row: <r>...</r> | Columns: <c>...</c> | Labels: <l>...</l> | Spacer: <spacer></spacer> --> \n';
        form_content +='[calendar]\n';
        form_content +='<div class="wpbc__form__div">\n';
        form_content +='	<r>\n';
        form_content +='		<c> <l>First Name (required):</l><br>[text* name] </c>\n';
        form_content +='		<c> <l>Last Name (required):</l><br>[text* secondname] </c>\n';
        form_content +='	</r>\n';
        form_content +='	<r>\n';
        form_content +='		<c> <l>Email (required):</l><br>[email* email] </c>\n';
        form_content +='		<c> <l>Phone:</l><br>[text phone] </c>\n';
        form_content +='	</r>\n';
        form_content +='	<r>\n';
        form_content +='		<c> <l>Address (required):</l><br>[text* address] </c>\n';
        form_content +='		<c> <l>City (required):</l><br>[text* city] </c>\n';
        form_content +='	</r>\n';
        form_content +='	<r>\n';
        form_content +='		<c> <l>Post code (required):</l><br>[text* postcode] </c>\n';
        form_content +='		<c> <l>Country (required):</l><br>[country] </c>\n';
        form_content +='	</r>\n';
        form_content +='	<r>\n';
        form_content +='		<c> <l>Adults:</l><br>[select visitors "1" "2" "3" "4" "5"] </c>\n';
        form_content +='		<c> <l>Children:</l><br>[select children "0" "1" "2" "3"] </c>\n';
        form_content +='	</r>\n';
        form_content +='	<r>\n';
        form_content +='		<c> <l>Details:</l><spacer></spacer> \n';
        form_content +='			[textarea details] </c>\n';
        form_content +='	</r><br>\n';
        form_content +='	<p>[submit class:btn "Send"]</p>\n';
        form_content +='</div>';
    }

    //FixIn: 8.8.2.6
    if (form_type == 'fields3columns')  { // 3 columns form
        form_content = '';
        form_content +='<!--  Simple HTML shortcodes in the form (check more at "Generate Tag" section): \n';
        form_content +='      Row: <r>...</r> | Columns: <c>...</c> | Labels: <l>...</l> | Spacer: <spacer></spacer> --> \n';
        form_content +='<r>\n';
        form_content +='    <c> [calendar] </c>\n';
        form_content +='    <c>\n';
        form_content +='        <div class="wpbc__form__div">\n';
        form_content +='            <r>\n';
        form_content +='                <c> <l>First Name (required):</l><br>[text* name] </c>\n';
        form_content +='                <c> <l>Last Name (required):</l><br>[text* secondname] </c>\n';
        form_content +='            </r>\n';
        form_content +='            <r>\n';
        form_content +='                <c> <l>Email (required):</l><br>[email* email] </c>\n';
        form_content +='                <c> <l>Phone:</l><br>[text phone] </c>\n';
        form_content +='            </r>\n';
        form_content +='            <r>\n';
        form_content +='                <c> <l>Address (required):</l><br>[text* address] </c>\n';
        form_content +='                <c> <l>City (required):</l><br>[text* city] </c>\n';
        form_content +='            </r>\n';
        form_content +='            <r>\n';
        form_content +='                <c> <l>Post code (required):</l><br>[text* postcode] </c>\n';
        form_content +='                <c> <l>Country (required):</l><br>[country] </c>\n';
        form_content +='            </r>\n';
        form_content +='            <r>\n';
        form_content +='                <c> <l>Adults:</l><br>[select visitors "1" "2" "3" "4" "5"] </c>\n';
        form_content +='                <c> <l>Children:</l><br>[select children "0" "1" "2" "3"] </c>\n';
        form_content +='            </r>\n';
        form_content +='            <r>\n';
        form_content +='                <c> <l>Details:</l><spacer></spacer> \n';
        form_content +='                    [textarea details] </c>\n';
        form_content +='            </r>\n';
        form_content +='            <p>[submit class:btn "Send"]</p>\n';
        form_content +='        </div>\n';
        form_content +='    </c>\n';
        form_content +='</r>\n';
    }


    //FixIn: 8.7.11.14
    if (form_type == 'fields2columnstimes')  { // 2 columns form
        form_content  = '';
        form_content +='<div class="wpbc__form__div"> \n';
        form_content +='    <r> \n';
        form_content +='		<c> <l>Select Date:</l><br />[calendar] </c> \n';
        form_content +='		<c> <l>Select Times*:</l><br /> \n';
        form_content +='			[select* rangetime "10:00 AM - 12:00 PM@@10:00 - 12:00" "12:00 PM - 02:00 PM@@12:00 - 14:00" "02:00 PM - 04:00 PM@@14:00 - 16:00" "04:00 PM - 06:00 PM@@16:00 - 18:00" "06:00 PM - 08:00 PM@@18:00 - 20:00"] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>First Name (required):</l><br />[text* name] </c> \n';
        form_content +='		<c> <l>Last Name (required):</l><br />[text* secondname] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Email (required):</l><br />[email* email] </c> \n';
        form_content +='		<c> <l>Phone:</l><br />[text phone] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Adults:</l><br />[select visitors "1" "2" "3" "4" "5"] </c> \n';
        form_content +='		<c> <l>Children:</l><br />[select children "0" "1" "2" "3"] </c> \n';
        form_content +='	</r> \n';
        form_content +='	<r> \n';
        form_content +='		<c> <l>Details:</l><spacer></spacer> \n';
        form_content +='			[textarea details] </c> \n';
        form_content +='	</r><br /> \n';
        form_content +='	<p>[submit "Send"]</p>\n';
        form_content +='</div>\n';
    }

    if (form_content == '') { // Default Form.
           form_content = '';
           form_content +='[calendar] \n'; 
           form_content +='<div class="standard-form"> \n';
           form_content +='     <p>First Name (required):<br />[text* name] </p> \n';
           form_content +='     <p>Last Name (required):<br />[text* secondname] </p> \n';
           form_content +='     <p>Email (required):<br />[email* email] </p>   \n';
           form_content +='     <p>Phone:<br />[text phone] </p> \n';
           form_content +='     <p>Adults:<br />[select visitors "1" "2" "3" "4"]</p> \n';
           form_content +='     <p>Children:<br />[select children "0" "1" "2" "3"]</p> \n';
           form_content +='     <p>Details:<br /> [textarea details] </p> \n';
           form_content +='     <p>[checkbox* term_and_condition use_label_element "I Accept term and conditions"] </p>\n';
           form_content +='     <p>[captcha]</p> \n';
           form_content +='     <p>[submit class:btn "Send"]</p> \n';
           form_content +='</div>';
    }
    
    return form_content;
}

function wpbc_reset__get_form_data( form_type ){
    var form_content = '';
        
    if ( (form_type == 'payment')  || (form_type == 'paymentUS') || ( 'fields2columns' == form_type ) || ( 'fields3columns' == form_type ) ) {               //FixIn: 8.7.7.15      //FixIn: 8.8.2.6
        form_content = '';
        form_content +='<div class="standard-content-form"> \n';
        form_content += '    <b>First Name</b>: <f>[name]</f><br>\n';
        form_content += '    <b>Last Name</b>:  <f>[secondname]</f><br>\n';
        form_content += '    <b>Email</b>:      <f>[email]</f><br>\n';
        form_content += '    <b>Phone</b>:      <f>[phone]</f><br>\n';
        form_content += '    <b>Address</b>:    <f>[address]</f><br>\n';
        form_content += '    <b>City</b>:       <f>[city]</f><br>\n';
        form_content += '    <b>Post code</b>:  <f>[postcode]</f><br>\n';
        form_content += '    <b>Country</b>:    <f>[country]</f><br>\n';
        if ( form_type == 'paymentUS' ) {
        form_content += '    <b>State</b>:      <f>[state]</f><br>\n';
        }
        form_content += '    <b>Adults</b>:     <f>[visitors]</f><br>\n';
        form_content += '    <b>Children</b>:   <f>[children]</f><br>\n';
        form_content += '    <b>Details</b>:    <f>[details]</f>\n';
        form_content += '</div>';
    }

    if ( (form_type == 'times') || (form_type == 'times30')  || (form_type == 'times15')  || ( form_type == 'timesweek') || ( 'fields2columnstimes' == form_type ) ){      //FixIn: 7.1.2.6       //FixIn: 8.7.11.14
        form_content = '';
        form_content +='<div class="standard-content-form"> \n';
        form_content += '    <b>Times</b>:      <f>[rangetime]</f><br>\n';
        form_content += '    <b>First Name</b>: <f>[name]</f><br>\n';
        form_content += '    <b>Last Name</b>:  <f>[secondname]</f><br>\n';
        form_content += '    <b>Email</b>:      <f>[email]</f><br>\n';
        form_content += '    <b>Phone</b>:      <f>[phone]</f><br>\n';
        form_content += '    <b>Adults</b>:     <f>[visitors]</f><br>\n';
        form_content += '    <b>Children</b>:   <f>[children]</f><br>\n';
        form_content += '    <b>Details</b>:    <f>[details]</f>\n';
        form_content +='</div>';
    }

    //FixIn: 8.7.3.5
    if ( 'hints-dev' == form_type ){
        form_content = '';
        form_content +='<div class="standard-content-form"> \n';
        form_content += '    <b>First Name</b>: <f>[name]</f><br>\n';
        form_content += '    <b>Last Name</b>:  <f>[secondname]</f><br>\n';
        form_content += '    <b>Email</b>:      <f>[email]</f><br>\n';
        form_content += '    <b>Adults</b>:     <f>[visitors]</f><br>\n';
        form_content += '    <b>Children</b>:   <f>[children]</f><br>\n';
        form_content += '    <b>Details</b>:    <f>[details]</f>\n';
        form_content +='</div>';
    }

    if (  (form_type == 'wizard') || (form_type == '2collumns') || (form_content == 'hints') || (form_content == '') ){
        form_content = '';
        form_content +='<div class="standard-content-form"> \n';
        form_content += '    <b>First Name</b>: <f>[name]</f><br>\n';
        form_content += '    <b>Last Name</b>:  <f>[secondname]</f><br>\n';
        form_content += '    <b>Email</b>:      <f>[email]</f><br>\n';
        form_content += '    <b>Phone</b>:      <f>[phone]</f><br>\n';
        form_content += '    <b>Adults</b>:     <f>[visitors]</f><br>\n';
        form_content += '    <b>Children</b>:   <f>[children]</f><br>\n';
        form_content += '    <b>Details</b>:    <f>[details]</f>\n';
        form_content +='</div>';
    }
    return form_content;
};
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/js/biz_s.js?ver=9.8.12 

/**
 *  >= Business Small ...
 */

	/**
	 * Hover dates in calendar, when mouse over
	 *
	 * @param sql_class_day
	 * @param date
	 * @param resource_id
	 */
	function wpbc__calendar__do_days_highlight__bs( sql_class_day, date, resource_id ){

		var inst = jQuery.datepick._getInst( document.getElementById( 'calendar_booking' + resource_id ) );

		if ( 'function' === typeof (wpbc__conditions__for_range_days__first_date__bm) ){
			wpbc__conditions__for_range_days__first_date__bm( date, resource_id );				// Highlight dates based on the conditions
		}


		var td_overs = [];
		var i;
		var start_day_num;
		var working_date;

		// Fixed Days Selection mode - 1 mouse click
		if ( 'fixed' == _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ) ){

			wpbc_calendars__clear_days_highlighting();																		// Clear days highlighting in all  calendar

			// Set START_WEEK_DAY 	depends on season
			if ( 'function' === typeof ( wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm ) ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, date, 'start' ); }

			// 1. Find the closest start WeekDay to the hover day
			if ( -1 != _wpbc.calendar__get_param_value( resource_id, 'fixed__week_days__start' ) ){

				start_day_num = wpbc_get_abs_closest_value_in_arr( date.getDay(), _wpbc.calendar__get_param_value( resource_id, 'fixed__week_days__start' ) );
				date.setDate( date.getDate() - (date.getDay() - start_day_num) );

				// Update NUMBER_OF_DAYS_TO_SELECT    depends on    week_day / season
				if ( 'function' === typeof (wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm)  ){ wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm( date, resource_id ); }
			}

			// Go back of    START_WEEK_DAY 	to original shortcode
			if ( 'function' === typeof ( wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm ) ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, date, 'end' ); }


			// 2. When we are mouseover the date, that selected. Do not highlight it.
			if ( wpbc_is_this_day_among_selected_days( date, inst.dates ) ){
				return false;
			}


			for ( i = 0; i < _wpbc.calendar__get_param_value( resource_id, 'fixed__days_num' ); i++ ){                                                      			// Recheck  if all days are available for the booking

				sql_class_day = wpbc__get__sql_class_date( date );

				if ( ! wpbc_is_this_day_selectable( resource_id, sql_class_day ) ){											// Check if day is selectable
					document.body.style.cursor = 'default';
					return false;
				}

				td_overs[ td_overs.length ] = '#calendar_booking' + resource_id + ' .cal4date-' + wpbc__get__td_class_date( date );

				date.setDate( date.getDate() + 1 );                                                               			// set next date
			}

			// Highlight days
			for ( i = 0; i < td_overs.length; i++ ){
				jQuery( td_overs[ i ] ).addClass( 'datepick-days-cell-over' );
			}
			return true;

		} // End Fixed days selection


		// Range Days Selection mode - 2 mouse clicks
		if ( 'dynamic' == _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ) ){

			wpbc_calendars__clear_days_highlighting();																		// Clear days highlighting in all  calendar

			// Highlight days before selection
			if ( 1 !== inst.dates.length ){         	// Situation, when we do not click 1 time. Not selected at all, or made selection.

				// Get this first mouse over date
				working_date = new Date();
				working_date.setFullYear( date.getFullYear(), (date.getMonth()), (date.getDate()) );

				// We are mouseover selected date - do not highlight it
				if ( wpbc_is_this_day_among_selected_days( working_date, inst.dates ) ){
					return false;
				}

				// Set START_WEEK_DAY 	depends on season
				if ( 'function' === typeof ( wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm ) ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, date, 'start' ); }

				if (  -1 != _wpbc.calendar__get_param_value( resource_id, 'dynamic__week_days__start' ) ){

					start_day_num = wpbc_get_abs_closest_value_in_arr( date.getDay(), _wpbc.calendar__get_param_value( resource_id, 'dynamic__week_days__start' ) );
					working_date.setDate( date.getDate() - (date.getDay() - start_day_num) );

					// Update NUMBER_OF_DAYS_TO_SELECT    depends on    week_day / season
					if ( 'function' === typeof (wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm)  ){ wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm( working_date, resource_id ); }

				}

				// Go back of    START_WEEK_DAY 	to original shortcode
				if ( 'function' === typeof ( wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm ) ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, date, 'end' ); }

				i = 0;

				// Get dates to select
				while ( i < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ) ){
					i++;
					sql_class_day = wpbc__get__sql_class_date( working_date );
					if ( ! wpbc_is_this_day_selectable( resource_id, sql_class_day ) ){										// Check if day is selectable
						document.body.style.cursor = 'default';
						return false;
					}
					td_overs[ td_overs.length ] = '#calendar_booking' + resource_id + ' .cal4date-' + wpbc__get__td_class_date( working_date );

					working_date.setDate( working_date.getDate() + 1 );                                       				// set next date
				}


			} else { 					// First day clicked in calendar e.g. -- (inst.dates.length == 1)

				/**
				 * If we already clicked 1st time on date in calendar, then we need to highlight dates starting from this first selected date,
				 * that's why  we start operation  here from  first  selected date,  e.g.:   inst.dates[ 0 ]
				 */

				working_date = new Date();
				working_date.setFullYear( inst.dates[ 0 ].getFullYear(), (inst.dates[ 0 ].getMonth()), (inst.dates[ 0 ].getDate()) ); 	// Get "FIRST SELECTED DATE"
				var is_check = true;
				i = 0;

				while ( ( is_check ) || ( i < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ) ) ){                                         		// Until rich MIN days number.
					i++;
					sql_class_day = wpbc__get__sql_class_date( working_date );

					if ( ! wpbc_is_this_day_selectable( resource_id, sql_class_day ) ){										// Check if day is selectable
						document.body.style.cursor = 'default';
						return false;
					}

					td_overs[ td_overs.length ] = '#calendar_booking' + resource_id + ' .cal4date-' + wpbc__get__td_class_date( working_date );

					// Check  for SEPARATE / DISCRETE DAYS, if we among them
					var is_discrete_ok = true;
					if ( _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' ).length > 0 ){              					// check if we set some discrete dates
						is_discrete_ok = false;
						for ( var di = 0; di < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' ).length; di++ ){   		// check if current number of days inside discrete one

							if ( i == _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' )[ di ] ){
								is_discrete_ok = true;
								break;
							}
						}
					}

					// Current Hovering date,  which  in [discrete]
					if (   (is_discrete_ok)
						&& (date.getMonth() == working_date.getMonth())
						&& (date.getDate() == working_date.getDate())
						&& (date.getFullYear() == working_date.getFullYear())
					){
						is_check = false;
					}

					// Inside  [min...max] and in [discrete]
					if (   ( is_discrete_ok )
						&& ( working_date > date )
						&& ( i >= _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ) )
						&& (  i < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_max' ) )
					){
						is_check = false;
					}

					// = Max day
					if ( i >= _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_max' ) ){
						is_check = false;
					}

					working_date.setDate( working_date.getDate() + 1 );                                       				// set next date
				}
			}


			// Highlight days
			for ( i = 0; i < td_overs.length; i++ ){
				jQuery( td_overs[ i ] ).addClass( 'datepick-days-cell-over' );
			}
			return true;

		} // End Range days selection

	}


	/**
	 * Do dates selection in calendar
	 *
	 * @param selected_dates
	 * @param resource_id
	 */
	function wpbc__calendar__do_days_select__bs( selected_dates, resource_id ){

		if ( typeof (wpbc__conditions__for_range_days__first_date__bm) == 'function' ){ wpbc__conditions__for_range_days__first_date__bm( selected_dates, resource_id ); }

		wpbc__calendar_range_days_select__bs( selected_dates, resource_id );


		/**
		 * Conditional showing form elements,     basically  can be SKIPed in REFACTOR,  but better  to  REFACTOR  it too
		 *
		 * We are need to  get the dates from  the textarea and not from  all_dates variable, because in the range days selection  the dates can be changed
		 */
		if ( typeof (check_condition_sections_in_bkform) == 'function' ){ check_condition_sections_in_bkform( jQuery( '#date_booking' + resource_id ).val(), resource_id ); }


					//TODO:  update it,  because here exist  such  variables: bk_2clicks_mode_days_min
					if ( typeof (showCostHintInsideBkForm) == 'function' ){ showCostHintInsideBkForm( resource_id ); }	//Calculate the cost and show inside of form
	}





//TODO: this function  need to  R E F A C T O R  and make it simpler

/**
 * Force range days selection functionality  for FIXED and DYNAMIC days selection
 *
 * @param selected_dates	DYNAMIC :: '19.08.2023 - 19.08.2023' / '19.08.2023 - 27.08.2023'  		FIXED :: '19.08.2023'
 * @param resource_id		'1'
 * @returns {boolean}
 */
function wpbc__calendar_range_days_select__bs( selected_dates, resource_id ){

	if (
		   (  'fixed' !== _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ))
		&& ('dynamic' !== _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ))
	){
		return false;
	}


	var td_class;
	var sql_class_day;
	var inst = jQuery.datepick._getInst( document.getElementById( 'calendar_booking' + resource_id ) );
	var internal__days_num__to_select = _wpbc.calendar__get_param_value( resource_id, 'fixed__days_num' );


	/**
	 * If 2 clicks,  then  dates can  be '19.08.2023 - 19.08.2023'  or "19.08.2023 - 27.08.2023" and then  we need to  check if it's possible to  finish  selection on 27/08/2023
	 * If 1 click    then  we have       '19.08.2023',  and after that  we need to  count how many  days to  select
	 */


	// Dynamic for 2 mouse clicks ======================================================================================
	if ( -1 != selected_dates.indexOf( ' - ' ) ){

			var start_end_date = selected_dates.split( " - " );

			var is_start_same_as_last_day__for_dynamic = true;
			if (
				   ( inst.dates.length > 1 ) 																			// inst.date = [ Date('26 Aug.') ]
				&& ( 'dynamic' === _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ) )
			){
				is_start_same_as_last_day__for_dynamic = false;
			}

			var is_only_first_click = ( (start_end_date[ 0 ] == start_end_date[ 1 ]) && (is_start_same_as_last_day__for_dynamic === true) );

			// FIRST_DAY_CLICK  --------------------------------------------------------------------------------------------
			if ( is_only_first_click ){

				var start_dynamic_date 		= start_end_date[ 0 ].split( "." );
				var date_js__check_in = new Date( parseInt( start_dynamic_date[ 2 ] ), (parseInt( start_dynamic_date[ 1 ] ) - 1), parseInt( start_dynamic_date[ 0 ] ) );

				if ( typeof (wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm) == 'function' ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, date_js__check_in, 'start' ); }

				// START selection on SPECIFIC WEEK DAYS
				if ( -1 != _wpbc.calendar__get_param_value( resource_id, 'dynamic__week_days__start' ) ){

					if ( date_js__check_in.getDay() != _wpbc.calendar__get_param_value( resource_id, 'dynamic__week_days__start' ) ){

						var startDay = wpbc_get_abs_closest_value_in_arr( date_js__check_in.getDay(), _wpbc.calendar__get_param_value( resource_id, 'dynamic__week_days__start' ) );
						date_js__check_in.setDate( date_js__check_in.getDate() - (date_js__check_in.getDay() - startDay) );


						selected_dates = jQuery.datepick._formatDate( inst, date_js__check_in );
						selected_dates += ' - ' + selected_dates;
						jQuery( '#date_booking' + resource_id ).val( selected_dates ); // Fill the input box

						if ( typeof (wpbc__conditions__for_range_days__first_date__bm) == 'function' ){ wpbc__conditions__for_range_days__first_date__bm( selected_dates, resource_id ); } // Highlight dates based on the conditions

						// Check this day for already booked
						var selceted_first_day = new Date;
						selceted_first_day.setFullYear( date_js__check_in.getFullYear(), (date_js__check_in.getMonth()), (date_js__check_in.getDate()) );
						i = 0;
						while ( i < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ) ) {

							sql_class_day = wpbc__get__sql_class_date( selceted_first_day );
							td_class      = wpbc__get__td_class_date( selceted_first_day );

							if ( ! wpbc_is_this_day_selectable( resource_id, sql_class_day ) ){

								wpbc_calendar__unselect_all_dates( resource_id );										// Unselect all dates and set  properties of Datepick

								return false;
							}

							selceted_first_day.setFullYear( selceted_first_day.getFullYear(), (selceted_first_day.getMonth()), (selceted_first_day.getDate() + 1) );
							i++;
						}

						// Selection of the day
						inst.cursorDate.setFullYear( date_js__check_in.getFullYear(), (date_js__check_in.getMonth()), (date_js__check_in.getDate()) );
						inst.dates = [inst.cursorDate];
						jQuery.datepick._updateDatepick( inst );
					}

				} else { // Set correct date, if only single date is selected, and possible press send button then.

					inst.cursorDate.setFullYear( date_js__check_in.getFullYear(), (date_js__check_in.getMonth()), (date_js__check_in.getDate()) );
					inst.dates = [inst.cursorDate];
					jQuery.datepick._updateDatepick( inst );
					jQuery( '#date_booking' + resource_id ).val( start_end_date[ 0 ] );
				}

				if ( typeof (wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm) == 'function' ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, '', 'end' ); }

				// Disable the submit button
				if ( _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ) > 1 ){
					wpbc_disable_submit_button_in_booking_form( resource_id );
				}
				setTimeout( function (){
										jQuery( '#calendar_booking' + resource_id + ' .datepick-unselectable.timespartly.check_out_time'
											  +',#calendar_booking' + resource_id + ' .datepick-unselectable.timespartly.check_in_time' ).removeClass( 'datepick-unselectable' );
							}, 500 );

				return false;

			}

			// LAST_DAY_CLICK  ---------------------------------------------------------------------------------------------
			if ( ! is_only_first_click ){

				wpbc_restore_submit_button_in_booking_form( resource_id );

				var start_dynamic_date = start_end_date[ 0 ].split( "." );
				var date_js__check_in = new Date();
				date_js__check_in.setFullYear( start_dynamic_date[ 2 ], start_dynamic_date[ 1 ] - 1, start_dynamic_date[ 0 ] );    // get date

				var end_dynamic_date = start_end_date[ 1 ].split( "." );
				var real_end_dynamic_date = new Date();
				real_end_dynamic_date.setFullYear( end_dynamic_date[ 2 ], end_dynamic_date[ 1 ] - 1, end_dynamic_date[ 0 ] );    // get date

				internal__days_num__to_select = 1; // need to count how many days right now

				var temp_date_for_count = new Date();

				//FixIn: 8.8.2.7
				for ( var j1 = 0; j1 < 3 * 365; j1++ ){
					temp_date_for_count = new Date();
					temp_date_for_count.setFullYear( date_js__check_in.getFullYear(), (date_js__check_in.getMonth()), (date_js__check_in.getDate() + j1) );

					if ( (temp_date_for_count.getFullYear() == real_end_dynamic_date.getFullYear()) && (temp_date_for_count.getMonth() == real_end_dynamic_date.getMonth()) && (temp_date_for_count.getDate() == real_end_dynamic_date.getDate()) ){
						internal__days_num__to_select = j1;
						j1 = 1000;
					}
				}
				internal__days_num__to_select++;
				selected_dates = start_end_date[ 0 ];
				if ( internal__days_num__to_select < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ) ){
					internal__days_num__to_select = _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' );
				}

				var is_backward_direction = false;
				if ( _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' ).length > 0 ){              // check if we set some discreet dates

					var is_discreet_ok = false;
					while ( is_discreet_ok === false ){

						for ( var di = 0; di < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' ).length; di++ ){   // check if current number of days inside of discreet one
							if (
								(internal__days_num__to_select == _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' )[ di ]) &&
								(internal__days_num__to_select <= _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_max' ) )
							){
								is_discreet_ok = true;
								di = (_wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' ).length + 1);
							}
						}
						if ( is_backward_direction === false ){
							if ( is_discreet_ok === false ){
								internal__days_num__to_select++;
							}
						}

						// BackWard directions, if we set more than maximum days
						if ( internal__days_num__to_select >= _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_max' ) ){
							is_backward_direction = true;
						}

						if ( is_backward_direction === true ){
							if ( is_discreet_ok === false ){
								internal__days_num__to_select--;
							}
						}

						if ( internal__days_num__to_select < _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ) ){
							is_discreet_ok = true;
						}
					}

				} else {
					if ( internal__days_num__to_select > _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_max' ) ){
						internal__days_num__to_select = _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_max' );
					}
				}


			}
	}
	// Dynamic for 2 mouse clicks  E N D  ==============================================================================



	// DO DAYS SELECTION INTENTIONALLY +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


	var temp_saved__days_selection_mode = _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' );
	_wpbc.calendar__set_param_value( resource_id, 'days_select_mode', 'multiple' );

		inst.dates = [];                                        // Empty dates in datepicker
		var all_dates_array;
		var date_array;
		var date;
		var date_to_ins;

		// Get array of dates
		if ( selected_dates.indexOf( ',' ) == -1 ){
			all_dates_array = [selected_dates];
		} else {
			all_dates_array = selected_dates.split( "," );
		}

		var original_array = [];
		var isMakeSelection = false;

		// F I X E D
		if ( 'dynamic' != temp_saved__days_selection_mode ){
			// Gathering original (already selected dates) date array
			for ( var j = 0; j < all_dates_array.length; j++ ){                           //loop array of dates
				all_dates_array[ j ] = all_dates_array[ j ].replace( /(^\s+)|(\s+$)/g, "" );  // trim white spaces in date string

				date_array = all_dates_array[ j ].split( "." );                             // get single date array

				date = new Date();
				date.setFullYear( date_array[ 2 ], date_array[ 1 ] - 1, date_array[ 0 ] );    // get date

				if ( (date.getFullYear() == inst.cursorDate.getFullYear()) && (date.getMonth() == inst.cursorDate.getMonth()) && (date.getDate() == inst.cursorDate.getDate()) ){
					isMakeSelection = true;

					if ( typeof (wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm) == 'function' ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, inst.cursorDate, 'start' ); }

					if (   -1 != _wpbc.calendar__get_param_value( resource_id, 'fixed__week_days__start' ) ){

						var startDay = wpbc_get_abs_closest_value_in_arr( inst.cursorDate.getDay(), _wpbc.calendar__get_param_value( resource_id, 'fixed__week_days__start' ) );

						inst.cursorDate.setDate( inst.cursorDate.getDate() - (inst.cursorDate.getDay() - startDay) );

						_wpbc.calendar__set_param_value( resource_id, 'days_select_mode' , temp_saved__days_selection_mode );

						if ( typeof (wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm) == 'function' ){ wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm( inst.cursorDate, resource_id ); } // Highlight dates based on the conditions

						temp_saved__days_selection_mode = _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' );
						_wpbc.calendar__set_param_value( resource_id, 'days_select_mode', 'multiple' );

						internal__days_num__to_select = _wpbc.calendar__get_param_value( resource_id, 'fixed__days_num' );
					}

					if ( typeof (wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm) == 'function' ){ wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, inst.cursorDate, 'end' ); }
				}
			}
		} else {
			isMakeSelection = true;                                                         // Dynamic range selection
		}

		var isEmptySelection = false;
		if ( isMakeSelection ){
			var date_start_range = inst.cursorDate;

			if ( 'dynamic' != temp_saved__days_selection_mode ){
				original_array.push( jQuery.datepick._restrictMinMax( inst, jQuery.datepick._determineDate( inst, inst.cursorDate, null ) ) ); 			//add date
			} else {
				original_array.push( jQuery.datepick._restrictMinMax( inst, jQuery.datepick._determineDate( inst, date_js__check_in, null ) ) ); 	//set 1st date from dynamic range
				date_start_range = date_js__check_in;
			}
			var dates_array = [];
			var range_array = [];
			var td;

			// Add dates to the range array
			for ( var i = 1; i < internal__days_num__to_select; i++ ){

				dates_array[ i ] = new Date();

				dates_array[ i ].setFullYear( date_start_range.getFullYear(), (date_start_range.getMonth()), (date_start_range.getDate() + i) );

				td_class = (dates_array[ i ].getMonth() + 1) + '-' + dates_array[ i ].getDate() + '-' + dates_array[ i ].getFullYear();
				sql_class_day = wpbc__get__sql_class_date( dates_array[ i ] );

				td = '#calendar_booking' + resource_id + ' .cal4date-' + td_class;

				if ( jQuery( td ).hasClass( 'datepick-unselectable' ) ){ // If we find some unselect option so then make no selection at all in this range
					jQuery( td ).removeClass( 'datepick-current-day' );
					isEmptySelection = true;
				}

				//Check if in selection range are reserved days, if so then do not make selection
				if ( ! wpbc_is_this_day_selectable( resource_id, sql_class_day ) ){
					isEmptySelection = true;
				}

				/////////////////////////////////////////////////////////////////////////////////////

				date_to_ins = jQuery.datepick._restrictMinMax( inst, jQuery.datepick._determineDate( inst, dates_array[ i ], null ) );

				range_array.push( date_to_ins );
			}

			// check if some dates are the same in the arrays so the remove them from both
			for ( i = 0; i < range_array.length; i++ ){
				for ( j = 0; j < original_array.length; j++ ){       //loop array of dates

					if ( (original_array[ j ] != -1) && (range_array[ i ] != -1) )
						if (
							   (range_array[ i ].getFullYear() == original_array[ j ].getFullYear())
							&& (range_array[ i ].getMonth() == original_array[ j ].getMonth())
							&& (range_array[ i ].getDate() == original_array[ j ].getDate())
						){
							range_array[ i ] = -1;
							original_array[ j ] = -1;
						}
				}
			}

			// Add to the dates array
			for ( j = 0; j < original_array.length; j++ ){       //loop array of dates
				if ( original_array[ j ] != -1 ){
					inst.dates.push( original_array[ j ] );
				}
			}
			for ( i = 0; i < range_array.length; i++ ){
				if ( range_array[ i ] != -1 ){
					inst.dates.push( range_array[ i ] );
				}
			}
		}

		if ( !isEmptySelection ){

			for ( j = 0; j < inst.dates.length; j++ ){
				sql_class_day = wpbc__get__sql_class_date( inst.dates[ j ] );
				if ( ! wpbc_is_this_day_selectable( resource_id, sql_class_day ) ){
					isEmptySelection = true;
					break;
				}
			}
		}

		if ( isEmptySelection ){
			inst.dates = [];
		}


		if ( 'dynamic' != temp_saved__days_selection_mode ){
			jQuery.datepick._updateInput( '#calendar_booking' + resource_id );
		} else {
			if ( isEmptySelection ){
				jQuery.datepick._updateInput( '#calendar_booking' + resource_id );
			} else {       // Dynamic range selections, transform days from jQuery.datepick
				var dateStr = (inst.dates.length == 0 ? '' : jQuery.datepick._formatDate( inst, inst.dates[ 0 ] )); // Get first date
				for ( i = 1; i < inst.dates.length; i++ ){
					dateStr += jQuery.datepick._get( inst, 'multiSeparator' ) + jQuery.datepick._formatDate( inst, inst.dates[ i ] );
				}
				jQuery( '#date_booking' + resource_id ).val( dateStr ); // Fill the input box
			}
		}

		if ( (is_start_same_as_last_day__for_dynamic === false) && (start_end_date[ 0 ] == start_end_date[ 1 ]) ){
			if ( inst.dates.length == 1 ){
				inst.dates.push( inst.dates[ 0 ] );
			}
		}
		jQuery.datepick._notifyChange( inst );																			// Call  this 'onChangeMonthYear' from  datepicker.
		jQuery.datepick._adjustInstDate( inst );
		jQuery.datepick._showDate( inst );																				// Update the input field with the current date(s)

	_wpbc.calendar__set_param_value( resource_id, 'days_select_mode', temp_saved__days_selection_mode );
}


	/**
	 * Disable submit button  in booking form
	 * @param resource_id		resource ID
	 */
	function wpbc_disable_submit_button_in_booking_form( resource_id ){

		jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).attr( 'disabled', 'disabled' );
		jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).attr( 'saved-button-color' , jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).css( 'color' ) );
		jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).css( 'color', '#aaa' );
	}


	/**
	 * Restore disabled submit button  in booking form
	 * @param resource_id		resource ID
	 */
	function wpbc_restore_submit_button_in_booking_form( resource_id ){

		jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).prop( 'disabled', false );

		if ( undefined != jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).attr( 'saved-button-color' ) ){     //FixIn: 9.5.1.2
			jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).css( 'color', jQuery( '#booking_form_div' + resource_id + ' input[type="button"]' ).attr( 'saved-button-color' ) );
		}
	}


/**
 * Tests :
 * 			var inst= wpbc_calendar__get_inst(3); wpbc__calendar_range_days_select__bs('20.08.2023 - 27.08.2023' , 3 );  jQuery.datepick._updateDatepick( inst );
 *
 * 		    var inst= wpbc_calendar__get_inst(3); inst.dates=[]; wpbc__calendar_range_days_select__bs('20.09.2023 - 20.09.2023' , 3 );  jQuery.datepick._updateDatepick( inst );
 */;
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/js/biz_m.js?ver=9.8.12 

/**
 *  >= Business Medium ...
 */


	/**
	 * Save initial values of days selection for later use in conditional day logic.   Load it,  when  start the page.
	 *
	 * @param resource_id
	 */
	function wpbc__conditions__SAVE_INITIAL__days_selection_params__bm( resource_id ){

		// Save it only ONCE initial values of variables: bk_days_selection_mode, ...
		if (  _wpbc.calendar__is_defined( resource_id ) ){

			_wpbc.calendar__set_param_value( resource_id, 'saved_variable___days_select_initial'
				, {
					'dynamic__days_min'     	: _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_min' ),
					'dynamic__days_max'     	: _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_max' ),
					'dynamic__days_specific'	: _wpbc.calendar__get_param_value( resource_id, 'dynamic__days_specific' ),
					'dynamic__week_days__start'	: _wpbc.calendar__get_param_value( resource_id, 'dynamic__week_days__start' ),

					'fixed__days_num'      		: _wpbc.calendar__get_param_value( resource_id, 'fixed__days_num' ),
					'fixed__week_days__start'  	: _wpbc.calendar__get_param_value( resource_id, 'fixed__week_days__start' )
				}
			);
		}
	}

	/**
	 * Define First selected date for start conditional dates selection
	 *
	 * @param  all_dates				date object | string
	 * @param resource_id				int | string  e.g. '1'
	 * @returns {boolean}
	 */
	function wpbc__conditions__for_range_days__first_date__bm( all_dates, resource_id ){

		if ( '' == all_dates ) { return false; }                   						// If no days selections so then skip all.

		if (    ( 'dynamic' != _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ) )
			 && ( 'fixed'   != _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ) )
		) { return false; }                   				// This conditional logic is possible only if the range days selection

		var selected_first_day = all_dates;

		if ( typeof (all_dates) == 'object' ){  	// H I G H L I G H T   		// If this parameter is object (Date), then we  highlight the dates

			all_dates = document.getElementById( 'date_booking' + resource_id ).value;      // Get dates from the textarea date booking to ''
			if ( all_dates != '' ){                                                  		// If some date is selected
				var first_date = get_first_day_of_selection( all_dates );            		// So we are NOT MAKE changing of highlighting if its was first click.
				var last_date  = get_last_day_of_selection( all_dates );
				if (
						( 'fixed' !== _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ) )
					&&  ( first_date == last_date )
				){    //FixIn: 8.4.4.8
					return false;
				}
			}
		} else {                                	// S E L E C T
			var first_date = get_first_day_of_selection( all_dates );
			var last_date  = get_last_day_of_selection( all_dates );
			if ( first_date != last_date ){
				return false;									// We are clicked second time
			}
			var date_sections = first_date.split( "." );
			selected_first_day = new Date;
			selected_first_day.setFullYear( parseInt( date_sections[ 2 ] - 0 ), parseInt( date_sections[ 1 ] - 1 ), parseInt( date_sections[ 0 ] - 0 ) );
		}

		wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm( selected_first_day, resource_id );
	}


	/**
	 *  Update dates selection parameters ( NUMBER_OF_DAYS_TO_SELECT) depends on belong current date to specific week day or season
	 *
	 * @param selected_first_date		date, which  we check for conditions
	 * @param resource_id				booking resource ID
	 * @returns {boolean}
	 */
	function wpbc__conditions__set_NUMBER_OF_DAYS_TO_SELECT__depend_on_date__bm( selected_first_date, resource_id ){

		var is_condition_applied = false;

		var class_day      = wpbc__get__td_class_date(  selected_first_date );
		var sql_class_date = wpbc__get__sql_class_date( selected_first_date );

		if ( jQuery( '#calendar_booking' + resource_id + ' .datepick-days-cell.cal4date-' + class_day ).length <= 0 ){
			return false;  // This date is not exist :( Why ?
		}
		var css_classes_date_arr = jQuery( '#calendar_booking' + resource_id + ' .datepick-days-cell.cal4date-' + class_day ).attr( 'class' ).split( /\s+/ );


		/**
		 * S E A S O N     C O N D I T I O N S    -    2.0
		 *
		 *	 		_wpbc.calendar__get_param_value(3,'conditions')['select-day']['season'] [0]['for'] = 'september_2023'	<- season name to check
		 *	 		_wpbc.calendar__get_param_value(3,'conditions')['select-day']['season'] [0]['value'] = '3,4,5'			<- number of days to  select
		 */
		var conditions = _wpbc.calendar__get_param_value( resource_id, 'conditions' );
		var single_css_date_class;
		var days_arr;
		if (
			   ( null !== conditions )
			&& ( 'undefined' !== typeof (conditions[ 'select-day' ]) )
			&& ( 'undefined' !== typeof (conditions[ 'select-day' ]['season']) )
			&& ( conditions[ 'select-day' ][ 'season' ].length > 0 )
		){
			for ( var i = 0; i < css_classes_date_arr.length; i++ ){

				single_css_date_class = css_classes_date_arr[i];

				// S E A S O N    F I L T E R    C O N D I T I O N S     - checking
				if ( single_css_date_class.indexOf( 'wpdevbk_season_' ) >= 0 ){

					single_css_date_class = single_css_date_class.replace( 'wpdevbk_season_', '' );

					for ( var j = 0; j < conditions[ 'select-day' ][ 'season' ].length; j++ ){

						if ( single_css_date_class === conditions[ 'select-day' ][ 'season' ][ j ][ 'for' ] ){			// Ok season in condition == season in a day

							days_arr = conditions[ 'select-day' ][ 'season' ][ j ][ 'value' ].split( ',' );

							// Update real vars
							_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_specific', days_arr );
							_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_min', 		days_arr[ 0 ] );
							_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_max', 		days_arr[ (days_arr.length - 1) ] );
							_wpbc.calendar__set_param_value( resource_id, 'fixed__days_num', 		days_arr[ 0 ] );

							is_condition_applied = true;
						}
					}
				}
			}
		}


		/**
		 * W E E K D A Y S     C O N D I T I O N S    -    2.0
		 *
		 *	 		_wpbc.calendar__get_param_value(3,'conditions')['select-day']['weekday'] [0]['for'] = '5'			<- number of Week day
		 *	 		_wpbc.calendar__get_param_value(3,'conditions')['select-day']['weekday'] [0]['value'] = '3,7'		<- number of days to  select
		 */
		if (
			   ( null !== conditions )
			&& ( 'undefined' !== typeof (conditions[ 'select-day' ]) )
			&& ( 'undefined' !== typeof (conditions[ 'select-day' ]['weekday']) )
			&& ( conditions[ 'select-day' ][ 'weekday' ].length > 0 )
		){

			for ( var j = 0; j < conditions[ 'select-day' ][ 'weekday' ].length; j++ ){

				if ( selected_first_date.getDay() == conditions[ 'select-day' ][ 'weekday' ][ j ][ 'for' ] ){			// Ok weekday condition == a week day of day

					days_arr = conditions[ 'select-day' ][ 'weekday' ][ j ][ 'value' ].split( ',' );

					// Update real vars
					_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_specific', days_arr );
					_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_min', 		days_arr[ 0 ] );
					_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_max', 		days_arr[ (days_arr.length - 1) ] );
					_wpbc.calendar__set_param_value( resource_id, 'fixed__days_num', 		days_arr[ 0 ] );

					is_condition_applied = true;
				}
			}
		}


		/**
		 * D A T E S     C O N D I T I O N S    -    New
		 *
		 *	 		_wpbc.calendar__get_param_value(3,'conditions')['select-day']['date'][0]['for'] = '2023-08-22'		<- Date
		 *	 		_wpbc.calendar__get_param_value(3,'conditions')['select-day']['date'][0]['value'] = '3,7'			<- number of days to  select
		 */
		if (
			   ( null !== conditions )
			&& ( 'undefined' !== typeof (conditions[ 'select-day' ]) )
			&& ( 'undefined' !== typeof (conditions[ 'select-day' ]['date']) )
			&& ( conditions[ 'select-day' ][ 'date' ].length > 0 )
		){

			for ( var j = 0; j < conditions[ 'select-day' ][ 'date' ].length; j++ ){

				if ( sql_class_date == conditions[ 'select-day' ][ 'date' ][ j ][ 'for' ] ){							// Ok date condition == a  date of selected day

					days_arr = conditions[ 'select-day' ][ 'date' ][ j ][ 'value' ].split( ',' );

					// Update real vars
					_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_specific', days_arr );
					_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_min', 		days_arr[ 0 ] );
					_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_max', 		days_arr[ (days_arr.length - 1) ] );
					_wpbc.calendar__set_param_value( resource_id, 'fixed__days_num', 		days_arr[ 0 ] );

					is_condition_applied = true;
				}
			}
		}


		// Reset to the global,  if conditional parameters was not applied
		if ( false === is_condition_applied ) {

			var saved_variable___days_select_initial = _wpbc.calendar__get_param_value( resource_id, 'saved_variable___days_select_initial' );

			// Update real vars
			_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_specific', saved_variable___days_select_initial['dynamic__days_specific'] );
			_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_min', 	    saved_variable___days_select_initial['dynamic__days_min'] );
			_wpbc.calendar__set_param_value( resource_id, 'dynamic__days_max', 	    saved_variable___days_select_initial['dynamic__days_max'] );
			_wpbc.calendar__set_param_value( resource_id, 'fixed__days_num', 	    saved_variable___days_select_initial['fixed__days_num'] );
		}

	}


	/**
	 * Update dates selection parameters ( START_WEEK_DAY)  depends on  belong current date to  specific   season
	 *
	 * @param resource_id				int
	 * @param selected_first_date		JS date
	 * @param is_start_or_end			'start' | 'end'
	 * @returns {boolean}
	 */
	function wpbc__conditions__set_START_WEEK_DAY__depend_on_season__bm( resource_id, selected_first_date, is_start_or_end ){

		if ( 'start' == is_start_or_end ){

			var class_day        = wpbc__get__td_class_date(  selected_first_date );
			// var sql_class_date = wpbc__get__sql_class_date( selected_first_date );

			if ( jQuery( '#calendar_booking' + resource_id + ' .datepick-days-cell.cal4date-' + class_day ).length <= 0 ){
				return false;  // This date is not exist :( Why ?
			}
			var css_classes_date_arr = jQuery( '#calendar_booking' + resource_id + ' .datepick-days-cell.cal4date-' + class_day ).attr( 'class' ).split( /\s+/ );


			/**
			 * START_WEEK_DAY  from  S E A S O N    -    2.0
			 *
			 *	 		_wpbc.calendar__get_param_value(3,'conditions')['start-day']['season'][0]['for'] = 'september_2023'		<- season name to check
			 *	 		_wpbc.calendar__get_param_value(3,'conditions')['start-day']['season'][0]['value']  = '2,5,6'			<- Week Days to  start  selection
			 */
			var conditions = _wpbc.calendar__get_param_value( resource_id, 'conditions' );
			var single_css_date_class;
			var days_arr;
			if (
				   ( null !== conditions )
				&& ( 'undefined' !== typeof (conditions[ 'start-day' ]) )
				&& ( 'undefined' !== typeof (conditions[ 'start-day' ]['season']) )
				&& ( conditions[ 'start-day' ][ 'season' ].length > 0 )
			){
				for ( var i = 0; i < css_classes_date_arr.length; i++ ){

					single_css_date_class = css_classes_date_arr[i];

					// S E A S O N    F I L T E R    C O N D I T I O N S     - checking
					if ( single_css_date_class.indexOf( 'wpdevbk_season_' ) >= 0 ){

						single_css_date_class = single_css_date_class.replace( 'wpdevbk_season_', '' );

						for ( var j = 0; j < conditions[ 'start-day' ][ 'season' ].length; j++ ){

							if ( single_css_date_class === conditions[ 'start-day' ][ 'season' ][ j ][ 'for' ] ){			// Ok season in condition == season in a day

								days_arr = conditions[ 'start-day' ][ 'season' ][ j ][ 'value' ].split( ',' );

								// Update real vars
								_wpbc.calendar__set_param_value( resource_id, 'dynamic__week_days__start' , days_arr );
								_wpbc.calendar__set_param_value( resource_id, 'fixed__week_days__start'   , days_arr );
							}
						}
					}
				}
			}
		}


		// START_WEEK_DAY  Back to INITIAL params
		if ( 'end' == is_start_or_end ){

			var saved_variable___days_select_initial = _wpbc.calendar__get_param_value( resource_id, 'saved_variable___days_select_initial' );
			_wpbc.calendar__set_param_value( resource_id, 'dynamic__week_days__start', saved_variable___days_select_initial[ 'dynamic__week_days__start' ] );
			_wpbc.calendar__set_param_value( resource_id, 'fixed__week_days__start',   saved_variable___days_select_initial[ 'fixed__week_days__start' ] );
		}

	}





/**
 * Calendar Day Cell Bottom  -  Get daily cost for specific date
 *
 * usually  used for showing daily cost in bottom  of calendar date cell
 *
 * @param param_calendar_id         {string}    ID of calendar - booking resource
 * @param my_thisDateTime           {Date}      JavaScript date
 * @returns                         {string}    Cost  - formatted - like  "$ 95.99"
 */
function wpbc_show_day_cost_in_date_bottom( param_calendar_id, my_thisDateTime ) {

	var resource_id = parseInt( param_calendar_id.replace( "calendar_booking", '' ) );

	// console.log( _wpbc.bookings_in_calendar__get( resource_id ) );		// for debug

	// 1. Get child booking resources  or single booking resource  that  exist  in dates :	[1] | [1,14,15,17]
	// var child_resources_arr = wpbc_clone_obj( _wpbc.booking__get_param_value( resource_id, 'resources_id_arr__in_dates' ) );

	// '2023-08-21'
	var sql_date = wpbc__get__sql_class_date( new Date( my_thisDateTime ) );

    var hint__in_day__cost = '';

    var get_for_date_obj = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date );

    if ( false !== get_for_date_obj ){

        if (
               (undefined != get_for_date_obj[ 'summary' ])
            && (undefined != get_for_date_obj[ 'summary' ].hint__in_day__cost)
        ){
            hint__in_day__cost = get_for_date_obj[ 'summary' ].hint__in_day__cost;		// "25.00£"
        }

    }

    return hint__in_day__cost;
}



/**
 * Admin Panel - Booking > Settings > Form page -- Delete custom  form
 *
 * @param form_name
 * @param user_id
 * @returns {boolean}
 */
function wpbc_delete_custom_booking_form( form_name, user_id ){

    wpbc_admin_show_message_processing( 'deleting' ); 
    
    jQuery.ajax({                                           // Start Ajax Sending        
        url: wpbc_ajaxurl,
        type:'POST',
        success: function (data, textStatus){if( textStatus == 'success')   jQuery('#ajax_respond').html( data );},
        error:function (XMLHttpRequest, textStatus, errorThrown){window.status = 'Ajax sending Error status:'+ textStatus;alert(XMLHttpRequest.status + ' ' + XMLHttpRequest.statusText);if (XMLHttpRequest.status == 500) {alert('Please check at this page according this error:' + ' https://wpbookingcalendar.com/faq/#ajax-sending-error');}},
        // beforeSend: someFunction,
        data:{
            action : 'DELETE_BK_FORM',        
            formname : form_name,
            user_id: user_id,
            wpbc_nonce: document.getElementById('wpbc_admin_panel_nonce').value 
        }
    });
    return false;
}

/**
 * Admin Panel - Booking > Settings > Form page -- Change custom  form
 *
 * @param selectObj
 */
function wpbc_change_custom_booking_form_in_url__and_reload(selectObj){

     var idx = selectObj.selectedIndex;     
     var my_form = selectObj.options[idx].value;

     var loc = location.href;
     if (loc.substr((loc.length-1),1)=='#') {
         loc = loc.substr(0,(loc.length-1) );
     }
          
     if ( loc.indexOf('booking_form=') == -1 ) {
        loc = loc + '&booking_form=' +my_form;}
     else { // Alredy have this paremeter at URL
         var start = loc.indexOf('&booking_form=');
         var fin = loc.indexOf('&', (start+15));
         if (fin == -1) {loc = loc.substr(0,start) + '&booking_form=' +my_form;} // at the end of row
         else { // at the middle of the row
              var loc1 = loc.substr(0,start) + '&booking_form=' +my_form;//alert(loc)
              loc = loc1 + loc.substr(fin);
         }
     }
     location.href = loc;
}



// TODO: refactor these 3 functions: (2023-09-01):
function showCostHintInsideBkForm( bk_type ){

    // if ( ! jQuery( '#calendar_booking' + bk_type ).length )                      //FixIn:6.1.1.16    //FixIn: 8.2.1.13
    //     return  false;

    ////////////////////////////////////////////////////////////////////

    // Disable updating cost hint during first click, if range days selection with  2 mouse clicks is active
    // if ( jQuery('#booking_form_div'+bk_type+' input[type="button"]').prop('disabled' ) ) {
    //     return;
    // }

    ////////////////////////////////////////////////////////////////////

    // submit_bk_color = jQuery('#booking_form_div'+bk_type+' input[type="button"]').css('color');
    // jQuery('#booking_form_div'+bk_type+' input[type="button"]').attr('disabled', 'disabled'); // Disable the submit button
    // jQuery('#booking_form_div'+bk_type+' input[type="button"]').css('color', '#aaa');

    ////////////////////////////////////////////////////////////////////

    if (document.getElementById('parent_of_additional_calendar' + bk_type) != null) { // Its mean that we get cost hint clicking at additional calendar
        bk_type = document.getElementById('parent_of_additional_calendar' + bk_type).value; // Get parent bk type from additional calendar
    }

    // if (document.getElementById('booking_hint' + bk_type) == null) return false;


    var all_dates = jQuery('#date_booking' + bk_type).val();
    var formdata  = getBookingFormElements(bk_type);

    setBookingFormElementsWheelScroll( bk_type );

    var wpbc_loader_icon = '<span class="wpbc_ajax_loader"><img style="vertical-align:middle;box-shadow:none;width:14px;" src="' + wpdev_bk_plugin_url + '/assets/img/ajax-loader.gif"><//span>';
    //var wpbc_loader_icon = '<span class="wpbc_ajax_loader wpdevelop"><span class="wpbc_icn_rotate_left wpbc_spin wpbc_ajax_icon"  aria-hidden="true"><//span><//span>';

    // Calculation in process ...
    jQuery('#booking_hint' + bk_type + ',.booking_hint' + bk_type ).html( wpbc_loader_icon );
	//FixIn: 8.4.2.1
    jQuery('#estimate_booking_day_cost_hint' + bk_type + ',.estimate_booking_day_cost_hint' + bk_type ).html( wpbc_loader_icon );
	//FixIn: 8.4.4.7
    jQuery('#estimate_booking_night_cost_hint' + bk_type + ',.estimate_booking_night_cost_hint' + bk_type ).html( wpbc_loader_icon );
    jQuery('#additional_booking_hint' + bk_type + ',.additional_booking_hint' + bk_type ).html( wpbc_loader_icon );
    jQuery('#original_booking_hint' + bk_type + ',.original_booking_hint' + bk_type ).html( wpbc_loader_icon );
    jQuery('#deposit_booking_hint' + bk_type + ',.deposit_booking_hint' + bk_type ).html( wpbc_loader_icon );
    jQuery('#coupon_discount_booking_hint' + bk_type + ',.coupon_discount_booking_hint' + bk_type ).html( wpbc_loader_icon );
    jQuery('#balance_booking_hint' + bk_type + ',.balance_booking_hint' + bk_type ).html( wpbc_loader_icon );

    // Dates and Times shortcodes
    jQuery('#cancel_date_hint_tip' + bk_type + ',.cancel_date_hint_tip' + bk_type ).html( wpbc_loader_icon );			//FixIn: 9.7.3.16
    jQuery('#check_in_date_hint_tip' + bk_type + ',.check_in_date_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#check_out_date_hint_tip' + bk_type + ',.check_out_date_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#check_out_plus1day_hint_tip' + bk_type + ',.check_out_plus1day_hint_tip' + bk_type ).html( wpbc_loader_icon ); //FixIn: 8.0.2.12

    jQuery('#start_time_hint_tip' + bk_type + ',.start_time_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#end_time_hint_tip' + bk_type + ',.end_time_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#selected_dates_hint_tip' + bk_type + ',.selected_dates_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#selected_timedates_hint_tip' + bk_type + ',.selected_timedates_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#selected_short_dates_hint_tip' + bk_type + ',.selected_short_dates_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#selected_short_timedates_hint_tip' + bk_type + ',.selected_short_timedates_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#days_number_hint_tip' + bk_type + ',.days_number_hint_tip' + bk_type ).html( wpbc_loader_icon );
    jQuery('#nights_number_hint_tip' + bk_type + ',.nights_number_hint_tip' + bk_type ).html( wpbc_loader_icon );

	// Check  if calendar exist ( for booking form ONLY shortcode) //FixIn: 8.3.3.11
	if ( undefined != document.getElementById( 'calendar_booking' + bk_type ) ){

		// Prevent of showing any hints,  if selected only Check In day if we are using range days selection mode using 2 mouse clicks
		if ( bk_days_selection_mode == 'dynamic' ){                                  //FixIn: 5.4.3
			var inst = jQuery.datepick._getInst( document.getElementById( 'calendar_booking' + bk_type ) );
			if ( typeof(inst) !== 'undefined' )                                     //FixIn: 6.1.1.16

			    var is_show_cost_after_first_click;                                 //FixIn: 8.4.2.6
                if ( 1 == bk_2clicks_mode_days_min ) {                              //FixIn: 8.7.6.6
                    is_show_cost_after_first_click = true;
                } else {
                    is_show_cost_after_first_click = false;
                }

				if ( ( inst.stayOpen == true ) && ( ! is_show_cost_after_first_click ) ) {

					// Comment these 2 lines,  if we need to  show cost  hints,  if selected only 1 day
					jQuery( '.wpbc_ajax_loader' ).html( '...' );
					//jQuery('#selected_short_timedates_hint_tip' + bk_type).html('Please click on check out day to finish days selection');
					return false;
				}
		}
	}


    var my_booking_form = '';
    if ( document.getElementById( 'booking_form_type' + bk_type ) != undefined ){
        my_booking_form = document.getElementById( 'booking_form_type' + bk_type ).value;
    }
    var ajax_type_action = 'CALCULATE_THE_COST';

    jQuery.ajax({                                           // Start Ajax Sending
        url: wpbc_ajaxurl, 
        type:'POST',
        success: function (data, textStatus){if( textStatus == 'success')   jQuery('#ajax_respond_insert' + bk_type).html( data ) ;},
        error:function (XMLHttpRequest, textStatus, errorThrown){window.status = 'Ajax sending Error status:'+ textStatus;alert(XMLHttpRequest.status + ' ' + XMLHttpRequest.statusText);if (XMLHttpRequest.status == 500) {alert('Please check at this page according this error:' + ' https://wpbookingcalendar.com/faq/#ajax-sending-error');}},
        // beforeSend: someFunction,
        data:{
            action: ajax_type_action,
            form: formdata,
            all_dates : all_dates,
            bk_type : bk_type,
            booking_form_type:my_booking_form,
            wpdev_active_locale:wpbc_active_locale,
            wpbc_nonce: document.getElementById('wpbc_nonce'+ ajax_type_action + bk_type).value 
        }
    });
    jQuery( ".booking_form_div" ).trigger( "show_cost_hints" , [ bk_type ] );        //FixIn:7.0.1.53
	jQuery( ".booking_form_div" ).trigger( "wpbc_booking_date_or_option_selected" , [ bk_type ] );
    return false;
}


        function getBookingFormElements(bk_type){

                var submit_form = document.getElementById('booking_form' +  bk_type );
                var formdata = '';

                if (submit_form != null) {
                        var count = submit_form.elements.length;
                        var inp_value;
                        var element;
                        var el_type;
                        // Serialize form here
                        for (var i=0; i<count; i++)   {
                            element = submit_form.elements[i];

                            if ( (element.type !=='button') && (element.type !=='hidden') && ( element.name !== ('date_booking' + bk_type) )   ) {           // Skip buttons and hidden element - type

                                // Get Element Value
                                if ( element.type == 'checkbox' ){

                                    if (element.value == '') {
                                        inp_value = element.checked;
                                    } else {
                                        if (element.checked) inp_value = element.value;
                                        else inp_value = '';
                                    }

                                } else if ( element.type == 'radio' ) {

                                    if (element.checked) inp_value = element.value;
                                    else continue;

                                } else {
                                    inp_value = element.value;
                                }

                                // Get value in selectbox of multiple selection
                                if (element.type =='select-multiple') {
                                    inp_value = jQuery('[name="'+element.name+'"]').val() ;
                                    if (( inp_value == null ) || (inp_value.toString() == '' ))
                                        inp_value='';
                                }


                                if ( element.name !== ('captcha_input' + bk_type) ) {
                                    if (formdata !=='') formdata +=  '~';                                                // next field element

                                    el_type = element.type;
                                    if ( element.className.indexOf('wpdev-validates-as-email') !== -1 )  el_type='email';
                                    if ( element.className.indexOf('wpdev-validates-as-coupon') !== -1 ) el_type='coupon';

                                    formdata +=  el_type + '^' + element.name + '^' + inp_value ;                    // element attr
                                }
                            }
                        }
                }
                return formdata;

        }


        function setBookingFormElementsWheelScroll( bk_type ){

            var submit_form = document.getElementById( 'booking_form' + bk_type );
            var element;
            var i;
            var count;
            var wpbc_loader_icon = '<span class="wpbc_ajax_loader"><img style="vertical-align:middle;box-shadow:none;width:14px;" src="' + wpdev_bk_plugin_url + '/assets/img/ajax-loader.gif"></span>';
            //var wpbc_loader_icon = '<span class="wpbc_ajax_loader wpdevelop"><span class="wpbc_icn_rotate_left wpbc_spin wpbc_ajax_icon"  aria-hidden="true"><//span><//span>';

            if ( submit_form != null ){

                count = submit_form.elements.length;

                for ( i = 0; i < count; i++ ){
                    element = submit_form.elements[ i ];
                    // Calculation in process ...
                    jQuery( '#bookinghint_' + element.id + ',.bookinghint_' + element.id ).html( wpbc_loader_icon );
                }
            }
        };
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/js/form-conditions.js?ver=9.8.12 

/**
 * Get elemnt ID of Conditional section,  relative to  specific day or false
 * 
 * @param string td_class  - day  in format: td_class = 11-23-2015
 * @param string bk_type   - ID of booking resources  
 * @returns bool | string
 */
function wpbc_get_conditional_section_id_for_weekday( td_class, bk_type ){      //FixIn: 5.4.5.2
    
    var date_sections = td_class.split("-");     
    var check_date = new Date;        
    check_date.setFullYear( parseInt(date_sections[2]-0) ,parseInt(date_sections[0]-1), parseInt(date_sections[1]-0) );

    
    var garbage_divs = jQuery( '#booking_form_garbage' + bk_type + ' div' );                // Check  for the    W E E K    D A Y S    conditions     
    var index;    
    var garbage_element = false;
    
    for (index = 0; index < garbage_divs.length; ++index) {

        if ( '' !== garbage_divs[ index ].id ){
            garbage_element = jQuery( '#' + garbage_divs[ index ].id );                           // Get Garbage DIV as jQuery element

            if ( garbage_element.hasClass( 'wpdevbk_weekday_' + check_date.getDay() ) ){       // Found our filter element of this date in garbage

                return '#' + garbage_divs[ index ].id;                                           // ID of garbage_element
            }
        }
    }

    // Check in booking form - its required for situation, when we selected date,  and some conditional section  already in booking form.
    var booking_form_element = jQuery( '#booking_form_div' + bk_type + ' .wpdevbk_optional_condition');    // .conditional_section_element_weekday-condition.wpdevbk_optional_condition

    if ( booking_form_element.hasClass( 'wpdevbk_weekday_' + check_date.getDay() ) ) {                     // Found our filter element of this date in garbage

        return '#booking_form_div' + bk_type + ' .wpdevbk_optional_condition' ;                                   
    }
    
    return false;
}



// // Show / hide  Fields  in the booking form,
// depend on from week day or season filter
function check_condition_sections_in_bkform(date, bk_type){                     
    
    // Reseting
    moveOptionalElementsToGarbage( bk_type );
    moveDefaultElementsToForm(     bk_type );

    if (date == '') return;                                                     // If no days selections so then skip all.
    
    date = get_first_day_of_selection(date);                                    // Get the  10.06.2013 from different dates selection Varibale : 11.06.2013, 12.06.2013, 13.06.2013, 10.06.2013 || 10.06.2013  || 10.06.2013 - 18.06.2013

    var date_sections = date.split("."); 
    var selceted_first_day = new Date;       
    selceted_first_day.setFullYear( parseInt(date_sections[2]-0) ,parseInt(date_sections[1]-1), parseInt(date_sections[0]-0) );
    
    
    var class_day = (selceted_first_day.getMonth()+1) + '-' + selceted_first_day.getDate() + '-' + selceted_first_day.getFullYear();
    if (jQuery('#calendar_booking'+bk_type+' .datepick-days-cell.cal4date-'+class_day).length <= 0) return;  // We are chnaged the month (hided previos with first selected date), so  this date cell is not exist  now, we are need to exist
    var calendarDateClassList =jQuery('#calendar_booking'+bk_type+' .datepick-days-cell.cal4date-'+class_day).attr('class').split(/\s+/);

    var formElementClassName = '';
    var garbageElement = false;
    
    jQuery.each( calendarDateClassList, function(index, singleClassCSS){
        
        // S E A S O N    F I L T E R    C O N D I T I O N S     - checking
        if ( singleClassCSS.indexOf("wpdevbk_season_") >= 0 ) {
            
            // 1.Get this element from the garbage - <div class="conditional_section_element_times  wpdevbk_optional_condition wpdevbk_season_high_season"> [...] </div>
            
            jQuery.each( jQuery('#booking_form_garbage'+bk_type + ' div') , function(index, conditionGarbageDIV){  // LOOP in the Garbage

                if ( '' !== conditionGarbageDIV.id ){                                   //FixIn: 9.7.3.6

                    garbageElement = jQuery( '#' + conditionGarbageDIV.id );            // Get Garbage DIV as jQuery element

                    if ( garbageElement.hasClass( singleClassCSS ) ){                   // We found our season filter element       in garbage with CSS class of that SEASON

                        // Get the ALL CSS classes of the DIV garbage element. Example: conditional_section_element_times  wpdevbk_optional_condition wpdevbk_season_high_season
                        var garbageElementClassList = garbageElement.attr( 'class' ).split( /\s+/ );

                        jQuery.each( garbageElementClassList, function ( index, garbageElementClassName ){

                            //Get the name of CSS, like this: conditional_section_element_times
                            if ( garbageElementClassName.indexOf( "conditional_section_element_" ) >= 0 ){

                                // 2.Get the class name in this element of the DIV section in the form
                                formElementClassName = garbageElementClassName.replace( '_element', '' );

                                // 3.Remove all elements from the form in that DIV into the Garbage
                                jQuery( '#booking_form_div' + bk_type + ' div.' + formElementClassName + ' div' ).appendTo( '#booking_form_garbage' + bk_type );

                                // 4.Insert this element into the form
                                garbageElement.appendTo( '#booking_form_div' + bk_type + ' div.' + formElementClassName );
                            }
                        } );
                    }
                }

            });  
        }
        
    });
    
    
    
    // Check  for the    W E E K    D A Y S    conditions //////////////////////////////////////////////////////////////////////////////////////
    jQuery.each( jQuery('#booking_form_garbage'+bk_type + ' div') , function(index, conditionGarbageDIV){  // LOOP in the Garbage

        if ( '' !== conditionGarbageDIV.id ){
            garbageElement = jQuery('#'+conditionGarbageDIV.id);            // Get Garbage DIV as jQuery element

            if ( garbageElement.hasClass( 'wpdevbk_weekday_' + selceted_first_day.getDay() ) ) {                // We found our filter element od this date      in garbage with CSS class of that SEASON


                // Get the ALL CSS classes of the DIV garbage element. Example: conditional_section_element_times  wpdevbk_optional_condition wpdevbk_season_high_season
                        var garbageElementClassList = garbageElement.attr('class').split(/\s+/);

                        jQuery.each( garbageElementClassList, function(index, garbageElementClassName ){

                            //Get the name of CSS, like this: conditional_section_element_times
                            if ( garbageElementClassName.indexOf("conditional_section_element_") >= 0 ) {

                // 2.Get the class name in this element of the DIV section in the form
                                formElementClassName = garbageElementClassName.replace('_element', '');

                // 3.Remove all elements from the form in that DIV into the Garbage
                                jQuery('#booking_form_div' + bk_type + ' div.' + formElementClassName + ' div').appendTo( '#booking_form_garbage' + bk_type );

                // 4.Insert this element into the form
                                garbageElement.appendTo( '#booking_form_div' + bk_type + ' div.' + formElementClassName );
                            }
                        });

            }
        }
    });

    // Select first available option (timeslot) in the dropdown list, that showing based on days conditions , after selection of date in calendar.       //FixIn: 8.7.11.3
    var is_skip;
    if ( '' !== formElementClassName ){
        jQuery.each( jQuery( '#booking_form_div' + bk_type + ' div.' + formElementClassName ).find( 'select' ), function ( index, select_el_in_form ){

            is_skip = false;
            jQuery.each( jQuery( select_el_in_form ).find( 'option' ), function ( index, option_in_select ){

                if ( (!is_skip) && (false === jQuery( option_in_select ).is( ':disabled' )) ){
                    // jQuery( option_in_select ).prop( "selected", true );         //FixIn: 8.9.1.1  Fix issue of not ability to auto select correct saved value for select boxes in conditional sections, while editing the bookings.
                    is_skip = true;
                }
            } );
        } );
    }
}


//  Optionals:  Form  ->  Garbage
function moveOptionalElementsToGarbage( bk_type ){
    jQuery('#booking_form_div' + bk_type + ' .wpdevbk_optional_condition').appendTo( '#booking_form_garbage'+bk_type ); 
    jQuery('#booking_form_garbage' + bk_type + ' .wpdevbk_optional_condition').show();                               // We are need to  show this elements, because by default they are hided
}


//  Defaults:  Garbage  ->  Form
function moveDefaultElementsToForm( bk_type ){
    
    var formElementClassName = '';
    var garbageElement = false;

    jQuery.each( jQuery('#booking_form_garbage'+bk_type + ' div') , function(index, conditionGarbageDIV){  // LOOP in the Garbage

        if ( '' !== conditionGarbageDIV.id ){

            garbageElement = jQuery('#'+conditionGarbageDIV.id);                    // Get Garbage DIV as jQuery element

            if ( garbageElement.hasClass( 'wpdevbk_default_condition' ) ) {         // We found our Default Element

                // Get the ALL CSS classes of this DIV garbage element.
                var garbageElementClassList = garbageElement.attr('class').split(/\s+/);

                jQuery.each( garbageElementClassList, function(index, garbageElementClassName ){

                    //Get the name of CSS, like this: conditional_section_element_times
                    if ( garbageElementClassName.indexOf("conditional_section_element_") >= 0 ) {

                        //Get the CSS class   of the DIV section in the form
                        formElementClassName = garbageElementClassName.replace('_element', '');

                        // Move this Default Garbage Element  ->  Form
                        garbageElement.appendTo( '#booking_form_div' + bk_type + ' div.' + formElementClassName );
                    }
                });

            }
        }

    });
};
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/js/biz_l.js?ver=9.8.12 
// --------------------------------------------------------------------------------------------------------------------
// Search Availability
// --------------------------------------------------------------------------------------------------------------------
    var wpbc_search_form_dates_format = 'yy-mm-dd';     //FixIn: 8.6.1.21

    //FixIn: 8.6.1.21
    function wpbc_search_form_click_new_page( my_form ){

        if (
               ( '' == jQuery( '#booking_search_check_in' ).val() )
            || ( '' == jQuery( '#booking_search_check_out' ).val() )
        ){
            alert( search_emty_days_warning );
            return false;
        }

	    var search_check_in_date = jQuery.datepick.parseDate( wpbc_search_form_dates_format , jQuery( '#booking_search_check_in' ).val() );         // Parse a string value into a date object
        var string_check_in_date = jQuery.datepick.formatDate( 'yy-mm-dd', search_check_in_date );                                                  // Format a date object into a string value.
        //jQuery( '#booking_search_check_in' ).val( string_check_in_date );
        jQuery( '[name="search_check_in"]' ).val( string_check_in_date );                                               //FixIn: 9.5.3.4

	    var search_check_out_date = jQuery.datepick.parseDate( wpbc_search_form_dates_format , jQuery( '#booking_search_check_out' ).val() );       // Parse a string value into a date object
        var string_check_out_date = jQuery.datepick.formatDate( 'yy-mm-dd', search_check_out_date );                                                // Format a date object into a string value.
        //jQuery( '#booking_search_check_out' ).val( string_check_out_date );
        jQuery( '[name="search_check_out"]' ).val( string_check_out_date );                                              //FixIn: 9.5.3.4

        return  true;
    }


    function searchFormClck( search_form, wpdev_active_locale ){

        if ( (search_form.check_in.value == '') || (search_form.check_out.value == '') ) {
            alert(search_emty_days_warning);
            return;
        }
        document.getElementById('booking_search_results' ).innerHTML = '<div style="height:20px;width:100%;text-align:center;margin:15px auto;"><img  style="vertical-align:middle;box-shadow:none;width:14px;" src="'+wpdev_bk_plugin_url+'/assets/img/ajax-loader.gif"><//div>';
        ajax_search_submit( search_form, wpdev_active_locale );

    }


    //<![CDATA[
    function ajax_search_submit( search_form, wpdev_active_locale ) {           //FixIn: 6.0.1.1

        //FixIn: 8.6.1.21
	    var search_check_in_date = jQuery.datepick.parseDate( wpbc_search_form_dates_format , search_form.check_in.value );     // Parse a string value into a date object
        var string_check_in_date = jQuery.datepick.formatDate( 'yy-mm-dd', search_check_in_date );                              // Format a date object into a string value.

	    var search_check_out_date = jQuery.datepick.parseDate( wpbc_search_form_dates_format , search_form.check_out.value );     // Parse a string value into a date object
        var string_check_out_date = jQuery.datepick.formatDate( 'yy-mm-dd', search_check_out_date );                              // Format a date object into a string value.

//console.log( 'search_check_in_date, string_check_out_date',string_check_in_date, string_check_out_date );

            // Ajax POST here
            var my_bk_category = '';
            var my_bk_tag = '';
            var my_bk_users = '';
            var my_bk_advanced = '';

            var elm1 = document.getElementById("booking_search_category");
            if( elm1 !== null) my_bk_category = search_form.category.value

            var elm2 = document.getElementById("booking_search_tag");
            if( elm2 !== null) my_bk_tag = search_form.tag.value

            var elm3 = document.getElementById("booking_bk_users");
            if( elm3 !== null) my_bk_users = search_form.bk_users.value
                        
            if ( jQuery("input[name='additional_search']:checked").length > 0 )
                my_bk_advanced = jQuery("input[name='additional_search']").val();

//            var all_paramas = '';
//            for(var i = 0; i < search_form.length; i++) {                       //FixIn:6.0.1
//                if ( ( search_form[i].type == 'checkbox' ) && ( ! search_form[i].checked ) )
//                    continue;
//                all_paramas += search_form[i].type + "^";
//                all_paramas += search_form[i].name + "^";
//                all_paramas += search_form[i].value + "~";
//            }

            //FixIn: 7.1.2.9
            var all_paramas = '';
            var inp_el;
            var inp_val
//console.log(search_form);            
//console.log(jQuery( search_form ));
            for( var i = 0; i < search_form.length; i++ ) {                       
                if ( ( search_form[i].type == 'checkbox' ) && ( ! search_form[i].checked ) )
                    continue;
                
                inp_el = search_form[i].type + "^" + search_form[i].name + "^";
                                 
                inp_val = jQuery( search_form[i] ).val();
//console.log(inp_el, inp_val);                
                if ( Array.isArray( inp_val ) ) {
                    jQuery.each( inp_val, function( index ){
                        all_paramas += inp_el + inp_val[ index ] + "~";
                    });
                } else {
                    all_paramas += inp_el + inp_val + "~";
                }
            } 
//console.log(all_paramas);
            jQuery(".booking_search_ajax_container").remove();
            
            jQuery.ajax({                                           // Start Ajax Sending
                // url: wpdev_bk_plugin_url+ '/' + wpdev_bk_plugin_filename,
                url: wpbc_ajaxurl,
                type:'POST',
                success: function (data, textStatus){if( textStatus == 'success')   jQuery('#booking_search_ajax' ).html( data ) ;},
                error:function (XMLHttpRequest, textStatus, errorThrown){window.status = 'Ajax search Error status:'+ textStatus;alert(XMLHttpRequest.status + ' ' + XMLHttpRequest.statusText);if (XMLHttpRequest.status == 500) {alert('Please check at this page according this error:' + ' https://wpbookingcalendar.com/faq/#ajax-sending-error');}},
                // beforeSend: someFunction,
                data:{
                    //ajax_action : 'BOOKING_SEARCH',
                    action : 'BOOKING_SEARCH',
                    bk_check_in: string_check_in_date ,
                    bk_check_out: string_check_out_date ,
                    bk_visitors: search_form.visitors.value,
                    bk_no_results_title: search_form.bk_no_results_title.value,
                    bk_search_results_title: search_form.bk_search_results_title.value,
                    bk_category:my_bk_category,
                    bk_tag:my_bk_tag,
                    bk_users:my_bk_users,
                    bk_search_params: all_paramas,
                    additional_search: my_bk_advanced,
                    wpdev_active_locale:wpdev_active_locale,
                    wpbc_nonce: document.getElementById('wpbc_search_nonce').value 
                }
            });
    }
    //]]>


    function setDaysSelectionsInCalendar(bk_type, check_in, check_out){

        clearTimeout(timeout_DSwindow);
        

        var inst = jQuery.datepick._getInst(document.getElementById('calendar_booking'+bk_type));
        inst.dates = [];

        var original_array = []; var date;

        for(var j=0; j < original_array.length ; j++) {       //loop array of dates
            if (original_array[j] != -1) inst.dates.push(original_array[j]);
        }
        var dateStr = (inst.dates.length == 0 ? '' : jQuery.datepick._formatDate(inst, inst.dates[0])); // Get first date
        for ( var i = 1; i < inst.dates.length; i++)
             dateStr += jQuery.datepick._get(inst, 'multiSeparator') +  jQuery.datepick._formatDate(inst, inst.dates[i]);  // Gathering all dates
        jQuery('#date_booking' + bk_type).val(dateStr); // Fill the input box

        if (original_array.length>0) { // Set showing of start month
            inst.cursorDate = original_array[0];
            inst.drawMonth = inst.cursorDate.getMonth();
            inst.drawYear = inst.cursorDate.getFullYear();
        }

        // Update calendar
        jQuery.datepick._notifyChange(inst);
        jQuery.datepick._adjustInstDate(inst);
        jQuery.datepick._showDate(inst);
        jQuery.datepick._updateDatepick(inst);
    }


    var timeout_SelectDaysInCalendar;
    jQuery(document).ready(function(){
       if (
             ( location.href.indexOf('bk_check_in=') > 0 ) &&
             ( location.href.indexOf('bk_check_out=') > 0 ) &&
             ( location.href.indexOf('bk_type=') > 0 )
           ) {
           timeout_SelectDaysInCalendar = setTimeout( "setDaySelectionsInCalendar()", 1500 );
       }
    });


    function setDaySelectionsInCalendar(){

        //FixIn: 8.8.2.3
        if ( 'On' == wpbc_global5.booking_search_results_days_select ){
            return false;                                                 // Disable days selection  in calendar,  after  redirection  from  the "Search results page,  after  search  availability"
        }
        clearTimeout( timeout_SelectDaysInCalendar );

        // Parse a URL
        var myURLParams = location.href.split('?');
        if ( myURLParams.length > 1 ){
            myURLParams = myURLParams[ 1 ].split( '&' );
            for ( var i = 0; i < myURLParams.length; i++ ){     //FixIn: 8.4.5.14
                var myParam = myURLParams[ i ].split( '=' );
                if ( myParam[ 0 ] == 'bk_check_in' ) var check_in_date = myParam[ 1 ];
                if ( myParam[ 0 ] == 'bk_check_out' ) var check_out_date = myParam[ 1 ];
                if ( myParam[ 0 ] == 'bk_type' ) var my_bk_type = myParam[ 1 ].split( '#' )[ 0 ];
            }
        }
        // Auto select some fields in the booking form, from parameters in URL of search form                           //FixIn: 9.6.2.9
        for ( var i = 0; i < myURLParams.length; i++ ){
            var myParam = myURLParams[ i ].split( '=' );
            if ( myParam[ 0 ] == 'bk_visitors' ){
                jQuery( 'select[name=visitors' + my_bk_type + ']' ).val( parseInt( myParam[ 1 ] ) );
            }
            if ( myParam[ 0 ] == 'bk_adults' ){
                jQuery( 'select[name=adults' + my_bk_type + ']' ).val( parseInt( myParam[ 1 ] ) );
            }
            if ( myParam[ 0 ] == 'bk_children' ){
                jQuery( 'select[name=children' + my_bk_type + ']' ).val( parseInt( myParam[ 1 ] ) );
            }
        }


        check_in_date = check_in_date.split('-');
        check_out_date = check_out_date.split('-');
        var bk_type = my_bk_type;

        var inst = jQuery.datepick._getInst(document.getElementById('calendar_booking'+bk_type));
        inst.dates = [];
        var original_array = [];
        var date;
        var bk_inputing = document.getElementById('date_booking' + bk_type);
        var bk_distinct_dates = [];

        date=new Date();
        date.setFullYear( check_in_date[0], (check_in_date[1]-1), check_in_date[2] );                                    // year, month, date
        var original_check_in_date = date;
        original_array.push( jQuery.datepick._restrictMinMax(inst, jQuery.datepick._determineDate(inst, date, null))  ); //add date
        if ( !  wpdev_in_array(bk_distinct_dates, (check_in_date[2]+'.'+check_in_date[1]+'.'+check_in_date[0]) ) ) {
            bk_distinct_dates.push(check_in_date[2]+'.'+check_in_date[1]+'.'+check_in_date[0]);
        }

        var date_out=new Date();
        date_out.setFullYear( check_out_date[0], (check_out_date[1]-1), check_out_date[2] );                                    // year, month, date
        var original_check_out_date = date_out;

        var mewDate=new Date(original_check_in_date.getFullYear(), original_check_in_date.getMonth(), original_check_in_date.getDate() );
        mewDate.setDate(original_check_in_date.getDate()+1);

        while(
                (original_check_out_date > date ) &&
                (original_check_in_date != original_check_out_date ) )
             {
            date=new Date(mewDate.getFullYear(), mewDate.getMonth(), mewDate.getDate() );

            original_array.push( jQuery.datepick._restrictMinMax(inst, jQuery.datepick._determineDate(inst, date, null))  ); //add date
            if ( !  wpdev_in_array(bk_distinct_dates, (date.getDate()+'.'+parseInt(date.getMonth()+1)+'.'+date.getFullYear()) ) ) {
                bk_distinct_dates.push((date.getDate()+'.'+parseInt(date.getMonth()+1)+'.'+date.getFullYear()));
            }

            mewDate=new Date(date.getFullYear(), date.getMonth(), date.getDate() );
            mewDate.setDate(mewDate.getDate()+1);
        }
        original_array.pop();
        bk_distinct_dates.pop();

        // Check minimum  number days condition                                 //FixIn: 7.0.1.31
        var is_continue_selection = true;
        if ( bk_days_selection_mode == 'dynamic' )
            if ( (bk_2clicks_mode_days_min != undefined) && (original_array.length < bk_2clicks_mode_days_min ) ){
                is_continue_selection = false        
            }
        if ( is_continue_selection ) {
            for(var j=0; j < original_array.length ; j++) {       //loop array of dates
                if (original_array[j] != -1) inst.dates.push(original_array[j]);
            }
            var dateStr = (inst.dates.length == 0 ? '' : jQuery.datepick._formatDate(inst, inst.dates[0])); // Get first date
            for ( i = 1; i < inst.dates.length; i++)
                 dateStr += jQuery.datepick._get(inst, 'multiSeparator') +  jQuery.datepick._formatDate(inst, inst.dates[i]);  // Gathering all dates
            jQuery('#date_booking' + bk_type).val(dateStr); // Fill the input box
        }
        if (original_array.length>0) { // Set showing of start month
            inst.cursorDate = original_array[0];
            inst.drawMonth = inst.cursorDate.getMonth();
            inst.drawYear = inst.cursorDate.getFullYear();
        }

        // Update calendar
        jQuery.datepick._notifyChange(inst);
        jQuery.datepick._adjustInstDate(inst);
        jQuery.datepick._showDate(inst);
        jQuery.datepick._updateDatepick(inst);
                
        check_condition_sections_in_bkform( jQuery('#date_booking' + bk_type).val() , bk_type);


        showCostHintInsideBkForm(bk_type);
    }

    //FixIn: 8.6.1.21
    function getMinRangeDaysSelections(){
        if ( bk_days_selection_mode == 'dynamic' ) return bk_2clicks_mode_days_min;
        if ( bk_days_selection_mode == 'fixed' ) return bk_1click_mode_days_num;
        return 0;
    }


    function wpbc_search_check_in_selected( date ) {

        // Parse a string value into a date object
        var search_check_in_date = jQuery.datepick.parseDate( wpbc_search_form_dates_format , jQuery( '#booking_search_check_in' ).val() );

        var date_to_check = new Date();
        date_to_check.setFullYear( search_check_in_date.getFullYear(), search_check_in_date.getMonth(), search_check_in_date.getDate() );


        if (  ( bk_days_selection_mode == 'fixed' ) && ( bk_1click_mode_days_start != -1 )  ){

            var startDay = wpbc_get_abs_closest_value_in_arr( date_to_check.getDay(), bk_1click_mode_days_start );
            date_to_check.setDate( date_to_check.getDate() - (date_to_check.getDay() - startDay) );

            var string_date = jQuery.datepick.formatDate( wpbc_search_form_dates_format, date_to_check );        // Format a date object into a string value.

            jQuery( '#booking_search_check_in' ).val( string_date );
        }
        if (  ( bk_days_selection_mode == 'dynamic' ) && ( bk_2clicks_mode_days_start != -1 )  ){

            var startDay = wpbc_get_abs_closest_value_in_arr( date_to_check.getDay(), bk_2clicks_mode_days_start );
            date_to_check.setDate( date_to_check.getDate() - (date_to_check.getDay() - startDay) );

            var string_date = jQuery.datepick.formatDate( wpbc_search_form_dates_format, date_to_check );        // Format a date object into a string value.
            jQuery( '#booking_search_check_in' ).val( string_date );
        }

        if ( document.getElementById( 'booking_search_check_out' ) != null ){

            var start_bk_month_4_check_out = jQuery.datepick.parseDate( wpbc_search_form_dates_format, jQuery( '#booking_search_check_in' ).val() );
            var myDate = new Date();
            myDate.setFullYear( start_bk_month_4_check_out.getFullYear(), start_bk_month_4_check_out.getMonth(), start_bk_month_4_check_out.getDate() );

            var days_interval = getMinRangeDaysSelections();
            if ( days_interval > 0 ) days_interval--;
            myDate.setDate( myDate.getDate() + days_interval );

            var string_date = jQuery.datepick.formatDate( wpbc_search_form_dates_format, myDate );        // Format a date object into a string value.
            jQuery( '#booking_search_check_out' ).val( string_date );
        }

    }


    function wpbc_search_apply_css_before_show_check_in(date ){

        var class_day = (date.getMonth() + 1) + '-' + date.getDate() + '-' + date.getFullYear();
        var additional_class = 'date_available ';

        for ( var i = 0; i < user_unavilable_days.length; i++ ){
            if ( date.getDay() == user_unavilable_days[ i ] ) return [false, 'cal4date-' + class_day + ' date_user_unavailable'];
        }

        var my_test_date = new Date();
        my_test_date.setFullYear( wpbc_today[ 0 ], (wpbc_today[ 1 ] - 1), wpbc_today[ 2 ], 0, 0, 0 ); //Get today
        if ( (days_between( date, my_test_date ) + 1) < block_some_dates_from_today ) return [false, 'cal4date-' + class_day + ' date_user_unavailable'];

        return [true, 'cal4date-' + class_day + ' ' + additional_class + ' ']; // Available
    }


    function wpbc_search_apply_css_before_show_check_out(date){

        var class_day = (date.getMonth() + 1) + '-' + date.getDate() + '-' + date.getFullYear();
        var additional_class = 'date_available ';

        for ( var i = 0; i < user_unavilable_days.length; i++ ){
            if ( date.getDay() == user_unavilable_days[ i ] ) return [false, 'cal4date-' + class_day + ' date_user_unavailable'];
        }

        var my_test_date = new Date();
        my_test_date.setFullYear( wpbc_today[ 0 ], (wpbc_today[ 1 ] - 1), wpbc_today[ 2 ], 0, 0, 0 );           //Get today
        if ( (days_between( date, my_test_date ) + 1) < block_some_dates_from_today ) return [false, 'cal4date-' + class_day + ' date_user_unavailable'];


        if (
               ( document.getElementById( 'booking_search_check_in' ) != null )
            && ( document.getElementById( 'booking_search_check_in' ).value != '' )
        ){

            // Parse a string value into a date object
            var checkInDate = jQuery.datepick.parseDate( wpbc_search_form_dates_format, jQuery( '#booking_search_check_in' ).val() );

            var days_interval = getMinRangeDaysSelections();
            if ( days_interval > 0 ) days_interval--;
            checkInDate.setDate( checkInDate.getDate() + days_interval );

            if ( checkInDate <= date ){
                return [true, 'cal4date-' + class_day + ' ' + additional_class + ' ']; // Available
            } else {
                return [false, ''];                                                     // Unavailable
            }

        } else {
            return [true, 'cal4date-' + class_day + ' ' + additional_class + ' '];      // Available
        }
    }


// --------------------------------------------------------------------------------------------------------------------
// >= Business Large ...
// --------------------------------------------------------------------------------------------------------------------

    /**
     * Is  LESS than required    of    MAX AVAILABLE SLOTS per each dates in each slot (child resource)
     *
     * @param resource_id	ID of booking resource
     * @param html_field	visitors HTML/DOM field   - or other field for definition  number of booked slots
     * @returns {boolean}
     */
    function wpbc__is_less_than_required__of_max_available_slots__bl( resource_id, html_field ){

        // Field for getting number of booked slots
        var booking_capacity_field = _wpbc.calendar__get_param_value( resource_id, 'booking_capacity_field' );          // 'visitors'

        if ( booking_capacity_field + resource_id != html_field.name ){
            // Because this is not the field for checking number of available
            return false;
        }

        var required_slots_to_book;

        //TODO: Check about some URL parameter to book parent resource as single resource!  see the same message,  where todo  the same
        if ( 1=== _wpbc.calendar__get_param_value( resource_id, 'is_parent_resource' ) ){
            required_slots_to_book = jQuery( html_field ).val();
            required_slots_to_book = parseInt( required_slots_to_book );
        } else {                                                                                // if this single booking resource:   resource_id then  required_slots_to_book have to == 1
            required_slots_to_book = 1;
        }

        var time_to_book__as_seconds_arr = wpbc_get_start_end_times__in_booking_form__as_seconds( resource_id )
        var available_slots = wpbc__get_available_slots__for_selected_dates_times__bl( resource_id, time_to_book__as_seconds_arr );

        /**
         *   [   '2023-09-10': [     0: Object { resource_id: 2,  is_available: false, booked__seconds: (1) […], … }
                                    1: Object { resource_id: 12, is_available: false, booked__seconds: (1) […], … }
                                    2: Object { resource_id: 10, is_available: false, booked__seconds: (1) […], … }
                                    3: Object { resource_id: 11, is_available: false, booked__seconds: (1) […], … }
                              ],
                '2023-09-14': [
                                0: Object { resource_id: 2,  is_available: true, booked__seconds: (1) […], … }
                                1: Object { resource_id: 12, is_available: true, booked__seconds: (1) […], … }
                                2: Object { resource_id: 10, is_available: false, booked__seconds: (1) […], … }
                                3: Object { resource_id: 11, is_available: true, booked__seconds: (1) […], … }
                              ]
            ]
         */

        var is_in_same_resource = _wpbc.calendar__get_param_value( resource_id, 'booking_is_dissbale_booking_for_different_sub_resources' );        // 'On' | 'Off'

        // -------------------------------------------------------------------------------------------------------------
        // Check if available slots in the same (child resource) for all  dates.
        // -------------------------------------------------------------------------------------------------------------

        // I F :
        if ( 'On' === is_in_same_resource ){
            // 1. Get child booking resources  or single booking resource  that  exist  in dates :	                    [1] | [1,14,15,17]
            var child_resources_arr = wpbc_clone_obj( _wpbc.booking__get_param_value( resource_id, 'resources_id_arr__in_dates' ) );
            var availability_in_same_child_resources = wpbc_clone_obj( child_resources_arr );

            for ( var i = 0; i < child_resources_arr.length; i++ ){                                                     // [1,14,15,17]
                for ( var day_sql_key in available_slots ){                                                             // '2023-09-10': [], '2023-09-14': [],
                    for ( var ind in available_slots[ day_sql_key ] ){                                                  // [ 0:{ resource_id: 2,  is_available: false,...} , .... ]
                        if (
                               ( child_resources_arr[ i ] == available_slots[ day_sql_key ][ ind ].resource_id )
                            && ( ! available_slots[ day_sql_key ][ ind ].is_available )
                        ){
                            // Remove child booking resource ID from availability array (because it's not available
                            availability_in_same_child_resources = availability_in_same_child_resources.filter( function ( e ){  return e !== child_resources_arr[ i ];  } );
                            break;
                        }
                    }
                }
            }

            // [ 2, 12, 11 ]  	<- 		ID of child booking resources, where we can  save our booking in the same child booking resource!
            if ( availability_in_same_child_resources.length >= required_slots_to_book ){
                return false;
            } else {

// We can not store booking in the same child booking resource !
console.groupCollapsed( 'WPBC__IS_LESS_THAN_REQUIRED__OF_MAX_AVAILABLE_SLOTS__BL' );
console.groupCollapsed( '== AVAILABILITY_IN_SAME_CHILD_RESOURCES ==' );
console.log( availability_in_same_child_resources, available_slots, required_slots_to_book );
console.groupEnd();

                wpbc_front_end__show_message__warning( html_field,
                                          '<div>' + _wpbc.get_other_param( 'message_dates_times_unavailable' )     + '</div>'
                                        + '<div>' + _wpbc.get_other_param( 'message_cannot_save_in_one_resource' ) + '</div>'
                                        + '<div><strong>' + _wpbc.get_other_param( 'message_choose_alternative_dates' )    + '</strong></div>'
                                );
                return true;
            } // -------------------------------------------------------------------------------------------------------------

        }

        // E L S E :

        // -------------------------------------------------------------------------------------------------------------
        // Check if available slots in ANY (child resource) for all  dates.
        // -------------------------------------------------------------------------------------------------------------

        var availability_in_any_child_resources = {};

        for ( var day_sql_key in available_slots ){
            // '2023-09-10': [], '2023-09-14': [],
            availability_in_any_child_resources[ day_sql_key ] = [];

            for ( var ind in available_slots[ day_sql_key ] ){
                // [ 0:{ resource_id: 2,  is_available: false,...} , .... ]
                if ( available_slots[ day_sql_key ][ ind ].is_available ){
                    availability_in_any_child_resources[ day_sql_key ].push( available_slots[ day_sql_key ][ ind ].resource_id );
                }
            }
        }
        /**
         * {    "2023-09-10": [ 2, 10, 11 ]				<- available ID of child resources in this date
                "2023-09-14": [ 4 ]						<- available ID of child resources in this date
           }
         */

        for ( var day_sql_key2 in availability_in_any_child_resources ){
            if ( availability_in_any_child_resources[ day_sql_key2 ].length < required_slots_to_book ){

// We can not store booking in this date  day_sql_key2,  number of available child booking resources less than  required
console.groupCollapsed( 'WPBC__IS_LESS_THAN_REQUIRED__OF_MAX_AVAILABLE_SLOTS__BL' );
console.groupCollapsed( '== AVAILABILITY_IN_ANY_CHILD_RESOURCES ==' );
console.log( availability_in_any_child_resources, available_slots, required_slots_to_book );
console.groupEnd();

                wpbc_front_end__show_message__warning( html_field,
                                          '<div>' + _wpbc.get_other_param( 'message_dates_times_unavailable' )     + '</div>'
                                        + '<div><strong>' + _wpbc.get_other_param( 'message_choose_alternative_dates' )    + '</strong></div>'
                                            );
                return true;
            }
        }

        return false; // Good save it.
    }


    /**
     * Get selected SECONDS to book:  [ 0 , 24 * 60 * 60 ]  |  [ 12*60*60 , 14*60*60 ]   ->   get  array of start and end time in seconds,  from  the booking form  fields
     *
     * @param resource_id
     * @returns {number[]}
     */
    function wpbc_get_start_end_times__in_booking_form__as_seconds( resource_id ){

        // 2.1 Get selected time ---------------------------------------------------------------------------------------
        // [ {jquery_option: {}, name: "rangetime2", times_as_seconds:[ 36000, 43200 ], value_option_24h: "10:00 - 12:00"} , ... ]
        var selected_time_fields = wpbc_get__selected_time_fields__in_booking_form__as_arr( resource_id  );

        // 2.2 Get selected SECONDS to  book ---------------------------------------------------------------------------
        var time_fields_obj = false;
        var time_as_seconds_arr = [ 0 , 24 * 60 * 60 ];                  // Full day  by  default

        for ( var field_key in selected_time_fields ){
            time_fields_obj = selected_time_fields[ field_key ];        // { times_as_seconds: [ 21600, 23400 ], value_option_24h: '06:00 - 06:30', name: 'rangetime2[]', jquery_option: jQuery_Object {}}

            if ( -1 !== time_fields_obj.name.indexOf( 'rangetime' ) ){
                time_as_seconds_arr[ 0 ] = time_fields_obj.times_as_seconds[ 0 ];
                time_as_seconds_arr[ 1 ] = time_fields_obj.times_as_seconds[ 1 ];
                //break;       // We can not break  here,  because possible using change over dates with  start/end time,  which has high priority     // If we have range-time then  skip  this loop
            }

            if ( -1 !== time_fields_obj.name.indexOf( 'starttime' ) ){
                time_as_seconds_arr[ 0 ] = time_fields_obj.times_as_seconds[ 0 ];
            }

            if ( -1 !== time_fields_obj.name.indexOf( 'endtime' ) ){
                time_as_seconds_arr[ 1 ] = time_fields_obj.times_as_seconds[ 0 ];
            }
        }

        // For duration time we need to  make a new loop,  because we need to be sure that was defined START_TIME before this,
        // and end time was NOT defined,  e.g. ==  (otherwise it's means that  we already  used END_TIME or RANGE_TIME)
        if (
               (           ( 0 ) !== time_as_seconds_arr[ 0 ] )
            && ( (24 * 60 * 60 ) === time_as_seconds_arr[ 1 ] )
        ){
            for ( var field_key in selected_time_fields ){
                time_fields_obj = selected_time_fields[ field_key ]; // { times_as_seconds: [ 21600, 23400 ], value_option_24h: '06:00 - 06:30', name: 'rangetime2[]', jquery_option: jQuery_Object {}}

                if ( -1 !== time_fields_obj.name.indexOf( 'durationtime' ) ){
                    time_as_seconds_arr[ 1 ] = time_as_seconds_arr[ 0 ] + time_fields_obj.times_as_seconds[ 0 ];
                    break;
                }
            }
        }

        return time_as_seconds_arr;
    }


    /**
     * Get available slots per each date in each slot (child resource). It's checking times as well.
     *
     * @param resource_id	            ID of booking resource
     * @param time_to_book__as_seconds_arr       TIME FOR BOOKING   Full day:[ 0 , 24 * 60 * 60 ]  |   time slot:[ 12*60*60 , 14*60*60 ]
     * @returns []
     *
     *	Example:  	[
     *					'2023-09-10': [
     *										0: Object { resource_id: 2,  is_available: false, booked__seconds: (1) […], … }
     *										1: Object { resource_id: 12, is_available: false, booked__seconds: (1) […], … }
     *										2: Object { resource_id: 10, is_available: false, booked__seconds: (1) […], … }
     *										3: Object { resource_id: 11, is_available: false, booked__seconds: (1) […], … }
     *								  ],
     *					'2023-09-14': [
     *									0: Object { resource_id: 2,  is_available: true, booked__seconds: (1) […], … }
     *									1: Object { resource_id: 12, is_available: true, booked__seconds: (1) […], … }
     *									2: Object { resource_id: 10, is_available: false, booked__seconds: (1) […], … }
     *									3: Object { resource_id: 11, is_available: true, booked__seconds: (1) […], … }
     *								  ]
     *				]
     */
    function wpbc__get_available_slots__for_selected_dates_times__bl( resource_id , time_to_book__as_seconds_arr ){

        // 1. Get selected dates ---------------------------------------------------------------------------------------
        // [ "2023-10-15", "2023-10-16", "2023-10-17", "2023-10-18", "2023-10-19", "2023-10-20", "2023-10-21" ]
        var selected_dates_sql__as_arr = wpbc_get__selected_dates_sql__as_arr( resource_id );


        // Shift time interval  in 30 seconds
        time_to_book__as_seconds_arr[ 0 ] = time_to_book__as_seconds_arr[ 0 ] + 30;
        time_to_book__as_seconds_arr[ 1 ] = time_to_book__as_seconds_arr[ 1 ] - 30;


        // 3.1 Get Data ------------------------------------------------------------------------------------------------
        var sql_class_day;
        var available_resources_arr = [];

        for ( var sql_class_day_number in selected_dates_sql__as_arr ){
            sql_class_day = selected_dates_sql__as_arr[ sql_class_day_number ]; // '2023-08-21'

            available_resources_arr[ sql_class_day ] = [];

            var date_bookings_obj = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_class_day );

            // ---------------------------------------------------------------------------------------------------------
            // 1. Get child booking resources  or single booking resource  that  exist  in dates :	[1] | [1,14,15,17]

            var child_resources_arr = wpbc_clone_obj( _wpbc.booking__get_param_value( resource_id, 'resources_id_arr__in_dates' ) );
            var child_resource_id;
            var merged_seconds;
            var is_intersect;

            var this_date_time_as_seconds_arr = wpbc_clone_obj( time_to_book__as_seconds_arr );

            // If we are using not time slot but the check in/out times ?
            var is_time_slots = _wpbc.calendar__get_param_value( resource_id, 'booking_recurrent_time' );               // 'On' | 'Off'
            if (
                    ( 'On' !== is_time_slots )
                 && ( selected_dates_sql__as_arr.length > 1 )
            ){
                if ( 0 == sql_class_day_number ){          // check in
                    this_date_time_as_seconds_arr[ 1 ] = 24 * 60 * 60;
                } else if ( (selected_dates_sql__as_arr.length - 1) == sql_class_day_number ){      // check out
                    this_date_time_as_seconds_arr[ 0 ] = 0;
                } else {
                    this_date_time_as_seconds_arr = [0, 24 * 60 * 60];
                }
            }


            // Loop all resources ID
            for ( var res_key in child_resources_arr ){
                // [ 2, 10, 12 ,11 ,9 ]  | [3]
                child_resource_id = child_resources_arr[ res_key ];

                //                                       date_bookings_obj [12].booked_time_slots.merged_seconds
                // _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[12].booked_time_slots.merged_seconds		= [ "07:00:11 - 07:30:02", "10:00:11 - 00:00:00" ]

                if ( false !== date_bookings_obj ){
                    if ( date_bookings_obj[ child_resource_id ].is_day_unavailable ){
                        // Unavailable
                        merged_seconds = [[0, 24 * 60 * 60]];
                    } else {
                        // Time slots or Available
                        merged_seconds = date_bookings_obj[ child_resource_id ].booked_time_slots.merged_seconds;       // [  [ 25211, 27002 ], [ 36011, 86400 ]  ]
                    }

                    is_intersect = wpbc_is_intersect__range_time_interval(
                                                                            [
                                                                                [
                                                                                  parseInt( this_date_time_as_seconds_arr[ 0 ] ) + 20
                                                                                , parseInt( this_date_time_as_seconds_arr[ 1 ] ) - 20
                                                                                ]
                                                                            ]
                                                                         , merged_seconds );

                    // Convert Back - Shift time intervals
                    var return_time_to_book = [
                                                            (  (parseInt( this_date_time_as_seconds_arr[ 0 ] ) - 30) < 0)     ? 0     : (parseInt( this_date_time_as_seconds_arr[ 0 ] ) - 30),
                                                            (  (parseInt( this_date_time_as_seconds_arr[ 1 ] ) + 30) > 86400) ? 86400 : (parseInt( this_date_time_as_seconds_arr[ 1 ] ) + 30)
                                                        ];

                    available_resources_arr[ sql_class_day ].push( {
                        'resource_id'           : child_resource_id,
                        'is_available'          : (! is_intersect),
                        'booked__seconds'       : merged_seconds,
                        'booked__readable'      : date_bookings_obj[ child_resource_id ].booked_time_slots.merged_readable,
                        'time_to_book__seconds' : return_time_to_book,
                        'time_to_book__readable': [
                                                    wpbc_js_convert__seconds__to_time_24( return_time_to_book[ 0 ] ),
                                                    wpbc_js_convert__seconds__to_time_24( return_time_to_book[ 1 ] )
                                                  ]
                    } );
                }
            } // End loop child resources --

        } // End loop dates ----------------

        return available_resources_arr;
    };
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/js/_out/capacity_hints.js?ver=9.8.12 
"use strict";

/**
 * Convert seconds to  24 hour format   3600 -> '10:00'
 * @param time_in_seconds
 * @returns {string}
 */
function wpbc_js_convert__seconds__to_time_24(time_in_seconds) {
  var hours = Math.floor(time_in_seconds % 31536000 % 86400 / 3600);

  if (86400 == time_in_seconds) {
    hours = 24;
  }

  var minutes = Math.floor(time_in_seconds % 31536000 % 86400 % 3600 / 60);

  if (hours < 10) {
    hours = '0' + hours.toString();
  }

  if (minutes < 10) {
    minutes = '0' + minutes.toString();
  }

  return hours + ':' + minutes;
}
/**
 * Convert seconds to  AM / PM time format   3600 -> '10:00 AM'
 *
 * @param time_in_seconds
 * @returns {string}
 */


function wpbc_js_convert__seconds__to_time_AMPM(time_in_seconds) {
  var hours = Math.floor(time_in_seconds % 31536000 % 86400 / 3600);

  if (86400 == time_in_seconds) {
    hours = 24;
  }

  var minutes = Math.floor(time_in_seconds % 31536000 % 86400 % 3600 / 60); // American Heritage Dictionary of the English Language states "By convention, 12 AM denotes midnight and 12 PM denotes NOON    -  '12:00 MIDNIGHT' for 00:00 and  - '12:00 NOON' for '12:00'

  var am_pm = parseInt(hours) > 12 ? 'PM' : 'AM';
  am_pm = 12 == hours ? 'PM' : am_pm;
  am_pm = 24 == hours ? 'AM' : am_pm;

  if (hours > 12) {
    hours = hours - 12;
  } // if ( hours < 10 ){
  //     hours = '0' + hours.toString();
  // }


  if (minutes < 10) {
    minutes = '0' + minutes.toString();
  }

  return hours + ':' + minutes + ' ' + am_pm;
}
/**
 * Convert Time slot from  seconds to Readable Time Format:  24 | AM/PM         [ 0, 13*60*60]  ->   '00:00 AM - 01:00 PM'    |       '00:00 - 13:00'
 *
 * @param resource_id                   int ID of resource
 * @param timeslot_in_seconds_arr       [ 0, 13*60*60]
 * @returns {string}                    '00:00 AM - 01:00 PM'    |       '00:00 - 13:00'
 */


function wpbc_js_convert__seconds__to__readable_time(resource_id, timeslot_in_seconds_arr) {
  var readable_time_format;
  var is_use_24;

  if (_wpbc.calendar__get_param_value(resource_id, 'booking_time_format').indexOf('A') > 0 || _wpbc.calendar__get_param_value(resource_id, 'booking_time_format').indexOf('a') > 0) {
    is_use_24 = false;
  } else {
    is_use_24 = true;
  }

  if (is_use_24) {
    readable_time_format = wpbc_js_convert__seconds__to_time_24(timeslot_in_seconds_arr[0]) + ' - ' + wpbc_js_convert__seconds__to_time_24(timeslot_in_seconds_arr[1]);
  } else {
    readable_time_format = wpbc_js_convert__seconds__to_time_AMPM(timeslot_in_seconds_arr[0]) + ' - ' + wpbc_js_convert__seconds__to_time_AMPM(timeslot_in_seconds_arr[1]);
  }

  return readable_time_format;
} // =====================================================================================================================
// [capacity_hint]
// =====================================================================================================================

/**
 *  Convert times seconds arr [ 21600, 23400 ] to redable obj  {}
 *
 * @param times_as_seconds_arr      [ 21600, 23400 ]
 *
 * @returns {{value_option_24h: string[], times_as_seconds_arr, readable_time: string}}
 */


function wpbc_convert_seconds_arr__to_readable_obj(resource_id, times_as_seconds_arr) {
  var readable_time_format = wpbc_js_convert__seconds__to__readable_time(resource_id, times_as_seconds_arr);
  var obj = {
    'times_as_seconds': wpbc_clone_obj(times_as_seconds_arr),
    'value_option_24h': [wpbc_js_convert__seconds__to_time_24(times_as_seconds_arr[0]), wpbc_js_convert__seconds__to_time_24(times_as_seconds_arr[1])],
    'readable_time': readable_time_format
  };
  return obj;
}

function wpbc_get_start_end_times_sec_arr__for_all_rangetime_slots_in_booking_form(resource_id) {
  // [ {jquery_option: {}, name: "rangetime2", times_as_seconds:[ 36000, 43200 ], value_option_24h: "10:00 - 12:00"} , ... ]
  var is_only_selected_time = false;
  var all_time_fields = wpbc_get__selected_time_fields__in_booking_form__as_arr(resource_id, is_only_selected_time);
  var time_as_seconds_arr = [];

  for (var t_key in all_time_fields) {
    if (all_time_fields[t_key]['name'].indexOf('rangetime') > -1) {
      time_as_seconds_arr.push(wpbc_convert_seconds_arr__to_readable_obj(resource_id, all_time_fields[t_key].times_as_seconds // { times_as_seconds: [ 21600, 23400 ], value_option_24h: '06:00 - 06:30', name: 'rangetime2[]', jquery_option: jQuery_Object {}}
      ));
    }
  }

  return time_as_seconds_arr;
}
/**
 * Get array  of available items for each  seelcted date and time slot in booking form
 *
 * @param int resource_id
 * @returns [
 *
 *              "2024-05-17": [
 *                              0_86400    : Object { available_items: 4, value_option_24h: "00:00 - 24:00", date_sql_key: "2024-05-17", … }
 *                              36000_43200: Object { available_items: 4, value_option_24h: "10:00 - 12:00", date_sql_key: "2024-05-17", … }
 *                              43200_50400: Object { available_items: 4, value_option_24h: "12:00 - 14:00", date_sql_key: "2024-05-17", … }
 *                              50400_57600: Object { available_items: 4, value_option_24h: "14:00 - 16:00", date_sql_key: "2024-05-17", … }
 *                              57600_64800: Object { available_items: 4, value_option_24h: "16:00 - 18:00", date_sql_key: "2024-05-17", … }
 *                              64800_72000: Object { available_items: 4, value_option_24h: "18:00 - 20:00", date_sql_key: "2024-05-17", … }
 *                            ]
 *              "2024-05-19": [
 *                              0_86400    : Object { available_items: 4, value_option_24h: "00:00 - 24:00", date_sql_key: "2024-05-19", … }
 *                              36000_43200: Object { available_items: 4, value_option_24h: "10:00 - 12:00", date_sql_key: "2024-05-19", … }
 *                              43200_50400: Object { available_items: 4, value_option_24h: "12:00 - 14:00", date_sql_key: "2024-05-19", … }
 *                              50400_57600: Object { available_items: 4, value_option_24h: "14:00 - 16:00", date_sql_key: "2024-05-19", … }
 *                              57600_64800: Object { available_items: 4, value_option_24h: "16:00 - 18:00", date_sql_key: "2024-05-19", … }
 *                              64800_72000: Object { availa...
 *                            ]
 *          ]
 */


function wpbc_get__available_items_for_selected_datetime(resource_id) {
  var selected_time_fields = []; // -------------------------------------------------------------------------------------------------------------
  // This is current selected / entered  ONE time slot  (if not entred time,  then  full date)
  // -------------------------------------------------------------------------------------------------------------
  // [ 0 , 24 * 60 * 60 ]  |  [ 12*60*60 , 14*60*60 ]    This is selected,  entered times. So  we will  show available slots only  for selected times

  var time_to_book__as_seconds_arr = wpbc_get_start_end_times__in_booking_form__as_seconds(resource_id); // [ 12*60*60 , 14*60*60 ]

  selected_time_fields.push(wpbc_convert_seconds_arr__to_readable_obj(resource_id, time_to_book__as_seconds_arr)); // -------------------------------------------------------------------------------------------------------------
  // This is all  time-slots from  range-time,  if any

  var all_rangetime_slots_arr = wpbc_get_start_end_times_sec_arr__for_all_rangetime_slots_in_booking_form(resource_id); // -------------------------------------------------------------------------------------------------------------

  var work_times_array = all_rangetime_slots_arr.length > 0 ? wpbc_clone_obj(all_rangetime_slots_arr) : wpbc_clone_obj(selected_time_fields);
  var capacity_dates_times = [];

  for (var obj_key in work_times_array) {
    // Object { name: "rangetime2", value_option_24h: "10:00 - 12:00", jquery_option: {…}, name: "rangetime2", times_as_seconds: Array [ 36000, 43200 ], value_option_24h: "10:00 - 12:00" }
    var one_times_readable_obj = work_times_array[obj_key]; // '43200_50400'

    var time_key = '' + one_times_readable_obj['times_as_seconds'][0] + '_' + one_times_readable_obj['times_as_seconds'][1];
    /**
     *  [   "2024-05-16": [  0: Object { resource_id: 2,  is_available: true, booked__seconds: [], … }
     *                       1: Object { resource_id: 10, is_available: true, booked__seconds: [], … }
     *                       2: Object { resource_id: 11, is_available: true, booked__seconds: [], … }
     *   ]
     */

    var available_slots_by_dates = wpbc__get_available_slots__for_selected_dates_times__bl(resource_id, wpbc_clone_obj(one_times_readable_obj['times_as_seconds'])); //console.log( 'available_slots_by_dates==',available_slots_by_dates);
    // Loop Dates

    for (var date_sql_key in available_slots_by_dates) {
      var available_slots_in_one_date = available_slots_by_dates[date_sql_key];
      var count_available_slots = 0;
      var time2book_in_sec_per_each_date = wpbc_clone_obj(one_times_readable_obj['times_as_seconds']); // Loop Available Slots in Date

      for (var i = 0; i < available_slots_in_one_date.length; i++) {
        if (available_slots_in_one_date[i]['is_available']) {
          count_available_slots++;
        } // Ovveride that  time by  times,  that  can  be different for several  dates,  if deactivated this option: 'Use selected times for each booking date'
        // For example if slecte time 10:00 - 11:00 and selected 3 dates, then  booked times here will be  10:00 - 24:00,   00:00 - 24:00,   00:00 - 11:00


        time2book_in_sec_per_each_date = wpbc_clone_obj(available_slots_in_one_date[i]['time_to_book__seconds']);
      } // Save info


      if ('undefined' === typeof capacity_dates_times[date_sql_key]) {
        capacity_dates_times[date_sql_key] = [];
      }

      var css_class = '';

      if (selected_time_fields.length > 0) {
        if (selected_time_fields[0]['times_as_seconds'][0] == time2book_in_sec_per_each_date[0] && selected_time_fields[0]['times_as_seconds'][1] == time2book_in_sec_per_each_date[1]) {
          css_class += ' wpbc_selected_timeslot';
        }
      } // -----------------------------------------------------------------------------------------------------
      // Readable Time Format:  24 | AM/PM
      // -----------------------------------------------------------------------------------------------------


      var readable_time_format = wpbc_js_convert__seconds__to__readable_time(resource_id, time2book_in_sec_per_each_date);
      capacity_dates_times[date_sql_key][time_key] = {
        // 'value_option_24h':one_times_readable_obj[ 'value_option_24h' ],
        'available_items': count_available_slots,
        'times_as_seconds': time2book_in_sec_per_each_date,
        'date_sql_key': date_sql_key,
        'readable_time': readable_time_format,
        'css_class': css_class
      };
    }
  }

  return capacity_dates_times;
} // ---------------------------------------------------------------------------------------------------------------------
// Template for shortcode hint
// ---------------------------------------------------------------------------------------------------------------------

/**
 * Update time hint shortcode content in booking form
 *
 * @param resource_id
 */


function wpbc_update_capacity_hint(resource_id) {
  /**
  *  [          "2024-05-17": [
  *                              0_86400    : Object { available_items: 4, value_option_24h: "00:00 - 24:00", date_sql_key: "2024-05-17", … }
  *                              36000_43200: Object { available_items: 4, value_option_24h: "10:00 - 12:00", date_sql_key: "2024-05-17", … }
  *                              43200_50400: Object { available_items: 4, value_option_24h: "12:00 - 14:00", date_sql_key: "2024-05-17", … }
  *                              50400_57600: Object { available_items: 4, value_option_24h: "14:00 - 16:00", date_sql_key: "2024-05-17", … }
  *                              57600_64800: Object { available_items: 4, value_option_24h: "16:00 - 18:00", date_sql_key: "2024-05-17", … }
  *                              64800_72000: Object { available_items: 4, value_option_24h: "18:00 - 20:00", date_sql_key: "2024-05-17", … }
  *                            ]
  *              "2024-05-19": [
  *                              0_86400    : Object { available_items: 4, value_option_24h: "00:00 - 24:00", date_sql_key: "2024-05-19", … }
  *                              36000_43200: Object { available_items: 4, value_option_24h: "10:00 - 12:00", date_sql_key: "2024-05-19", … }
  *                              43200_50400: Object { available_items: 4, value_option_24h: "12:00 - 14:00", date_sql_key: "2024-05-19", … }
  *                              50400_57600: Object { available_items: 4, value_option_24h: "14:00 - 16:00", date_sql_key: "2024-05-19", … }
  *                              57600_64800: Object { available_items: 4, value_option_24h: "16:00 - 18:00", date_sql_key: "2024-05-19", … }
  *                              64800_72000: Object { availa...
  *                            ]
  *          ]
  */
  var available_items_arr = wpbc_get__available_items_for_selected_datetime(resource_id);
  var is_full_day_booking = true;

  for (var obj_date_tag in available_items_arr) {
    if (Object.keys(available_items_arr[obj_date_tag]).length > 1) {
      is_full_day_booking = false;
      break;
    }

    for (var time_key in available_items_arr[obj_date_tag]) {
      if (available_items_arr[obj_date_tag][time_key]['times_as_seconds'][0] > 0 && available_items_arr[obj_date_tag][time_key]['times_as_seconds'][1] < 86400) {
        is_full_day_booking = false;
        break;
      }
    }

    if (!is_full_day_booking) {
      break;
    }
  }

  var css_is_full_day_booking = is_full_day_booking ? ' wpbc_chint__full_day_bookings' : '';
  var tooltip_hint = '<div class="wpbc_capacity_hint_container' + css_is_full_day_booking + '">';

  for (var obj_date_tag in available_items_arr) {
    var timeslots_in_day = available_items_arr[obj_date_tag];
    tooltip_hint += '<div class="wpbc_chint__datetime_container">'; // JSON.stringify(available_items_arr).match(/[^\\]":/g).length

    if (Object.keys(available_items_arr).length > 1 || is_full_day_booking) {
      tooltip_hint += '<div class="wpbc_chint__date_container">';
      tooltip_hint += '<div class="wpbc_chint__date">' + obj_date_tag + '</div> ';
      tooltip_hint += '<div class="wpbc_chint__date_divider">:</div> ';
      tooltip_hint += '</div> ';
    }

    for (var time_key in timeslots_in_day) {
      tooltip_hint += '<div class="wpbc_chint__time_container">'; // If not full day booking: e.g  00:00 - 24:00
      //if ( (timeslots_in_day[ time_key ][ 'times_as_seconds' ][ 0 ] > 0) && (timeslots_in_day[ time_key ][ 'times_as_seconds' ][ 1 ] < 86400) ){

      tooltip_hint += '<div class="wpbc_chint__timeslot ' + timeslots_in_day[time_key]['css_class'] + '">' + timeslots_in_day[time_key]['readable_time'] + '</div> ';
      tooltip_hint += '<div class="wpbc_chint__timeslot_divider">: </div> '; //}

      tooltip_hint += '<div class="wpbc_chint__availability availability_num_' + timeslots_in_day[time_key]['available_items'] + '">' + timeslots_in_day[time_key]['available_items'] + '</div> ';
      tooltip_hint += '</div> ';
    }

    tooltip_hint += '</div> ';
  }

  tooltip_hint += '</div> '; //console.log( ':: available_items_arr ::', available_items_arr );

  jQuery('.capacity_hint_' + resource_id).html(tooltip_hint);
  jQuery('.capacity_hint_' + resource_id).removeClass('wpbc_chin_newline');

  if (Object.keys(available_items_arr).length > 1) {
    jQuery('.capacity_hint_' + resource_id).addClass('wpbc_chin_newline');
  }
} // Run shortcode changing after  dates selection,  and options selection.


jQuery(document).ready(function () {
  jQuery('.booking_form_div').on('wpbc_booking_date_or_option_selected', function (event, resource_id) {
    wpbc_update_capacity_hint(resource_id);
  });
});
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluYy9qcy9fc3JjL2NhcGFjaXR5X2hpbnRzLmpzIl0sIm5hbWVzIjpbIndwYmNfanNfY29udmVydF9fc2Vjb25kc19fdG9fdGltZV8yNCIsInRpbWVfaW5fc2Vjb25kcyIsImhvdXJzIiwiTWF0aCIsImZsb29yIiwibWludXRlcyIsInRvU3RyaW5nIiwid3BiY19qc19jb252ZXJ0X19zZWNvbmRzX190b190aW1lX0FNUE0iLCJhbV9wbSIsInBhcnNlSW50Iiwid3BiY19qc19jb252ZXJ0X19zZWNvbmRzX190b19fcmVhZGFibGVfdGltZSIsInJlc291cmNlX2lkIiwidGltZXNsb3RfaW5fc2Vjb25kc19hcnIiLCJyZWFkYWJsZV90aW1lX2Zvcm1hdCIsImlzX3VzZV8yNCIsIl93cGJjIiwiY2FsZW5kYXJfX2dldF9wYXJhbV92YWx1ZSIsImluZGV4T2YiLCJ3cGJjX2NvbnZlcnRfc2Vjb25kc19hcnJfX3RvX3JlYWRhYmxlX29iaiIsInRpbWVzX2FzX3NlY29uZHNfYXJyIiwib2JqIiwid3BiY19jbG9uZV9vYmoiLCJ3cGJjX2dldF9zdGFydF9lbmRfdGltZXNfc2VjX2Fycl9fZm9yX2FsbF9yYW5nZXRpbWVfc2xvdHNfaW5fYm9va2luZ19mb3JtIiwiaXNfb25seV9zZWxlY3RlZF90aW1lIiwiYWxsX3RpbWVfZmllbGRzIiwid3BiY19nZXRfX3NlbGVjdGVkX3RpbWVfZmllbGRzX19pbl9ib29raW5nX2Zvcm1fX2FzX2FyciIsInRpbWVfYXNfc2Vjb25kc19hcnIiLCJ0X2tleSIsInB1c2giLCJ0aW1lc19hc19zZWNvbmRzIiwid3BiY19nZXRfX2F2YWlsYWJsZV9pdGVtc19mb3Jfc2VsZWN0ZWRfZGF0ZXRpbWUiLCJzZWxlY3RlZF90aW1lX2ZpZWxkcyIsInRpbWVfdG9fYm9va19fYXNfc2Vjb25kc19hcnIiLCJ3cGJjX2dldF9zdGFydF9lbmRfdGltZXNfX2luX2Jvb2tpbmdfZm9ybV9fYXNfc2Vjb25kcyIsImFsbF9yYW5nZXRpbWVfc2xvdHNfYXJyIiwid29ya190aW1lc19hcnJheSIsImxlbmd0aCIsImNhcGFjaXR5X2RhdGVzX3RpbWVzIiwib2JqX2tleSIsIm9uZV90aW1lc19yZWFkYWJsZV9vYmoiLCJ0aW1lX2tleSIsImF2YWlsYWJsZV9zbG90c19ieV9kYXRlcyIsIndwYmNfX2dldF9hdmFpbGFibGVfc2xvdHNfX2Zvcl9zZWxlY3RlZF9kYXRlc190aW1lc19fYmwiLCJkYXRlX3NxbF9rZXkiLCJhdmFpbGFibGVfc2xvdHNfaW5fb25lX2RhdGUiLCJjb3VudF9hdmFpbGFibGVfc2xvdHMiLCJ0aW1lMmJvb2tfaW5fc2VjX3Blcl9lYWNoX2RhdGUiLCJpIiwiY3NzX2NsYXNzIiwid3BiY191cGRhdGVfY2FwYWNpdHlfaGludCIsImF2YWlsYWJsZV9pdGVtc19hcnIiLCJpc19mdWxsX2RheV9ib29raW5nIiwib2JqX2RhdGVfdGFnIiwiT2JqZWN0Iiwia2V5cyIsImNzc19pc19mdWxsX2RheV9ib29raW5nIiwidG9vbHRpcF9oaW50IiwidGltZXNsb3RzX2luX2RheSIsImpRdWVyeSIsImh0bWwiLCJyZW1vdmVDbGFzcyIsImFkZENsYXNzIiwiZG9jdW1lbnQiLCJyZWFkeSIsIm9uIiwiZXZlbnQiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNBLG9DQUFULENBQStDQyxlQUEvQyxFQUFnRTtBQUU1RCxNQUFJQyxLQUFLLEdBQUtDLElBQUksQ0FBQ0MsS0FBTCxDQUFpQkgsZUFBZSxHQUFHLFFBQW5CLEdBQStCLEtBQW5DLEdBQTRDLElBQXhELENBQWQ7O0FBQ0EsTUFBSyxTQUFTQSxlQUFkLEVBQStCO0FBQzNCQyxJQUFBQSxLQUFLLEdBQUcsRUFBUjtBQUNIOztBQUNELE1BQUlHLE9BQU8sR0FBR0YsSUFBSSxDQUFDQyxLQUFMLENBQWlCSCxlQUFlLEdBQUcsUUFBbkIsR0FBK0IsS0FBakMsR0FBMEMsSUFBNUMsR0FBcUQsRUFBakUsQ0FBZDs7QUFFQSxNQUFLQyxLQUFLLEdBQUcsRUFBYixFQUFpQjtBQUNiQSxJQUFBQSxLQUFLLEdBQUcsTUFBTUEsS0FBSyxDQUFDSSxRQUFOLEVBQWQ7QUFDSDs7QUFDRCxNQUFLRCxPQUFPLEdBQUcsRUFBZixFQUFtQjtBQUNmQSxJQUFBQSxPQUFPLEdBQUcsTUFBTUEsT0FBTyxDQUFDQyxRQUFSLEVBQWhCO0FBQ0g7O0FBRUQsU0FBT0osS0FBSyxHQUFHLEdBQVIsR0FBY0csT0FBckI7QUFDSDtBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBU0Usc0NBQVQsQ0FBaUROLGVBQWpELEVBQWtFO0FBRTlELE1BQUlDLEtBQUssR0FBS0MsSUFBSSxDQUFDQyxLQUFMLENBQWlCSCxlQUFlLEdBQUcsUUFBbkIsR0FBK0IsS0FBbkMsR0FBNEMsSUFBeEQsQ0FBZDs7QUFDQSxNQUFLLFNBQVNBLGVBQWQsRUFBK0I7QUFDM0JDLElBQUFBLEtBQUssR0FBRyxFQUFSO0FBQ0g7O0FBQ0QsTUFBSUcsT0FBTyxHQUFHRixJQUFJLENBQUNDLEtBQUwsQ0FBaUJILGVBQWUsR0FBRyxRQUFuQixHQUErQixLQUFqQyxHQUEwQyxJQUE1QyxHQUFxRCxFQUFqRSxDQUFkLENBTjhELENBUTlEOztBQUNBLE1BQUlPLEtBQUssR0FBSUMsUUFBUSxDQUFFUCxLQUFGLENBQVIsR0FBb0IsRUFBckIsR0FBMkIsSUFBM0IsR0FBa0MsSUFBOUM7QUFDQU0sRUFBQUEsS0FBSyxHQUFJLE1BQU1OLEtBQVAsR0FBZ0IsSUFBaEIsR0FBdUJNLEtBQS9CO0FBQ0FBLEVBQUFBLEtBQUssR0FBSSxNQUFNTixLQUFQLEdBQWdCLElBQWhCLEdBQXVCTSxLQUEvQjs7QUFFQSxNQUFLTixLQUFLLEdBQUcsRUFBYixFQUFpQjtBQUNiQSxJQUFBQSxLQUFLLEdBQUdBLEtBQUssR0FBRyxFQUFoQjtBQUNILEdBZjZELENBZ0I5RDtBQUNBO0FBQ0E7OztBQUVBLE1BQUtHLE9BQU8sR0FBRyxFQUFmLEVBQW1CO0FBQ2ZBLElBQUFBLE9BQU8sR0FBRyxNQUFNQSxPQUFPLENBQUNDLFFBQVIsRUFBaEI7QUFDSDs7QUFFRCxTQUFPSixLQUFLLEdBQUcsR0FBUixHQUFjRyxPQUFkLEdBQXdCLEdBQXhCLEdBQThCRyxLQUFyQztBQUNIO0FBR0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNBLFNBQVNFLDJDQUFULENBQXNEQyxXQUF0RCxFQUFtRUMsdUJBQW5FLEVBQTRGO0FBRXhGLE1BQUlDLG9CQUFKO0FBQ0EsTUFBSUMsU0FBSjs7QUFDQSxNQUNTQyxLQUFLLENBQUNDLHlCQUFOLENBQWlDTCxXQUFqQyxFQUE4QyxxQkFBOUMsRUFBc0VNLE9BQXRFLENBQStFLEdBQS9FLElBQXVGLENBQXpGLElBQ0VGLEtBQUssQ0FBQ0MseUJBQU4sQ0FBaUNMLFdBQWpDLEVBQThDLHFCQUE5QyxFQUFzRU0sT0FBdEUsQ0FBK0UsR0FBL0UsSUFBdUYsQ0FGaEcsRUFJRTtBQUNFSCxJQUFBQSxTQUFTLEdBQUcsS0FBWjtBQUNILEdBTkQsTUFNTztBQUNIQSxJQUFBQSxTQUFTLEdBQUcsSUFBWjtBQUNIOztBQUVELE1BQUtBLFNBQUwsRUFBZ0I7QUFDWkQsSUFBQUEsb0JBQW9CLEdBQUdiLG9DQUFvQyxDQUFFWSx1QkFBdUIsQ0FBRSxDQUFGLENBQXpCLENBQXBDLEdBQ0QsS0FEQyxHQUVEWixvQ0FBb0MsQ0FBRVksdUJBQXVCLENBQUUsQ0FBRixDQUF6QixDQUYxRDtBQUdILEdBSkQsTUFJTztBQUNIQyxJQUFBQSxvQkFBb0IsR0FBR04sc0NBQXNDLENBQUVLLHVCQUF1QixDQUFFLENBQUYsQ0FBekIsQ0FBdEMsR0FDRCxLQURDLEdBRURMLHNDQUFzQyxDQUFFSyx1QkFBdUIsQ0FBRSxDQUFGLENBQXpCLENBRjVEO0FBR0g7O0FBRUQsU0FBT0Msb0JBQVA7QUFDSCxDLENBSUQ7QUFDQTtBQUNBOztBQUVJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDSSxTQUFTSyx5Q0FBVCxDQUFvRFAsV0FBcEQsRUFBaUVRLG9CQUFqRSxFQUF1RjtBQUduRixNQUFJTixvQkFBb0IsR0FBR0gsMkNBQTJDLENBQUVDLFdBQUYsRUFBZVEsb0JBQWYsQ0FBdEU7QUFFQSxNQUFJQyxHQUFHLEdBQUc7QUFDTix3QkFBb0JDLGNBQWMsQ0FBRUYsb0JBQUYsQ0FENUI7QUFFTix3QkFBb0IsQ0FDSW5CLG9DQUFvQyxDQUFFbUIsb0JBQW9CLENBQUUsQ0FBRixDQUF0QixDQUR4QyxFQUVJbkIsb0NBQW9DLENBQUVtQixvQkFBb0IsQ0FBRSxDQUFGLENBQXRCLENBRnhDLENBRmQ7QUFNTixxQkFBb0JOO0FBTmQsR0FBVjtBQVFBLFNBQU9PLEdBQVA7QUFDSDs7QUFHRCxTQUFTRSx5RUFBVCxDQUFvRlgsV0FBcEYsRUFBaUc7QUFFN0Y7QUFDQSxNQUFJWSxxQkFBcUIsR0FBRyxLQUE1QjtBQUNBLE1BQUlDLGVBQWUsR0FBR0MsdURBQXVELENBQUVkLFdBQUYsRUFBZ0JZLHFCQUFoQixDQUE3RTtBQUVBLE1BQUlHLG1CQUFtQixHQUFHLEVBQTFCOztBQUVBLE9BQU0sSUFBSUMsS0FBVixJQUFtQkgsZUFBbkIsRUFBb0M7QUFFaEMsUUFBS0EsZUFBZSxDQUFFRyxLQUFGLENBQWYsQ0FBMEIsTUFBMUIsRUFBbUNWLE9BQW5DLENBQTRDLFdBQTVDLElBQTRELENBQUMsQ0FBbEUsRUFBcUU7QUFFakVTLE1BQUFBLG1CQUFtQixDQUFDRSxJQUFwQixDQUM0QlYseUNBQXlDLENBQUdQLFdBQUgsRUFDckJhLGVBQWUsQ0FBRUcsS0FBRixDQUFmLENBQXlCRSxnQkFESixDQUNtQztBQURuQyxPQURyRTtBQUtIO0FBQ0o7O0FBRUQsU0FBT0gsbUJBQVA7QUFDSDtBQUdEO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0ksU0FBU0ksK0NBQVQsQ0FBMERuQixXQUExRCxFQUF1RTtBQUVsRSxNQUFJb0Isb0JBQW9CLEdBQUcsRUFBM0IsQ0FGa0UsQ0FJbkU7QUFDQTtBQUNBO0FBQ0E7O0FBQ0EsTUFBSUMsNEJBQTRCLEdBQUdDLHFEQUFxRCxDQUFFdEIsV0FBRixDQUF4RixDQVJtRSxDQVNLOztBQUN4RW9CLEVBQUFBLG9CQUFvQixDQUFDSCxJQUFyQixDQUE0QlYseUNBQXlDLENBQUVQLFdBQUYsRUFBZXFCLDRCQUFmLENBQXJFLEVBVm1FLENBWW5FO0FBQ0E7O0FBQ0EsTUFBSUUsdUJBQXVCLEdBQUdaLHlFQUF5RSxDQUFFWCxXQUFGLENBQXZHLENBZG1FLENBZW5FOztBQUdBLE1BQUl3QixnQkFBZ0IsR0FBSUQsdUJBQXVCLENBQUNFLE1BQXhCLEdBQWlDLENBQWxDLEdBQ09mLGNBQWMsQ0FBRWEsdUJBQUYsQ0FEckIsR0FFT2IsY0FBYyxDQUFFVSxvQkFBRixDQUY1QztBQUlBLE1BQUlNLG9CQUFvQixHQUFHLEVBQTNCOztBQUVBLE9BQU0sSUFBSUMsT0FBVixJQUFxQkgsZ0JBQXJCLEVBQXVDO0FBRW5DO0FBQ0EsUUFBSUksc0JBQXNCLEdBQUdKLGdCQUFnQixDQUFFRyxPQUFGLENBQTdDLENBSG1DLENBS25DOztBQUNBLFFBQUlFLFFBQVEsR0FBRyxLQUFLRCxzQkFBc0IsQ0FBRSxrQkFBRixDQUF0QixDQUE4QyxDQUE5QyxDQUFMLEdBQXlELEdBQXpELEdBQStEQSxzQkFBc0IsQ0FBRSxrQkFBRixDQUF0QixDQUE4QyxDQUE5QyxDQUE5RTtBQUdBO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFDWSxRQUFJRSx3QkFBd0IsR0FBR0MsdURBQXVELENBQUUvQixXQUFGLEVBQWVVLGNBQWMsQ0FBRWtCLHNCQUFzQixDQUFFLGtCQUFGLENBQXhCLENBQTdCLENBQXRGLENBZm1DLENBZ0IvQztBQUVZOztBQUNBLFNBQU0sSUFBSUksWUFBVixJQUEwQkYsd0JBQTFCLEVBQW9EO0FBRWhELFVBQUlHLDJCQUEyQixHQUFHSCx3QkFBd0IsQ0FBRUUsWUFBRixDQUExRDtBQUVBLFVBQUlFLHFCQUFxQixHQUFHLENBQTVCO0FBRUEsVUFBSUMsOEJBQThCLEdBQUd6QixjQUFjLENBQUVrQixzQkFBc0IsQ0FBRSxrQkFBRixDQUF4QixDQUFuRCxDQU5nRCxDQVFoRDs7QUFDQSxXQUFNLElBQUlRLENBQUMsR0FBRyxDQUFkLEVBQWlCQSxDQUFDLEdBQUdILDJCQUEyQixDQUFDUixNQUFqRCxFQUF5RFcsQ0FBQyxFQUExRCxFQUE4RDtBQUMxRCxZQUFLSCwyQkFBMkIsQ0FBRUcsQ0FBRixDQUEzQixDQUFrQyxjQUFsQyxDQUFMLEVBQXlEO0FBQ3JERixVQUFBQSxxQkFBcUI7QUFDeEIsU0FIeUQsQ0FLMUQ7QUFDQTs7O0FBQ0FDLFFBQUFBLDhCQUE4QixHQUFHekIsY0FBYyxDQUFFdUIsMkJBQTJCLENBQUVHLENBQUYsQ0FBM0IsQ0FBaUMsdUJBQWpDLENBQUYsQ0FBL0M7QUFDSCxPQWpCK0MsQ0FtQmhEOzs7QUFDQSxVQUFLLGdCQUFnQixPQUFRVixvQkFBb0IsQ0FBRU0sWUFBRixDQUFqRCxFQUFvRTtBQUNoRU4sUUFBQUEsb0JBQW9CLENBQUVNLFlBQUYsQ0FBcEIsR0FBdUMsRUFBdkM7QUFDSDs7QUFFRCxVQUFJSyxTQUFTLEdBQUcsRUFBaEI7O0FBQ0EsVUFBS2pCLG9CQUFvQixDQUFDSyxNQUFyQixHQUE4QixDQUFuQyxFQUFzQztBQUNsQyxZQUFRTCxvQkFBb0IsQ0FBRSxDQUFGLENBQXBCLENBQTJCLGtCQUEzQixFQUFpRCxDQUFqRCxLQUF3RGUsOEJBQThCLENBQUUsQ0FBRixDQUF2RixJQUNDZixvQkFBb0IsQ0FBRSxDQUFGLENBQXBCLENBQTJCLGtCQUEzQixFQUFpRCxDQUFqRCxLQUF3RGUsOEJBQThCLENBQUUsQ0FBRixDQUQ5RixFQUNzRztBQUNsR0UsVUFBQUEsU0FBUyxJQUFJLHlCQUFiO0FBQ0g7QUFDSixPQTlCK0MsQ0FnQ2hEO0FBQ0E7QUFDQTs7O0FBQ0EsVUFBSW5DLG9CQUFvQixHQUFHSCwyQ0FBMkMsQ0FBRUMsV0FBRixFQUFlbUMsOEJBQWYsQ0FBdEU7QUFFQVQsTUFBQUEsb0JBQW9CLENBQUVNLFlBQUYsQ0FBcEIsQ0FBc0NILFFBQXRDLElBQW1EO0FBQ0M7QUFDQSwyQkFBbUJLLHFCQUZwQjtBQUdDLDRCQUFvQkMsOEJBSHJCO0FBSUMsd0JBQW9CSCxZQUpyQjtBQUtDLHlCQUFvQjlCLG9CQUxyQjtBQU1DLHFCQUFvQm1DO0FBTnJCLE9BQW5EO0FBUUg7QUFDSjs7QUFFRCxTQUFPWCxvQkFBUDtBQUVILEMsQ0FJTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ0EsU0FBU1kseUJBQVQsQ0FBb0N0QyxXQUFwQyxFQUFpRDtBQUU1QztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNJLE1BQUl1QyxtQkFBbUIsR0FBR3BCLCtDQUErQyxDQUFFbkIsV0FBRixDQUF6RTtBQUVBLE1BQUl3QyxtQkFBbUIsR0FBRyxJQUExQjs7QUFDQSxPQUFNLElBQUlDLFlBQVYsSUFBMEJGLG1CQUExQixFQUErQztBQUUzQyxRQUFLRyxNQUFNLENBQUNDLElBQVAsQ0FBYUosbUJBQW1CLENBQUVFLFlBQUYsQ0FBaEMsRUFBbURoQixNQUFuRCxHQUE0RCxDQUFqRSxFQUFvRTtBQUNoRWUsTUFBQUEsbUJBQW1CLEdBQUcsS0FBdEI7QUFDQTtBQUNIOztBQUNELFNBQU0sSUFBSVgsUUFBVixJQUFzQlUsbUJBQW1CLENBQUVFLFlBQUYsQ0FBekMsRUFBMkQ7QUFDdkQsVUFBTUYsbUJBQW1CLENBQUVFLFlBQUYsQ0FBbkIsQ0FBcUNaLFFBQXJDLEVBQWlELGtCQUFqRCxFQUF1RSxDQUF2RSxJQUE2RSxDQUE5RSxJQUFxRlUsbUJBQW1CLENBQUVFLFlBQUYsQ0FBbkIsQ0FBcUNaLFFBQXJDLEVBQWlELGtCQUFqRCxFQUF1RSxDQUF2RSxJQUE2RSxLQUF2SyxFQUErSztBQUMzS1csUUFBQUEsbUJBQW1CLEdBQUcsS0FBdEI7QUFDQTtBQUNIO0FBQ0o7O0FBQ0QsUUFBSyxDQUFDQSxtQkFBTixFQUEyQjtBQUN2QjtBQUNIO0FBQ0o7O0FBQ0QsTUFBSUksdUJBQXVCLEdBQUlKLG1CQUFELEdBQXdCLGdDQUF4QixHQUEyRCxFQUF6RjtBQUVBLE1BQUlLLFlBQVksR0FBRyw2Q0FBNkNELHVCQUE3QyxHQUF1RSxJQUExRjs7QUFFQSxPQUFNLElBQUlILFlBQVYsSUFBMEJGLG1CQUExQixFQUErQztBQUUzQyxRQUFJTyxnQkFBZ0IsR0FBR1AsbUJBQW1CLENBQUVFLFlBQUYsQ0FBMUM7QUFFQUksSUFBQUEsWUFBWSxJQUFJLDhDQUFoQixDQUoyQyxDQU0zQzs7QUFDQSxRQUFNSCxNQUFNLENBQUNDLElBQVAsQ0FBYUosbUJBQWIsRUFBbUNkLE1BQW5DLEdBQTRDLENBQTdDLElBQW9EZSxtQkFBekQsRUFBK0U7QUFDM0VLLE1BQUFBLFlBQVksSUFBSSwwQ0FBaEI7QUFDSUEsTUFBQUEsWUFBWSxJQUFJLG1DQUFtQ0osWUFBbkMsR0FBa0QsU0FBbEU7QUFDQUksTUFBQUEsWUFBWSxJQUFJLGdEQUFoQjtBQUNKQSxNQUFBQSxZQUFZLElBQUksU0FBaEI7QUFDSDs7QUFFRCxTQUFNLElBQUloQixRQUFWLElBQXNCaUIsZ0JBQXRCLEVBQXdDO0FBQ2hDRCxNQUFBQSxZQUFZLElBQUksMENBQWhCLENBRGdDLENBR2hDO0FBQ0E7O0FBRUtBLE1BQUFBLFlBQVksSUFBSSxzQ0FBc0NDLGdCQUFnQixDQUFFakIsUUFBRixDQUFoQixDQUE4QixXQUE5QixDQUF0QyxHQUFvRixJQUFwRixHQUNLaUIsZ0JBQWdCLENBQUVqQixRQUFGLENBQWhCLENBQThCLGVBQTlCLENBREwsR0FFQSxTQUZoQjtBQUdEZ0IsTUFBQUEsWUFBWSxJQUFJLHFEQUFoQixDQVQ0QixDQVVoQzs7QUFFSUEsTUFBQUEsWUFBWSxJQUFJLDJEQUEyREMsZ0JBQWdCLENBQUVqQixRQUFGLENBQWhCLENBQThCLGlCQUE5QixDQUEzRCxHQUErRyxJQUEvRyxHQUNNaUIsZ0JBQWdCLENBQUVqQixRQUFGLENBQWhCLENBQThCLGlCQUE5QixDQUROLEdBRUEsU0FGaEI7QUFHSmdCLE1BQUFBLFlBQVksSUFBSSxTQUFoQjtBQUNQOztBQUNEQSxJQUFBQSxZQUFZLElBQUksU0FBaEI7QUFDSDs7QUFFREEsRUFBQUEsWUFBWSxJQUFJLFNBQWhCLENBOUU2QyxDQWlGakQ7O0FBR0lFLEVBQUFBLE1BQU0sQ0FBRSxvQkFBb0IvQyxXQUF0QixDQUFOLENBQTBDZ0QsSUFBMUMsQ0FBZ0RILFlBQWhEO0FBRUFFLEVBQUFBLE1BQU0sQ0FBRSxvQkFBb0IvQyxXQUF0QixDQUFOLENBQTBDaUQsV0FBMUMsQ0FBdUQsbUJBQXZEOztBQUNBLE1BQUtQLE1BQU0sQ0FBQ0MsSUFBUCxDQUFhSixtQkFBYixFQUFtQ2QsTUFBbkMsR0FBNEMsQ0FBakQsRUFBb0Q7QUFDaERzQixJQUFBQSxNQUFNLENBQUUsb0JBQW9CL0MsV0FBdEIsQ0FBTixDQUEwQ2tELFFBQTFDLENBQW9ELG1CQUFwRDtBQUNIO0FBQ0osQyxDQUdHOzs7QUFDQUgsTUFBTSxDQUFFSSxRQUFGLENBQU4sQ0FBbUJDLEtBQW5CLENBQTBCLFlBQVc7QUFDakNMLEVBQUFBLE1BQU0sQ0FBRSxtQkFBRixDQUFOLENBQThCTSxFQUE5QixDQUFrQyxzQ0FBbEMsRUFBMEUsVUFBV0MsS0FBWCxFQUFrQnRELFdBQWxCLEVBQStCO0FBQ3JHc0MsSUFBQUEseUJBQXlCLENBQUV0QyxXQUFGLENBQXpCO0FBQ0gsR0FGRDtBQUlILENBTEQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICogQ29udmVydCBzZWNvbmRzIHRvICAyNCBob3VyIGZvcm1hdCAgIDM2MDAgLT4gJzEwOjAwJ1xyXG4gKiBAcGFyYW0gdGltZV9pbl9zZWNvbmRzXHJcbiAqIEByZXR1cm5zIHtzdHJpbmd9XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2pzX2NvbnZlcnRfX3NlY29uZHNfX3RvX3RpbWVfMjQoIHRpbWVfaW5fc2Vjb25kcyApe1xyXG5cclxuICAgIHZhciBob3VycyAgID0gTWF0aC5mbG9vciggKCAgICh0aW1lX2luX3NlY29uZHMgJSAzMTUzNjAwMCkgJSA4NjQwMCkgLyAzNjAwICk7XHJcbiAgICBpZiAoIDg2NDAwID09IHRpbWVfaW5fc2Vjb25kcyApe1xyXG4gICAgICAgIGhvdXJzID0gMjQ7XHJcbiAgICB9XHJcbiAgICB2YXIgbWludXRlcyA9IE1hdGguZmxvb3IoICggKCAodGltZV9pbl9zZWNvbmRzICUgMzE1MzYwMDApICUgODY0MDApICUgMzYwMCApIC8gNjAgKTtcclxuXHJcbiAgICBpZiAoIGhvdXJzIDwgMTAgKXtcclxuICAgICAgICBob3VycyA9ICcwJyArIGhvdXJzLnRvU3RyaW5nKCk7XHJcbiAgICB9XHJcbiAgICBpZiAoIG1pbnV0ZXMgPCAxMCApe1xyXG4gICAgICAgIG1pbnV0ZXMgPSAnMCcgKyBtaW51dGVzLnRvU3RyaW5nKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGhvdXJzICsgJzonICsgbWludXRlcztcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0IHNlY29uZHMgdG8gIEFNIC8gUE0gdGltZSBmb3JtYXQgICAzNjAwIC0+ICcxMDowMCBBTSdcclxuICpcclxuICogQHBhcmFtIHRpbWVfaW5fc2Vjb25kc1xyXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19qc19jb252ZXJ0X19zZWNvbmRzX190b190aW1lX0FNUE0oIHRpbWVfaW5fc2Vjb25kcyApe1xyXG5cclxuICAgIHZhciBob3VycyAgID0gTWF0aC5mbG9vciggKCAgICh0aW1lX2luX3NlY29uZHMgJSAzMTUzNjAwMCkgJSA4NjQwMCkgLyAzNjAwICk7XHJcbiAgICBpZiAoIDg2NDAwID09IHRpbWVfaW5fc2Vjb25kcyApe1xyXG4gICAgICAgIGhvdXJzID0gMjQ7XHJcbiAgICB9XHJcbiAgICB2YXIgbWludXRlcyA9IE1hdGguZmxvb3IoICggKCAodGltZV9pbl9zZWNvbmRzICUgMzE1MzYwMDApICUgODY0MDApICUgMzYwMCApIC8gNjAgKTtcclxuXHJcbiAgICAvLyBBbWVyaWNhbiBIZXJpdGFnZSBEaWN0aW9uYXJ5IG9mIHRoZSBFbmdsaXNoIExhbmd1YWdlIHN0YXRlcyBcIkJ5IGNvbnZlbnRpb24sIDEyIEFNIGRlbm90ZXMgbWlkbmlnaHQgYW5kIDEyIFBNIGRlbm90ZXMgTk9PTiAgICAtICAnMTI6MDAgTUlETklHSFQnIGZvciAwMDowMCBhbmQgIC0gJzEyOjAwIE5PT04nIGZvciAnMTI6MDAnXHJcbiAgICB2YXIgYW1fcG0gPSAocGFyc2VJbnQoIGhvdXJzICkgPiAxMikgPyAnUE0nIDogJ0FNJztcclxuICAgIGFtX3BtID0gKDEyID09IGhvdXJzKSA/ICdQTScgOiBhbV9wbTtcclxuICAgIGFtX3BtID0gKDI0ID09IGhvdXJzKSA/ICdBTScgOiBhbV9wbTtcclxuXHJcbiAgICBpZiAoIGhvdXJzID4gMTIgKXtcclxuICAgICAgICBob3VycyA9IGhvdXJzIC0gMTI7XHJcbiAgICB9XHJcbiAgICAvLyBpZiAoIGhvdXJzIDwgMTAgKXtcclxuICAgIC8vICAgICBob3VycyA9ICcwJyArIGhvdXJzLnRvU3RyaW5nKCk7XHJcbiAgICAvLyB9XHJcblxyXG4gICAgaWYgKCBtaW51dGVzIDwgMTAgKXtcclxuICAgICAgICBtaW51dGVzID0gJzAnICsgbWludXRlcy50b1N0cmluZygpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBob3VycyArICc6JyArIG1pbnV0ZXMgKyAnICcgKyBhbV9wbTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0IFRpbWUgc2xvdCBmcm9tICBzZWNvbmRzIHRvIFJlYWRhYmxlIFRpbWUgRm9ybWF0OiAgMjQgfCBBTS9QTSAgICAgICAgIFsgMCwgMTMqNjAqNjBdICAtPiAgICcwMDowMCBBTSAtIDAxOjAwIFBNJyAgICB8ICAgICAgICcwMDowMCAtIDEzOjAwJ1xyXG4gKlxyXG4gKiBAcGFyYW0gcmVzb3VyY2VfaWQgICAgICAgICAgICAgICAgICAgaW50IElEIG9mIHJlc291cmNlXHJcbiAqIEBwYXJhbSB0aW1lc2xvdF9pbl9zZWNvbmRzX2FyciAgICAgICBbIDAsIDEzKjYwKjYwXVxyXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAgICAgICAgICAgICAgICAgICAgJzAwOjAwIEFNIC0gMDE6MDAgUE0nICAgIHwgICAgICAgJzAwOjAwIC0gMTM6MDAnXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2pzX2NvbnZlcnRfX3NlY29uZHNfX3RvX19yZWFkYWJsZV90aW1lKCByZXNvdXJjZV9pZCwgdGltZXNsb3RfaW5fc2Vjb25kc19hcnIgKXtcclxuXHJcbiAgICB2YXIgcmVhZGFibGVfdGltZV9mb3JtYXQ7XHJcbiAgICB2YXIgaXNfdXNlXzI0O1xyXG4gICAgaWYgKFxyXG4gICAgICAgICAgICggX3dwYmMuY2FsZW5kYXJfX2dldF9wYXJhbV92YWx1ZSggcmVzb3VyY2VfaWQsICdib29raW5nX3RpbWVfZm9ybWF0JyApLmluZGV4T2YoICdBJyApID4gMCApXHJcbiAgICAgICAgfHwgKCBfd3BiYy5jYWxlbmRhcl9fZ2V0X3BhcmFtX3ZhbHVlKCByZXNvdXJjZV9pZCwgJ2Jvb2tpbmdfdGltZV9mb3JtYXQnICkuaW5kZXhPZiggJ2EnICkgPiAwIClcclxuXHJcbiAgICApIHtcclxuICAgICAgICBpc191c2VfMjQgPSBmYWxzZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaXNfdXNlXzI0ID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIGlzX3VzZV8yNCApe1xyXG4gICAgICAgIHJlYWRhYmxlX3RpbWVfZm9ybWF0ID0gd3BiY19qc19jb252ZXJ0X19zZWNvbmRzX190b190aW1lXzI0KCB0aW1lc2xvdF9pbl9zZWNvbmRzX2FyclsgMCBdIClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJyAtICdcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgd3BiY19qc19jb252ZXJ0X19zZWNvbmRzX190b190aW1lXzI0KCB0aW1lc2xvdF9pbl9zZWNvbmRzX2FyclsgMSBdICk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJlYWRhYmxlX3RpbWVfZm9ybWF0ID0gd3BiY19qc19jb252ZXJ0X19zZWNvbmRzX190b190aW1lX0FNUE0oIHRpbWVzbG90X2luX3NlY29uZHNfYXJyWyAwIF0gKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAnIC0gJ1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKyB3cGJjX2pzX2NvbnZlcnRfX3NlY29uZHNfX3RvX3RpbWVfQU1QTSggdGltZXNsb3RfaW5fc2Vjb25kc19hcnJbIDEgXSApO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByZWFkYWJsZV90aW1lX2Zvcm1hdDtcclxufVxyXG5cclxuXHJcblxyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuLy8gW2NhcGFjaXR5X2hpbnRdXHJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogIENvbnZlcnQgdGltZXMgc2Vjb25kcyBhcnIgWyAyMTYwMCwgMjM0MDAgXSB0byByZWRhYmxlIG9iaiAge31cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gdGltZXNfYXNfc2Vjb25kc19hcnIgICAgICBbIDIxNjAwLCAyMzQwMCBdXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge3t2YWx1ZV9vcHRpb25fMjRoOiBzdHJpbmdbXSwgdGltZXNfYXNfc2Vjb25kc19hcnIsIHJlYWRhYmxlX3RpbWU6IHN0cmluZ319XHJcbiAgICAgKi9cclxuICAgIGZ1bmN0aW9uIHdwYmNfY29udmVydF9zZWNvbmRzX2Fycl9fdG9fcmVhZGFibGVfb2JqKCByZXNvdXJjZV9pZCwgdGltZXNfYXNfc2Vjb25kc19hcnIgKXtcclxuXHJcblxyXG4gICAgICAgIHZhciByZWFkYWJsZV90aW1lX2Zvcm1hdCA9IHdwYmNfanNfY29udmVydF9fc2Vjb25kc19fdG9fX3JlYWRhYmxlX3RpbWUoIHJlc291cmNlX2lkLCB0aW1lc19hc19zZWNvbmRzX2FyciApO1xyXG5cclxuICAgICAgICB2YXIgb2JqID0ge1xyXG4gICAgICAgICAgICAndGltZXNfYXNfc2Vjb25kcyc6IHdwYmNfY2xvbmVfb2JqKCB0aW1lc19hc19zZWNvbmRzX2FyciApLFxyXG4gICAgICAgICAgICAndmFsdWVfb3B0aW9uXzI0aCc6IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd3BiY19qc19jb252ZXJ0X19zZWNvbmRzX190b190aW1lXzI0KCB0aW1lc19hc19zZWNvbmRzX2FyclsgMCBdICksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdwYmNfanNfY29udmVydF9fc2Vjb25kc19fdG9fdGltZV8yNCggdGltZXNfYXNfc2Vjb25kc19hcnJbIDEgXSApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgJ3JlYWRhYmxlX3RpbWUnICAgOiByZWFkYWJsZV90aW1lX2Zvcm1hdFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgcmV0dXJuIG9iajtcclxuICAgIH1cclxuXHJcblxyXG4gICAgZnVuY3Rpb24gd3BiY19nZXRfc3RhcnRfZW5kX3RpbWVzX3NlY19hcnJfX2Zvcl9hbGxfcmFuZ2V0aW1lX3Nsb3RzX2luX2Jvb2tpbmdfZm9ybSggcmVzb3VyY2VfaWQgKXtcclxuXHJcbiAgICAgICAgLy8gWyB7anF1ZXJ5X29wdGlvbjoge30sIG5hbWU6IFwicmFuZ2V0aW1lMlwiLCB0aW1lc19hc19zZWNvbmRzOlsgMzYwMDAsIDQzMjAwIF0sIHZhbHVlX29wdGlvbl8yNGg6IFwiMTA6MDAgLSAxMjowMFwifSAsIC4uLiBdXHJcbiAgICAgICAgdmFyIGlzX29ubHlfc2VsZWN0ZWRfdGltZSA9IGZhbHNlO1xyXG4gICAgICAgIHZhciBhbGxfdGltZV9maWVsZHMgPSB3cGJjX2dldF9fc2VsZWN0ZWRfdGltZV9maWVsZHNfX2luX2Jvb2tpbmdfZm9ybV9fYXNfYXJyKCByZXNvdXJjZV9pZCAsIGlzX29ubHlfc2VsZWN0ZWRfdGltZSApO1xyXG5cclxuICAgICAgICB2YXIgdGltZV9hc19zZWNvbmRzX2FyciA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKCB2YXIgdF9rZXkgaW4gYWxsX3RpbWVfZmllbGRzICl7XHJcblxyXG4gICAgICAgICAgICBpZiAoIGFsbF90aW1lX2ZpZWxkc1sgdF9rZXkgXVsgJ25hbWUnIF0uaW5kZXhPZiggJ3JhbmdldGltZScgKSA+IC0xICl7XHJcblxyXG4gICAgICAgICAgICAgICAgdGltZV9hc19zZWNvbmRzX2Fyci5wdXNoKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdwYmNfY29udmVydF9zZWNvbmRzX2Fycl9fdG9fcmVhZGFibGVfb2JqKCAgcmVzb3VyY2VfaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxfdGltZV9maWVsZHNbIHRfa2V5IF0udGltZXNfYXNfc2Vjb25kcyAgICAgICAgICAgICAgIC8vIHsgdGltZXNfYXNfc2Vjb25kczogWyAyMTYwMCwgMjM0MDAgXSwgdmFsdWVfb3B0aW9uXzI0aDogJzA2OjAwIC0gMDY6MzAnLCBuYW1lOiAncmFuZ2V0aW1lMltdJywganF1ZXJ5X29wdGlvbjogalF1ZXJ5X09iamVjdCB7fX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGltZV9hc19zZWNvbmRzX2FycjtcclxuICAgIH1cclxuXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXQgYXJyYXkgIG9mIGF2YWlsYWJsZSBpdGVtcyBmb3IgZWFjaCAgc2VlbGN0ZWQgZGF0ZSBhbmQgdGltZSBzbG90IGluIGJvb2tpbmcgZm9ybVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBpbnQgcmVzb3VyY2VfaWRcclxuICAgICAqIEByZXR1cm5zIFtcclxuICAgICAqXHJcbiAgICAgKiAgICAgICAgICAgICAgXCIyMDI0LTA1LTE3XCI6IFtcclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMF84NjQwMCAgICA6IE9iamVjdCB7IGF2YWlsYWJsZV9pdGVtczogNCwgdmFsdWVfb3B0aW9uXzI0aDogXCIwMDowMCAtIDI0OjAwXCIsIGRhdGVfc3FsX2tleTogXCIyMDI0LTA1LTE3XCIsIOKApiB9XHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDM2MDAwXzQzMjAwOiBPYmplY3QgeyBhdmFpbGFibGVfaXRlbXM6IDQsIHZhbHVlX29wdGlvbl8yNGg6IFwiMTA6MDAgLSAxMjowMFwiLCBkYXRlX3NxbF9rZXk6IFwiMjAyNC0wNS0xN1wiLCDigKYgfVxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA0MzIwMF81MDQwMDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjEyOjAwIC0gMTQ6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTdcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNTA0MDBfNTc2MDA6IE9iamVjdCB7IGF2YWlsYWJsZV9pdGVtczogNCwgdmFsdWVfb3B0aW9uXzI0aDogXCIxNDowMCAtIDE2OjAwXCIsIGRhdGVfc3FsX2tleTogXCIyMDI0LTA1LTE3XCIsIOKApiB9XHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDU3NjAwXzY0ODAwOiBPYmplY3QgeyBhdmFpbGFibGVfaXRlbXM6IDQsIHZhbHVlX29wdGlvbl8yNGg6IFwiMTY6MDAgLSAxODowMFwiLCBkYXRlX3NxbF9rZXk6IFwiMjAyNC0wNS0xN1wiLCDigKYgfVxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA2NDgwMF83MjAwMDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjE4OjAwIC0gMjA6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTdcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIF1cclxuICAgICAqICAgICAgICAgICAgICBcIjIwMjQtMDUtMTlcIjogW1xyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwXzg2NDAwICAgIDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjAwOjAwIC0gMjQ6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTlcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMzYwMDBfNDMyMDA6IE9iamVjdCB7IGF2YWlsYWJsZV9pdGVtczogNCwgdmFsdWVfb3B0aW9uXzI0aDogXCIxMDowMCAtIDEyOjAwXCIsIGRhdGVfc3FsX2tleTogXCIyMDI0LTA1LTE5XCIsIOKApiB9XHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQzMjAwXzUwNDAwOiBPYmplY3QgeyBhdmFpbGFibGVfaXRlbXM6IDQsIHZhbHVlX29wdGlvbl8yNGg6IFwiMTI6MDAgLSAxNDowMFwiLCBkYXRlX3NxbF9rZXk6IFwiMjAyNC0wNS0xOVwiLCDigKYgfVxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1MDQwMF81NzYwMDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjE0OjAwIC0gMTY6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTlcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNTc2MDBfNjQ4MDA6IE9iamVjdCB7IGF2YWlsYWJsZV9pdGVtczogNCwgdmFsdWVfb3B0aW9uXzI0aDogXCIxNjowMCAtIDE4OjAwXCIsIGRhdGVfc3FsX2tleTogXCIyMDI0LTA1LTE5XCIsIOKApiB9XHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDY0ODAwXzcyMDAwOiBPYmplY3QgeyBhdmFpbGEuLi5cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIF1cclxuICAgICAqICAgICAgICAgIF1cclxuICAgICAqL1xyXG4gICAgZnVuY3Rpb24gd3BiY19nZXRfX2F2YWlsYWJsZV9pdGVtc19mb3Jfc2VsZWN0ZWRfZGF0ZXRpbWUoIHJlc291cmNlX2lkICl7XHJcblxyXG4gICAgICAgICB2YXIgc2VsZWN0ZWRfdGltZV9maWVsZHMgPSBbXTtcclxuXHJcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgICAgIC8vIFRoaXMgaXMgY3VycmVudCBzZWxlY3RlZCAvIGVudGVyZWQgIE9ORSB0aW1lIHNsb3QgIChpZiBub3QgZW50cmVkIHRpbWUsICB0aGVuICBmdWxsIGRhdGUpXHJcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgICAgIC8vIFsgMCAsIDI0ICogNjAgKiA2MCBdICB8ICBbIDEyKjYwKjYwICwgMTQqNjAqNjAgXSAgICBUaGlzIGlzIHNlbGVjdGVkLCAgZW50ZXJlZCB0aW1lcy4gU28gIHdlIHdpbGwgIHNob3cgYXZhaWxhYmxlIHNsb3RzIG9ubHkgIGZvciBzZWxlY3RlZCB0aW1lc1xyXG4gICAgICAgIHZhciB0aW1lX3RvX2Jvb2tfX2FzX3NlY29uZHNfYXJyID0gd3BiY19nZXRfc3RhcnRfZW5kX3RpbWVzX19pbl9ib29raW5nX2Zvcm1fX2FzX3NlY29uZHMoIHJlc291cmNlX2lkICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWyAxMio2MCo2MCAsIDE0KjYwKjYwIF1cclxuICAgICAgICBzZWxlY3RlZF90aW1lX2ZpZWxkcy5wdXNoKCAgd3BiY19jb252ZXJ0X3NlY29uZHNfYXJyX190b19yZWFkYWJsZV9vYmooIHJlc291cmNlX2lkLCB0aW1lX3RvX2Jvb2tfX2FzX3NlY29uZHNfYXJyICkgKTtcclxuXHJcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgICAgIC8vIFRoaXMgaXMgYWxsICB0aW1lLXNsb3RzIGZyb20gIHJhbmdlLXRpbWUsICBpZiBhbnlcclxuICAgICAgICB2YXIgYWxsX3JhbmdldGltZV9zbG90c19hcnIgPSB3cGJjX2dldF9zdGFydF9lbmRfdGltZXNfc2VjX2Fycl9fZm9yX2FsbF9yYW5nZXRpbWVfc2xvdHNfaW5fYm9va2luZ19mb3JtKCByZXNvdXJjZV9pZCApO1xyXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblxyXG4gICAgICAgIHZhciB3b3JrX3RpbWVzX2FycmF5ID0gKGFsbF9yYW5nZXRpbWVfc2xvdHNfYXJyLmxlbmd0aCA+IDApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gd3BiY19jbG9uZV9vYmooIGFsbF9yYW5nZXRpbWVfc2xvdHNfYXJyIClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB3cGJjX2Nsb25lX29iaiggc2VsZWN0ZWRfdGltZV9maWVsZHMgKTtcclxuXHJcbiAgICAgICAgdmFyIGNhcGFjaXR5X2RhdGVzX3RpbWVzID0gW107XHJcblxyXG4gICAgICAgIGZvciAoIHZhciBvYmpfa2V5IGluIHdvcmtfdGltZXNfYXJyYXkgKXtcclxuXHJcbiAgICAgICAgICAgIC8vIE9iamVjdCB7IG5hbWU6IFwicmFuZ2V0aW1lMlwiLCB2YWx1ZV9vcHRpb25fMjRoOiBcIjEwOjAwIC0gMTI6MDBcIiwganF1ZXJ5X29wdGlvbjoge+KApn0sIG5hbWU6IFwicmFuZ2V0aW1lMlwiLCB0aW1lc19hc19zZWNvbmRzOiBBcnJheSBbIDM2MDAwLCA0MzIwMCBdLCB2YWx1ZV9vcHRpb25fMjRoOiBcIjEwOjAwIC0gMTI6MDBcIiB9XHJcbiAgICAgICAgICAgIHZhciBvbmVfdGltZXNfcmVhZGFibGVfb2JqID0gd29ya190aW1lc19hcnJheVsgb2JqX2tleSBdO1xyXG5cclxuICAgICAgICAgICAgLy8gJzQzMjAwXzUwNDAwJ1xyXG4gICAgICAgICAgICB2YXIgdGltZV9rZXkgPSAnJyArIG9uZV90aW1lc19yZWFkYWJsZV9vYmpbICd0aW1lc19hc19zZWNvbmRzJyBdWyAwIF0gKyAnXycgKyBvbmVfdGltZXNfcmVhZGFibGVfb2JqWyAndGltZXNfYXNfc2Vjb25kcycgXVsgMSBdO1xyXG5cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiAgWyAgIFwiMjAyNC0wNS0xNlwiOiBbICAwOiBPYmplY3QgeyByZXNvdXJjZV9pZDogMiwgIGlzX2F2YWlsYWJsZTogdHJ1ZSwgYm9va2VkX19zZWNvbmRzOiBbXSwg4oCmIH1cclxuICAgICAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgIDE6IE9iamVjdCB7IHJlc291cmNlX2lkOiAxMCwgaXNfYXZhaWxhYmxlOiB0cnVlLCBib29rZWRfX3NlY29uZHM6IFtdLCDigKYgfVxyXG4gICAgICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgMjogT2JqZWN0IHsgcmVzb3VyY2VfaWQ6IDExLCBpc19hdmFpbGFibGU6IHRydWUsIGJvb2tlZF9fc2Vjb25kczogW10sIOKApiB9XHJcbiAgICAgICAgICAgICAqICAgXVxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgdmFyIGF2YWlsYWJsZV9zbG90c19ieV9kYXRlcyA9IHdwYmNfX2dldF9hdmFpbGFibGVfc2xvdHNfX2Zvcl9zZWxlY3RlZF9kYXRlc190aW1lc19fYmwoIHJlc291cmNlX2lkLCB3cGJjX2Nsb25lX29iaiggb25lX3RpbWVzX3JlYWRhYmxlX29ialsgJ3RpbWVzX2FzX3NlY29uZHMnIF0gKSApO1xyXG4vL2NvbnNvbGUubG9nKCAnYXZhaWxhYmxlX3Nsb3RzX2J5X2RhdGVzPT0nLGF2YWlsYWJsZV9zbG90c19ieV9kYXRlcyk7XHJcblxyXG4gICAgICAgICAgICAvLyBMb29wIERhdGVzXHJcbiAgICAgICAgICAgIGZvciAoIHZhciBkYXRlX3NxbF9rZXkgaW4gYXZhaWxhYmxlX3Nsb3RzX2J5X2RhdGVzICl7XHJcblxyXG4gICAgICAgICAgICAgICAgdmFyIGF2YWlsYWJsZV9zbG90c19pbl9vbmVfZGF0ZSA9IGF2YWlsYWJsZV9zbG90c19ieV9kYXRlc1sgZGF0ZV9zcWxfa2V5IF07XHJcblxyXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50X2F2YWlsYWJsZV9zbG90cyA9IDBcclxuXHJcbiAgICAgICAgICAgICAgICB2YXIgdGltZTJib29rX2luX3NlY19wZXJfZWFjaF9kYXRlID0gd3BiY19jbG9uZV9vYmooIG9uZV90aW1lc19yZWFkYWJsZV9vYmpbICd0aW1lc19hc19zZWNvbmRzJyBdICk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gTG9vcCBBdmFpbGFibGUgU2xvdHMgaW4gRGF0ZVxyXG4gICAgICAgICAgICAgICAgZm9yICggdmFyIGkgPSAwOyBpIDwgYXZhaWxhYmxlX3Nsb3RzX2luX29uZV9kYXRlLmxlbmd0aDsgaSsrICl7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCBhdmFpbGFibGVfc2xvdHNfaW5fb25lX2RhdGVbIGkgXVsgJ2lzX2F2YWlsYWJsZScgXSApe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudF9hdmFpbGFibGVfc2xvdHMrKztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIE92dmVyaWRlIHRoYXQgIHRpbWUgYnkgIHRpbWVzLCAgdGhhdCAgY2FuICBiZSBkaWZmZXJlbnQgZm9yIHNldmVyYWwgIGRhdGVzLCAgaWYgZGVhY3RpdmF0ZWQgdGhpcyBvcHRpb246ICdVc2Ugc2VsZWN0ZWQgdGltZXMgZm9yIGVhY2ggYm9va2luZyBkYXRlJ1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIEZvciBleGFtcGxlIGlmIHNsZWN0ZSB0aW1lIDEwOjAwIC0gMTE6MDAgYW5kIHNlbGVjdGVkIDMgZGF0ZXMsIHRoZW4gIGJvb2tlZCB0aW1lcyBoZXJlIHdpbGwgYmUgIDEwOjAwIC0gMjQ6MDAsICAgMDA6MDAgLSAyNDowMCwgICAwMDowMCAtIDExOjAwXHJcbiAgICAgICAgICAgICAgICAgICAgdGltZTJib29rX2luX3NlY19wZXJfZWFjaF9kYXRlID0gd3BiY19jbG9uZV9vYmooIGF2YWlsYWJsZV9zbG90c19pbl9vbmVfZGF0ZVsgaSBdWyd0aW1lX3RvX2Jvb2tfX3NlY29uZHMnXSApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNhdmUgaW5mb1xyXG4gICAgICAgICAgICAgICAgaWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIChjYXBhY2l0eV9kYXRlc190aW1lc1sgZGF0ZV9zcWxfa2V5IF0pICl7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FwYWNpdHlfZGF0ZXNfdGltZXNbIGRhdGVfc3FsX2tleSBdID0gW107XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgdmFyIGNzc19jbGFzcyA9ICcnO1xyXG4gICAgICAgICAgICAgICAgaWYgKCBzZWxlY3RlZF90aW1lX2ZpZWxkcy5sZW5ndGggPiAwICl7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCAgIChzZWxlY3RlZF90aW1lX2ZpZWxkc1sgMCBdWyAndGltZXNfYXNfc2Vjb25kcycgXVsgMCBdID09IHRpbWUyYm9va19pbl9zZWNfcGVyX2VhY2hfZGF0ZVsgMCBdKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAmJiAoc2VsZWN0ZWRfdGltZV9maWVsZHNbIDAgXVsgJ3RpbWVzX2FzX3NlY29uZHMnIF1bIDEgXSA9PSB0aW1lMmJvb2tfaW5fc2VjX3Blcl9lYWNoX2RhdGVbIDEgXSkgKXtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY3NzX2NsYXNzICs9ICcgd3BiY19zZWxlY3RlZF90aW1lc2xvdCdcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgICAgICAgICAgICAgIC8vIFJlYWRhYmxlIFRpbWUgRm9ybWF0OiAgMjQgfCBBTS9QTVxyXG4gICAgICAgICAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgICAgICAgICAgICAgIHZhciByZWFkYWJsZV90aW1lX2Zvcm1hdCA9IHdwYmNfanNfY29udmVydF9fc2Vjb25kc19fdG9fX3JlYWRhYmxlX3RpbWUoIHJlc291cmNlX2lkLCB0aW1lMmJvb2tfaW5fc2VjX3Blcl9lYWNoX2RhdGUgKVxyXG5cclxuICAgICAgICAgICAgICAgIGNhcGFjaXR5X2RhdGVzX3RpbWVzWyBkYXRlX3NxbF9rZXkgXVsgdGltZV9rZXkgXSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAndmFsdWVfb3B0aW9uXzI0aCc6b25lX3RpbWVzX3JlYWRhYmxlX29ialsgJ3ZhbHVlX29wdGlvbl8yNGgnIF0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2F2YWlsYWJsZV9pdGVtcyc6IGNvdW50X2F2YWlsYWJsZV9zbG90cyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndGltZXNfYXNfc2Vjb25kcyc6IHRpbWUyYm9va19pbl9zZWNfcGVyX2VhY2hfZGF0ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZGF0ZV9zcWxfa2V5JyAgICA6IGRhdGVfc3FsX2tleSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncmVhZGFibGVfdGltZScgICA6IHJlYWRhYmxlX3RpbWVfZm9ybWF0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjc3NfY2xhc3MnICAgICAgIDogY3NzX2NsYXNzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gY2FwYWNpdHlfZGF0ZXNfdGltZXM7XHJcblxyXG4gICAgfVxyXG5cclxuXHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuLy8gVGVtcGxhdGUgZm9yIHNob3J0Y29kZSBoaW50XHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIFVwZGF0ZSB0aW1lIGhpbnQgc2hvcnRjb2RlIGNvbnRlbnQgaW4gYm9va2luZyBmb3JtXHJcbiAqXHJcbiAqIEBwYXJhbSByZXNvdXJjZV9pZFxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY191cGRhdGVfY2FwYWNpdHlfaGludCggcmVzb3VyY2VfaWQgKXtcclxuXHJcbiAgICAgLyoqXHJcbiAgICAgKiAgWyAgICAgICAgICBcIjIwMjQtMDUtMTdcIjogW1xyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwXzg2NDAwICAgIDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjAwOjAwIC0gMjQ6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTdcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMzYwMDBfNDMyMDA6IE9iamVjdCB7IGF2YWlsYWJsZV9pdGVtczogNCwgdmFsdWVfb3B0aW9uXzI0aDogXCIxMDowMCAtIDEyOjAwXCIsIGRhdGVfc3FsX2tleTogXCIyMDI0LTA1LTE3XCIsIOKApiB9XHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQzMjAwXzUwNDAwOiBPYmplY3QgeyBhdmFpbGFibGVfaXRlbXM6IDQsIHZhbHVlX29wdGlvbl8yNGg6IFwiMTI6MDAgLSAxNDowMFwiLCBkYXRlX3NxbF9rZXk6IFwiMjAyNC0wNS0xN1wiLCDigKYgfVxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1MDQwMF81NzYwMDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjE0OjAwIC0gMTY6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTdcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNTc2MDBfNjQ4MDA6IE9iamVjdCB7IGF2YWlsYWJsZV9pdGVtczogNCwgdmFsdWVfb3B0aW9uXzI0aDogXCIxNjowMCAtIDE4OjAwXCIsIGRhdGVfc3FsX2tleTogXCIyMDI0LTA1LTE3XCIsIOKApiB9XHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDY0ODAwXzcyMDAwOiBPYmplY3QgeyBhdmFpbGFibGVfaXRlbXM6IDQsIHZhbHVlX29wdGlvbl8yNGg6IFwiMTg6MDAgLSAyMDowMFwiLCBkYXRlX3NxbF9rZXk6IFwiMjAyNC0wNS0xN1wiLCDigKYgfVxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgXVxyXG4gICAgICogICAgICAgICAgICAgIFwiMjAyNC0wNS0xOVwiOiBbXHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBfODY0MDAgICAgOiBPYmplY3QgeyBhdmFpbGFibGVfaXRlbXM6IDQsIHZhbHVlX29wdGlvbl8yNGg6IFwiMDA6MDAgLSAyNDowMFwiLCBkYXRlX3NxbF9rZXk6IFwiMjAyNC0wNS0xOVwiLCDigKYgfVxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzNjAwMF80MzIwMDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjEwOjAwIC0gMTI6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTlcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNDMyMDBfNTA0MDA6IE9iamVjdCB7IGF2YWlsYWJsZV9pdGVtczogNCwgdmFsdWVfb3B0aW9uXzI0aDogXCIxMjowMCAtIDE0OjAwXCIsIGRhdGVfc3FsX2tleTogXCIyMDI0LTA1LTE5XCIsIOKApiB9XHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDUwNDAwXzU3NjAwOiBPYmplY3QgeyBhdmFpbGFibGVfaXRlbXM6IDQsIHZhbHVlX29wdGlvbl8yNGg6IFwiMTQ6MDAgLSAxNjowMFwiLCBkYXRlX3NxbF9rZXk6IFwiMjAyNC0wNS0xOVwiLCDigKYgfVxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1NzYwMF82NDgwMDogT2JqZWN0IHsgYXZhaWxhYmxlX2l0ZW1zOiA0LCB2YWx1ZV9vcHRpb25fMjRoOiBcIjE2OjAwIC0gMTg6MDBcIiwgZGF0ZV9zcWxfa2V5OiBcIjIwMjQtMDUtMTlcIiwg4oCmIH1cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNjQ4MDBfNzIwMDA6IE9iamVjdCB7IGF2YWlsYS4uLlxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgXVxyXG4gICAgICogICAgICAgICAgXVxyXG4gICAgICovXHJcbiAgICB2YXIgYXZhaWxhYmxlX2l0ZW1zX2FyciA9IHdwYmNfZ2V0X19hdmFpbGFibGVfaXRlbXNfZm9yX3NlbGVjdGVkX2RhdGV0aW1lKCByZXNvdXJjZV9pZCApO1xyXG5cclxuICAgIHZhciBpc19mdWxsX2RheV9ib29raW5nID0gdHJ1ZTtcclxuICAgIGZvciAoIHZhciBvYmpfZGF0ZV90YWcgaW4gYXZhaWxhYmxlX2l0ZW1zX2FyciApe1xyXG5cclxuICAgICAgICBpZiAoIE9iamVjdC5rZXlzKCBhdmFpbGFibGVfaXRlbXNfYXJyWyBvYmpfZGF0ZV90YWcgXSApLmxlbmd0aCA+IDEgKXtcclxuICAgICAgICAgICAgaXNfZnVsbF9kYXlfYm9va2luZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgICAgZm9yICggdmFyIHRpbWVfa2V5IGluIGF2YWlsYWJsZV9pdGVtc19hcnJbIG9ial9kYXRlX3RhZyBdICl7XHJcbiAgICAgICAgICAgIGlmICggKGF2YWlsYWJsZV9pdGVtc19hcnJbIG9ial9kYXRlX3RhZyBdWyB0aW1lX2tleSBdWyAndGltZXNfYXNfc2Vjb25kcycgXVsgMCBdID4gMCkgJiYgKGF2YWlsYWJsZV9pdGVtc19hcnJbIG9ial9kYXRlX3RhZyBdWyB0aW1lX2tleSBdWyAndGltZXNfYXNfc2Vjb25kcycgXVsgMSBdIDwgODY0MDApICl7XHJcbiAgICAgICAgICAgICAgICBpc19mdWxsX2RheV9ib29raW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoICFpc19mdWxsX2RheV9ib29raW5nICl7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHZhciBjc3NfaXNfZnVsbF9kYXlfYm9va2luZyA9IChpc19mdWxsX2RheV9ib29raW5nKSA/ICcgd3BiY19jaGludF9fZnVsbF9kYXlfYm9va2luZ3MnIDogJyc7XHJcblxyXG4gICAgdmFyIHRvb2x0aXBfaGludCA9ICc8ZGl2IGNsYXNzPVwid3BiY19jYXBhY2l0eV9oaW50X2NvbnRhaW5lcicgKyBjc3NfaXNfZnVsbF9kYXlfYm9va2luZyArICdcIj4nO1xyXG5cclxuICAgIGZvciAoIHZhciBvYmpfZGF0ZV90YWcgaW4gYXZhaWxhYmxlX2l0ZW1zX2FyciApe1xyXG5cclxuICAgICAgICB2YXIgdGltZXNsb3RzX2luX2RheSA9IGF2YWlsYWJsZV9pdGVtc19hcnJbIG9ial9kYXRlX3RhZyBdXHJcblxyXG4gICAgICAgIHRvb2x0aXBfaGludCArPSAnPGRpdiBjbGFzcz1cIndwYmNfY2hpbnRfX2RhdGV0aW1lX2NvbnRhaW5lclwiPic7XHJcblxyXG4gICAgICAgIC8vIEpTT04uc3RyaW5naWZ5KGF2YWlsYWJsZV9pdGVtc19hcnIpLm1hdGNoKC9bXlxcXFxdXCI6L2cpLmxlbmd0aFxyXG4gICAgICAgIGlmICggKE9iamVjdC5rZXlzKCBhdmFpbGFibGVfaXRlbXNfYXJyICkubGVuZ3RoID4gMSkgfHwgKGlzX2Z1bGxfZGF5X2Jvb2tpbmcpICl7XHJcbiAgICAgICAgICAgIHRvb2x0aXBfaGludCArPSAnPGRpdiBjbGFzcz1cIndwYmNfY2hpbnRfX2RhdGVfY29udGFpbmVyXCI+JztcclxuICAgICAgICAgICAgICAgIHRvb2x0aXBfaGludCArPSAnPGRpdiBjbGFzcz1cIndwYmNfY2hpbnRfX2RhdGVcIj4nICsgb2JqX2RhdGVfdGFnICsgJzwvZGl2PiAnO1xyXG4gICAgICAgICAgICAgICAgdG9vbHRpcF9oaW50ICs9ICc8ZGl2IGNsYXNzPVwid3BiY19jaGludF9fZGF0ZV9kaXZpZGVyXCI+OjwvZGl2PiAnO1xyXG4gICAgICAgICAgICB0b29sdGlwX2hpbnQgKz0gJzwvZGl2PiAnO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yICggdmFyIHRpbWVfa2V5IGluIHRpbWVzbG90c19pbl9kYXkgKXtcclxuICAgICAgICAgICAgICAgIHRvb2x0aXBfaGludCArPSAnPGRpdiBjbGFzcz1cIndwYmNfY2hpbnRfX3RpbWVfY29udGFpbmVyXCI+JztcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBJZiBub3QgZnVsbCBkYXkgYm9va2luZzogZS5nICAwMDowMCAtIDI0OjAwXHJcbiAgICAgICAgICAgICAgICAvL2lmICggKHRpbWVzbG90c19pbl9kYXlbIHRpbWVfa2V5IF1bICd0aW1lc19hc19zZWNvbmRzJyBdWyAwIF0gPiAwKSAmJiAodGltZXNsb3RzX2luX2RheVsgdGltZV9rZXkgXVsgJ3RpbWVzX2FzX3NlY29uZHMnIF1bIDEgXSA8IDg2NDAwKSApe1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgdG9vbHRpcF9oaW50ICs9ICc8ZGl2IGNsYXNzPVwid3BiY19jaGludF9fdGltZXNsb3QgJyArIHRpbWVzbG90c19pbl9kYXlbIHRpbWVfa2V5IF1bICdjc3NfY2xhc3MnIF0gKyAnXCI+J1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyB0aW1lc2xvdHNfaW5fZGF5WyB0aW1lX2tleSBdWyAncmVhZGFibGVfdGltZScgXVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgJzwvZGl2PiAnO1xyXG4gICAgICAgICAgICAgICAgICAgIHRvb2x0aXBfaGludCArPSAnPGRpdiBjbGFzcz1cIndwYmNfY2hpbnRfX3RpbWVzbG90X2RpdmlkZXJcIj46IDwvZGl2PiAnO1xyXG4gICAgICAgICAgICAgICAgLy99XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHRvb2x0aXBfaGludCArPSAnPGRpdiBjbGFzcz1cIndwYmNfY2hpbnRfX2F2YWlsYWJpbGl0eSBhdmFpbGFiaWxpdHlfbnVtXycgKyB0aW1lc2xvdHNfaW5fZGF5WyB0aW1lX2tleSBdWyAnYXZhaWxhYmxlX2l0ZW1zJyBdICsgJ1wiPidcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgdGltZXNsb3RzX2luX2RheVsgdGltZV9rZXkgXVsgJ2F2YWlsYWJsZV9pdGVtcycgXVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAnPC9kaXY+ICc7XHJcbiAgICAgICAgICAgICAgICB0b29sdGlwX2hpbnQgKz0gJzwvZGl2PiAnO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0b29sdGlwX2hpbnQgKz0gJzwvZGl2PiAnO1xyXG4gICAgfVxyXG5cclxuICAgIHRvb2x0aXBfaGludCArPSAnPC9kaXY+ICc7XHJcblxyXG5cclxuLy9jb25zb2xlLmxvZyggJzo6IGF2YWlsYWJsZV9pdGVtc19hcnIgOjonLCBhdmFpbGFibGVfaXRlbXNfYXJyICk7XHJcblxyXG5cclxuICAgIGpRdWVyeSggJy5jYXBhY2l0eV9oaW50XycgKyByZXNvdXJjZV9pZCApLmh0bWwoIHRvb2x0aXBfaGludCApO1xyXG5cclxuICAgIGpRdWVyeSggJy5jYXBhY2l0eV9oaW50XycgKyByZXNvdXJjZV9pZCApLnJlbW92ZUNsYXNzKCAnd3BiY19jaGluX25ld2xpbmUnICk7XHJcbiAgICBpZiAoIE9iamVjdC5rZXlzKCBhdmFpbGFibGVfaXRlbXNfYXJyICkubGVuZ3RoID4gMSApe1xyXG4gICAgICAgIGpRdWVyeSggJy5jYXBhY2l0eV9oaW50XycgKyByZXNvdXJjZV9pZCApLmFkZENsYXNzKCAnd3BiY19jaGluX25ld2xpbmUnICk7XHJcbiAgICB9XHJcbn1cclxuXHJcblxyXG4gICAgLy8gUnVuIHNob3J0Y29kZSBjaGFuZ2luZyBhZnRlciAgZGF0ZXMgc2VsZWN0aW9uLCAgYW5kIG9wdGlvbnMgc2VsZWN0aW9uLlxyXG4gICAgalF1ZXJ5KCBkb2N1bWVudCApLnJlYWR5KCBmdW5jdGlvbiAoKXtcclxuICAgICAgICBqUXVlcnkoICcuYm9va2luZ19mb3JtX2RpdicgKS5vbiggJ3dwYmNfYm9va2luZ19kYXRlX29yX29wdGlvbl9zZWxlY3RlZCcsIGZ1bmN0aW9uICggZXZlbnQsIHJlc291cmNlX2lkICl7XHJcbiAgICAgICAgICAgIHdwYmNfdXBkYXRlX2NhcGFjaXR5X2hpbnQoIHJlc291cmNlX2lkICk7XHJcbiAgICAgICAgfSApO1xyXG5cclxuICAgIH0gKTtcclxuIl0sImZpbGUiOiJpbmMvanMvX291dC9jYXBhY2l0eV9oaW50cy5qcyJ9;
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/inc/gateways/ideal/iDEAL.js?ver=9.8.12 
function wpbc_pay_via_ideal( booking_resource_id ){
    
    // Get Values
    var wpbc_ideal_obj = {
                              'payment' : jQuery( '#ideal_' + booking_resource_id + ' select[name="ideal_payment"]' ).find( ':selected' ).val()
                            , 'issuerid' : jQuery( '#ideal_' + booking_resource_id + ' select[name="ideal_issuerid"]' ).find( ':selected' ).val()
                            , 'purchaseid' : jQuery( '#ideal_' + booking_resource_id + ' input[name="purchaseid"]' ).val()
                            , 'description' : jQuery( '#ideal_' + booking_resource_id + ' input[name="description"]' ).val()
                            , 'amount' : jQuery( '#ideal_' + booking_resource_id + ' input[name="amount"]' ).val()
                            , 'ideal_nonce' : jQuery( '#ideal_' + booking_resource_id + ' input[name="ideal_nonce"]' ).val()
                        };

    jQuery( '#ideal_' + booking_resource_id + ' .wpbc_ideal_payment_table').html( '<span class="glyphicon glyphicon-refresh wpbc_spin"></span> &nbsp Processing...' );      // '<div style="height:20px;width:100%;text-align:center;margin:15px auto;">Loading ... <img style="vertical-align:middle;box-shadow:none;width:14px;" src="'+wpdev_bk_plugin_url+'/assets/img/ajax-loader.gif"><//div>'
    
// console.log( wpbc_ideal_obj );
    
    jQuery.ajax({                                       
        url: wpbc_ajaxurl, 
        type:'POST',                                                            
        success: function ( data, textStatus ){                                 // Note,  here we direct show HTML to TimeLine frame
                    if( textStatus == 'success') {
                        jQuery( '#ideal_' + booking_resource_id + ' .wpbc_ideal_ajax_response' ).html( data ); 
                        return true;
                    }
                },
        error:  function ( XMLHttpRequest, textStatus, errorThrown){ 
                    console.log( 'Ajax Error! Status: ' + textStatus );
                    alert( 'Ajax Error! Status: ' + XMLHttpRequest.status + ' ' + XMLHttpRequest.statusText );
                },
        // beforeSend: someFunction,
        data:{
                action:             'WPBC_PAY_VIA_iDEAL',
                ideal_obj:          wpbc_ideal_obj,
                wpdev_active_locale:wpbc_active_locale,
                wpbc_nonce:         document.getElementById('wpbc_nonce_' + 'ideal_' + booking_resource_id ).value 
        }
    });     
    
};
// source --> https://www.bbzeevantijddomburg.nl/wp-content/plugins/booking.bl.9.8.12/core/timeline/v2/_out/timeline_v2.js?ver=9.8.12 
"use strict";

function wpbc_flextimeline_nav(timeline_obj, nav_step) {
  jQuery(".wpbc_timeline_front_end").trigger("timeline_nav", [timeline_obj, nav_step]); //FixIn:7.0.1.48
  // jQuery( '#'+timeline_obj.html_client_id + ' .wpbc_tl_prev,#'+timeline_obj.html_client_id + ' .wpbc_tl_next').remove();
  // jQuery('#'+timeline_obj.html_client_id + ' .wpbc_tl_title').html( '<span class="glyphicon glyphicon-refresh wpbc_spin"></span> &nbsp Loading...' );      // '<div style="height:20px;width:100%;text-align:center;margin:15px auto;">Loading ... <img style="vertical-align:middle;box-shadow:none;width:14px;" src="'+wpdev_bk_plugin_url+'/assets/img/ajax-loader.gif"><//div>'

  jQuery('#' + timeline_obj.html_client_id + ' .flex_tl_prev,#' + timeline_obj.html_client_id + ' .flex_tl_next').remove();
  jQuery('#' + timeline_obj.html_client_id + ' .flex_tl_title').html('<span class="glyphicon glyphicon-refresh wpbc_spin"></span> &nbsp Loading...'); // '<div style="height:20px;width:100%;text-align:center;margin:15px auto;">Loading ... <img style="vertical-align:middle;box-shadow:none;width:14px;" src="'+wpdev_bk_plugin_url+'/assets/img/ajax-loader.gif"><//div>'
  //Deprecated: FixIn: 9.0.1.1.1
  // if ( 'function' === typeof( jQuery(".popover_click.popover_bottom" ).popover )  )       //FixIn: 7.0.1.2  - 2016-12-10
  //     jQuery('.popover_click.popover_bottom').popover( 'hide' );                      //Hide all opned popovers

  jQuery.ajax({
    url: wpbc_ajaxurl,
    type: 'POST',
    success: function success(data, textStatus) {
      // Note,  here we direct show HTML to TimeLine frame
      if (textStatus == 'success') {
        jQuery('#' + timeline_obj.html_client_id + ' .wpbc_timeline_ajax_replace').html(data);
        return true;
      }
    },
    error: function error(XMLHttpRequest, textStatus, errorThrown) {
      window.status = 'Ajax Error! Status: ' + textStatus;
      alert('Ajax Error! Status: ' + XMLHttpRequest.status + ' ' + XMLHttpRequest.statusText);
    },
    // beforeSend: someFunction,
    data: {
      action: 'WPBC_FLEXTIMELINE_NAV',
      timeline_obj: timeline_obj,
      nav_step: nav_step,
      wpdev_active_locale: wpbc_active_locale,
      wpbc_nonce: document.getElementById('wpbc_nonce_' + timeline_obj.html_client_id).value
    }
  });
}
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvcmUvdGltZWxpbmUvdjIvX3NyYy90aW1lbGluZV92Mi5qcyJdLCJuYW1lcyI6WyJ3cGJjX2ZsZXh0aW1lbGluZV9uYXYiLCJ0aW1lbGluZV9vYmoiLCJuYXZfc3RlcCIsImpRdWVyeSIsInRyaWdnZXIiLCJodG1sX2NsaWVudF9pZCIsInJlbW92ZSIsImh0bWwiLCJhamF4IiwidXJsIiwid3BiY19hamF4dXJsIiwidHlwZSIsInN1Y2Nlc3MiLCJkYXRhIiwidGV4dFN0YXR1cyIsImVycm9yIiwiWE1MSHR0cFJlcXVlc3QiLCJlcnJvclRocm93biIsIndpbmRvdyIsInN0YXR1cyIsImFsZXJ0Iiwic3RhdHVzVGV4dCIsImFjdGlvbiIsIndwZGV2X2FjdGl2ZV9sb2NhbGUiLCJ3cGJjX2FjdGl2ZV9sb2NhbGUiLCJ3cGJjX25vbmNlIiwiZG9jdW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsInZhbHVlIl0sIm1hcHBpbmdzIjoiOztBQUNBLFNBQVNBLHFCQUFULENBQWdDQyxZQUFoQyxFQUE4Q0MsUUFBOUMsRUFBd0Q7QUFFcERDLEVBQUFBLE1BQU0sQ0FBRSwwQkFBRixDQUFOLENBQXFDQyxPQUFyQyxDQUE4QyxjQUE5QyxFQUErRCxDQUFFSCxZQUFGLEVBQWdCQyxRQUFoQixDQUEvRCxFQUZvRCxDQUVnRDtBQUVwRztBQUNBOztBQUVBQyxFQUFBQSxNQUFNLENBQUUsTUFBSUYsWUFBWSxDQUFDSSxjQUFqQixHQUFrQyxrQkFBbEMsR0FBcURKLFlBQVksQ0FBQ0ksY0FBbEUsR0FBbUYsZ0JBQXJGLENBQU4sQ0FBNkdDLE1BQTdHO0FBQ0FILEVBQUFBLE1BQU0sQ0FBQyxNQUFJRixZQUFZLENBQUNJLGNBQWpCLEdBQWtDLGlCQUFuQyxDQUFOLENBQTRERSxJQUE1RCxDQUFrRSw4RUFBbEUsRUFSb0QsQ0FRcUc7QUFHN0o7QUFDQTtBQUNBOztBQUVJSixFQUFBQSxNQUFNLENBQUNLLElBQVAsQ0FBWTtBQUNSQyxJQUFBQSxHQUFHLEVBQUVDLFlBREc7QUFFUkMsSUFBQUEsSUFBSSxFQUFDLE1BRkc7QUFHUkMsSUFBQUEsT0FBTyxFQUFFLGlCQUFXQyxJQUFYLEVBQWlCQyxVQUFqQixFQUE2QjtBQUFrQztBQUM1RCxVQUFJQSxVQUFVLElBQUksU0FBbEIsRUFBNkI7QUFDekJYLFFBQUFBLE1BQU0sQ0FBQyxNQUFNRixZQUFZLENBQUNJLGNBQW5CLEdBQW9DLDhCQUFyQyxDQUFOLENBQTRFRSxJQUE1RSxDQUFrRk0sSUFBbEY7QUFDQSxlQUFPLElBQVA7QUFDSDtBQUNKLEtBUkQ7QUFTUkUsSUFBQUEsS0FBSyxFQUFHLGVBQVdDLGNBQVgsRUFBMkJGLFVBQTNCLEVBQXVDRyxXQUF2QyxFQUFtRDtBQUMvQ0MsTUFBQUEsTUFBTSxDQUFDQyxNQUFQLEdBQWdCLHlCQUF5QkwsVUFBekM7QUFDQU0sTUFBQUEsS0FBSyxDQUFFLHlCQUF5QkosY0FBYyxDQUFDRyxNQUF4QyxHQUFpRCxHQUFqRCxHQUF1REgsY0FBYyxDQUFDSyxVQUF4RSxDQUFMO0FBQ0gsS0FaRDtBQWFSO0FBQ0FSLElBQUFBLElBQUksRUFBQztBQUNHUyxNQUFBQSxNQUFNLEVBQWMsdUJBRHZCO0FBRUdyQixNQUFBQSxZQUFZLEVBQVFBLFlBRnZCO0FBR0dDLE1BQUFBLFFBQVEsRUFBWUEsUUFIdkI7QUFJR3FCLE1BQUFBLG1CQUFtQixFQUFDQyxrQkFKdkI7QUFLR0MsTUFBQUEsVUFBVSxFQUFVQyxRQUFRLENBQUNDLGNBQVQsQ0FBd0IsZ0JBQWUxQixZQUFZLENBQUNJLGNBQXBELEVBQW9FdUI7QUFMM0Y7QUFkRyxHQUFaO0FBc0JIIiwic291cmNlc0NvbnRlbnQiOlsiXHJcbmZ1bmN0aW9uIHdwYmNfZmxleHRpbWVsaW5lX25hdiggdGltZWxpbmVfb2JqLCBuYXZfc3RlcCApe1xyXG5cclxuICAgIGpRdWVyeSggXCIud3BiY190aW1lbGluZV9mcm9udF9lbmRcIiApLnRyaWdnZXIoIFwidGltZWxpbmVfbmF2XCIgLCBbIHRpbWVsaW5lX29iaiwgbmF2X3N0ZXAgXSApOyAgICAgICAgLy9GaXhJbjo3LjAuMS40OFxyXG5cclxuICAgIC8vIGpRdWVyeSggJyMnK3RpbWVsaW5lX29iai5odG1sX2NsaWVudF9pZCArICcgLndwYmNfdGxfcHJldiwjJyt0aW1lbGluZV9vYmouaHRtbF9jbGllbnRfaWQgKyAnIC53cGJjX3RsX25leHQnKS5yZW1vdmUoKTtcclxuICAgIC8vIGpRdWVyeSgnIycrdGltZWxpbmVfb2JqLmh0bWxfY2xpZW50X2lkICsgJyAud3BiY190bF90aXRsZScpLmh0bWwoICc8c3BhbiBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tcmVmcmVzaCB3cGJjX3NwaW5cIj48L3NwYW4+ICZuYnNwIExvYWRpbmcuLi4nICk7ICAgICAgLy8gJzxkaXYgc3R5bGU9XCJoZWlnaHQ6MjBweDt3aWR0aDoxMDAlO3RleHQtYWxpZ246Y2VudGVyO21hcmdpbjoxNXB4IGF1dG87XCI+TG9hZGluZyAuLi4gPGltZyBzdHlsZT1cInZlcnRpY2FsLWFsaWduOm1pZGRsZTtib3gtc2hhZG93Om5vbmU7d2lkdGg6MTRweDtcIiBzcmM9XCInK3dwZGV2X2JrX3BsdWdpbl91cmwrJy9hc3NldHMvaW1nL2FqYXgtbG9hZGVyLmdpZlwiPjwvL2Rpdj4nXHJcblxyXG4gICAgalF1ZXJ5KCAnIycrdGltZWxpbmVfb2JqLmh0bWxfY2xpZW50X2lkICsgJyAuZmxleF90bF9wcmV2LCMnK3RpbWVsaW5lX29iai5odG1sX2NsaWVudF9pZCArICcgLmZsZXhfdGxfbmV4dCcpLnJlbW92ZSgpO1xyXG4gICAgalF1ZXJ5KCcjJyt0aW1lbGluZV9vYmouaHRtbF9jbGllbnRfaWQgKyAnIC5mbGV4X3RsX3RpdGxlJykuaHRtbCggJzxzcGFuIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1yZWZyZXNoIHdwYmNfc3BpblwiPjwvc3Bhbj4gJm5ic3AgTG9hZGluZy4uLicgKTsgICAgICAvLyAnPGRpdiBzdHlsZT1cImhlaWdodDoyMHB4O3dpZHRoOjEwMCU7dGV4dC1hbGlnbjpjZW50ZXI7bWFyZ2luOjE1cHggYXV0bztcIj5Mb2FkaW5nIC4uLiA8aW1nIHN0eWxlPVwidmVydGljYWwtYWxpZ246bWlkZGxlO2JveC1zaGFkb3c6bm9uZTt3aWR0aDoxNHB4O1wiIHNyYz1cIicrd3BkZXZfYmtfcGx1Z2luX3VybCsnL2Fzc2V0cy9pbWcvYWpheC1sb2FkZXIuZ2lmXCI+PC8vZGl2PidcclxuXHJcblxyXG4vL0RlcHJlY2F0ZWQ6IEZpeEluOiA5LjAuMS4xLjFcclxuLy8gaWYgKCAnZnVuY3Rpb24nID09PSB0eXBlb2YoIGpRdWVyeShcIi5wb3BvdmVyX2NsaWNrLnBvcG92ZXJfYm90dG9tXCIgKS5wb3BvdmVyICkgICkgICAgICAgLy9GaXhJbjogNy4wLjEuMiAgLSAyMDE2LTEyLTEwXHJcbi8vICAgICBqUXVlcnkoJy5wb3BvdmVyX2NsaWNrLnBvcG92ZXJfYm90dG9tJykucG9wb3ZlciggJ2hpZGUnICk7ICAgICAgICAgICAgICAgICAgICAgIC8vSGlkZSBhbGwgb3BuZWQgcG9wb3ZlcnNcclxuXHJcbiAgICBqUXVlcnkuYWpheCh7XHJcbiAgICAgICAgdXJsOiB3cGJjX2FqYXh1cmwsXHJcbiAgICAgICAgdHlwZTonUE9TVCcsXHJcbiAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKCBkYXRhLCB0ZXh0U3RhdHVzICl7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90ZSwgIGhlcmUgd2UgZGlyZWN0IHNob3cgSFRNTCB0byBUaW1lTGluZSBmcmFtZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmKCB0ZXh0U3RhdHVzID09ICdzdWNjZXNzJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBqUXVlcnkoJyMnICsgdGltZWxpbmVfb2JqLmh0bWxfY2xpZW50X2lkICsgJyAud3BiY190aW1lbGluZV9hamF4X3JlcGxhY2UnICkuaHRtbCggZGF0YSApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAgZnVuY3Rpb24gKCBYTUxIdHRwUmVxdWVzdCwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pe1xyXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zdGF0dXMgPSAnQWpheCBFcnJvciEgU3RhdHVzOiAnICsgdGV4dFN0YXR1cztcclxuICAgICAgICAgICAgICAgICAgICBhbGVydCggJ0FqYXggRXJyb3IhIFN0YXR1czogJyArIFhNTEh0dHBSZXF1ZXN0LnN0YXR1cyArICcgJyArIFhNTEh0dHBSZXF1ZXN0LnN0YXR1c1RleHQgKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgLy8gYmVmb3JlU2VuZDogc29tZUZ1bmN0aW9uLFxyXG4gICAgICAgIGRhdGE6e1xyXG4gICAgICAgICAgICAgICAgYWN0aW9uOiAgICAgICAgICAgICAnV1BCQ19GTEVYVElNRUxJTkVfTkFWJyxcclxuICAgICAgICAgICAgICAgIHRpbWVsaW5lX29iajogICAgICAgdGltZWxpbmVfb2JqLFxyXG4gICAgICAgICAgICAgICAgbmF2X3N0ZXA6ICAgICAgICAgICBuYXZfc3RlcCxcclxuICAgICAgICAgICAgICAgIHdwZGV2X2FjdGl2ZV9sb2NhbGU6d3BiY19hY3RpdmVfbG9jYWxlLFxyXG4gICAgICAgICAgICAgICAgd3BiY19ub25jZTogICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnd3BiY19ub25jZV8nKyB0aW1lbGluZV9vYmouaHRtbF9jbGllbnRfaWQpLnZhbHVlXHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcbn1cclxuXHJcbiJdLCJmaWxlIjoiY29yZS90aW1lbGluZS92Mi9fb3V0L3RpbWVsaW5lX3YyLmpzIn0=;