/* === storage/rsx-tmp/npm_import_declarations_95a6f602c98037611b640b0b5342830b.js === */ // NPM Import Declarations for App Bundle // Auto-generated to provide NPM modules to app bundle scope // Cache key: 95a6f602c98037611b640b0b5342830b const jqhtml = window._rsx_npm.jqhtml; if (!jqhtml) { throw new Error( 'RSX Framework Error: NPM module "jqhtml" not found.\n' + 'Expected window._rsx_npm.jqhtml to be defined by the vendor bundle.' ); } const _Base_Jqhtml_Component = window._rsx_npm._Base_Jqhtml_Component; if (!_Base_Jqhtml_Component) { throw new Error( 'RSX Framework Error: NPM module "_Base_Jqhtml_Component" not found.\n' + 'Expected window._rsx_npm._Base_Jqhtml_Component to be defined by the vendor bundle.' ); } // Clean up NPM container to prevent console access delete window._rsx_npm; /* === app/RSpade/Core/Js/decorator.js (babel) === */ "use strict"; /** * Decorator function that marks a function as a decorator implementation. * * When a function has @decorator in its JSDoc comment, it whitelists that function * to be used as a decorator on other methods throughout the codebase. * * The function itself performs no operation - it simply returns its input unchanged. * Its purpose is purely as a marker for the manifest validation system. * * Usage: * // /** * // * My custom decorator implementation * // * @decorator * // *\/ * function my_custom_decorator(target, key, descriptor) { * // Decorator implementation * } * * This allows my_custom_decorator to be used as @my_custom_decorator on static methods. * * TODO: This is probably no longer necessary? maybe? */ function decorator(value) { return value; } /* === app/RSpade/Core/Js/browser.js (babel) === */ "use strict"; /* * Browser and DOM utility functions for the RSpade framework. * These functions handle browser detection, viewport utilities, and DOM manipulation. */ // ============================================================================ // BROWSER DETECTION // ============================================================================ /** * Detects if user is on a mobile device or using mobile viewport * @returns {boolean} True if mobile device or viewport < 992px * @todo Improve user agent detection for all mobile devices */ function is_mobile() { if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { return true; } else if ($(window).width() < 992) { // 992px = bootstrap 4 col-md- return true; } else { return false; } } /** * Detects if user is on desktop (not mobile) * @returns {boolean} True if not mobile device/viewport */ function is_desktop() { return !is_mobile(); } /** * Detects the user's operating system * @returns {string} OS name: 'Mac OS', 'iPhone', 'iPad', 'Windows', 'Android-Phone', 'Android-Tablet', 'Linux', or 'Unknown' */ function get_os() { let user_agent = window.navigator.userAgent, platform = window.navigator.platform, macos_platforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], windows_platforms = ['Win32', 'Win64', 'Windows', 'WinCE'], ios_platforms = ['iPhone', 'iPad', 'iPod'], os = null; let is_mobile_device = is_mobile(); if (macos_platforms.indexOf(platform) !== -1) { os = 'Mac OS'; } else if (ios_platforms.indexOf(platform) !== -1 && is_mobile_device) { os = 'iPhone'; } else if (ios_platforms.indexOf(platform) !== -1 && !is_mobile_device) { os = 'iPad'; } else if (windows_platforms.indexOf(platform) !== -1) { os = 'Windows'; } else if (/Android/.test(user_agent) && is_mobile_device) { os = 'Android-Phone'; } else if (/Android/.test(user_agent) && !is_mobile_device) { os = 'Android-Tablet'; } else if (!os && /Linux/.test(platform)) { os = 'Linux'; } else { os = 'Unknown'; } return os; } /** * Detects if the user agent is a web crawler/bot * @returns {boolean} True if user agent appears to be a bot/crawler */ function is_crawler() { let user_agent = navigator.userAgent; let bot_pattern = /bot|spider|crawl|slurp|archiver|ping|search|dig|tracker|monitor|snoopy|yahoo|baidu|msn|ask|teoma|axios/i; return bot_pattern.test(user_agent); } // ============================================================================ // DOM SCROLLING UTILITIES // ============================================================================ /** * Scrolls parent container to make target element visible if needed * @param {string|HTMLElement|jQuery} target - Target element to scroll into view */ function scroll_into_view_if_needed(target) { const $target = $(target); // Find the closest parent with overflow-y: auto const $parent = $target.parent(); // Calculate the absolute top position of the target const target_top = $target.position().top + $parent.scrollTop(); const target_height = $target.outerHeight(); const parent_height = $parent.height(); const scroll_position = $parent.scrollTop(); // Check if the target is out of view if (target_top < scroll_position || target_top + target_height > scroll_position + parent_height) { Debugger.console_debug('UI', 'Scrolling!', target_top); // Calculate the new scroll position to center the target let new_scroll_position = target_top + target_height / 2 - parent_height / 2; // Limit the scroll position between 0 and the maximum scrollable height new_scroll_position = Math.max(0, Math.min(new_scroll_position, $parent[0].scrollHeight - parent_height)); // Scroll the parent to the new scroll position $parent.scrollTop(new_scroll_position); } } /** * Scrolls page to make target element visible if needed (with animation) * @param {string|HTMLElement|jQuery} target - Target element to scroll into view */ function scroll_page_into_view_if_needed(target) { const $target = $(target); // Calculate the absolute top position of the target relative to the document const target_top = $target.offset().top; const target_height = $target.outerHeight(); const window_height = $(window).height(); const window_scroll_position = $(window).scrollTop(); // Check if the target is out of view if (target_top < window_scroll_position || target_top + target_height > window_scroll_position + window_height) { Debugger.console_debug('UI', 'Scrolling!', target_top); // Calculate the new scroll position to center the target const new_scroll_position = target_top + target_height / 2 - window_height / 2; // Animate the scroll to the new position $('html, body').animate({ scrollTop: new_scroll_position }, 1000); // duration of the scroll animation in milliseconds } } // ============================================================================ // DOM UTILITIES // ============================================================================ /** * Waits for all images on the page to load * @param {Function} callback - Function to call when all images are loaded */ function wait_for_images(callback) { const $images = $('img'); // Get all img tags const total_images = $images.length; let images_loaded = 0; if (total_images === 0) { callback(); // if there are no images, immediately call the callback } $images.each(function () { const img = new Image(); img.onload = function () { images_loaded++; if (images_loaded === total_images) { callback(); // call the callback when all images are loaded } }; img.onerror = function () { images_loaded++; if (images_loaded === total_images) { callback(); // also call the callback if an image fails to load } }; img.src = this.src; // this triggers the loading }); } /** * Creates a jQuery element containing a non-breaking space * @returns {jQuery} jQuery span element with   */ function $nbsp() { return $(' '); } /** * Escapes special characters in a jQuery selector * @param {string} id - Element ID to escape * @returns {string} jQuery selector string with escaped special characters * @warning Not safe for security-critical operations */ function escape_jq_selector(id) { return '#' + id.replace(/(:|\.|\[|\]|,|=|@)/g, '\\$1'); } /* === app/RSpade/Core/Js/datetime.js (babel) === */ "use strict"; /* * Date and time utility functions for the RSpade framework. * These functions handle date/time conversions and Unix timestamps. */ // ============================================================================ // DATE/TIME UTILITIES // ============================================================================ /** * Gets the current Unix timestamp (seconds since epoch) * @returns {number} Current Unix timestamp in seconds * @todo Calculate based on server time at page render * @todo Move to a date library */ function unix_time() { return Math.round(new Date().getTime() / 1000); } /** * Converts a date string to Unix timestamp * @param {string} str_date - Date string (Y-m-d H:i:s format) * @returns {number} Unix timestamp in seconds */ function ymdhis_to_unix(str_date) { const date = new Date(str_date); return date.getTime() / 1000; } /* === app/RSpade/Core/Js/error.js (babel) === */ "use strict"; /* * Error handling utility functions for the RSpade framework. * These functions handle error creation and debugging utilities. */ // ============================================================================ // ERROR HANDLING // ============================================================================ /** * Creates an error object from a string * @param {string|Object} str - Error message or existing error object * @param {number} [error_code] - Optional error status code * @returns {Object} Error object with error and status properties */ function error(str, error_code) { if (typeof str.error != undef) { return str; } else { if (typeof error_code == undef) { return { error: str, status: null }; } else { return { error: str, status: error_code }; } } } /** * Sanity check failure handler for JavaScript * * This function should be called when a sanity check fails - i.e., when the code * encounters a condition that "shouldn't happen" if everything is working correctly. * * Unlike PHP, we can't stop JavaScript execution, but we can: * 1. Throw an error that will be caught by error handlers * 2. Log a clear error to the console * 3. Provide stack trace for debugging * * Use this instead of silently returning or continuing when encountering unexpected conditions. * * @param {string} message Optional specific message about what shouldn't have happened * @throws {Error} Always throws with location and context information */ function shouldnt_happen() { let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; const error = new Error(); const stack = error.stack || ''; const stackLines = stack.split('\n'); // Get the caller location (skip the Error line and this function) let callerInfo = 'unknown location'; if (stackLines.length > 2) { const callerLine = stackLines[2] || stackLines[1] || ''; // Extract file and line number from stack trace const match = callerLine.match(/at\s+.*?\s+\((.*?):(\d+):(\d+)\)/) || callerLine.match(/at\s+(.*?):(\d+):(\d+)/); if (match) { callerInfo = `${match[1]}:${match[2]}`; } } let errorMessage = `Fatal: shouldnt_happen() was called at ${callerInfo}\n`; errorMessage += 'This indicates a sanity check failed - the code is not behaving as expected.\n'; if (message) { errorMessage += `Details: ${message}\n`; } errorMessage += 'Please thoroughly review the related code to determine why this error occurred.'; // Log to console with full visibility console.error('='.repeat(80)); console.error('SANITY CHECK FAILURE'); console.error('='.repeat(80)); console.error(errorMessage); console.error('Stack trace:', stack); console.error('='.repeat(80)); // Throw error to stop execution flow const fatalError = new Error(errorMessage); fatalError.name = 'SanityCheckFailure'; throw fatalError; } /* === app/RSpade/Core/Js/hash.js (babel) === */ "use strict"; /* * Hashing and comparison utility functions for the RSpade framework. * These functions handle object hashing and deep comparison. */ // ============================================================================ // HASHING AND COMPARISON // ============================================================================ /** * Generates a unique hash for any value (handles objects, arrays, circular references) * @param {*} the_var - Value to hash * @param {boolean} [calc_sha1=true] - If true, returns SHA1 hash; if false, returns JSON * @param {Array} [ignored_keys=null] - Keys to ignore when hashing objects * @returns {string} SHA1 hash or JSON string of the value */ function hash(the_var) { let calc_sha1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; let ignored_keys = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; if (typeof the_var == undef) { the_var = '__undefined__'; } if (ignored_keys === null) { ignored_keys = ['$']; } // Converts value to json, discarding circular references let json_stringify_nocirc = function (value) { const cache = []; return JSON.stringify(value, function (key, v) { if (typeof v === 'object' && typeof the_var._cache_key == 'function') { return the_var._hash_key(); } else if (typeof v === 'object' && v !== null) { if (cache.indexOf(v) !== -1) { // Duplicate reference found, discard key return; } cache.push(v); } return v; }); }; // Turn every property and all its children into a single depth array of values that we can then // sort and hash as a whole let flat_var = {}; let _flatten = function (the_var, prefix) { let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; // If a class object is provided, circular references can make the call stack recursive. // For the purposes of how the hash function is called, this should be sufficient. if (depth > 10) { return; } // Does not account for dates i think... if (is_object(the_var) && typeof the_var._cache_key == 'function') { // Use _cache_key to hash components flat_var[prefix] = the_var._hash_key(); } else if (is_object(the_var) && typeof Abstract !== 'undefined' && the_var instanceof Abstract) { // Stringify all class objects flat_var[prefix] = json_stringify_nocirc(the_var); } else if (is_object(the_var)) { // Iterate other objects flat_var[prefix] = {}; for (let k in the_var) { if (the_var.hasOwnProperty(k) && ignored_keys.indexOf(k) == -1) { _flatten(the_var[k], prefix + '..' + k, depth + 1); } } } else if (is_array(the_var)) { // Iterate arrays flat_var[prefix] = []; let i = 0; foreach(the_var, v => { _flatten(v, prefix + '..' + i, depth + 1); i++; }); } else if (is_function(the_var)) { // nothing } else if (!is_numeric(the_var)) { flat_var[prefix] = String(the_var); } else { flat_var[prefix] = the_var; } }; _flatten(the_var, '_'); let sorter = []; foreach(flat_var, function (v, k) { sorter.push([k, v]); }); sorter.sort(function (a, b) { return a[0] > b[0]; }); let json = JSON.stringify(sorter); if (calc_sha1) { let hashed = sha1.sha1(json); return hashed; } else { return json; } } /** * Deep comparison of two values (ignores property order and functions) * @param {*} a - First value to compare * @param {*} b - Second value to compare * @returns {boolean} True if values are deeply equal */ function deep_equal(a, b) { return hash(a, false) == hash(b, false); } /* === app/RSpade/Core/Js/Mutex.js (babel) === */ "use strict"; /** * Mutex decorator for exclusive method execution * * Without arguments: Per-instance locking (each object has its own lock per method) * @mutex * async my_method() { ... } * * With ID argument: Global locking by ID (all instances share the lock) * @mutex('operation_name') * async my_method() { ... } * * @decorator * @param {string} [global_id] - Optional global mutex ID for cross-instance locking */ function mutex(global_id) { // Storage (using IIFEs to keep WeakMap/Map in closure scope) const instance_mutexes = function () { if (!mutex._instance_storage) { mutex._instance_storage = new WeakMap(); } return mutex._instance_storage; }(); const global_mutexes = function () { if (!mutex._global_storage) { mutex._global_storage = new Map(); } return mutex._global_storage; }(); /** * Get or create a mutex for a specific instance and method */ function get_instance_mutex(instance, method_name) { let instance_locks = instance_mutexes.get(instance); if (!instance_locks) { instance_locks = new Map(); instance_mutexes.set(instance, instance_locks); } let lock_state = instance_locks.get(method_name); if (!lock_state) { lock_state = { active: false, queue: [] }; instance_locks.set(method_name, lock_state); } return lock_state; } /** * Get or create a global mutex by ID */ function get_global_mutex(id) { let lock_state = global_mutexes.get(id); if (!lock_state) { lock_state = { active: false, queue: [] }; global_mutexes.set(id, lock_state); } return lock_state; } /** * Execute the next queued operation for a mutex */ function schedule_next(lock_state) { if (lock_state.active || lock_state.queue.length === 0) { return; } const { fn, resolve, reject } = lock_state.queue.shift(); lock_state.active = true; Promise.resolve().then(fn).then(resolve, reject).finally(() => { lock_state.active = false; schedule_next(lock_state); }); } /** * Acquire a mutex lock and execute callback */ function acquire_lock(lock_state, fn) { return new Promise((resolve, reject) => { lock_state.queue.push({ fn, resolve, reject }); schedule_next(lock_state); }); } // If called with an ID argument: @mutex('id') if (typeof global_id === 'string') { return function (target, key, descriptor) { const original_method = descriptor.value; if (typeof original_method !== 'function') { throw new Error(`@mutex can only be applied to methods (tried to apply to ${key})`); } descriptor.value = function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } const lock_state = get_global_mutex(global_id); return acquire_lock(lock_state, () => original_method.apply(this, args)); }; return descriptor; }; } // If called without arguments: @mutex (target is the first argument) const target = global_id; // In this case, first arg is target const key = arguments[1]; const descriptor = arguments[2]; const original_method = descriptor.value; if (typeof original_method !== 'function') { throw new Error(`@mutex can only be applied to methods (tried to apply to ${key})`); } descriptor.value = function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } const lock_state = get_instance_mutex(this, key); return acquire_lock(lock_state, () => original_method.apply(this, args)); }; return descriptor; } /* === app/RSpade/Core/Js/async.js (babel) === */ "use strict"; /* * Async utility functions for the RSpade framework. * These functions handle asynchronous operations, delays, debouncing, and mutexes. */ // ============================================================================ // ASYNC UTILITIES // ============================================================================ /** * Pauses execution for specified milliseconds * @param {number} [milliseconds=0] - Delay in milliseconds (0 uses requestAnimationFrame) * @returns {Promise} Promise that resolves after delay * @example await sleep(1000); // Wait 1 second */ function sleep() { let milliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; return new Promise(resolve => { if (milliseconds == 0 && requestAnimationFrame) { requestAnimationFrame(resolve); } else { setTimeout(resolve, milliseconds); } }); } /** * Creates a debounced function with exclusivity and promise fan-in * * This function, when invoked, immediately runs the callback exclusively. * For subsequent invocations, it applies a delay before running the callback exclusively again. * The delay starts after the current asynchronous operation resolves. * * If 'delay' is set to 0, the function will only prevent enqueueing multiple executions of the * same method more than once, but will still run them immediately in an exclusive sequential manner. * * The most recent invocation of the function will be the parameters that get passed to the function * when it invokes. * * The function returns a promise that resolves when the next exclusive execution completes. * * Usage as function: * const debouncedFn = debounce(myFunction, 250); * * Usage as decorator: * @debounce(250) * myMethod() { ... } * * @param {function|number} callback_or_delay The callback function OR delay when used as decorator * @param {number} delay The delay in milliseconds before subsequent invocations * @param {boolean} immediate if true, the first time the action is called, the callback executes immediately * @returns {function} A function that when invoked, runs the callback immediately and exclusively, * * @decorator */ function debounce(callback_or_delay, delay) { let immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; // Decorator usage: @debounce(250) or @debounce(250, true) // First argument is a number (the delay), returns decorator function if (typeof callback_or_delay === 'number') { const decorator_delay = callback_or_delay; const decorator_immediate = delay || false; // TC39 decorator form: receives (value, context) return function (value, context) { if (context.kind === 'method') { return debounce_impl(value, decorator_delay, decorator_immediate); } }; } // Function usage: debounce(fn, 250) // First argument is a function (the callback) const callback = callback_or_delay; return debounce_impl(callback, delay, immediate); } /** * Internal implementation of debounce logic * @private */ function debounce_impl(callback, delay) { let immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; let running = false; let queued = false; let last_end_time = 0; // timestamp of last completed run let timer = null; let next_args = []; let next_context = null; let resolve_queue = []; let reject_queue = []; const run_function = async () => { const these_resolves = resolve_queue; const these_rejects = reject_queue; const args = next_args; const context = next_context; resolve_queue = []; reject_queue = []; next_args = []; next_context = null; queued = false; running = true; try { const result = await callback.apply(context, args); for (const resolve of these_resolves) resolve(result); } catch (err) { for (const reject of these_rejects) reject(err); } finally { running = false; last_end_time = Date.now(); if (queued) { clearTimeout(timer); timer = setTimeout(run_function, Math.max(delay, 0)); } else { timer = null; } } }; return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } next_args = args; next_context = this; return new Promise((resolve, reject) => { resolve_queue.push(resolve); reject_queue.push(reject); // Nothing running and nothing scheduled if (!running && !timer) { const first_call = last_end_time === 0; if (immediate && first_call) { run_function(); return; } const since = first_call ? Infinity : Date.now() - last_end_time; if (since >= delay) { run_function(); } else { const wait = Math.max(delay - since, 0); clearTimeout(timer); timer = setTimeout(run_function, wait); } return; } // If we're already running or a timer exists, just mark queued. // The finally{} of run_function handles scheduling after full delay. queued = true; }); }; } // ============================================================================ // READ-WRITE LOCK FUNCTIONS - Delegated to ReadWriteLock class // ============================================================================ /** * Acquire an exclusive write lock by name. * Only one writer runs at a time; blocks readers until finished. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ function rwlock(name, cb) { return ReadWriteLock.acquire(name, cb); } /** * Acquire a shared read lock by name. * Multiple readers run in parallel, but readers are blocked by queued/active writers. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ function rwlock_read(name, cb) { return ReadWriteLock.acquire_read(name, cb); } /** * Forcefully clear all locks and queues for a given name. * @param {string} name */ function rwlock_force_unlock(name) { ReadWriteLock.force_unlock(name); } /** * Inspect lock state for debugging. * @param {string} name * @returns {{readers:number, writer_active:boolean, reader_q:number, writer_q:number}} */ function rwlock_pending(name) { return ReadWriteLock.pending(name); } /* === app/RSpade/Core/Js/functions.js (babel) === */ "use strict"; /* * Core utility functions for the RSpade framework. * These functions handle type checking, type conversion, string manipulation, * and object/array utilities. They mirror functionality from PHP functions. * * Other utility functions are organized in: * - async.js: Async utilities (sleep, debounce, mutex) * - browser.js: Browser/DOM utilities (is_mobile, scroll functions) * - datetime.js: Date/time utilities * - hash.js: Hashing and comparison * - error.js: Error handling */ // Todo: test that prod build identifies and removes uncalled functions from the final bundle. // ============================================================================ // CONSTANTS AND HELPERS // ============================================================================ // Define commonly used constants const undef = 'undefined'; /** * Iterates over arrays or objects with promise support * * Works with both synchronous and asynchronous callbacks. If the callback * returns promises, they are executed in parallel and this function returns * a promise that resolves when all parallel tasks complete. * * @param {Array|Object} obj - Collection to iterate * @param {Function} callback - Function to call for each item (value, key) - can be async * @returns {Promise|undefined} Promise if any callbacks return promises, undefined otherwise * * @example * // Synchronous usage * foreach([1,2,3], (val) => console.log(val)); * * @example * // Asynchronous usage - waits for all to complete * await foreach([1,2,3], async (val) => { * await fetch('/api/process/' + val); * }); */ function foreach(obj, callback) { const results = []; if (Array.isArray(obj)) { obj.forEach((value, index) => { results.push(callback(value, index)); }); } else if (obj && typeof obj === 'object') { for (let key in obj) { if (obj.hasOwnProperty(key)) { results.push(callback(obj[key], key)); } } } // Filter for promises const promises = results.filter(result => result && typeof result.then === 'function'); // If there are any promises, return Promise.all to wait for all to complete if (promises.length > 0) { return Promise.all(promises); } // No promises returned, so we're done return undefined; } // ============================================================================ // TYPE CHECKING FUNCTIONS // ============================================================================ /** * Checks if a value is numeric * @param {*} n - Value to check * @returns {boolean} True if the value is a finite number */ function is_numeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } /** * Checks if a value is a string * @param {*} s - Value to check * @returns {boolean} True if the value is a string */ function is_string(s) { return typeof s == 'string'; } /** * Checks if a value is an integer * @param {*} n - Value to check * @returns {boolean} True if the value is an integer */ function is_integer(n) { return Number.isInteger(n); } /** * Checks if a value is a promise-like object * @param {*} obj - Value to check * @returns {boolean} True if the value has a then method */ function is_promise(obj) { return typeof obj == 'object' && typeof obj.then == 'function'; } /** * Checks if a value is an array * @param {*} obj - Value to check * @returns {boolean} True if the value is an array */ function is_array(obj) { return Array.isArray(obj); } /** * Checks if a value is an object (excludes null) * @param {*} obj - Value to check * @returns {boolean} True if the value is an object and not null */ function is_object(obj) { return typeof obj === 'object' && obj !== null; } /** * Checks if a value is a function * @param {*} function_to_check - Value to check * @returns {boolean} True if the value is a function */ function is_function(function_to_check) { return function_to_check && {}.toString.call(function_to_check) === '[object Function]'; } /** * Checks if a string is a valid email address * Uses a practical RFC 5322 compliant regex that matches 99.99% of real-world email addresses * @param {string} email - Email address to validate * @returns {boolean} True if the string is a valid email address */ function is_email(email) { if (!is_string(email)) { return false; } const regex = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i; return regex.test(email); } /** * Checks if a value is defined (not undefined) * @param {*} value - Value to check * @returns {boolean} True if value is not undefined */ function isset(value) { return typeof value != undef; } /** * Checks if a value is empty (null, undefined, 0, "", empty array/object) * @param {*} object - Value to check * @returns {boolean} True if the value is considered empty */ function empty(object) { if (typeof object == undef) { return true; } if (object === null) { return true; } if (typeof object == 'string' && object == '') { return true; } if (typeof object == 'number') { return object == 0; } if (Array.isArray(object)) { return !object.length; } if (typeof object == 'function') { return false; } for (let key in object) { if (object.hasOwnProperty(key)) { return false; } } return true; } // ============================================================================ // TYPE CONVERSION FUNCTIONS // ============================================================================ /** * Converts a value to a floating point number * Returns 0 for null, undefined, NaN, or non-numeric values * @param {*} val - Value to convert * @returns {number} Floating point number */ function float(val) { // Handle null, undefined, empty string if (val === null || val === undefined || val === '') { return 0.0; } // Try to parse the value const parsed = parseFloat(val); // Check for NaN and return 0 if parsing failed return isNaN(parsed) ? 0.0 : parsed; } /** * Converts a value to an integer * Returns 0 for null, undefined, NaN, or non-numeric values * @param {*} val - Value to convert * @returns {number} Integer value */ function int(val) { // Handle null, undefined, empty string if (val === null || val === undefined || val === '') { return 0; } // Try to parse the value const parsed = parseInt(val, 10); // Check for NaN and return 0 if parsing failed return isNaN(parsed) ? 0 : parsed; } /** * Converts a value to a string * Returns empty string for null or undefined * @param {*} val - Value to convert * @returns {string} String representation */ function str(val) { // Handle null and undefined specially if (val === null || val === undefined) { return ''; } // Convert to string return String(val); } /** * Converts numeric strings to numbers, returns all other values unchanged * Used when you need to ensure numeric types but don't want to force * conversion of non-numeric values (which would become 0) * @param {*} val - Value to convert * @returns {*} Number if input was numeric string, otherwise unchanged */ function value_unless_numeric_string_then_numeric_value(val) { // If it's already a number, return it if (typeof val === 'number') { return val; } // If it's a string and numeric, convert it if (is_string(val) && is_numeric(val)) { // Use parseFloat to handle both integers and floats return parseFloat(val); } // Return everything else unchanged (null, objects, non-numeric strings, etc.) return val; } // ============================================================================ // STRING MANIPULATION FUNCTIONS // ============================================================================ /** * Escapes HTML special characters (uses Lodash escape) * @param {string} str - String to escape * @returns {string} HTML-escaped string */ function html(str) { return _.escape(str); } /** * Converts newlines to HTML line breaks * @param {string} str - String to convert * @returns {string} String with newlines replaced by
*/ function nl2br(str) { if (typeof str === undef || str === null) { return ''; } return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1
$2'); } /** * Escapes HTML and converts newlines to
* @param {string} str - String to process * @returns {string} HTML-escaped string with line breaks */ function htmlbr(str) { return nl2br(html(str)); } /** * URL-encodes a string * @param {string} str - String to encode * @returns {string} URL-encoded string */ function urlencode(str) { return encodeURIComponent(str); } /** * URL-decodes a string * @param {string} str - String to decode * @returns {string} URL-decoded string */ function urldecode(str) { return decodeURIComponent(str); } /** * JSON-encodes a value * @param {*} value - Value to encode * @returns {string} JSON string */ function json_encode(value) { return JSON.stringify(value); } /** * JSON-decodes a string * @param {string} str - JSON string to decode * @returns {*} Decoded value */ function json_decode(str) { return JSON.parse(str); } /** * Console debug output with channel filtering * Alias for Debugger.console_debug * @param {string} channel - Debug channel name * @param {...*} values - Values to log */ function console_debug(channel) { for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { values[_key - 1] = arguments[_key]; } Debugger.console_debug(channel, ...values); } /** * Replaces all occurrences of a substring in a string * @param {string} string - String to search in * @param {string} search - Substring to find * @param {string} replace - Replacement substring * @returns {string} String with all occurrences replaced */ function replace_all(string, search, replace) { if (!is_string(string)) { string = string + ''; } return string.split(search).join(replace); } /** * Capitalizes the first letter of each word * @param {string} input - String to capitalize * @returns {string} String with first letter of each word capitalized */ function ucwords(input) { return input.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); } // ============================================================================ // OBJECT AND ARRAY UTILITIES // ============================================================================ /** * Counts the number of properties in an object or elements in an array * @param {Object|Array} o - Object or array to count * @returns {number} Number of own properties/elements */ function count(o) { let c = 0; for (const k in o) { if (o.hasOwnProperty(k)) { ++c; } } return c; } /** * Creates a shallow clone of an object, array, or function * @param {*} obj - Value to clone * @returns {*} Cloned value */ function clone(obj) { if (typeof Function.prototype.__clone == undef) { Function.prototype.__clone = function () { //https://stackoverflow.com/questions/1833588/javascript-clone-a-function const that = this; let temp = function cloned() { return that.apply(this, arguments); }; for (let key in this) { if (this.hasOwnProperty(key)) { temp[key] = this[key]; } } return temp; }; } if (typeof obj == 'function') { return obj.__clone(); } else if (obj.constructor && obj.constructor == Array) { return obj.slice(0); } else { // https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object/30042948#30042948 return Object.assign({}, obj); } } /** * Returns the first non-null/undefined value from arguments * @param {...*} arguments - Values to check * @returns {*} First non-null/undefined value, or null if none found */ function coalesce() { let args = Array.from(arguments); let return_val = null; args.forEach(function (arg) { if (return_val === null && typeof arg != undef && arg !== null) { return_val = arg; } }); return return_val; } /** * Converts CSV string to array, trimming each element * @param {string} str_csv - CSV string to convert * @returns {Array} Array of trimmed values * @todo Handle quoted/escaped characters */ function csv_to_array_trim(str_csv) { const parts = str_csv.split(','); const ret = []; foreach(parts, part => { ret.push(part.trim()); }); return ret; } /* === app/RSpade/Core/Js/Manifest.js (babel) === */ "use strict"; /** * Manifest - JavaScript class registry and metadata system * * This class maintains a registry of all JavaScript classes in the bundle, * tracking their names and inheritance relationships. It provides utilities * for working with class hierarchies and calling initialization methods. */ class Manifest { /** * Define classes in the manifest (framework internal) * @param {Array} items - Array of class definitions [[Class, "ClassName", ParentClass, decorators], ...] */ static _define(items) { // Initialize the classes object if not already defined if (typeof Manifest._classes === 'undefined') { Manifest._classes = {}; } // Process each class definition items.forEach(item => { let class_object = item[0]; let class_name = item[1]; let class_extends = item[2] || null; let decorators = item[3] || null; // Store the class information (using object to avoid duplicates) Manifest._classes[class_name] = { class: class_object, name: class_name, extends: class_extends, decorators: decorators // Store compact decorator data }; // Add metadata to the class object itself class_object._name = class_name; class_object._extends = class_extends; class_object._decorators = decorators; }); // Build the subclass index after all classes are defined Manifest._build_subclass_index(); } /** * Build an index of subclasses for efficient lookups * This creates a mapping where each class name points to an array of all its subclasses * @private */ static _build_subclass_index() { // Initialize the subclass index Manifest._subclass_index = {}; // Step through each class and walk up its parent chain for (let class_name in Manifest._classes) { const classdata = Manifest._classes[class_name]; let current_class_name = class_name; let current_classdata = classdata; // Walk up the parent chain until we reach the root while (current_classdata) { const extends_name = current_classdata.extends; if (extends_name) { // Initialize the parent's subclass array if needed if (!Manifest._subclass_index[extends_name]) { Manifest._subclass_index[extends_name] = []; } // Add this class to its parent's subclass list if (!Manifest._subclass_index[extends_name].includes(class_name)) { Manifest._subclass_index[extends_name].push(class_name); } // Move up to the parent's metadata (if it exists in manifest) if (Manifest._classes[extends_name]) { current_classdata = Manifest._classes[extends_name]; } else { // Parent not in manifest (e.g., native JavaScript class), stop here current_classdata = null; } } else { // No parent, we've reached the root current_classdata = null; } } } } /** * Get all classes that extend a given base class * @param {Class|string} base_class - The base class (object or name string) to check for * @returns {Array} Array of objects with {class_name, class_object} for classes that extend the base class */ static get_extending(base_class) { if (!Manifest._classes) { return []; } // Convert string to class object if needed let base_class_object = base_class; if (typeof base_class === 'string') { base_class_object = Manifest.get_class_by_name(base_class); if (!base_class_object) { throw new Error(`Base class not found: ${base_class}`); } } const classes = []; for (let class_name in Manifest._classes) { const classdata = Manifest._classes[class_name]; if (Manifest.js_is_subclass_of(classdata.class, base_class_object)) { classes.push({ class_name: class_name, class_object: classdata.class }); } } // Sort alphabetically by class name to ensure deterministic behavior and prevent race condition bugs classes.sort((a, b) => a.class_name.localeCompare(b.class_name)); return classes; } /** * Check if a class is a subclass of another class * Matches PHP Manifest::js_is_subclass_of() signature and behavior * @param {Class|string} subclass - The child class (object or name) to check * @param {Class|string} superclass - The parent class (object or name) to check against * @returns {boolean} True if subclass extends superclass (directly or indirectly) */ static js_is_subclass_of(subclass, superclass) { // Convert string names to class objects let subclass_object = subclass; if (typeof subclass === 'string') { subclass_object = Manifest.get_class_by_name(subclass); if (!subclass_object) { // Can't resolve subclass - return false per spec return false; } } let superclass_object = superclass; if (typeof superclass === 'string') { superclass_object = Manifest.get_class_by_name(superclass); if (!superclass_object) { // Can't resolve superclass - fail loud per spec throw new Error(`Superclass not found in manifest: ${superclass}`); } } // Classes are not subclasses of themselves if (subclass_object === superclass_object) { return false; } // Walk up the inheritance chain let current_class = subclass_object; while (current_class) { if (current_class === superclass_object) { return true; } // Move up to parent class if (current_class._extends) { // _extends may be a string or class reference if (typeof current_class._extends === 'string') { current_class = Manifest.get_class_by_name(current_class._extends); } else { current_class = current_class._extends; } } else { current_class = null; } } return false; } /** * Get a class by its name * @param {string} class_name - The name of the class * @returns {Class|null} The class object or null if not found */ static get_class_by_name(class_name) { if (!Manifest._classes || !Manifest._classes[class_name]) { return null; } return Manifest._classes[class_name].class; } /** * Get all registered classes * @returns {Array} Array of objects with {class_name, class_object, extends} */ static get_all_classes() { if (!Manifest._classes) { return []; } const results = []; for (let class_name in Manifest._classes) { const classdata = Manifest._classes[class_name]; results.push({ class_name: classdata.name, class_object: classdata.class, extends: classdata.extends }); } // Sort alphabetically by class name to ensure deterministic behavior and prevent race condition bugs results.sort((a, b) => a.class_name.localeCompare(b.class_name)); return results; } /** * Get the build key from the application configuration * @returns {string} The build key or "NOBUILD" if not available */ static build_key() { if (window.rsxapp && window.rsxapp.build_key) { return window.rsxapp.build_key; } return 'NOBUILD'; } /** * Get decorators for a specific class and method * @param {string|Class} class_name - The class name or class object * @param {string} method_name - The method name * @returns {Array|null} Array of decorator objects or null if none found */ static get_decorators(class_name, method_name) { // Convert class object to name if needed if (typeof class_name !== 'string') { class_name = class_name._name || class_name.name; } const class_info = Manifest._classes[class_name]; if (!class_info || !class_info.decorators || !class_info.decorators[method_name]) { return null; } // Transform compact format to object format return Manifest._transform_decorators(class_info.decorators[method_name]); } /** * Get all methods with decorators for a class * @param {string|Class} class_name - The class name or class object * @returns {Object} Object with method names as keys and decorator arrays as values */ static get_all_decorators(class_name) { // Convert class object to name if needed if (typeof class_name !== 'string') { class_name = class_name._name || class_name.name; } const class_info = Manifest._classes[class_name]; if (!class_info || !class_info.decorators) { return {}; } // Transform all decorators from compact to object format const result = {}; for (let method_name in class_info.decorators) { result[method_name] = Manifest._transform_decorators(class_info.decorators[method_name]); } return result; } /** * Transform compact decorator format to object format * @param {Array} compact_decorators - Array of [name, [args]] tuples * @returns {Array} Array of decorator objects with name and arguments properties * @private */ static _transform_decorators(compact_decorators) { if (!Array.isArray(compact_decorators)) { return []; } return compact_decorators.map(decorator => { if (Array.isArray(decorator) && decorator.length >= 2) { return { name: decorator[0], arguments: decorator[1] || [] }; } // Handle malformed decorator data return { name: 'unknown', arguments: [] }; }); } /** * Check if a method has a specific decorator * @param {string|Class} class_name - The class name or class object * @param {string} method_name - The method name * @param {string} decorator_name - The decorator name to check for * @returns {boolean} True if the method has the decorator */ static has_decorator(class_name, method_name, decorator_name) { const decorators = Manifest.get_decorators(class_name, method_name); if (!decorators) { return false; } return decorators.some(d => d.name === decorator_name); } /** * Get all subclasses of a given class using the pre-built index * This is the JavaScript equivalent of PHP's Manifest::js_get_subclasses_of() * @param {Class|string} base_class - The base class (object or name string) to get subclasses of * @returns {Array} Array of actual class objects that are subclasses of the base class */ static js_get_subclasses_of(base_class) { // Initialize index if needed if (!Manifest._subclass_index) { Manifest._build_subclass_index(); } // Convert class object to name if needed let base_class_name = base_class; if (typeof base_class !== 'string') { base_class_name = base_class._name || base_class.name; } // Check if the base class exists if (!Manifest._classes[base_class_name]) { // Base class not in manifest - return empty array return []; } // Get subclass names from the index const subclass_names = Manifest._subclass_index[base_class_name] || []; // Convert names to actual class objects const subclass_objects = []; for (let subclass_name of subclass_names) { const classdata = Manifest._classes[subclass_name]; subclass_objects.push(classdata.class); } // Sort by class name for deterministic behavior subclass_objects.sort((a, b) => { const name_a = a._name || a.name; const name_b = b._name || b.name; return name_a.localeCompare(name_b); }); return subclass_objects; } } // RSX manifest automatically makes classes global - no manual assignment needed /* === app/RSpade/Core/Js/Rsx_Behaviors.js (babel) === */ "use strict"; /** * Rsx_Behaviors - Core Framework User Experience Enhancements * * This class provides automatic quality-of-life behaviors that improve the default * browser experience for RSX applications. These behaviors are transparent to * application developers and run automatically on framework initialization. * * These behaviors use jQuery event delegation to handle both existing and dynamically * added content. They are implemented with low priority to allow application code to * override default behaviors when needed. * * @internal Framework use only - not part of public API */ class Rsx_Behaviors { static _on_framework_core_init() { Rsx_Behaviors._init_ignore_invalid_anchor_links(); Rsx_Behaviors._trim_copied_text(); } /** * - Anchor link handling: Prevents broken "#" links from causing page jumps or URL changes * - Ignores "#" (empty hash) to prevent scroll-to-top behavior * - Ignores "#placeholder*" links used as route placeholders during development * - Validates anchor targets exist before allowing navigation * - Preserves normal anchor behavior when targets exist */ static _init_ignore_invalid_anchor_links() { return; // disabled for now - make this into a configurable option // Use event delegation on document to handle all current and future anchor clicks // Use mousedown instead of click to run before most application handlers $(document).on('mousedown', 'a[href^="#"]', function (e) { const $link = $(this); const href = $link.attr('href'); // Check if another handler has already prevented default if (e.isDefaultPrevented()) { return; } // Allow data-rsx-allow-hash attribute to bypass this behavior if ($link.data('rsx-allow-hash')) { return; } // Handle empty hash - prevent scroll to top if (href === '#') { e.preventDefault(); e.stopImmediatePropagation(); return false; } // Handle placeholder links used during development if (href.startsWith('#placeholder')) { e.preventDefault(); e.stopImmediatePropagation(); return false; } // For other hash links, check if target exists const targetId = href.substring(1); if (targetId) { // Check for element with matching ID or name attribute const targetExists = document.getElementById(targetId) !== null || document.querySelector(`[name="${targetId}"]`) !== null; if (!targetExists) { // Target doesn't exist - prevent navigation e.preventDefault(); e.stopImmediatePropagation(); return false; } // Target exists - allow normal anchor behavior } }); } /** * - Copy text trimming: Automatically removes leading/trailing whitespace from copied text * - Hold Shift to preserve whitespace * - Skips trimming in code blocks, textareas, and contenteditable elements */ static _trim_copied_text() { document.addEventListener('copy', function (event) { // Don't trim if user is holding Shift (allows copying with whitespace if needed) if (event.shiftKey) return; let selection = window.getSelection(); let selected_text = selection.toString(); // Don't trim if selection is empty if (!selected_text) return; // Don't trim if copying from code blocks, textareas, or content-editable (preserve formatting) let container = selection.getRangeAt(0).commonAncestorContainer; if (container.nodeType === 3) container = container.parentNode; // Text node to element if (container.closest('pre, code, .code-block, textarea, [contenteditable="true"]')) return; let trimmed_text = selected_text.trim(); // Only modify if there's actually whitespace to trim if (trimmed_text !== selected_text && trimmed_text.length > 0) { event.preventDefault(); event.clipboardData.setData('text/plain', trimmed_text); console.log('Copy: trimmed whitespace from selection'); } }); } } /* === app/RSpade/Core/Js/Rsx_Cache.js (babel) === */ "use strict"; // Simple key value cache. Can only store 5000 entries, will reset after 5000 entries. // Todo: keep local cache concept the same, replace global cache concept with the nov 2019 version of // session cache. Use a session key & build key to track cache keys so cached values only last until user logs out. // review session code to ensure that session key *always* rotates on logout. Make session id a protected value. class Rsx_Cache { static on_core_define() { Core_Cache._caches = { global: {}, instance: {} }; Core_Cache._caches_set = 0; } // Alias for get_instance static get(key) { return Rsx_Cache.get_instance(key); } // Returns from the pool of cached data for this 'instance'. An instance // in this case is a virtual page load / navigation in the SPA. Call Main.lib.reset() to reset. // Returns null on failure static get_instance(key) { if (Main.debug('no_api_cache')) { return null; } let key_encoded = Rsx_Cache._encodekey(key); if (typeof Core_Cache._caches.instance[key_encoded] != undef) { return JSON.parse(Core_Cache._caches.instance[key_encoded]); } return null; } // Returns null on failure // Returns a cached value from global cache (unique to page load, survives reset()) static get_global(key) { if (Main.debug('no_api_cache')) { return null; } let key_encoded = Rsx_Cache._encodekey(key); if (typeof Core_Cache._caches.global[key_encoded] != undef) { return JSON.parse(Core_Cache._caches.global[key_encoded]); } return null; } // Sets a value in instance and global cache (not shared between browser tabs) static set(key, value) { if (Main.debug('no_api_cache')) { return; } if (value === null) { return; } if (value.length > 64 * 1024) { Debugger.console_debug('CACHE', 'Warning - not caching large cache entry', key); return; } let key_encoded = Rsx_Cache._encodekey(key); Core_Cache._caches.global[key_encoded] = JSON.stringify(value); Core_Cache._caches.instance[key_encoded] = JSON.stringify(value); // Debugger.console_debug("CACHE", "Set", key, value); Core_Cache._caches_set++; // Reset cache after 5000 items set if (Core_Cache._caches_set > 5000) { // Get an accurate count Core_Cache._caches_set = count(Core_Cache._caches.global); if (Core_Cache._caches_set > 5000) { Core_Cache._caches = { global: {}, instance: {} }; Core_Cache._caches_set = 0; } } } // Returns null on failure // Returns a cached value from session cache (shared between browser tabs) static get_session(key) { if (Main.debug('no_api_cache')) { return null; } if (!Rsx_Cache._supportsStorage()) { return null; } let key_encoded = Rsx_Cache._encodekey(key); let rs = sessionStorage.getItem(key_encoded); if (!empty(rs)) { return JSON.parse(rs); } else { return null; } } // Sets a value in session cache (shared between browser tabs) static set_session(key, value) { let _tryagain = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; if (Main.debug('no_api_cache')) { return; } if (value.length > 64 * 1024) { Debugger.console_debug('CACHE', 'Warning - not caching large cache entry', key); return; } if (!Rsx_Cache._supportsStorage()) { return null; } let key_encoded = Rsx_Cache._encodekey(key); try { sessionStorage.removeItem(key_encoded); sessionStorage.setItem(key_encoded, JSON.stringify(value)); } catch (e) { if (Rsx_Cache._isOutOfSpace(e) && sessionStorage.length) { sessionStorage.clear(); if (_tryagain) { Core_Cache.set_session(key, value, false); } } } } static _reset() { Core_Cache._caches.instance = {}; } /** * For given key of any type including an object, return a string representing * the key that the cached value should be stored as in sessionstorage */ static _encodekey(key) { const prefix = 'cache_'; // Session reimplement // var prefix = "cache_" + Spa.session().user_id() + "_"; if (is_string(key) && key.length < 150 && key.indexOf(' ') == -1) { return prefix + Manifest.build_key() + '_' + key; } else { return prefix + hash([Manifest.build_key(), key]); } } // Determines if sessionStorage is supported in the browser; // result is cached for better performance instead of being run each time. // Feature detection is based on how Modernizr does it; // it's not straightforward due to FF4 issues. // It's not run at parse-time as it takes 200ms in Android. // Code from https://github.com/pamelafox/lscache/blob/master/lscache.js, Apache License Pamelafox static _supportsStorage() { let key = '__cachetest__'; let value = key; if (Rsx_Cache.__supportsStorage !== undefined) { return Rsx_Cache.__supportsStorage; } // some browsers will throw an error if you try to access local storage (e.g. brave browser) // hence check is inside a try/catch try { if (!sessionStorage) { return false; } } catch (ex) { return false; } try { sessionStorage.setItem(key, value); sessionStorage.removeItem(key); Rsx_Cache.__supportsStorage = true; } catch (e) { // If we hit the limit, and we don't have an empty sessionStorage then it means we have support if (Rsx_Cache._isOutOfSpace(e) && sessionStorage.length) { Rsx_Cache.__supportsStorage = true; // just maxed it out and even the set test failed. } else { Rsx_Cache.__supportsStorage = false; } } return Rsx_Cache.__supportsStorage; } // Check to set if the error is us dealing with being out of space static _isOutOfSpace(e) { return e && (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED' || e.name === 'QuotaExceededError'); } } /* === app/RSpade/Core/Js/Rsx_Init.js (babel) === */ "use strict"; /** * Rsx_Init - Core framework initialization and environment validation */ class Rsx_Init { /** * Called via Rsx._rsx_core_boot * Initializes the core environment and runs basic sanity checks */ static _on_framework_core_init() { if (!Rsx.is_prod()) { Rsx_Init.__environment_checks(); } } /** * Development environment checks to ensure proper configuration */ static __environment_checks() { // Find all script tags in the DOM const scripts = document.getElementsByTagName('script'); for (let i = 0; i < scripts.length; i++) { const script = scripts[i]; // Skip inline scripts (no src attribute) if (!script.src) { continue; } // Check if script has defer attribute if (!script.defer) { const src = script.src || '(inline script)'; const reason = `All script tags used in an RSpade project must have defer attribute. Found script without defer: ${src}`; // Stop framework boot with reason Rsx._rsx_core_boot_stop(reason); // Also log to console for visibility console.error(`[RSX BOOT STOPPED] ${reason}`); // Stop checking after first violation return; } } } } /* === app/RSpade/Core/Js/Rsx_Js_Model.js (babel) === */ "use strict"; // @FILE-SUBCLASS-01-EXCEPTION /** * Base class for JavaScript ORM models * * Provides core functionality for fetching records from backend PHP models. * All model stubs generated by the manifest extend this base class. * * Example usage: * // Fetch single record * const user = await User_Model.fetch(123); * * // Fetch multiple records * const users = await User_Model.fetch([1, 2, 3]); * * // Create instance with data * const user = new User_Model({id: 1, name: 'John'}); * * @Instantiatable */ class Rsx_Js_Model { /** * Constructor - Initialize model instance with data * * @param {Object} data - Key-value pairs to populate the model */ constructor() { let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; // __MODEL SYSTEM: Enables automatic ORM instantiation when fetching from PHP models. // PHP models add "__MODEL": "ClassName" to JSON, JavaScript uses it to create proper instances. // This provides typed model objects instead of plain JSON, with methods and type checking. // This constructor filters out the __MODEL marker that was used to identify which class // to instantiate, keeping only the actual data properties on the instance. const { __MODEL, ...modelData } = data; Object.assign(this, modelData); } /** * Fetch record(s) from the backend model * * This method mirrors the PHP Model::fetch() functionality. * The backend model must have a fetch() method with the * #[Ajax_Endpoint_Model_Fetch] annotation to be callable. * * @param {number|Array} id - Single ID or array of IDs to fetch * @returns {Promise} - Single model instance, array of instances, or false */ static async fetch(id) { const CurrentClass = this; // Get the model class name from the current class const modelName = CurrentClass.name; const response = await $.ajax({ url: `/_fetch/${modelName}`, method: 'POST', data: { id: id }, dataType: 'json' }); // Handle response based on type if (response === false) { return false; } // Use _instantiate_models_recursive to handle ORM instantiation // This will automatically detect __MODEL properties and create appropriate instances return Rsx_Js_Model._instantiate_models_recursive(response); } /** * Get the model class name * Used internally for API calls * * @returns {string} The class name */ static getModelName() { const CurrentClass = this; return CurrentClass.name; } /** * Refresh this instance with latest data from server * * @returns {Promise} Updated instance or false if not found */ async refresh() { const that = this; if (!that.id) { shouldnt_happen('Cannot refresh model without id property'); } const fresh = await that.constructor.fetch(that.id); if (fresh === false) { return false; } // Update this instance with fresh data Object.assign(that, fresh); return that; } /** * Convert model instance to plain object * Useful for serialization or sending to APIs * * @returns {Object} Plain object representation */ toObject() { const that = this; const obj = {}; for (const key in that) { if (that.hasOwnProperty(key) && typeof that[key] !== 'function') { obj[key] = that[key]; } } return obj; } /** * Convert model instance to JSON string * * @returns {string} JSON representation */ toJSON() { const that = this; return JSON.stringify(that.toObject()); } /** * Recursively instantiate ORM models in response data * * Looks for objects with __MODEL property and instantiates the appropriate * JavaScript model class if it exists in the global scope. * * @param {*} data - The data to process (can be any type) * @returns {*} The data with ORM objects instantiated */ static _instantiate_models_recursive(data) { // __MODEL SYSTEM: Enables automatic ORM instantiation when fetching from PHP models. // PHP models add "__MODEL": "ClassName" to JSON, JavaScript uses it to create proper instances. // This provides typed model objects instead of plain JSON, with methods and type checking. // This recursive processor scans all API response data looking for __MODEL markers. // When found, it attempts to instantiate the appropriate JavaScript model class, // converting {__MODEL: "User_Model", id: 1, name: "John"} into new User_Model({...}). // Works recursively through arrays and nested objects to handle complex data structures. // Handle null/undefined if (data === null || data === undefined) { return data; } // Handle arrays - recursively process each element if (Array.isArray(data)) { return data.map(item => Rsx_Js_Model._instantiate_models_recursive(item)); } // Handle objects if (typeof data === 'object') { // Check if this object has a __MODEL property if (data.__MODEL && typeof data.__MODEL === 'string') { // Try to find the model class in the global scope const ModelClass = window[data.__MODEL]; // If the model class exists and extends Rsx_Js_Model, instantiate it // Dynamic model resolution requires checking class existence - @JS-DEFENSIVE-01-EXCEPTION if (ModelClass && ModelClass.prototype instanceof Rsx_Js_Model) { return new ModelClass(data); } } // Recursively process all object properties const result = {}; for (const key in data) { if (data.hasOwnProperty(key)) { result[key] = Rsx_Js_Model._instantiate_models_recursive(data[key]); } } return result; } // Return primitive values as-is return data; } } /* === app/RSpade/Core/Js/Rsx_View_Transitions.js (babel) === */ "use strict"; /** * View_Transitions - Smooth page-to-page transitions using View Transitions API * * Enables cross-document view transitions so the browser doesn't paint the new page * until it's ready, creating smooth animations between pages. * * Falls back gracefully if View Transitions API is not available. */ class Rsx_View_Transitions { /** * Called during framework core init phase * Checks for View Transitions API support and enables if available */ static _on_framework_core_init() { // Check if View Transitions API is supported if (!document.startViewTransition) { console_debug('VIEW_TRANSITIONS', 'View Transitions API not supported, skipping'); return; } // Enable cross-document view transitions via CSS Rsx_View_Transitions._inject_transition_css(); } /** * Inject CSS to enable cross-document view transitions * * The @view-transition { navigation: auto; } rule tells the browser to: * 1. Capture a snapshot of the current page before navigation * 2. Fetch the new page * 3. Wait until the new page is fully loaded and painted (document.ready) * 4. Animate smoothly between the two states * * This prevents the white flash during navigation and creates app-like transitions. */ static _inject_transition_css() { const style = document.createElement('style'); style.textContent = ` @view-transition { navigation: auto; } /* Disable animation - instant transition */ ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation-duration: 0s; } `; document.head.appendChild(style); } } /* === app/RSpade/Core/Js/ReadWriteLock.js (babel) === */ "use strict"; var _50ae609e_ReadWriteLock; function _50ae609e_assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); } /** * ReadWriteLock implementation for RSpade framework * Provides exclusive (write) and shared (read) locking mechanisms for asynchronous operations */ class ReadWriteLock { /** * Acquire an exclusive mutex lock by name. * Only one writer runs at a time; blocks readers until finished. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ static acquire(name, cb) { return new Promise((resolve, reject) => { const s = _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_get_lock).call(this, name); s.writer_q.push({ cb, resolve, reject }); _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); } /** * Acquire a shared read lock by name. * Multiple readers can run in parallel; blocks when writer is active. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ static acquire_read(name, cb) { return new Promise((resolve, reject) => { const s = _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_get_lock).call(this, name); if (s.writer_active || s.writer_q.length > 0) { s.reader_q.push({ cb, resolve, reject }); return _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_schedule).call(this, name); } s.readers += 1; Promise.resolve().then(cb).then(resolve, reject).finally(() => { s.readers -= 1; if (s.readers === 0) _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); }); } /** * Force-unlock a mutex (use with caution). * Completely removes the lock state, potentially breaking waiting operations. * @param {string} name */ static force_unlock(name) { _50ae609e_assertClassBrand(ReadWriteLock, this, _locks)._.delete(name); } /** * Get information about pending operations on a mutex. * @param {string} name * @returns {{readers: number, writer_active: boolean, reader_q: number, writer_q: number}} */ static pending(name) { const s = _50ae609e_assertClassBrand(ReadWriteLock, this, _locks)._.get(name); if (!s) return { readers: 0, writer_active: false, reader_q: 0, writer_q: 0 }; return { readers: s.readers, writer_active: s.writer_active, reader_q: s.reader_q.length, writer_q: s.writer_q.length }; } } _50ae609e_ReadWriteLock = ReadWriteLock; /** * Get or create a lock object for a given name * @private */ function _50ae609e_get_lock(name) { let s = _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _locks)._.get(name); if (!s) { s = { readers: 0, writer_active: false, reader_q: [], writer_q: [] }; _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _locks)._.set(name, s); } return s; } /** * Schedule the next operation for a lock * @private */ function _50ae609e_schedule(name) { const s = _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _50ae609e_get_lock).call(this, name); if (s.writer_active || s.readers > 0) return; // run one writer if queued if (s.writer_q.length > 0) { const { cb, resolve, reject } = s.writer_q.shift(); s.writer_active = true; Promise.resolve().then(cb).then(resolve, reject).finally(() => { s.writer_active = false; _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); return; } // otherwise run all queued readers in parallel if (s.reader_q.length > 0) { const batch = s.reader_q.splice(0); s.readers += batch.length; for (const { cb, resolve, reject } of batch) { Promise.resolve().then(cb).then(resolve, reject).finally(() => { s.readers -= 1; if (s.readers === 0) _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); } } } var _locks = { _: new Map() }; /* === app/RSpade/Core/Js/Form_Utils.js (babel) === */ "use strict"; /** * Form utilities for validation and error handling */ class Form_Utils { /** * Framework initialization hook to register jQuery plugin * Creates $.fn.ajax_submit() for form elements * @private */ static _on_framework_core_define() { let params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; $.fn.ajax_submit = function () { let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; const $element = $(this); if (!$element.is('form')) { throw new Error('ajax_submit() can only be called on form elements'); } const url = $element.attr('action'); if (!url) { throw new Error('Form must have an action attribute'); } const { controller, action } = Ajax.ajax_url_to_controller_action(url); return Form_Utils.ajax_submit($element, controller, action, options); }; } /** * Shows form validation errors * * REQUIRED HTML STRUCTURE: * For inline field errors to display properly, form fields must follow this structure: * *
* * *
* * Key requirements: * - Wrap each field in a container with class "form-group" (or "form-check" / "input-group") * - Input must have a "name" attribute matching the error key * - Use "form-control" class on inputs for Bootstrap 5 styling * * Accepts three formats: * - String: Single error shown as alert * - Array of strings: Multiple errors shown as bulleted alert * - Object: Field names mapped to errors, shown inline (unmatched shown as alert) * * @param {string} parent_selector - jQuery selector for parent element * @param {string|Object|Array} errors - Error messages to display * @returns {Promise} Promise that resolves when all animations complete */ static apply_form_errors(parent_selector, errors) { console.error(errors); const $parent = $(parent_selector); // Reset the form errors before applying new ones Form_Utils.reset_form_errors(parent_selector); // Normalize input to standard format const normalized = Form_Utils._normalize_errors(errors); return new Promise(resolve => { let animations = []; if (normalized.type === 'string') { // Single error message animations = Form_Utils._apply_general_errors($parent, normalized.data); } else if (normalized.type === 'array') { // Array of error messages const deduplicated = Form_Utils._deduplicate_errors(normalized.data); animations = Form_Utils._apply_general_errors($parent, deduplicated); } else if (normalized.type === 'fields') { // Field-specific errors const result = Form_Utils._apply_field_errors($parent, normalized.data); animations = result.animations; // Count matched fields const matched_count = Object.keys(normalized.data).length - Object.keys(result.unmatched).length; const unmatched_deduplicated = Form_Utils._deduplicate_errors(result.unmatched); const unmatched_count = Object.keys(unmatched_deduplicated).length; // Show summary alert if there are any field errors (matched or unmatched) if (matched_count > 0 || unmatched_count > 0) { // Build summary message let summary_msg = ''; if (matched_count > 0) { summary_msg = matched_count === 1 ? 'Please correct the error highlighted below.' : 'Please correct the errors highlighted below.'; } // If there are unmatched errors, add them as a bulleted list if (unmatched_count > 0) { const summary_animations = Form_Utils._apply_combined_error($parent, summary_msg, unmatched_deduplicated); animations.push(...summary_animations); } else { // Just the summary message, no unmatched errors const summary_animations = Form_Utils._apply_general_errors($parent, summary_msg); animations.push(...summary_animations); } } } // Resolve the promise once all animations are complete Promise.all(animations).then(() => { // Scroll to error container if it exists const $error_container = $parent.find('[data-id="error_container"]').first(); if ($error_container.length > 0) { const container_top = $error_container.offset().top; // Calculate fixed header offset const fixed_header_height = Form_Utils._get_fixed_header_height(); // Scroll to position error container 20px below any fixed headers const target_scroll = container_top - fixed_header_height - 20; $('html, body').animate({ scrollTop: target_scroll }, 500); } resolve(); }); }); } /** * Clears form validation errors and resets all form values to defaults * @param {string|jQuery} form_selector - jQuery selector or jQuery object for form element */ static reset(form_selector) { const $form = typeof form_selector === 'string' ? $(form_selector) : form_selector; Form_Utils.reset_form_errors(form_selector); $form.trigger('reset'); } /** * Serializes form data into key-value object * Returns all input elements with name attributes as object properties * @param {string|jQuery} form_selector - jQuery selector or jQuery object for form element * @returns {Object} Form data as key-value pairs */ static serialize(form_selector) { const $form = typeof form_selector === 'string' ? $(form_selector) : form_selector; const data = {}; $form.serializeArray().forEach(item => { data[item.name] = item.value; }); return data; } /** * Submits form to RSX controller action via AJAX * @param {string|jQuery} form_selector - jQuery selector or jQuery object for form element * @param {string} controller - Controller class name (e.g., 'User_Controller') * @param {string} action - Action method name (e.g., 'save_profile') * @param {Object} options - Optional configuration {on_success: fn, on_error: fn} * @returns {Promise} Promise that resolves with response data */ static async ajax_submit(form_selector, controller, action) { let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; const $form = typeof form_selector === 'string' ? $(form_selector) : form_selector; const form_data = Form_Utils.serialize($form); Form_Utils.reset_form_errors(form_selector); try { const response = await Ajax.call(controller, action, form_data); if (options.on_success) { options.on_success(response); } return response; } catch (error) { if (error.type === 'form_error' && error.details) { await Form_Utils.apply_form_errors(form_selector, error.details); } else { await Form_Utils.apply_form_errors(form_selector, error.message || 'An error occurred'); } if (options.on_error) { options.on_error(error); } throw error; } } /** * Removes form validation errors * @param {string} parent_selector - jQuery selector for parent element */ static reset_form_errors(parent_selector) { const $parent = $(parent_selector); // Remove flash messages $('.flash-messages').remove(); // Remove alert-danger messages $parent.find('.alert-danger').remove(); // Remove validation error classes and text from form elements $parent.find('.is-invalid').removeClass('is-invalid'); $parent.find('.invalid-feedback').remove(); } // ------------------------ /** * Normalizes error input into standard formats * @param {string|Object|Array} errors - Raw error input * @returns {Object} Normalized errors as {type: 'string'|'array'|'fields', data: ...} * @private */ static _normalize_errors(errors) { // Handle null/undefined if (!errors) { return { type: 'string', data: 'An error has occurred' }; } // Handle string if (typeof errors === 'string') { return { type: 'string', data: errors }; } // Handle array if (Array.isArray(errors)) { // Array of strings - general errors if (errors.every(e => typeof e === 'string')) { return { type: 'array', data: errors }; } // Array with object as first element - extract it if (errors.length > 0 && typeof errors[0] === 'object') { return Form_Utils._normalize_errors(errors[0]); } // Empty or mixed array return { type: 'array', data: [] }; } // Handle object - check for Laravel response wrapper if (typeof errors === 'object') { // Unwrap {errors: {...}} or {error: {...}} const unwrapped = errors.errors || errors.error; if (unwrapped) { return Form_Utils._normalize_errors(unwrapped); } // Convert Laravel validator format {field: [msg1, msg2]} to {field: msg1} const normalized = {}; for (const field in errors) { if (errors.hasOwnProperty(field)) { const value = errors[field]; if (Array.isArray(value) && value.length > 0) { normalized[field] = value[0]; } else if (typeof value === 'string') { normalized[field] = value; } else { normalized[field] = String(value); } } } return { type: 'fields', data: normalized }; } // Final catch-all* return { type: 'string', data: String(errors) }; } /** * Removes duplicate error messages from array or object values * @param {Array|Object} errors - Errors to deduplicate * @returns {Array|Object} Deduplicated errors * @private */ static _deduplicate_errors(errors) { if (Array.isArray(errors)) { return [...new Set(errors)]; } if (typeof errors === 'object') { const seen = new Set(); const result = {}; for (const key in errors) { const value = errors[key]; if (!seen.has(value)) { seen.add(value); result[key] = value; } } return result; } return errors; } /** * Applies field-specific validation errors to form inputs * @param {jQuery} $parent - Parent element containing form * @param {Object} field_errors - Object mapping field names to error messages * @returns {Object} Object containing {animations: Array, unmatched: Object} * @private */ static _apply_field_errors($parent, field_errors) { const animations = []; const unmatched = {}; for (const field_name in field_errors) { const error_message = field_errors[field_name]; const $input = $parent.find(`[name="${field_name}"]`); if (!$input.length) { unmatched[field_name] = error_message; continue; } const $error = $('
').html(error_message); const $target = $input.closest('.form-group, .form-check, .input-group'); if (!$target.length) { unmatched[field_name] = error_message; continue; } $input.addClass('is-invalid'); $error.appendTo($target); animations.push($error.hide().fadeIn(300).promise()); } return { animations, unmatched }; } /** * Applies combined error message with summary and unmatched field errors * @param {jQuery} $parent - Parent element containing form * @param {string} summary_msg - Summary message (e.g., "Please correct the errors below") * @param {Object} unmatched_errors - Object of field errors that couldn't be matched to fields * @returns {Array} Array of animation promises * @private */ static _apply_combined_error($parent, summary_msg, unmatched_errors) { const animations = []; const $error_container = $parent.find('[data-id="error_container"]').first(); const $target = $error_container.length > 0 ? $error_container : $parent; // Create alert with summary message and bulleted list of unmatched errors const $alert = $(''); // Add summary message if provided if (summary_msg) { $('

').text(summary_msg).appendTo($alert); } // Add unmatched errors as bulleted list if (Object.keys(unmatched_errors).length > 0) { const $list = $('
    '); for (const field_name in unmatched_errors) { const error_msg = unmatched_errors[field_name]; $('
  • ').html(error_msg).appendTo($list); } $list.appendTo($alert); } if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } return animations; } /** * Applies general error messages as alert box * @param {jQuery} $parent - Parent element to prepend alert to * @param {string|Array} messages - Error message(s) to display * @returns {Array} Array of animation promises * @private */ static _apply_general_errors($parent, messages) { const animations = []; // Look for a specific error container div (e.g., in Rsx_Form component) const $error_container = $parent.find('[data-id="error_container"]').first(); const $target = $error_container.length > 0 ? $error_container : $parent; if (typeof messages === 'string') { // Single error - simple alert without list const $alert = $('').text(messages); if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } } else if (Array.isArray(messages) && messages.length > 0) { // Multiple errors - bulleted list const $alert = $(''); const $list = $alert.find('ul'); messages.forEach(msg => { const text = (msg + '').trim() || 'An error has occurred'; $('
  • ').html(text).appendTo($list); }); if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } } else if (typeof messages === 'object' && !Array.isArray(messages)) { // Object of unmatched field errors - convert to array const error_list = Object.values(messages).map(v => String(v).trim()).filter(v => v); if (error_list.length > 0) { return Form_Utils._apply_general_errors($parent, error_list); } } return animations; } /** * Calculates the total height of fixed/sticky headers at the top of the page * @returns {number} Total height in pixels of fixed top elements * @private */ static _get_fixed_header_height() { let total_height = 0; // Find all fixed or sticky positioned elements $('*').each(function () { const $el = $(this); const position = $el.css('position'); // Only check fixed or sticky elements if (position !== 'fixed' && position !== 'sticky') { return; } // Check if element is positioned at or near the top const top = parseInt($el.css('top')) || 0; if (top > 50) { return; // Not a top header } // Check if element is visible if (!$el.is(':visible')) { return; } // Check if element spans significant width (likely a header/navbar) const width = $el.outerWidth(); const viewport_width = $(window).width(); if (width < viewport_width * 0.5) { return; // Too narrow to be a header } // Add this element's height total_height += $el.outerHeight(); }); return total_height; } } /* === app/RSpade/Core/Js/Debugger.js (babel) === */ "use strict"; function _27e0e986_defineProperty(e, r, t) { return (r = _27e0e986_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _27e0e986_toPropertyKey(t) { var i = _27e0e986_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _27e0e986_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /** * Debugger class for console_debug and browser error logging * Handles batched submission to server when configured */ class Debugger { /** * Initialize framework error handling * Called during framework initialization */ static _on_framework_core_init() { // Check if browser error logging is enabled if (window.rsxapp && window.rsxapp.log_browser_errors) { // Register global error handler window.addEventListener('error', function (event) { Debugger._handle_browser_error({ message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, stack: event.error ? event.error.stack : null, type: 'error' }); }); // Register unhandled promise rejection handler window.addEventListener('unhandledrejection', function (event) { Debugger._handle_browser_error({ message: event.reason ? event.reason.message || String(event.reason) : 'Unhandled promise rejection', stack: event.reason && event.reason.stack ? event.reason.stack : null, type: 'unhandledrejection' }); }); } // Register ui refresh handler Rsx.on('refresh', Debugger.on_refresh); } // In dev mode, some ui elements can be automatically applied to assist with development static on_refresh() { if (!Rsx.is_prod()) { // Add an underline 2 px blue to all a tags with href === "#" using jquery // Todo: maybe this should be a configurable debug option? // $('a[href="#"]').css({ // 'border-bottom': '2px solid blue', // 'text-decoration': 'none' // }); } } /** * JavaScript implementation of console_debug * Mirrors PHP functionality with batching for Laravel log */ static console_debug(channel) { // Check if console_debug is enabled if (!window.rsxapp || !window.rsxapp.console_debug || !window.rsxapp.console_debug.enabled) { return; } const config = window.rsxapp.console_debug; // Normalize channel name channel = String(channel).toUpperCase().replace(/[\[\]]/g, ''); // Apply filtering if (config.filter_mode === 'specific') { const specific = config.specific_channel; if (specific) { // Split comma-separated values and normalize const channels = specific.split(',').map(c => c.trim().toUpperCase()); if (!channels.includes(channel)) { return; } } } else if (config.filter_mode === 'whitelist') { const whitelist = (config.filter_channels || []).map(c => c.toUpperCase()); if (!whitelist.includes(channel)) { return; } } else if (config.filter_mode === 'blacklist') { const blacklist = (config.filter_channels || []).map(c => c.toUpperCase()); if (blacklist.includes(channel)) { return; } } // Prepare the message for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { values[_key - 1] = arguments[_key]; } let message = { channel: channel, values: values, timestamp: new Date().toISOString() }; // Add location if configured if (config.include_location || config.include_backtrace) { const error = new Error(); const stack = error.stack || ''; const stackLines = stack.split('\n'); if (config.include_location && stackLines.length > 2) { // Skip Error line and this function const callerLine = stackLines[2] || ''; const match = callerLine.match(/at\s+.*?\s+\((.*?):(\d+):(\d+)\)/) || callerLine.match(/at\s+(.*?):(\d+):(\d+)/); if (match) { message.location = `${match[1]}:${match[2]}`; } } if (config.include_backtrace) { // Include first 5 stack frames, skipping this function message.backtrace = stackLines.slice(2, 7).map(line => line.trim()).filter(line => line); } } // Output to browser console if enabled if (config.outputs && config.outputs.browser) { const prefix = config.include_benchmark ? `[${Debugger._get_time_prefix()}] ` : ''; const channelPrefix = `[${channel}]`; // Use appropriate console method based on channel let consoleMethod = 'log'; if (channel.includes('ERROR')) consoleMethod = 'error';else if (channel.includes('WARN')) consoleMethod = 'warn';else if (channel.includes('INFO')) consoleMethod = 'info'; console[consoleMethod](prefix + channelPrefix, ...values); } // Batch for Laravel log if enabled if (config.outputs && config.outputs.laravel_log) { Debugger._batch_console_message(message); } } /** * Log an error to the server * Used manually or by Ajax error handling */ static log_error(error) { // Check if browser error logging is enabled if (!window.rsxapp || !window.rsxapp.log_browser_errors) { return; } // Normalize error format let errorData = {}; if (typeof error === 'string') { errorData.message = error; errorData.type = 'manual'; } else if (error instanceof Error) { errorData.message = error.message; errorData.stack = error.stack; errorData.type = 'exception'; } else if (error && typeof error === 'object') { errorData = error; if (!errorData.type) { errorData.type = 'manual'; } } Debugger._handle_browser_error(errorData); } /** * Internal: Handle browser errors with batching */ static _handle_browser_error(errorData) { // Check limits if (Debugger._error_count >= Debugger.MAX_ERRORS_PER_PAGE) { return; } if (Debugger._error_batch_count >= Debugger.MAX_ERROR_BATCHES) { return; } Debugger._error_count++; // Add metadata errorData.url = window.location.href; errorData.userAgent = navigator.userAgent; errorData.timestamp = new Date().toISOString(); // Add to batch Debugger._error_batch.push(errorData); // Clear existing timer if (Debugger._error_timer) { clearTimeout(Debugger._error_timer); } // Set debounce timer Debugger._error_timer = setTimeout(() => { Debugger._flush_error_batch(); }, Debugger.DEBOUNCE_MS); } /** * Internal: Batch console_debug messages for Laravel log */ static _batch_console_message(message) { Debugger._console_batch.push(message); // Clear existing timer if (Debugger._console_timer) { clearTimeout(Debugger._console_timer); } // Set debounce timer Debugger._console_timer = setTimeout(() => { Debugger._flush_console_batch(); }, Debugger.DEBOUNCE_MS); } /** * Internal: Flush console_debug batch to server */ static async _flush_console_batch() { if (Debugger._console_batch.length === 0) { return; } const messages = Debugger._console_batch; Debugger._console_batch = []; Debugger._console_timer = null; try { return Ajax.call(Rsx.Route('Debugger_Controller', 'log_console_messages'), { messages: messages }); } catch (error) { // Silently fail - don't create error loop console.error('Failed to send console_debug messages to server:', error); } } /** * Internal: Flush error batch to server */ static async _flush_error_batch() { if (Debugger._error_batch.length === 0) { return; } const errors = Debugger._error_batch; Debugger._error_batch = []; Debugger._error_timer = null; Debugger._error_batch_count++; try { return Ajax.call(Rsx.Route('Debugger_Controller', 'log_browser_errors'), { errors: errors }); } catch (error) { // Silently fail - don't create error loop console.error('Failed to send browser errors to server:', error); } } /** * Internal: Get time prefix for benchmarking */ static _get_time_prefix() { const now = Date.now(); if (!Debugger._start_time) { Debugger._start_time = now; } const elapsed = now - Debugger._start_time; return (elapsed / 1000).toFixed(3) + 's'; } } // Batching state for console_debug messages _27e0e986_defineProperty(Debugger, "_console_batch", []); _27e0e986_defineProperty(Debugger, "_console_timer", null); _27e0e986_defineProperty(Debugger, "_console_batch_count", 0); // Batching state for error messages _27e0e986_defineProperty(Debugger, "_error_batch", []); _27e0e986_defineProperty(Debugger, "_error_timer", null); _27e0e986_defineProperty(Debugger, "_error_count", 0); _27e0e986_defineProperty(Debugger, "_error_batch_count", 0); // Constants _27e0e986_defineProperty(Debugger, "DEBOUNCE_MS", 2000); _27e0e986_defineProperty(Debugger, "MAX_ERRORS_PER_PAGE", 20); _27e0e986_defineProperty(Debugger, "MAX_ERROR_BATCHES", 5); // Store start time for benchmarking _27e0e986_defineProperty(Debugger, "_start_time", null); /* === app/RSpade/Core/Js/Rsx_Jq_Helpers.js (babel) === */ "use strict"; // @JS-THIS-01-EXCEPTION /** * jQuery helper extensions for the RSX framework * These extensions add utility methods to jQuery's prototype * Note: 'this' references in jQuery extensions refer to jQuery objects by design */ class Rsx_Jq_Helpers { /** * Initialize jQuery extensions when the framework core is defined * This method is called during framework initialization */ static _on_framework_core_define() { // Returns true if jquery selector matched an element $.fn.exists = function () { return this.length > 0; }; // Returns true if jquery element is visible $.fn.is_visible = function () { return this.is(':visible'); }; // Scrolls to the target element, only scrolls up. Todo: Create a version // of this that also scrolls only down, or both $.fn.scroll_up_to = function () { let speed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; if (!this.exists()) { // console.warn("Could not find target element to scroll to"); return; } if (!this.is_in_dom()) { // console.warn("Target element for scroll is not on dom"); return; } let e_top = Math.round(this.offset().top); let s_top = $('body').scrollTop(); if (e_top < 0) { let target = s_top + e_top; $('html, body').animate({ scrollTop: target }, speed); } }; // $().is(":focus") - check if element has focus $.expr[':'].focus = function (elem) { return elem === document.activeElement && (elem.type || elem.href); }; // Save native click behavior before override $.fn._click_native = $.fn.click; // Override .click() to call preventDefault by default // This prevents accidental page navigation/form submission - the correct behavior 95% of the time $.fn.click = function (handler) { // If no handler provided, trigger click event (jQuery .click() with no args) if (typeof handler === 'undefined') { return this._click_native(); } // Attach click handler with automatic preventDefault return this.on('click', function (e) { // Save original preventDefault const original_preventDefault = e.preventDefault.bind(e); // Override preventDefault to show warning when called explicitly e.preventDefault = function () { console.warn('event.preventDefault() is called automatically by RSpade .click() handlers and can be removed.'); return original_preventDefault(); }; // Call preventDefault before handler original_preventDefault(); return handler.call(this, e); }); }; // Escape hatch: click handler without preventDefault for the 5% case $.fn.click_allow_default = function (handler) { if (typeof handler === 'undefined') { return this._click_native(); } return this._click_native(handler); }; // Returns true if the jquery element exists in and is attached to the DOM $.fn.is_in_dom = function () { let $element = this; let _ancestor = function (HTMLobj) { while (HTMLobj.parentElement) { HTMLobj = HTMLobj.parentElement; } return HTMLobj; }; return _ancestor($element[0]) === document.documentElement; }; // Returns true if the element is visible in the viewport $.fn.is_in_viewport = function () { let scrolltop = $(window).scrollTop() > 0 ? $(window).scrollTop() : $('body').scrollTop(); let $element = this; const top_of_element = $element.offset().top; const bottom_of_element = $element.offset().top + $element.outerHeight(); const bottom_of_screen = scrolltop + $(window).innerHeight(); const top_of_screen = scrolltop; if (bottom_of_screen > top_of_element && top_of_screen < bottom_of_element) { return true; } else { return false; } }; // Gets the tagname of a jquery element $.fn.tagname = function () { return this.prop('tagName').toLowerCase(); }; // Returns true if a href is not same domain $.fn.is_external = function () { const host = window.location.host; const link = $('', { href: this.attr('href') })[0].hostname; return link !== host; }; // HTML5 form validation wrappers $.fn.checkValidity = function () { if (this.length === 0) return false; return this[0].checkValidity(); }; $.fn.reportValidity = function () { if (this.length === 0) return false; return this[0].reportValidity(); }; $.fn.requestSubmit = function () { if (this.length === 0) return this; this[0].requestSubmit(); return this; }; // Find related components by searching up the ancestor tree // Like .closest() but searches within ancestors instead of matching them $.fn.closest_sibling = function (selector) { let $current = this; let $parent = $current.parent(); // Keep going up the tree until we hit body while ($parent.length > 0 && !$parent.is('body')) { // Search within this parent for the selector let $found = $parent.find(selector); if ($found.length > 0) { return $found; } // Move up one level $parent = $parent.parent(); } // If we reached body, search within body as well if ($parent.is('body')) { let $found = $parent.find(selector); if ($found.length > 0) { return $found; } } // Return empty jQuery object if nothing found return $(); }; // Override $.ajax to prevent direct AJAX calls to local server // Developers must use the Ajax endpoint pattern: await Controller.method(params) const native_ajax = $.ajax; $.ajax = function (url, options) { // Handle both $.ajax(url, options) and $.ajax(options) signatures let settings; if (typeof url === 'string') { settings = options || {}; settings.url = url; } else { settings = url || {}; } // Check if this is a local request (relative URL or same domain) const request_url = settings.url || ''; const is_relative = !request_url.match(/^https?:\/\//); const is_same_domain = request_url.startsWith(window.location.origin); const is_local_request = is_relative || is_same_domain; // Allow framework Ajax.call() to function if (settings.__local_integration === true) { return native_ajax.call(this, settings); } // Allow file upload endpoint - requires native $.ajax for FormData support const is_file_upload = request_url === '/_upload' || request_url.endsWith('/_upload'); if (is_file_upload) { return native_ajax.call(this, settings); } // Block local AJAX requests that don't use the Ajax endpoint pattern if (is_local_request) { // Try to parse controller and action from URL let controller_name = null; let action_name = null; const url_match = request_url.match(/\/_rsx_api\/([^\/]+)\/([^\/\?]+)/); if (url_match) { controller_name = url_match[1]; action_name = url_match[2]; } let error_message = 'AJAX requests to localhost via $.ajax() are prohibited.\n\n'; if (controller_name && action_name) { error_message += `Instead of:\n`; error_message += ` $.ajax({url: '${request_url}', ...})\n\n`; error_message += `Use:\n`; error_message += ` await ${controller_name}.${action_name}(parameters)\n\n`; } else { error_message += `Use the Ajax endpoint pattern:\n`; error_message += ` await Controller_Name.action_name(parameters)\n\n`; } error_message += `The controller method must have the #[Ajax_Endpoint] attribute.`; shouldnt_happen(error_message); } // Allow external requests (different domain) return native_ajax.call(this, settings); }; } } /* === app/RSpade/Core/Js/Rsx.js (babel) === */ "use strict"; function _e8211f5b_defineProperty(e, r, t) { return (r = _e8211f5b_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _e8211f5b_toPropertyKey(t) { var i = _e8211f5b_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _e8211f5b_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } // @ROUTE-EXISTS-01-EXCEPTION - This file contains documentation examples with fictional route names /** * Rsx - Core JavaScript Runtime System * * The Rsx class is the central hub for the RSX JavaScript runtime, providing essential * system-level utilities that all other framework components depend on. It serves as the * foundation for the client-side framework, handling core operations that must be globally * accessible and consistently available. * * Core Responsibilities: * - Event System: Application-wide event bus for framework lifecycle and custom events * - Environment Detection: Runtime environment identification (dev/production) * - Route Management: Type-safe route generation and URL building * - Unique ID Generation: Client-side unique identifier generation * - Framework Bootstrap: Multi-phase initialization orchestration * - Logging: Centralized logging interface (delegates to console_debug) * * The Rsx class deliberately keeps its scope limited to core utilities. Advanced features * are delegated to specialized classes: * - Manifest operations → Manifest class * - Caching → Rsx_Cache class * - AJAX/API calls → Ajax_* classes * - Route proxies → Rsx_Route_Proxy class * - Behaviors → Rsx_Behaviors class * * All methods are static - Rsx is never instantiated. It's available globally from the * moment bundles load and remains constant throughout the application lifecycle. * * Usage Examples: * ```javascript * // Event system * Rsx.on('app_ready', () => console.log('App initialized')); * Rsx.trigger('custom_event', {data: 'value'}); * * // Environment detection * if (Rsx.is_dev()) { console.log('Development mode'); } * * // Route generation * const url = Rsx.Route('Controller', 'action').url(); * * // Unique IDs * const uniqueId = Rsx.uid(); // e.g., "rsx_1234567890_1" * ``` * * @static * @global */ class Rsx { // Initialize event handlers storage static _init_events() { if (typeof Rsx._event_handlers === 'undefined') { Rsx._event_handlers = {}; } if (typeof Rsx._triggered_events === 'undefined') { Rsx._triggered_events = {}; } } // Register an event handler static on(event, callback) { Rsx._init_events(); if (typeof callback !== 'function') { throw new Error('Callback must be a function'); } if (!Rsx._event_handlers[event]) { Rsx._event_handlers[event] = []; } Rsx._event_handlers[event].push(callback); // If this event was already triggered, call the callback immediately if (Rsx._triggered_events[event]) { console_debug('RSX_INIT', 'Triggering ' + event + ' for late registered callback'); callback(Rsx._triggered_events[event]); } } // Trigger an event with optional data static trigger(event) { let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; Rsx._init_events(); // Record that this event was triggered Rsx._triggered_events[event] = data; if (!Rsx._event_handlers[event]) { return; } console_debug('RSX_INIT', 'Triggering ' + event + ' for ' + Rsx._event_handlers[event].length + ' callbacks'); // Call all registered handlers for this event in order for (const callback of Rsx._event_handlers[event]) { callback(data); } } // Alias for trigger.refresh(''), should be called after major UI updates to apply such effects as // underlining links to unimplemented # routes static trigger_refresh() { // Use Rsx.on('refresh', callback); to register a callback for refresh this.trigger('refresh'); } // Log to server that an event happened static log(type) { let message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'notice'; Core_Log.log(type, message); } // Returns true if the app is being run in dev mode // This should affect caching and some debug checks static is_dev() { return window.rsxapp.debug; } static is_prod() { return !window.rsxapp.debug; } // Generates a unique number for the application instance static uid() { if (typeof Rsx._uid == undef) { Rsx._uid = 0; } return Rsx._uid++; } // Storage for route definitions loaded from bundles /** * Define routes from bundled data * Called by generated JavaScript in bundles */ static _define_routes(routes) { // Merge routes into the global route storage for (const class_name in routes) { if (!Rsx._routes[class_name]) { Rsx._routes[class_name] = {}; } for (const method_name in routes[class_name]) { Rsx._routes[class_name][method_name] = routes[class_name][method_name]; } } } /** * Generate URL for a controller route * * This method generates URLs for controller actions by looking up route patterns * and replacing parameters. It handles both regular routes and Ajax endpoints. * * If the route is not found in the route definitions, a default pattern is used: * `/_/{controller}/{action}` with all parameters appended as query strings. * * Usage examples: * ```javascript * // Simple route without parameters (defaults to 'index' action) * const url = Rsx.Route('Frontend_Index_Controller'); * // Returns: /dashboard * * // Route with explicit action * const url = Rsx.Route('Frontend_Index_Controller', 'index'); * // Returns: /dashboard * * // Route with integer parameter (sets 'id') * const url = Rsx.Route('Frontend_Client_View_Controller', 'view', 123); * // Returns: /clients/view/123 * * // Route with named parameters (object) * const url = Rsx.Route('Frontend_Client_View_Controller', 'view', {id: 'C001'}); * // Returns: /clients/view/C001 * * // Route with required and query parameters * const url = Rsx.Route('Frontend_Client_View_Controller', 'view', { * id: 'C001', * tab: 'history' * }); * // Returns: /clients/view/C001?tab=history * * // Route not found - uses default pattern * const url = Rsx.Route('Unimplemented_Controller', 'some_action', {foo: 'bar'}); * // Returns: /_/Unimplemented_Controller/some_action?foo=bar * * // Placeholder route * const url = Rsx.Route('Future_Controller', '#index'); * // Returns: # * ``` * * @param {string} class_name The controller class name (e.g., 'User_Controller') * @param {string} [action_name='index'] The action/method name (defaults to 'index'). Use '#action' for placeholders. * @param {number|Object} [params=null] Route parameters. Integer sets 'id', object provides named params. * @returns {string} The generated URL */ static Route(class_name) { let action_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'index'; let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; // Normalize params to object let params_obj = {}; if (typeof params === 'number') { params_obj = { id: params }; } else if (params && typeof params === 'object') { params_obj = params; } else if (params !== null && params !== undefined) { throw new Error('Params must be number, object, or null'); } // Placeholder route: action starts with # means unimplemented/scaffolding if (action_name.startsWith('#')) { return '#'; } // Check if route exists in definitions let pattern; if (Rsx._routes[class_name] && Rsx._routes[class_name][action_name]) { pattern = Rsx._routes[class_name][action_name]; } else { // Route not found - use default pattern /_/{controller}/{action} pattern = `/_/${class_name}/${action_name}`; } // Generate URL from pattern return Rsx._generate_url_from_pattern(pattern, params_obj); } /** * Generate URL from route pattern by replacing parameters * * @param {string} pattern The route pattern (e.g., '/users/:id/view') * @param {Object} params Parameters to fill into the route * @returns {string} The generated URL */ static _generate_url_from_pattern(pattern, params) { // Extract required parameters from the pattern const required_params = []; const matches = pattern.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g); if (matches) { // Remove the : prefix from each match for (const match of matches) { required_params.push(match.substring(1)); } } // Check for required parameters const missing = []; for (const required of required_params) { if (!(required in params)) { missing.push(required); } } if (missing.length > 0) { throw new Error(`Required parameters [${missing.join(', ')}] are missing for route ${pattern}`); } // Build the URL by replacing parameters let url = pattern; const used_params = {}; for (const param_name of required_params) { const value = params[param_name]; // URL encode the value const encoded_value = encodeURIComponent(value); url = url.replace(':' + param_name, encoded_value); used_params[param_name] = true; } // Collect any extra parameters for query string const query_params = {}; for (const key in params) { if (!used_params[key]) { query_params[key] = params[key]; } } // Append query string if there are extra parameters if (Object.keys(query_params).length > 0) { const query_string = Object.entries(query_params).map(_ref => { let [key, value] = _ref; return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; }).join('&'); url += '?' + query_string; } return url; } /** * Internal: Call a specific method on all classes that have it * Collects promises from return values and waits for all to resolve * @param {string} method_name The method name to call on all classes * @returns {Promise} Promise that resolves when all method calls complete */ static async _rsx_call_all_classes(method_name) { const all_classes = Manifest.get_all_classes(); const classes_with_method = []; const promise_pile = []; for (const class_info of all_classes) { const class_object = class_info.class_object; const class_name = class_info.class_name; // Check if this class has the method (static methods are on the class itself) if (typeof class_object[method_name] === 'function') { classes_with_method.push(class_name); const return_value = await class_object[method_name](); // Collect promises from return value if (return_value instanceof Promise) { promise_pile.push(return_value); } else if (Array.isArray(return_value)) { for (const item of return_value) { if (item instanceof Promise) { promise_pile.push(item); } } } if (Rsx.__stopped) { return; } } } if (classes_with_method.length > 0) { console_debug('RSX_INIT', `${method_name}: ${classes_with_method.length} classes`); } // Await all promises before returning if (promise_pile.length > 0) { console_debug('RSX_INIT', `${method_name}: Awaiting ${promise_pile.length} promises`); await Promise.all(promise_pile); } } /** * Internal: Execute multi-phase initialization for all registered classes * This runs various initialization phases in order to properly set up the application * @returns {Promise} Promise that resolves when all initialization phases complete */ static async _rsx_core_boot() { if (Rsx.__booted) { console.error('Rsx._rsx_core_boot called more than once'); return; } Rsx.__booted = true; // Get all registered classes from the manifest const all_classes = Manifest.get_all_classes(); console_debug('RSX_INIT', `Starting _rsx_core_boot with ${all_classes.length} classes`); if (!all_classes || all_classes.length === 0) { // No classes to initialize shouldnt_happen('No classes registered in js - there should be at least the core framework classes'); return; } // Define initialization phases in order const phases = [{ event: 'framework_core_define', method: '_on_framework_core_define' }, { event: 'framework_modules_define', method: '_on_framework_modules_define' }, { event: 'framework_core_init', method: '_on_framework_core_init' }, { event: 'app_modules_define', method: 'on_app_modules_define' }, { event: 'app_define', method: 'on_app_define' }, { event: 'framework_modules_init', method: '_on_framework_modules_init' }, { event: 'app_modules_init', method: 'on_app_modules_init' }, { event: 'app_init', method: 'on_app_init' }, { event: 'app_ready', method: 'on_app_ready' }]; // Execute each phase in order for (const phase of phases) { await Rsx._rsx_call_all_classes(phase.method); if (Rsx.__stopped) { return; } Rsx.trigger(phase.event); } // Ui refresh callbacks Rsx.trigger_refresh(); // All phases complete console_debug('RSX_INIT', 'Initialization complete'); // TODO: Find a good wait to wait for all jqhtml components to load, then trigger on_ready and on('ready') emulating the top level last syntax that jqhtml components operateas, but as a standard js class (such as a page class). The biggest question is, how do we efficiently choose only the top level jqhtml components. do we only consider components cretaed directly on blade templates? that seams reasonable... // Trigger _debug_ready event - this is ONLY for tooling like rsx:debug // DO NOT use this in application code - use on_app_ready() phase instead // This event exists solely for debugging tools that need to run after full initialization Rsx.trigger('_debug_ready'); } /* Calling this stops the boot process. */ static async _rsx_core_boot_stop(reason) { console.error(reason); Rsx.__stopped = true; } /** * Parse URL hash into key-value object * Handles format: #key=value&key2=value2 * * @returns {Object} Parsed hash parameters */ static _parse_hash() { const hash = window.location.hash; if (!hash || hash === '#') { return {}; } // Remove leading # and parse as query string const hash_string = hash.substring(1); const params = {}; const pairs = hash_string.split('&'); for (const pair of pairs) { const [key, value] = pair.split('='); if (key) { params[decodeURIComponent(key)] = value ? decodeURIComponent(value) : ''; } } return params; } /** * Serialize object into URL hash format * Produces format: #key=value&key2=value2 * * @param {Object} params Key-value pairs to encode * @returns {string} Encoded hash string (with leading #, or empty string) */ static _serialize_hash(params) { const pairs = []; for (const key in params) { const value = params[key]; if (value !== null && value !== undefined && value !== '') { pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`); } } return pairs.length > 0 ? '#' + pairs.join('&') : ''; } /** * Get all page state from URL hash * * Usage: * ```javascript * const state = Rsx.get_all_page_state(); * // Returns: {dg_page: '2', dg_sort: 'name'} * ``` * * @returns {Object} All hash parameters as key-value pairs */ static get_all_page_state() { return Rsx._parse_hash(); } /** * Get single value from URL hash state * * Usage: * ```javascript * const page = Rsx.get_page_state('dg_page'); * // Returns: '2' or null if not set * ``` * * @param {string} key The key to retrieve * @returns {string|null} The value or null if not found */ static get_page_state(key) { var _state$key; const state = Rsx._parse_hash(); return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null; } /** * Set single value in URL hash state (replaces history, doesn't add) * * Usage: * ```javascript * Rsx.set_page_state('dg_page', 2); * // URL becomes: http://example.com/page#dg_page=2 * * Rsx.set_page_state('dg_page', null); // Remove key * ``` * * @param {string} key The key to set * @param {string|number|null} value The value (null/empty removes the key) */ static set_page_state(key, value) { const state = Rsx._parse_hash(); // Update or remove the key if (value === null || value === undefined || value === '') { delete state[key]; } else { state[key] = String(value); } // Update URL without adding history const new_hash = Rsx._serialize_hash(state); const url = window.location.pathname + window.location.search + new_hash; history.replaceState(null, '', url); } /** * Set multiple values in URL hash state at once * * Usage: * ```javascript * Rsx.set_all_page_state({dg_page: 2, dg_sort: 'name'}); * // URL becomes: http://example.com/page#dg_page=2&dg_sort=name * ``` * * @param {Object} new_state Object with key-value pairs to set */ static set_all_page_state(new_state) { const state = Rsx._parse_hash(); // Merge new state for (const key in new_state) { const value = new_state[key]; if (value === null || value === undefined || value === '') { delete state[key]; } else { state[key] = String(value); } } // Update URL without adding history const new_hash = Rsx._serialize_hash(state); const url = window.location.pathname + window.location.search + new_hash; history.replaceState(null, '', url); } /** * Render an error in a DOM element * * Displays errors from Ajax calls in a standardized format. Handles different * error types (fatal, validation, auth, generic) with appropriate formatting. * * Usage: * ```javascript * try { * const result = await Controller.method(); * } catch (error) { * Rsx.render_error(error, '#error_container'); * } * ``` * * @param {Error|Object} error - Error object from Ajax call * @param {jQuery|string} container - jQuery element or selector for error display */ static render_error(error, container) { const $container = $(container); if (!$container.exists()) { console.error('Rsx.render_error: Container not found', container); return; } // Clear existing content $container.empty(); let html = ''; // Handle different error types if (error.type === 'fatal' && error.details) { // Fatal PHP error with file/line/error const details = error.details; const file = details.file || 'Unknown file'; const line = details.line || '?'; const message = details.error || error.message || 'Fatal error occurred'; html = ` `; } else if (error.type === 'form_error' && error.details) { // Validation errors - show unmatched errors only // (matched errors should be handled by Form_Utils.apply_form_errors) const errors = error.details; const error_list = []; for (const field in errors) { error_list.push(errors[field]); } if (error_list.length > 0) { html = ` `; } } else if (error.type === 'auth_required' || error.type === 'unauthorized') { // Authentication/authorization errors const message = error.message || 'Authentication required'; html = ` `; } else if (error.type === 'network') { // Network errors const message = error.message || 'Unable to reach server. Please check your connection.'; html = ` `; } else { // Generic/unknown error const message = error.message || error.toString() || 'An unknown error occurred'; html = ` `; } $container.html(html); } /** * Escape HTML to prevent XSS in error messages * @private */ static _escape_html(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } } // Gets set to true to interupt startup sequence _e8211f5b_defineProperty(Rsx, "__stopped", false); _e8211f5b_defineProperty(Rsx, "_routes", {}); /* === app/RSpade/Core/Js/Ajax.js (babel) === */ "use strict"; // @FILE-SUBCLASS-01-EXCEPTION /** * Client-side Ajax class for making API calls to RSX controllers * * Automatically batches multiple calls into single HTTP requests to reduce network overhead. * Batches up to 20 calls or flushes after setTimeout(0) debounce. */ class Ajax { /** * Initialize Ajax system * Called automatically when class is loaded */ static _on_framework_core_init() { // Queue of pending calls waiting to be batched Ajax._pending_calls = {}; // Timer for batching flush Ajax._flush_timeout = null; // Call counter for generating unique call IDs Ajax._call_counter = 0; // Maximum batch size before forcing immediate flush Ajax.MAX_BATCH_SIZE = 20; // Debounce time in milliseconds Ajax.DEBOUNCE_MS = 0; // Track promises from Ajax calls to detect uncaught rejections Ajax._tracked_promises = new WeakSet(); // Set up global unhandled rejection handler for Ajax errors window.addEventListener('unhandledrejection', async event => { // Only handle rejections from Ajax promises if (Ajax._tracked_promises.has(event.promise)) { event.preventDefault(); // Prevent browser's default "Uncaught (in promise)" error const error = event.reason; console.error('Uncaught Ajax error:', error); // Show Modal.error() for uncaught Ajax errors if (typeof Modal !== 'undefined' && Modal.error) { await Modal.error(error, 'Uncaught Ajax Error'); } } }); } /** * Make an AJAX call to an RSX controller action * * All calls are automatically batched unless window.rsxapp.ajax_disable_batching is true. * * @param {string|object|function} url - The Ajax URL (e.g., '/_ajax/Controller_Name/action_name') or an object/function with a .path property * @param {object} params - Parameters to send to the action * @returns {Promise} - Resolves with the return value, rejects with error */ static async call(url) { let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // If url is an object or function with a .path property, use that as the URL if (url && typeof url === 'object' && url.path) { url = url.path; } else if (url && typeof url === 'function' && url.path) { url = url.path; } // Validate url is a non-empty string if (typeof url !== 'string' || url.length === 0) { throw new Error('Ajax.call() requires a non-empty string URL or an object/function with a .path property'); } // Extract controller and action from URL const { controller, action } = Ajax.ajax_url_to_controller_action(url); console.log('Ajax:', controller, action, params); // Check if batching is disabled for debugging let promise; if (window.rsxapp && window.rsxapp.ajax_disable_batching) { promise = Ajax._call_direct(controller, action, params); } else { promise = Ajax._call_batch(controller, action, params); } // Track this promise for unhandled rejection detection Ajax._tracked_promises.add(promise); return promise; } /** * Make a batched Ajax call * @private */ static _call_batch(controller, action) { let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; console.log('Ajax Batch:', controller, action, params); return new Promise((resolve, reject) => { // Generate call key for deduplication const call_key = Ajax._generate_call_key(controller, action, params); // Check if this exact call is already pending if (Ajax._pending_calls[call_key]) { const existing_call = Ajax._pending_calls[call_key]; // If call already completed (cached), return immediately if (existing_call.is_complete) { if (existing_call.is_error) { reject(existing_call.error); } else { resolve(existing_call.result); } return; } // Call is pending, add this promise to callbacks existing_call.callbacks.push({ resolve, reject }); return; } // Create new pending call const call_id = Ajax._call_counter++; const pending_call = { call_id: call_id, call_key: call_key, controller: controller, action: action, params: params, callbacks: [{ resolve, reject }], is_complete: false, is_error: false, result: null, error: null }; // Add to pending queue Ajax._pending_calls[call_key] = pending_call; // Count pending calls const pending_count = Object.keys(Ajax._pending_calls).filter(key => !Ajax._pending_calls[key].is_complete).length; // If we've hit the batch size limit, flush immediately if (pending_count >= Ajax.MAX_BATCH_SIZE) { clearTimeout(Ajax._flush_timeout); Ajax._flush_timeout = null; Ajax._flush_pending_calls(); } else { // Schedule batch flush with debounce clearTimeout(Ajax._flush_timeout); Ajax._flush_timeout = setTimeout(() => { Ajax._flush_pending_calls(); }, Ajax.DEBOUNCE_MS); } }); } /** * Make a direct (non-batched) Ajax call * @private */ static async _call_direct(controller, action) { let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; // Construct URL from controller and action const url = `/_ajax/${controller}/${action}`; // Log the AJAX call using console_debug if (typeof Debugger !== 'undefined' && Debugger.console_debug) { Debugger.console_debug('AJAX', `Calling ${controller}.${action} (unbatched)`, params); } return new Promise((resolve, reject) => { $.ajax({ url: url, method: 'POST', data: params, dataType: 'json', __local_integration: true, // Bypass $.ajax override success: response => { // Handle console_debug messages if (response.console_debug && Array.isArray(response.console_debug)) { response.console_debug.forEach(msg => { if (!Array.isArray(msg) || msg.length !== 2) { throw new Error('Invalid console_debug message format - expected [channel, [arguments]]'); } const [channel, args] = msg; console.log(channel, ...args); }); } // Check if the response was successful if (response._success === true) { // @JS-AJAX-02-EXCEPTION - Unwrap server responses with _ajax_return_value const processed_value = Rsx_Js_Model._instantiate_models_recursive(response._ajax_return_value); resolve(processed_value); } else { // Handle error responses const error_type = response.error_type || 'unknown_error'; const reason = response.reason || 'Unknown error occurred'; const details = response.details || {}; // Handle specific error types switch (error_type) { case 'fatal': // Fatal PHP error with full error details const fatal_error_data = response.error || {}; const error_message = fatal_error_data.error || 'Fatal error occurred'; console.error('Ajax error response from server:', response.error); const fatal_error = new Error(error_message); fatal_error.type = 'fatal'; fatal_error.details = response.error; // Log to server if browser error logging is enabled Debugger.log_error({ message: `Ajax Fatal Error: ${error_message}`, type: 'ajax_fatal', endpoint: url, details: response.error }); reject(fatal_error); break; case 'response_auth_required': console.error('The user is no longer authenticated, this is a placeholder for future code which handles this scenario.'); const auth_error = new Error(reason); auth_error.type = 'auth_required'; auth_error.details = details; reject(auth_error); break; case 'response_unauthorized': console.error('The user is unauthorized to perform this action, this is a placeholder for future code which handles this scenario.'); const unauth_error = new Error(reason); unauth_error.type = 'unauthorized'; unauth_error.details = details; reject(unauth_error); break; case 'response_form_error': const form_error = new Error(reason); form_error.type = 'form_error'; form_error.details = details; reject(form_error); break; default: const generic_error = new Error(reason); generic_error.type = error_type; generic_error.details = details; reject(generic_error); break; } } }, error: (xhr, status, error) => { const error_message = Ajax._extract_error_message(xhr); const network_error = new Error(error_message); network_error.type = 'network_error'; network_error.status = xhr.status; network_error.statusText = status; // Log server errors (500+) to the server if browser error logging is enabled if (xhr.status >= 500) { Debugger.log_error({ message: `Ajax Server Error ${xhr.status}: ${error_message}`, type: 'ajax_server_error', endpoint: url, status: xhr.status, statusText: status }); } reject(network_error); } }); }); } /** * Flush all pending calls by sending batch request * @private */ static async _flush_pending_calls() { // Collect all pending calls const calls_to_send = []; const call_map = {}; // Map call_id to pending_call object for (const call_key in Ajax._pending_calls) { const pending_call = Ajax._pending_calls[call_key]; if (!pending_call.is_complete) { calls_to_send.push({ call_id: pending_call.call_id, controller: pending_call.controller, action: pending_call.action, params: pending_call.params }); call_map[pending_call.call_id] = pending_call; } } // Nothing to send if (calls_to_send.length === 0) { return; } // Log batch for debugging if (typeof Debugger !== 'undefined' && Debugger.console_debug) { Debugger.console_debug('AJAX_BATCH', `Sending batch of ${calls_to_send.length} calls`, calls_to_send.map(c => `${c.controller}.${c.action}`)); } try { // Send batch request const response = await $.ajax({ url: '/_ajax/_batch', method: 'POST', data: { batch_calls: JSON.stringify(calls_to_send) }, dataType: 'json', __local_integration: true // Bypass $.ajax override }); // Process batch response // Response format: { C_0: {success, _ajax_return_value}, C_1: {...}, ... } for (const response_key in response) { if (!response_key.startsWith('C_')) { continue; } const call_id = parseInt(response_key.substring(2), 10); const call_response = response[response_key]; const pending_call = call_map[call_id]; if (!pending_call) { console.error('Received response for unknown call_id:', call_id); continue; } // Handle console_debug messages if present if (call_response.console_debug && Array.isArray(call_response.console_debug)) { call_response.console_debug.forEach(msg => { if (!Array.isArray(msg) || msg.length !== 2) { throw new Error('Invalid console_debug message format - expected [channel, [arguments]]'); } const [channel, args] = msg; console.log(channel, ...args); }); } // Mark call as complete pending_call.is_complete = true; // Check if successful if (call_response._success === true) { // @JS-AJAX-02-EXCEPTION - Batch system unwraps server responses with _ajax_return_value const processed_value = Rsx_Js_Model._instantiate_models_recursive(call_response._ajax_return_value); pending_call.result = processed_value; // Resolve all callbacks pending_call.callbacks.forEach(_ref => { let { resolve } = _ref; resolve(processed_value); }); } else { // Handle error const error_type = call_response.error_type || 'unknown_error'; let error_message; let error_details; if (error_type === 'fatal' && call_response.error) { // Fatal PHP error with full error details const fatal_error_data = call_response.error; error_message = fatal_error_data.error || 'Fatal error occurred'; error_details = call_response.error; console.error('Ajax error response from server:', call_response.error); } else { // Other error types error_message = call_response.reason || 'Unknown error occurred'; error_details = call_response.details || {}; } const error = new Error(error_message); error.type = error_type; error.details = error_details; pending_call.is_error = true; pending_call.error = error; // Reject all callbacks pending_call.callbacks.forEach(_ref2 => { let { reject } = _ref2; reject(error); }); } } } catch (xhr_error) { // Network or server error - reject all pending calls const error_message = Ajax._extract_error_message(xhr_error); const error = new Error(error_message); error.type = 'network_error'; for (const call_id in call_map) { const pending_call = call_map[call_id]; pending_call.is_complete = true; pending_call.is_error = true; pending_call.error = error; pending_call.callbacks.forEach(_ref3 => { let { reject } = _ref3; reject(error); }); } console.error('Batch Ajax request failed:', error_message); } } /** * Generate a unique key for deduplicating calls * @private */ static _generate_call_key(controller, action, params) { // Create a stable string representation of the call // Sort params keys for consistent hashing const sorted_params = {}; Object.keys(params).sort().forEach(key => { sorted_params[key] = params[key]; }); return `${controller}::${action}::${JSON.stringify(sorted_params)}`; } /** * Extract error message from jQuery XHR object * @private */ static _extract_error_message(xhr) { if (xhr.responseJSON && xhr.responseJSON.message) { return xhr.responseJSON.message; } else if (xhr.responseText) { try { const response = JSON.parse(xhr.responseText); if (response.message) { return response.message; } } catch (e) { // Not JSON } } return `${xhr.status}: ${xhr.statusText || 'Unknown error'}`; } /** * Parses an AJAX URL into controller and action * Supports both /_ajax/ and /_/ URL prefixes * @param {string|object|function} url - URL in format '/_ajax/Controller_Name/action_name' or '/_/Controller_Name/action_name', or an object/function with a .path property * @returns {Object} Object with {controller: string, action: string} * @throws {Error} If URL doesn't start with /_ajax or /_ or has invalid structure */ static ajax_url_to_controller_action(url) { // If url is an object or function with a .path property, use that as the URL if (url && typeof url === 'object' && url.path) { url = url.path; } else if (url && typeof url === 'function' && url.path) { url = url.path; } // Validate url is a string if (typeof url !== 'string') { throw new Error(`URL must be a string or have a .path property, got: ${typeof url}`); } if (!url.startsWith('/_ajax') && !url.startsWith('/_/')) { throw new Error(`URL must start with /_ajax or /_, got: ${url}`); } const parts = url.split('/').filter(part => part !== ''); if (parts.length < 2) { throw new Error(`Invalid AJAX URL structure: ${url}`); } if (parts.length > 3) { throw new Error(`AJAX URL has too many segments: ${url}`); } const controller = parts[1]; const action = parts[2] || 'index'; return { controller, action }; } /** * Auto-initialize static properties when class is first loaded */ static on_core_define() { Ajax._on_framework_core_init(); } } /* === app/RSpade/Integrations/Jqhtml/Component.js (babel) === */ "use strict"; /** * Component - Base class for JQHTML components in RSX framework * * This class wraps the jqhtml.Component from the npm package and provides * the standard interface for RSX components following the Upper_Case naming convention. * * _Base_Jqhtml_Component is imported from npm via Jqhtml_Bundle. * * @Instantiatable */ class Component extends _Base_Jqhtml_Component {} // RSX manifest automatically makes classes global - no manual assignment needed /* === app/RSpade/Integrations/Jqhtml/Jqhtml_Integration.js (babel) === */ "use strict"; /** * JQHTML Integration - Automatic component registration and binding * * This module automatically: * 1. Registers component classes that extend Component * 2. Binds templates to component classes when names match * 3. Enables $(selector).component("Component_Name") syntax */ class Jqhtml_Integration { /** * Compiled Jqhtml templates self-register. The developer (the framework in this case) is still * responsible for registering es6 component classes with jqhtml. This does so at an early stage * of framework init. */ static _on_framework_modules_define() { let jqhtml_components = Manifest.get_extending('Component'); console_debug('JQHTML_INIT', 'Registering ' + jqhtml_components.length + ' Jqhtml Components'); for (let component of jqhtml_components) { jqhtml.register_component(component.class_name, component.class_object); } } /** * Framework modules init phase - Bind components and initialize DOM * This runs after templates are registered to bind component classes * @param {jQuery} [$scope] Optional scope to search within (defaults to body) * @returns {Array|undefined} Array of promises for recursive calls, undefined for top-level */ static _on_framework_modules_init($scope) { const is_top_level = !$scope; const promises = []; const components_needing_init = ($scope || $('body')).find('.Component_Init'); if (components_needing_init.length > 0) { console_debug('JQHTML_INIT', `Initializing ${components_needing_init.length} DOM components`); } components_needing_init.each(function () { const $element = $(this); // Skip if element is no longer attached to the document // (may have been removed by a parent component's .empty() call) if (!document.contains($element[0])) { return; } // Check if any parent has Component_Init class - skip nested components let parent = $element[0].parentElement; while (parent) { if (parent.classList.contains('Component_Init')) { return; // Skip this element, it's nested } parent = parent.parentElement; } const component_name = $element.attr('data-component-init-name'); // jQuery's .data() doesn't auto-parse JSON - we need to parse it manually let component_args = {}; const args_string = $element.attr('data-component-args'); // Unset component- php side initialization args, it is no longer needed as a compionent attribute // Unsetting also prevents undesired access to this code in other parts of the program, prevening an // unwanted future dependency on this paradigm $element.removeAttr('data-component-init-name'); $element.removeAttr('data-component-args'); $element.removeData('component-init-name'); $element.removeData('component-args'); if (args_string) { try { component_args = JSON.parse(args_string); } catch (e) { console.error(`[JQHTML Integration] Failed to parse component args for ${component_name}:`, e); component_args = {}; } } if (component_name) { // Transform $ prefixed keys to data- attributes let component_args_filtered = {}; for (const [key, value] of Object.entries(component_args)) { // if (key.startsWith('$')) { // component_args_filtered[key.substring(1)] = value; // } else if (key.startsWith('data-')) { component_args_filtered[key.substring(5)] = value; } else { component_args_filtered[key] = value; } } try { // Store inner HTML as string for nested component processing component_args_filtered._inner_html = $element.html(); $element.empty(); // Remove the init class before instantiation to prevent re-initialization $element.removeClass('Component_Init'); // Create promise for this component's initialization const component_promise = new Promise(resolve => { // Use jQuery component plugin to create the component // Plugin handles element internally, just pass args // Get the updated $element from let component = $element.component(component_name, component_args_filtered); component.on('render', function () { // Recursively collect promises from nested components // Getting the updated component here - if the tag name was not div, the element would have been recreated, so we need to get the element set on the component, not from our earlier selector const nested_promises = Jqhtml_Integration._on_framework_modules_init(component.$); promises.push(...nested_promises); // Resolve this component's promise resolve(); }).$; }); promises.push(component_promise); } catch (error) { console.error(`[JQHTML Integration] Failed to initialize component ${component_name}:`, error); console.error('Error details:', error.stack || error); } } }); // Top-level call: spawn async handler to wait for all promises, then trigger event if (is_top_level) { (async () => { await Promise.all(promises); await Rsx._rsx_call_all_classes('on_jqhtml_ready'); Rsx.trigger('jqhtml_ready'); })(); return; } // Recursive call: return promises for parent to collect return promises; } /** * Get all registered component names * @returns {Array} Array of component names */ static get_component_names() { return jqhtml.get_component_names(); } /** * Check if a component is registered * @param {string} name Component name * @returns {boolean} True if component is registered */ static has_component(name) { return jqhtml.has_component(name); } } // RSX manifest automatically makes classes global - no manual assignment needed /* === storage/rsx-tmp/bundle_Bootstrap5_Bundle_57b2a356.js === */ // JavaScript Manifest - Generated by BundleCompiler // Registers all classes in this bundle for runtime introspection Manifest._define([ [Manifest, "Manifest", null], [Rsx_Behaviors, "Rsx_Behaviors", null], [Rsx_Cache, "Rsx_Cache", null], [Rsx_Init, "Rsx_Init", null], [Rsx_Js_Model, "Rsx_Js_Model", null], [Rsx_View_Transitions, "Rsx_View_Transitions", null], [ReadWriteLock, "ReadWriteLock", null], [Form_Utils, "Form_Utils", null], [Debugger, "Debugger", null], [Rsx_Jq_Helpers, "Rsx_Jq_Helpers", null], [Rsx, "Rsx", null], [Ajax, "Ajax", null], [Component, "Component", _Base_Jqhtml_Component], [Jqhtml_Integration, "Jqhtml_Integration", null] ]); /* === storage/rsx-tmp/bundle_Bootstrap5_Bundle_e83e43d3.js === */ $(document).ready(async function() { try { console_debug('RSX_INIT', 'Document ready, starting Rsx._rsx_core_boot'); await Rsx._rsx_core_boot(); console_debug('RSX_INIT', 'Initialization complete'); } catch (error) { console.error('[RSX_INIT] Initialization failed:', error); console.error('[RSX_INIT] Stack:', error.stack); throw error; } }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0b3JhZ2UvcnN4LXRtcC9ucG1faW1wb3J0X2RlY2xhcmF0aW9uc185NWE2ZjYwMmM5ODAzNzYxMWI2NDBiMGI1MzQyODMwYi5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kZWNvcmF0b3IuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvYnJvd3Nlci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kYXRldGltZS5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9lcnJvci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9oYXNoLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL011dGV4LmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2FzeW5jLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2Z1bmN0aW9ucy5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9NYW5pZmVzdC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfQmVoYXZpb3JzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeF9DYWNoZS5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSW5pdC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSnNfTW9kZWwuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUnN4X1ZpZXdfVHJhbnNpdGlvbnMuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUmVhZFdyaXRlTG9jay5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Gb3JtX1V0aWxzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL0RlYnVnZ2VyLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeF9KcV9IZWxwZXJzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9BamF4LmpzIiwiYXBwL1JTcGFkZS9JbnRlZ3JhdGlvbnMvSnFodG1sL0pxaHRtbF9Db21wb25lbnQuanMiLCJhcHAvUlNwYWRlL0ludGVncmF0aW9ucy9KcWh0bWwvSnFodG1sX0ludGVncmF0aW9uLmpzIiwic3RvcmFnZS9yc3gtdG1wL2J1bmRsZV9Cb290c3RyYXA1X0J1bmRsZV81N2IyYTM1Ni5qcyIsInN0b3JhZ2UvcnN4LXRtcC9idW5kbGVfQm9vdHN0cmFwNV9CdW5kbGVfZTgzZTQzZDMuanMiXSwibmFtZXMiOlsiZGVjb3JhdG9yIiwidmFsdWUiLCJpc19tb2JpbGUiLCJ0ZXN0IiwibmF2aWdhdG9yIiwidXNlckFnZW50IiwiJCIsIndpbmRvdyIsIndpZHRoIiwiaXNfZGVza3RvcCIsImdldF9vcyIsInVzZXJfYWdlbnQiLCJwbGF0Zm9ybSIsIm1hY29zX3BsYXRmb3JtcyIsIndpbmRvd3NfcGxhdGZvcm1zIiwiaW9zX3BsYXRmb3JtcyIsIm9zIiwiaXNfbW9iaWxlX2RldmljZSIsImluZGV4T2YiLCJpc19jcmF3bGVyIiwiYm90X3BhdHRlcm4iLCJzY3JvbGxfaW50b192aWV3X2lmX25lZWRlZCIsInRhcmdldCIsIiR0YXJnZXQiLCIkcGFyZW50IiwicGFyZW50IiwidGFyZ2V0X3RvcCIsInBvc2l0aW9uIiwidG9wIiwic2Nyb2xsVG9wIiwidGFyZ2V0X2hlaWdodCIsIm91dGVySGVpZ2h0IiwicGFyZW50X2hlaWdodCIsImhlaWdodCIsInNjcm9sbF9wb3NpdGlvbiIsIkRlYnVnZ2VyIiwiY29uc29sZV9kZWJ1ZyIsIm5ld19zY3JvbGxfcG9zaXRpb24iLCJNYXRoIiwibWF4IiwibWluIiwic2Nyb2xsSGVpZ2h0Iiwic2Nyb2xsX3BhZ2VfaW50b192aWV3X2lmX25lZWRlZCIsIm9mZnNldCIsIndpbmRvd19oZWlnaHQiLCJ3aW5kb3dfc2Nyb2xsX3Bvc2l0aW9uIiwiYW5pbWF0ZSIsIndhaXRfZm9yX2ltYWdlcyIsImNhbGxiYWNrIiwiJGltYWdlcyIsInRvdGFsX2ltYWdlcyIsImxlbmd0aCIsImltYWdlc19sb2FkZWQiLCJlYWNoIiwiaW1nIiwiSW1hZ2UiLCJvbmxvYWQiLCJvbmVycm9yIiwic3JjIiwiJG5ic3AiLCJlc2NhcGVfanFfc2VsZWN0b3IiLCJpZCIsInJlcGxhY2UiLCJ1bml4X3RpbWUiLCJyb3VuZCIsIkRhdGUiLCJnZXRUaW1lIiwieW1kaGlzX3RvX3VuaXgiLCJzdHJfZGF0ZSIsImRhdGUiLCJlcnJvciIsInN0ciIsImVycm9yX2NvZGUiLCJ1bmRlZiIsInN0YXR1cyIsInNob3VsZG50X2hhcHBlbiIsIm1lc3NhZ2UiLCJhcmd1bWVudHMiLCJ1bmRlZmluZWQiLCJFcnJvciIsInN0YWNrIiwic3RhY2tMaW5lcyIsInNwbGl0IiwiY2FsbGVySW5mbyIsImNhbGxlckxpbmUiLCJtYXRjaCIsImVycm9yTWVzc2FnZSIsImNvbnNvbGUiLCJyZXBlYXQiLCJmYXRhbEVycm9yIiwibmFtZSIsImhhc2giLCJ0aGVfdmFyIiwiY2FsY19zaGExIiwiaWdub3JlZF9rZXlzIiwianNvbl9zdHJpbmdpZnlfbm9jaXJjIiwiY2FjaGUiLCJKU09OIiwic3RyaW5naWZ5Iiwia2V5IiwidiIsIl9jYWNoZV9rZXkiLCJfaGFzaF9rZXkiLCJwdXNoIiwiZmxhdF92YXIiLCJfZmxhdHRlbiIsInByZWZpeCIsImRlcHRoIiwiaXNfb2JqZWN0IiwiQWJzdHJhY3QiLCJrIiwiaGFzT3duUHJvcGVydHkiLCJpc19hcnJheSIsImkiLCJmb3JlYWNoIiwiaXNfZnVuY3Rpb24iLCJpc19udW1lcmljIiwiU3RyaW5nIiwic29ydGVyIiwic29ydCIsImEiLCJiIiwianNvbiIsImhhc2hlZCIsInNoYTEiLCJkZWVwX2VxdWFsIiwibXV0ZXgiLCJnbG9iYWxfaWQiLCJpbnN0YW5jZV9tdXRleGVzIiwiX2luc3RhbmNlX3N0b3JhZ2UiLCJXZWFrTWFwIiwiZ2xvYmFsX211dGV4ZXMiLCJfZ2xvYmFsX3N0b3JhZ2UiLCJNYXAiLCJnZXRfaW5zdGFuY2VfbXV0ZXgiLCJpbnN0YW5jZSIsIm1ldGhvZF9uYW1lIiwiaW5zdGFuY2VfbG9ja3MiLCJnZXQiLCJzZXQiLCJsb2NrX3N0YXRlIiwiYWN0aXZlIiwicXVldWUiLCJnZXRfZ2xvYmFsX211dGV4Iiwic2NoZWR1bGVfbmV4dCIsImZuIiwicmVzb2x2ZSIsInJlamVjdCIsInNoaWZ0IiwiUHJvbWlzZSIsInRoZW4iLCJmaW5hbGx5IiwiYWNxdWlyZV9sb2NrIiwiZGVzY3JpcHRvciIsIm9yaWdpbmFsX21ldGhvZCIsIl9sZW4iLCJhcmdzIiwiQXJyYXkiLCJfa2V5IiwiYXBwbHkiLCJfbGVuMiIsIl9rZXkyIiwic2xlZXAiLCJtaWxsaXNlY29uZHMiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJzZXRUaW1lb3V0IiwiZGVib3VuY2UiLCJjYWxsYmFja19vcl9kZWxheSIsImRlbGF5IiwiaW1tZWRpYXRlIiwiZGVjb3JhdG9yX2RlbGF5IiwiZGVjb3JhdG9yX2ltbWVkaWF0ZSIsImNvbnRleHQiLCJraW5kIiwiZGVib3VuY2VfaW1wbCIsInJ1bm5pbmciLCJxdWV1ZWQiLCJsYXN0X2VuZF90aW1lIiwidGltZXIiLCJuZXh0X2FyZ3MiLCJuZXh0X2NvbnRleHQiLCJyZXNvbHZlX3F1ZXVlIiwicmVqZWN0X3F1ZXVlIiwicnVuX2Z1bmN0aW9uIiwidGhlc2VfcmVzb2x2ZXMiLCJ0aGVzZV9yZWplY3RzIiwicmVzdWx0IiwiZXJyIiwibm93IiwiY2xlYXJUaW1lb3V0IiwiZmlyc3RfY2FsbCIsInNpbmNlIiwiSW5maW5pdHkiLCJ3YWl0Iiwicndsb2NrIiwiY2IiLCJSZWFkV3JpdGVMb2NrIiwiYWNxdWlyZSIsInJ3bG9ja19yZWFkIiwiYWNxdWlyZV9yZWFkIiwicndsb2NrX2ZvcmNlX3VubG9jayIsImZvcmNlX3VubG9jayIsInJ3bG9ja19wZW5kaW5nIiwicGVuZGluZyIsIm9iaiIsInJlc3VsdHMiLCJpc0FycmF5IiwiZm9yRWFjaCIsImluZGV4IiwicHJvbWlzZXMiLCJmaWx0ZXIiLCJhbGwiLCJuIiwiaXNOYU4iLCJwYXJzZUZsb2F0IiwiaXNGaW5pdGUiLCJpc19zdHJpbmciLCJzIiwiaXNfaW50ZWdlciIsIk51bWJlciIsImlzSW50ZWdlciIsImlzX3Byb21pc2UiLCJmdW5jdGlvbl90b19jaGVjayIsInRvU3RyaW5nIiwiY2FsbCIsImlzX2VtYWlsIiwiZW1haWwiLCJyZWdleCIsImlzc2V0IiwiZW1wdHkiLCJvYmplY3QiLCJmbG9hdCIsInZhbCIsInBhcnNlZCIsImludCIsInBhcnNlSW50IiwidmFsdWVfdW5sZXNzX251bWVyaWNfc3RyaW5nX3RoZW5fbnVtZXJpY192YWx1ZSIsImh0bWwiLCJfIiwiZXNjYXBlIiwibmwyYnIiLCJodG1sYnIiLCJ1cmxlbmNvZGUiLCJlbmNvZGVVUklDb21wb25lbnQiLCJ1cmxkZWNvZGUiLCJkZWNvZGVVUklDb21wb25lbnQiLCJqc29uX2VuY29kZSIsImpzb25fZGVjb2RlIiwicGFyc2UiLCJjaGFubmVsIiwidmFsdWVzIiwicmVwbGFjZV9hbGwiLCJzdHJpbmciLCJzZWFyY2giLCJqb2luIiwidWN3b3JkcyIsImlucHV0IiwibWFwIiwid29yZCIsImNoYXJBdCIsInRvVXBwZXJDYXNlIiwic2xpY2UiLCJjb3VudCIsIm8iLCJjIiwiY2xvbmUiLCJGdW5jdGlvbiIsInByb3RvdHlwZSIsIl9fY2xvbmUiLCJ0aGF0IiwidGVtcCIsImNsb25lZCIsImNvbnN0cnVjdG9yIiwiT2JqZWN0IiwiYXNzaWduIiwiY29hbGVzY2UiLCJmcm9tIiwicmV0dXJuX3ZhbCIsImFyZyIsImNzdl90b19hcnJheV90cmltIiwic3RyX2NzdiIsInBhcnRzIiwicmV0IiwicGFydCIsInRyaW0iLCJNYW5pZmVzdCIsIl9kZWZpbmUiLCJpdGVtcyIsIl9jbGFzc2VzIiwiaXRlbSIsImNsYXNzX29iamVjdCIsImNsYXNzX25hbWUiLCJjbGFzc19leHRlbmRzIiwiZGVjb3JhdG9ycyIsImNsYXNzIiwiZXh0ZW5kcyIsIl9uYW1lIiwiX2V4dGVuZHMiLCJfZGVjb3JhdG9ycyIsIl9idWlsZF9zdWJjbGFzc19pbmRleCIsIl9zdWJjbGFzc19pbmRleCIsImNsYXNzZGF0YSIsImN1cnJlbnRfY2xhc3NfbmFtZSIsImN1cnJlbnRfY2xhc3NkYXRhIiwiZXh0ZW5kc19uYW1lIiwiaW5jbHVkZXMiLCJnZXRfZXh0ZW5kaW5nIiwiYmFzZV9jbGFzcyIsImJhc2VfY2xhc3Nfb2JqZWN0IiwiZ2V0X2NsYXNzX2J5X25hbWUiLCJjbGFzc2VzIiwianNfaXNfc3ViY2xhc3Nfb2YiLCJsb2NhbGVDb21wYXJlIiwic3ViY2xhc3MiLCJzdXBlcmNsYXNzIiwic3ViY2xhc3Nfb2JqZWN0Iiwic3VwZXJjbGFzc19vYmplY3QiLCJjdXJyZW50X2NsYXNzIiwiZ2V0X2FsbF9jbGFzc2VzIiwiYnVpbGRfa2V5IiwicnN4YXBwIiwiZ2V0X2RlY29yYXRvcnMiLCJjbGFzc19pbmZvIiwiX3RyYW5zZm9ybV9kZWNvcmF0b3JzIiwiZ2V0X2FsbF9kZWNvcmF0b3JzIiwiY29tcGFjdF9kZWNvcmF0b3JzIiwiaGFzX2RlY29yYXRvciIsImRlY29yYXRvcl9uYW1lIiwic29tZSIsImQiLCJqc19nZXRfc3ViY2xhc3Nlc19vZiIsImJhc2VfY2xhc3NfbmFtZSIsInN1YmNsYXNzX25hbWVzIiwic3ViY2xhc3Nfb2JqZWN0cyIsInN1YmNsYXNzX25hbWUiLCJuYW1lX2EiLCJuYW1lX2IiLCJSc3hfQmVoYXZpb3JzIiwiX29uX2ZyYW1ld29ya19jb3JlX2luaXQiLCJfaW5pdF9pZ25vcmVfaW52YWxpZF9hbmNob3JfbGlua3MiLCJfdHJpbV9jb3BpZWRfdGV4dCIsImRvY3VtZW50Iiwib24iLCJlIiwiJGxpbmsiLCJocmVmIiwiYXR0ciIsImlzRGVmYXVsdFByZXZlbnRlZCIsImRhdGEiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiIsInN0YXJ0c1dpdGgiLCJ0YXJnZXRJZCIsInN1YnN0cmluZyIsInRhcmdldEV4aXN0cyIsImdldEVsZW1lbnRCeUlkIiwicXVlcnlTZWxlY3RvciIsImFkZEV2ZW50TGlzdGVuZXIiLCJldmVudCIsInNoaWZ0S2V5Iiwic2VsZWN0aW9uIiwiZ2V0U2VsZWN0aW9uIiwic2VsZWN0ZWRfdGV4dCIsImNvbnRhaW5lciIsImdldFJhbmdlQXQiLCJjb21tb25BbmNlc3RvckNvbnRhaW5lciIsIm5vZGVUeXBlIiwicGFyZW50Tm9kZSIsImNsb3Nlc3QiLCJ0cmltbWVkX3RleHQiLCJjbGlwYm9hcmREYXRhIiwic2V0RGF0YSIsImxvZyIsIlJzeF9DYWNoZSIsIm9uX2NvcmVfZGVmaW5lIiwiQ29yZV9DYWNoZSIsIl9jYWNoZXMiLCJnbG9iYWwiLCJfY2FjaGVzX3NldCIsImdldF9pbnN0YW5jZSIsIk1haW4iLCJkZWJ1ZyIsImtleV9lbmNvZGVkIiwiX2VuY29kZWtleSIsImdldF9nbG9iYWwiLCJnZXRfc2Vzc2lvbiIsIl9zdXBwb3J0c1N0b3JhZ2UiLCJycyIsInNlc3Npb25TdG9yYWdlIiwiZ2V0SXRlbSIsInNldF9zZXNzaW9uIiwiX3RyeWFnYWluIiwicmVtb3ZlSXRlbSIsInNldEl0ZW0iLCJfaXNPdXRPZlNwYWNlIiwiY2xlYXIiLCJfcmVzZXQiLCJfX3N1cHBvcnRzU3RvcmFnZSIsImV4IiwiUnN4X0luaXQiLCJSc3giLCJpc19wcm9kIiwiX19lbnZpcm9ubWVudF9jaGVja3MiLCJzY3JpcHRzIiwiZ2V0RWxlbWVudHNCeVRhZ05hbWUiLCJzY3JpcHQiLCJkZWZlciIsInJlYXNvbiIsIl9yc3hfY29yZV9ib290X3N0b3AiLCJSc3hfSnNfTW9kZWwiLCJfX01PREVMIiwibW9kZWxEYXRhIiwiZmV0Y2giLCJDdXJyZW50Q2xhc3MiLCJtb2RlbE5hbWUiLCJyZXNwb25zZSIsImFqYXgiLCJ1cmwiLCJtZXRob2QiLCJkYXRhVHlwZSIsIl9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlIiwiZ2V0TW9kZWxOYW1lIiwicmVmcmVzaCIsImZyZXNoIiwidG9PYmplY3QiLCJ0b0pTT04iLCJNb2RlbENsYXNzIiwiUnN4X1ZpZXdfVHJhbnNpdGlvbnMiLCJzdGFydFZpZXdUcmFuc2l0aW9uIiwiX2luamVjdF90cmFuc2l0aW9uX2NzcyIsInN0eWxlIiwiY3JlYXRlRWxlbWVudCIsInRleHRDb250ZW50IiwiaGVhZCIsImFwcGVuZENoaWxkIiwiXzUwYWU2MDllX2Fzc2VydENsYXNzQnJhbmQiLCJfNTBhZTYwOWVfZ2V0X2xvY2siLCJ3cml0ZXJfcSIsIl81MGFlNjA5ZV9zY2hlZHVsZSIsIndyaXRlcl9hY3RpdmUiLCJyZWFkZXJfcSIsInJlYWRlcnMiLCJfbG9ja3MiLCJkZWxldGUiLCJfNTBhZTYwOWVfUmVhZFdyaXRlTG9jayIsImJhdGNoIiwic3BsaWNlIiwiRm9ybV9VdGlscyIsIl9vbl9mcmFtZXdvcmtfY29yZV9kZWZpbmUiLCJwYXJhbXMiLCJhamF4X3N1Ym1pdCIsIm9wdGlvbnMiLCIkZWxlbWVudCIsImlzIiwiY29udHJvbGxlciIsImFjdGlvbiIsIkFqYXgiLCJhamF4X3VybF90b19jb250cm9sbGVyX2FjdGlvbiIsImFwcGx5X2Zvcm1fZXJyb3JzIiwicGFyZW50X3NlbGVjdG9yIiwiZXJyb3JzIiwicmVzZXRfZm9ybV9lcnJvcnMiLCJub3JtYWxpemVkIiwiX25vcm1hbGl6ZV9lcnJvcnMiLCJhbmltYXRpb25zIiwidHlwZSIsIl9hcHBseV9nZW5lcmFsX2Vycm9ycyIsImRlZHVwbGljYXRlZCIsIl9kZWR1cGxpY2F0ZV9lcnJvcnMiLCJfYXBwbHlfZmllbGRfZXJyb3JzIiwibWF0Y2hlZF9jb3VudCIsImtleXMiLCJ1bm1hdGNoZWQiLCJ1bm1hdGNoZWRfZGVkdXBsaWNhdGVkIiwidW5tYXRjaGVkX2NvdW50Iiwic3VtbWFyeV9tc2ciLCJzdW1tYXJ5X2FuaW1hdGlvbnMiLCJfYXBwbHlfY29tYmluZWRfZXJyb3IiLCIkZXJyb3JfY29udGFpbmVyIiwiZmluZCIsImZpcnN0IiwiY29udGFpbmVyX3RvcCIsImZpeGVkX2hlYWRlcl9oZWlnaHQiLCJfZ2V0X2ZpeGVkX2hlYWRlcl9oZWlnaHQiLCJ0YXJnZXRfc2Nyb2xsIiwicmVzZXQiLCJmb3JtX3NlbGVjdG9yIiwiJGZvcm0iLCJ0cmlnZ2VyIiwic2VyaWFsaXplIiwic2VyaWFsaXplQXJyYXkiLCJmb3JtX2RhdGEiLCJvbl9zdWNjZXNzIiwiZGV0YWlscyIsIm9uX2Vycm9yIiwicmVtb3ZlIiwicmVtb3ZlQ2xhc3MiLCJldmVyeSIsInVud3JhcHBlZCIsImZpZWxkIiwiU2V0Iiwic2VlbiIsImhhcyIsImFkZCIsImZpZWxkX2Vycm9ycyIsImZpZWxkX25hbWUiLCJlcnJvcl9tZXNzYWdlIiwiJGlucHV0IiwiJGVycm9yIiwiYWRkQ2xhc3MiLCJhcHBlbmRUbyIsImhpZGUiLCJmYWRlSW4iLCJwcm9taXNlIiwidW5tYXRjaGVkX2Vycm9ycyIsIiRhbGVydCIsInRleHQiLCIkbGlzdCIsImVycm9yX21zZyIsInByZXBlbmRUbyIsIm1lc3NhZ2VzIiwibXNnIiwiZXJyb3JfbGlzdCIsInRvdGFsX2hlaWdodCIsIiRlbCIsImNzcyIsIm91dGVyV2lkdGgiLCJ2aWV3cG9ydF93aWR0aCIsImxvZ19icm93c2VyX2Vycm9ycyIsIl9oYW5kbGVfYnJvd3Nlcl9lcnJvciIsImZpbGVuYW1lIiwibGluZW5vIiwiY29sbm8iLCJvbl9yZWZyZXNoIiwiZW5hYmxlZCIsImNvbmZpZyIsImZpbHRlcl9tb2RlIiwic3BlY2lmaWMiLCJzcGVjaWZpY19jaGFubmVsIiwiY2hhbm5lbHMiLCJ3aGl0ZWxpc3QiLCJmaWx0ZXJfY2hhbm5lbHMiLCJibGFja2xpc3QiLCJ0aW1lc3RhbXAiLCJ0b0lTT1N0cmluZyIsImluY2x1ZGVfbG9jYXRpb24iLCJpbmNsdWRlX2JhY2t0cmFjZSIsImxvY2F0aW9uIiwiYmFja3RyYWNlIiwibGluZSIsIm91dHB1dHMiLCJicm93c2VyIiwiaW5jbHVkZV9iZW5jaG1hcmsiLCJfZ2V0X3RpbWVfcHJlZml4IiwiY2hhbm5lbFByZWZpeCIsImNvbnNvbGVNZXRob2QiLCJsYXJhdmVsX2xvZyIsIl9iYXRjaF9jb25zb2xlX21lc3NhZ2UiLCJsb2dfZXJyb3IiLCJlcnJvckRhdGEiLCJfZXJyb3JfY291bnQiLCJNQVhfRVJST1JTX1BFUl9QQUdFIiwiX2Vycm9yX2JhdGNoX2NvdW50IiwiTUFYX0VSUk9SX0JBVENIRVMiLCJfZXJyb3JfYmF0Y2giLCJfZXJyb3JfdGltZXIiLCJfZmx1c2hfZXJyb3JfYmF0Y2giLCJERUJPVU5DRV9NUyIsIl9jb25zb2xlX2JhdGNoIiwiX2NvbnNvbGVfdGltZXIiLCJfZmx1c2hfY29uc29sZV9iYXRjaCIsIlJvdXRlIiwiX3N0YXJ0X3RpbWUiLCJlbGFwc2VkIiwidG9GaXhlZCIsIl8yN2UwZTk4Nl9kZWZpbmVQcm9wZXJ0eSIsIlJzeF9KcV9IZWxwZXJzIiwiZXhpc3RzIiwiaXNfdmlzaWJsZSIsInNjcm9sbF91cF90byIsInNwZWVkIiwiaXNfaW5fZG9tIiwiZV90b3AiLCJzX3RvcCIsImV4cHIiLCJmb2N1cyIsImVsZW0iLCJhY3RpdmVFbGVtZW50IiwiX2NsaWNrX25hdGl2ZSIsImNsaWNrIiwiaGFuZGxlciIsIm9yaWdpbmFsX3ByZXZlbnREZWZhdWx0IiwiYmluZCIsIndhcm4iLCJjbGlja19hbGxvd19kZWZhdWx0IiwiX2FuY2VzdG9yIiwiSFRNTG9iaiIsInBhcmVudEVsZW1lbnQiLCJkb2N1bWVudEVsZW1lbnQiLCJpc19pbl92aWV3cG9ydCIsInNjcm9sbHRvcCIsInRvcF9vZl9lbGVtZW50IiwiYm90dG9tX29mX2VsZW1lbnQiLCJib3R0b21fb2Zfc2NyZWVuIiwiaW5uZXJIZWlnaHQiLCJ0b3Bfb2Zfc2NyZWVuIiwidGFnbmFtZSIsInByb3AiLCJ0b0xvd2VyQ2FzZSIsImlzX2V4dGVybmFsIiwiaG9zdCIsImxpbmsiLCJob3N0bmFtZSIsImNoZWNrVmFsaWRpdHkiLCJyZXBvcnRWYWxpZGl0eSIsInJlcXVlc3RTdWJtaXQiLCJjbG9zZXN0X3NpYmxpbmciLCJzZWxlY3RvciIsIiRjdXJyZW50IiwiJGZvdW5kIiwibmF0aXZlX2FqYXgiLCJzZXR0aW5ncyIsInJlcXVlc3RfdXJsIiwiaXNfcmVsYXRpdmUiLCJpc19zYW1lX2RvbWFpbiIsIm9yaWdpbiIsImlzX2xvY2FsX3JlcXVlc3QiLCJfX2xvY2FsX2ludGVncmF0aW9uIiwiaXNfZmlsZV91cGxvYWQiLCJlbmRzV2l0aCIsImNvbnRyb2xsZXJfbmFtZSIsImFjdGlvbl9uYW1lIiwidXJsX21hdGNoIiwiX2luaXRfZXZlbnRzIiwiX2V2ZW50X2hhbmRsZXJzIiwiX3RyaWdnZXJlZF9ldmVudHMiLCJ0cmlnZ2VyX3JlZnJlc2giLCJDb3JlX0xvZyIsImlzX2RldiIsInVpZCIsIl91aWQiLCJfZGVmaW5lX3JvdXRlcyIsInJvdXRlcyIsIl9yb3V0ZXMiLCJwYXJhbXNfb2JqIiwicGF0dGVybiIsIl9nZW5lcmF0ZV91cmxfZnJvbV9wYXR0ZXJuIiwicmVxdWlyZWRfcGFyYW1zIiwibWF0Y2hlcyIsIm1pc3NpbmciLCJyZXF1aXJlZCIsInVzZWRfcGFyYW1zIiwicGFyYW1fbmFtZSIsImVuY29kZWRfdmFsdWUiLCJxdWVyeV9wYXJhbXMiLCJxdWVyeV9zdHJpbmciLCJlbnRyaWVzIiwiX3JlZiIsIl9yc3hfY2FsbF9hbGxfY2xhc3NlcyIsImFsbF9jbGFzc2VzIiwiY2xhc3Nlc193aXRoX21ldGhvZCIsInByb21pc2VfcGlsZSIsInJldHVybl92YWx1ZSIsIl9fc3RvcHBlZCIsIl9yc3hfY29yZV9ib290IiwiX19ib290ZWQiLCJwaGFzZXMiLCJwaGFzZSIsIl9wYXJzZV9oYXNoIiwiaGFzaF9zdHJpbmciLCJwYWlycyIsInBhaXIiLCJfc2VyaWFsaXplX2hhc2giLCJnZXRfYWxsX3BhZ2Vfc3RhdGUiLCJnZXRfcGFnZV9zdGF0ZSIsIl9zdGF0ZSRrZXkiLCJzdGF0ZSIsInNldF9wYWdlX3N0YXRlIiwibmV3X2hhc2giLCJwYXRobmFtZSIsImhpc3RvcnkiLCJyZXBsYWNlU3RhdGUiLCJzZXRfYWxsX3BhZ2Vfc3RhdGUiLCJuZXdfc3RhdGUiLCJyZW5kZXJfZXJyb3IiLCIkY29udGFpbmVyIiwiZmlsZSIsIl9lc2NhcGVfaHRtbCIsImRpdiIsImlubmVySFRNTCIsIl9lODIxMWY1Yl9kZWZpbmVQcm9wZXJ0eSIsIl9wZW5kaW5nX2NhbGxzIiwiX2ZsdXNoX3RpbWVvdXQiLCJfY2FsbF9jb3VudGVyIiwiTUFYX0JBVENIX1NJWkUiLCJfdHJhY2tlZF9wcm9taXNlcyIsIldlYWtTZXQiLCJNb2RhbCIsInBhdGgiLCJhamF4X2Rpc2FibGVfYmF0Y2hpbmciLCJfY2FsbF9kaXJlY3QiLCJfY2FsbF9iYXRjaCIsImNhbGxfa2V5IiwiX2dlbmVyYXRlX2NhbGxfa2V5IiwiZXhpc3RpbmdfY2FsbCIsImlzX2NvbXBsZXRlIiwiaXNfZXJyb3IiLCJjYWxsYmFja3MiLCJjYWxsX2lkIiwicGVuZGluZ19jYWxsIiwicGVuZGluZ19jb3VudCIsIl9mbHVzaF9wZW5kaW5nX2NhbGxzIiwic3VjY2VzcyIsIl9zdWNjZXNzIiwicHJvY2Vzc2VkX3ZhbHVlIiwiX2FqYXhfcmV0dXJuX3ZhbHVlIiwiZXJyb3JfdHlwZSIsImZhdGFsX2Vycm9yX2RhdGEiLCJmYXRhbF9lcnJvciIsImVuZHBvaW50IiwiYXV0aF9lcnJvciIsInVuYXV0aF9lcnJvciIsImZvcm1fZXJyb3IiLCJnZW5lcmljX2Vycm9yIiwieGhyIiwiX2V4dHJhY3RfZXJyb3JfbWVzc2FnZSIsIm5ldHdvcmtfZXJyb3IiLCJzdGF0dXNUZXh0IiwiY2FsbHNfdG9fc2VuZCIsImNhbGxfbWFwIiwiYmF0Y2hfY2FsbHMiLCJyZXNwb25zZV9rZXkiLCJjYWxsX3Jlc3BvbnNlIiwiZXJyb3JfZGV0YWlscyIsIl9yZWYyIiwieGhyX2Vycm9yIiwiX3JlZjMiLCJzb3J0ZWRfcGFyYW1zIiwicmVzcG9uc2VKU09OIiwicmVzcG9uc2VUZXh0IiwiSnFodG1sX0NvbXBvbmVudCIsIl9CYXNlX0pxaHRtbF9Db21wb25lbnQiLCJKcWh0bWxfSW50ZWdyYXRpb24iLCJfb25fZnJhbWV3b3JrX21vZHVsZXNfZGVmaW5lIiwianFodG1sX2NvbXBvbmVudHMiLCJjb21wb25lbnQiLCJqcWh0bWwiLCJyZWdpc3Rlcl9jb21wb25lbnQiLCJfb25fZnJhbWV3b3JrX21vZHVsZXNfaW5pdCIsIiRzY29wZSIsImlzX3RvcF9sZXZlbCIsImNvbXBvbmVudHNfbmVlZGluZ19pbml0IiwiY29udGFpbnMiLCJjbGFzc0xpc3QiLCJjb21wb25lbnRfbmFtZSIsImNvbXBvbmVudF9hcmdzIiwiYXJnc19zdHJpbmciLCJyZW1vdmVBdHRyIiwicmVtb3ZlRGF0YSIsImNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkIiwiX2lubmVyX2h0bWwiLCJjb21wb25lbnRfcHJvbWlzZSIsIm5lc3RlZF9wcm9taXNlcyIsImdldF9jb21wb25lbnRfbmFtZXMiLCJoYXNfY29tcG9uZW50Il0sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNBLFNBQVNBLENBQUNDLEtBQUssRUFBRTtFQUN0QixPQUFPQSxLQUFLO0FBQ2hCOzs7Ozs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyxTQUFTQSxDQUFBLEVBQUc7RUFDakIsSUFBSSxnRUFBZ0UsQ0FBQ0MsSUFBSSxDQUFDQyxTQUFTLENBQUNDLFNBQVMsQ0FBQyxFQUFFO0lBQzVGLE9BQU8sSUFBSTtFQUNmLENBQUMsTUFBTSxJQUFJQyxDQUFDLENBQUNDLE1BQU0sQ0FBQyxDQUFDQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsRUFBRTtJQUNoQztJQUNBLE9BQU8sSUFBSTtFQUNmLENBQUMsTUFBTTtJQUNILE9BQU8sS0FBSztFQUNoQjtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsVUFBVUEsQ0FBQSxFQUFHO0VBQ2xCLE9BQU8sQ0FBQ1AsU0FBUyxDQUFDLENBQUM7QUFDdkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTUSxNQUFNQSxDQUFBLEVBQUc7RUFDZCxJQUFJQyxVQUFVLEdBQUdKLE1BQU0sQ0FBQ0gsU0FBUyxDQUFDQyxTQUFTO0lBQ3ZDTyxRQUFRLEdBQUdMLE1BQU0sQ0FBQ0gsU0FBUyxDQUFDUSxRQUFRO0lBQ3BDQyxlQUFlLEdBQUcsQ0FBQyxXQUFXLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUM7SUFDL0RDLGlCQUFpQixHQUFHLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDO0lBQzFEQyxhQUFhLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUMxQ0MsRUFBRSxHQUFHLElBQUk7RUFFYixJQUFJQyxnQkFBZ0IsR0FBR2YsU0FBUyxDQUFDLENBQUM7RUFFbEMsSUFBSVcsZUFBZSxDQUFDSyxPQUFPLENBQUNOLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO0lBQzFDSSxFQUFFLEdBQUcsUUFBUTtFQUNqQixDQUFDLE1BQU0sSUFBSUQsYUFBYSxDQUFDRyxPQUFPLENBQUNOLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJSyxnQkFBZ0IsRUFBRTtJQUNuRUQsRUFBRSxHQUFHLFFBQVE7RUFDakIsQ0FBQyxNQUFNLElBQUlELGFBQWEsQ0FBQ0csT0FBTyxDQUFDTixRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDSyxnQkFBZ0IsRUFBRTtJQUNwRUQsRUFBRSxHQUFHLE1BQU07RUFDZixDQUFDLE1BQU0sSUFBSUYsaUJBQWlCLENBQUNJLE9BQU8sQ0FBQ04sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7SUFDbkRJLEVBQUUsR0FBRyxTQUFTO0VBQ2xCLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQ2IsSUFBSSxDQUFDUSxVQUFVLENBQUMsSUFBSU0sZ0JBQWdCLEVBQUU7SUFDdkRELEVBQUUsR0FBRyxlQUFlO0VBQ3hCLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQ2IsSUFBSSxDQUFDUSxVQUFVLENBQUMsSUFBSSxDQUFDTSxnQkFBZ0IsRUFBRTtJQUN4REQsRUFBRSxHQUFHLGdCQUFnQjtFQUN6QixDQUFDLE1BQU0sSUFBSSxDQUFDQSxFQUFFLElBQUksT0FBTyxDQUFDYixJQUFJLENBQUNTLFFBQVEsQ0FBQyxFQUFFO0lBQ3RDSSxFQUFFLEdBQUcsT0FBTztFQUNoQixDQUFDLE1BQU07SUFDSEEsRUFBRSxHQUFHLFNBQVM7RUFDbEI7RUFFQSxPQUFPQSxFQUFFO0FBQ2I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTRyxVQUFVQSxDQUFBLEVBQUc7RUFDbEIsSUFBSVIsVUFBVSxHQUFHUCxTQUFTLENBQUNDLFNBQVM7RUFDcEMsSUFBSWUsV0FBVyxHQUFHLHlHQUF5RztFQUUzSCxPQUFPQSxXQUFXLENBQUNqQixJQUFJLENBQUNRLFVBQVUsQ0FBQztBQUN2Qzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTVSwwQkFBMEJBLENBQUNDLE1BQU0sRUFBRTtFQUN4QyxNQUFNQyxPQUFPLEdBQUdqQixDQUFDLENBQUNnQixNQUFNLENBQUM7O0VBRXpCO0VBQ0EsTUFBTUUsT0FBTyxHQUFHRCxPQUFPLENBQUNFLE1BQU0sQ0FBQyxDQUFDOztFQUVoQztFQUNBLE1BQU1DLFVBQVUsR0FBR0gsT0FBTyxDQUFDSSxRQUFRLENBQUMsQ0FBQyxDQUFDQyxHQUFHLEdBQUdKLE9BQU8sQ0FBQ0ssU0FBUyxDQUFDLENBQUM7RUFFL0QsTUFBTUMsYUFBYSxHQUFHUCxPQUFPLENBQUNRLFdBQVcsQ0FBQyxDQUFDO0VBQzNDLE1BQU1DLGFBQWEsR0FBR1IsT0FBTyxDQUFDUyxNQUFNLENBQUMsQ0FBQztFQUN0QyxNQUFNQyxlQUFlLEdBQUdWLE9BQU8sQ0FBQ0ssU0FBUyxDQUFDLENBQUM7O0VBRTNDO0VBQ0EsSUFBSUgsVUFBVSxHQUFHUSxlQUFlLElBQUlSLFVBQVUsR0FBR0ksYUFBYSxHQUFHSSxlQUFlLEdBQUdGLGFBQWEsRUFBRTtJQUM5RkcsUUFBUSxDQUFDQyxhQUFhLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRVYsVUFBVSxDQUFDOztJQUV0RDtJQUNBLElBQUlXLG1CQUFtQixHQUFHWCxVQUFVLEdBQUdJLGFBQWEsR0FBRyxDQUFDLEdBQUdFLGFBQWEsR0FBRyxDQUFDOztJQUU1RTtJQUNBSyxtQkFBbUIsR0FBR0MsSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQyxFQUFFRCxJQUFJLENBQUNFLEdBQUcsQ0FBQ0gsbUJBQW1CLEVBQUViLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQ2lCLFlBQVksR0FBR1QsYUFBYSxDQUFDLENBQUM7O0lBRXpHO0lBQ0FSLE9BQU8sQ0FBQ0ssU0FBUyxDQUFDUSxtQkFBbUIsQ0FBQztFQUMxQztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0ssK0JBQStCQSxDQUFDcEIsTUFBTSxFQUFFO0VBQzdDLE1BQU1DLE9BQU8sR0FBR2pCLENBQUMsQ0FBQ2dCLE1BQU0sQ0FBQzs7RUFFekI7RUFDQSxNQUFNSSxVQUFVLEdBQUdILE9BQU8sQ0FBQ29CLE1BQU0sQ0FBQyxDQUFDLENBQUNmLEdBQUc7RUFFdkMsTUFBTUUsYUFBYSxHQUFHUCxPQUFPLENBQUNRLFdBQVcsQ0FBQyxDQUFDO0VBQzNDLE1BQU1hLGFBQWEsR0FBR3RDLENBQUMsQ0FBQ0MsTUFBTSxDQUFDLENBQUMwQixNQUFNLENBQUMsQ0FBQztFQUN4QyxNQUFNWSxzQkFBc0IsR0FBR3ZDLENBQUMsQ0FBQ0MsTUFBTSxDQUFDLENBQUNzQixTQUFTLENBQUMsQ0FBQzs7RUFFcEQ7RUFDQSxJQUFJSCxVQUFVLEdBQUdtQixzQkFBc0IsSUFBSW5CLFVBQVUsR0FBR0ksYUFBYSxHQUFHZSxzQkFBc0IsR0FBR0QsYUFBYSxFQUFFO0lBQzVHVCxRQUFRLENBQUNDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFVixVQUFVLENBQUM7O0lBRXREO0lBQ0EsTUFBTVcsbUJBQW1CLEdBQUdYLFVBQVUsR0FBR0ksYUFBYSxHQUFHLENBQUMsR0FBR2MsYUFBYSxHQUFHLENBQUM7O0lBRTlFO0lBQ0F0QyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUN3QyxPQUFPLENBQ25CO01BQ0lqQixTQUFTLEVBQUVRO0lBQ2YsQ0FBQyxFQUNELElBQ0osQ0FBQyxDQUFDLENBQUM7RUFDUDtBQUNKOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNVLGVBQWVBLENBQUNDLFFBQVEsRUFBRTtFQUMvQixNQUFNQyxPQUFPLEdBQUczQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztFQUMxQixNQUFNNEMsWUFBWSxHQUFHRCxPQUFPLENBQUNFLE1BQU07RUFDbkMsSUFBSUMsYUFBYSxHQUFHLENBQUM7RUFFckIsSUFBSUYsWUFBWSxLQUFLLENBQUMsRUFBRTtJQUNwQkYsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0VBQ2hCO0VBRUFDLE9BQU8sQ0FBQ0ksSUFBSSxDQUFDLFlBQVk7SUFDckIsTUFBTUMsR0FBRyxHQUFHLElBQUlDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZCRCxHQUFHLENBQUNFLE1BQU0sR0FBRyxZQUFZO01BQ3JCSixhQUFhLEVBQUU7TUFDZixJQUFJQSxhQUFhLEtBQUtGLFlBQVksRUFBRTtRQUNoQ0YsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO01BQ2hCO0lBQ0osQ0FBQztJQUNETSxHQUFHLENBQUNHLE9BQU8sR0FBRyxZQUFZO01BQ3RCTCxhQUFhLEVBQUU7TUFDZixJQUFJQSxhQUFhLEtBQUtGLFlBQVksRUFBRTtRQUNoQ0YsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO01BQ2hCO0lBQ0osQ0FBQztJQUNETSxHQUFHLENBQUNJLEdBQUcsR0FBRyxJQUFJLENBQUNBLEdBQUcsQ0FBQyxDQUFDO0VBQ3hCLENBQUMsQ0FBQztBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsS0FBS0EsQ0FBQSxFQUFHO0VBQ2IsT0FBT3JELENBQUMsQ0FBQyxxQkFBcUIsQ0FBQztBQUNuQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTc0Qsa0JBQWtCQSxDQUFDQyxFQUFFLEVBQUU7RUFDNUIsT0FBTyxHQUFHLEdBQUdBLEVBQUUsQ0FBQ0MsT0FBTyxDQUFDLHFCQUFxQixFQUFFLE1BQU0sQ0FBQztBQUMxRDs7Ozs7O0FDck1BO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyxTQUFTQSxDQUFBLEVBQUc7RUFDakIsT0FBT3pCLElBQUksQ0FBQzBCLEtBQUssQ0FBQyxJQUFJQyxJQUFJLENBQUMsQ0FBQyxDQUFDQyxPQUFPLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztBQUNsRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsY0FBY0EsQ0FBQ0MsUUFBUSxFQUFFO0VBQzlCLE1BQU1DLElBQUksR0FBRyxJQUFJSixJQUFJLENBQUNHLFFBQVEsQ0FBQztFQUMvQixPQUFPQyxJQUFJLENBQUNILE9BQU8sQ0FBQyxDQUFDLEdBQUcsSUFBSTtBQUNoQzs7Ozs7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTSSxLQUFLQSxDQUFDQyxHQUFHLEVBQUVDLFVBQVUsRUFBRTtFQUM1QixJQUFJLE9BQU9ELEdBQUcsQ0FBQ0QsS0FBSyxJQUFJRyxLQUFLLEVBQUU7SUFDM0IsT0FBT0YsR0FBRztFQUNkLENBQUMsTUFBTTtJQUNILElBQUksT0FBT0MsVUFBVSxJQUFJQyxLQUFLLEVBQUU7TUFDNUIsT0FBTztRQUFFSCxLQUFLLEVBQUVDLEdBQUc7UUFBRUcsTUFBTSxFQUFFO01BQUssQ0FBQztJQUN2QyxDQUFDLE1BQU07TUFDSCxPQUFPO1FBQUVKLEtBQUssRUFBRUMsR0FBRztRQUFFRyxNQUFNLEVBQUVGO01BQVcsQ0FBQztJQUM3QztFQUNKO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTRyxlQUFlQSxDQUFBLEVBQWlCO0VBQUEsSUFBaEJDLE9BQU8sR0FBQUMsU0FBQSxDQUFBMUIsTUFBQSxRQUFBMEIsU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBRyxJQUFJO0VBQ25DLE1BQU1QLEtBQUssR0FBRyxJQUFJUyxLQUFLLENBQUMsQ0FBQztFQUN6QixNQUFNQyxLQUFLLEdBQUdWLEtBQUssQ0FBQ1UsS0FBSyxJQUFJLEVBQUU7RUFDL0IsTUFBTUMsVUFBVSxHQUFHRCxLQUFLLENBQUNFLEtBQUssQ0FBQyxJQUFJLENBQUM7O0VBRXBDO0VBQ0EsSUFBSUMsVUFBVSxHQUFHLGtCQUFrQjtFQUNuQyxJQUFJRixVQUFVLENBQUM5QixNQUFNLEdBQUcsQ0FBQyxFQUFFO0lBQ3ZCLE1BQU1pQyxVQUFVLEdBQUdILFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSUEsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUU7SUFDdkQ7SUFDQSxNQUFNSSxLQUFLLEdBQUdELFVBQVUsQ0FBQ0MsS0FBSyxDQUFDLGtDQUFrQyxDQUFDLElBQUlELFVBQVUsQ0FBQ0MsS0FBSyxDQUFDLHdCQUF3QixDQUFDO0lBQ2hILElBQUlBLEtBQUssRUFBRTtNQUNQRixVQUFVLEdBQUcsR0FBR0UsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJQSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDMUM7RUFDSjtFQUVBLElBQUlDLFlBQVksR0FBRywwQ0FBMENILFVBQVUsSUFBSTtFQUMzRUcsWUFBWSxJQUFJLGdGQUFnRjtFQUVoRyxJQUFJVixPQUFPLEVBQUU7SUFDVFUsWUFBWSxJQUFJLFlBQVlWLE9BQU8sSUFBSTtFQUMzQztFQUVBVSxZQUFZLElBQUksaUZBQWlGOztFQUVqRztFQUNBQyxPQUFPLENBQUNqQixLQUFLLENBQUMsR0FBRyxDQUFDa0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0VBQzdCRCxPQUFPLENBQUNqQixLQUFLLENBQUMsc0JBQXNCLENBQUM7RUFDckNpQixPQUFPLENBQUNqQixLQUFLLENBQUMsR0FBRyxDQUFDa0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0VBQzdCRCxPQUFPLENBQUNqQixLQUFLLENBQUNnQixZQUFZLENBQUM7RUFDM0JDLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyxjQUFjLEVBQUVVLEtBQUssQ0FBQztFQUNwQ08sT0FBTyxDQUFDakIsS0FBSyxDQUFDLEdBQUcsQ0FBQ2tCLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQzs7RUFFN0I7RUFDQSxNQUFNQyxVQUFVLEdBQUcsSUFBSVYsS0FBSyxDQUFDTyxZQUFZLENBQUM7RUFDMUNHLFVBQVUsQ0FBQ0MsSUFBSSxHQUFHLG9CQUFvQjtFQUN0QyxNQUFNRCxVQUFVO0FBQ3BCOzs7Ozs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0UsSUFBSUEsQ0FBQ0MsT0FBTyxFQUF5QztFQUFBLElBQXZDQyxTQUFTLEdBQUFoQixTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLElBQUk7RUFBQSxJQUFFaUIsWUFBWSxHQUFBakIsU0FBQSxDQUFBMUIsTUFBQSxRQUFBMEIsU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBRyxJQUFJO0VBQ3hELElBQUksT0FBT2UsT0FBTyxJQUFJbkIsS0FBSyxFQUFFO0lBQ3pCbUIsT0FBTyxHQUFHLGVBQWU7RUFDN0I7RUFFQSxJQUFJRSxZQUFZLEtBQUssSUFBSSxFQUFFO0lBQ3ZCQSxZQUFZLEdBQUcsQ0FBQyxHQUFHLENBQUM7RUFDeEI7O0VBRUE7RUFDQSxJQUFJQyxxQkFBcUIsR0FBRyxTQUFBQSxDQUFVOUYsS0FBSyxFQUFFO0lBQ3pDLE1BQU0rRixLQUFLLEdBQUcsRUFBRTtJQUNoQixPQUFPQyxJQUFJLENBQUNDLFNBQVMsQ0FBQ2pHLEtBQUssRUFBRSxVQUFVa0csR0FBRyxFQUFFQyxDQUFDLEVBQUU7TUFDM0MsSUFBSSxPQUFPQSxDQUFDLEtBQUssUUFBUSxJQUFJLE9BQU9SLE9BQU8sQ0FBQ1MsVUFBVSxJQUFJLFVBQVUsRUFBRTtRQUNsRSxPQUFPVCxPQUFPLENBQUNVLFNBQVMsQ0FBQyxDQUFDO01BQzlCLENBQUMsTUFBTSxJQUFJLE9BQU9GLENBQUMsS0FBSyxRQUFRLElBQUlBLENBQUMsS0FBSyxJQUFJLEVBQUU7UUFDNUMsSUFBSUosS0FBSyxDQUFDOUUsT0FBTyxDQUFDa0YsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7VUFDekI7VUFDQTtRQUNKO1FBQ0FKLEtBQUssQ0FBQ08sSUFBSSxDQUFDSCxDQUFDLENBQUM7TUFDakI7TUFDQSxPQUFPQSxDQUFDO0lBQ1osQ0FBQyxDQUFDO0VBQ04sQ0FBQzs7RUFFRDtFQUNBO0VBQ0EsSUFBSUksUUFBUSxHQUFHLENBQUMsQ0FBQztFQUNqQixJQUFJQyxRQUFRLEdBQUcsU0FBQUEsQ0FBVWIsT0FBTyxFQUFFYyxNQUFNLEVBQWE7SUFBQSxJQUFYQyxLQUFLLEdBQUE5QixTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLENBQUM7SUFDL0M7SUFDQTtJQUNBLElBQUk4QixLQUFLLEdBQUcsRUFBRSxFQUFFO01BQ1o7SUFDSjs7SUFFQTs7SUFFQSxJQUFJQyxTQUFTLENBQUNoQixPQUFPLENBQUMsSUFBSSxPQUFPQSxPQUFPLENBQUNTLFVBQVUsSUFBSSxVQUFVLEVBQUU7TUFDL0Q7TUFDQUcsUUFBUSxDQUFDRSxNQUFNLENBQUMsR0FBR2QsT0FBTyxDQUFDVSxTQUFTLENBQUMsQ0FBQztJQUMxQyxDQUFDLE1BQU0sSUFBSU0sU0FBUyxDQUFDaEIsT0FBTyxDQUFDLElBQUksT0FBT2lCLFFBQVEsS0FBSyxXQUFXLElBQUlqQixPQUFPLFlBQVlpQixRQUFRLEVBQUU7TUFDN0Y7TUFDQUwsUUFBUSxDQUFDRSxNQUFNLENBQUMsR0FBR1gscUJBQXFCLENBQUNILE9BQU8sQ0FBQztJQUNyRCxDQUFDLE1BQU0sSUFBSWdCLFNBQVMsQ0FBQ2hCLE9BQU8sQ0FBQyxFQUFFO01BQzNCO01BQ0FZLFFBQVEsQ0FBQ0UsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO01BQ3JCLEtBQUssSUFBSUksQ0FBQyxJQUFJbEIsT0FBTyxFQUFFO1FBQ25CLElBQUlBLE9BQU8sQ0FBQ21CLGNBQWMsQ0FBQ0QsQ0FBQyxDQUFDLElBQUloQixZQUFZLENBQUM1RSxPQUFPLENBQUM0RixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRTtVQUM1REwsUUFBUSxDQUFDYixPQUFPLENBQUNrQixDQUFDLENBQUMsRUFBRUosTUFBTSxHQUFHLElBQUksR0FBR0ksQ0FBQyxFQUFFSCxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ3REO01BQ0o7SUFDSixDQUFDLE1BQU0sSUFBSUssUUFBUSxDQUFDcEIsT0FBTyxDQUFDLEVBQUU7TUFDMUI7TUFDQVksUUFBUSxDQUFDRSxNQUFNLENBQUMsR0FBRyxFQUFFO01BQ3JCLElBQUlPLENBQUMsR0FBRyxDQUFDO01BQ1RDLE9BQU8sQ0FBQ3RCLE9BQU8sRUFBR1EsQ0FBQyxJQUFLO1FBQ3BCSyxRQUFRLENBQUNMLENBQUMsRUFBRU0sTUFBTSxHQUFHLElBQUksR0FBR08sQ0FBQyxFQUFFTixLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ3pDTSxDQUFDLEVBQUU7TUFDUCxDQUFDLENBQUM7SUFDTixDQUFDLE1BQU0sSUFBSUUsV0FBVyxDQUFDdkIsT0FBTyxDQUFDLEVBQUU7TUFDN0I7SUFBQSxDQUNILE1BQU0sSUFBSSxDQUFDd0IsVUFBVSxDQUFDeEIsT0FBTyxDQUFDLEVBQUU7TUFDN0JZLFFBQVEsQ0FBQ0UsTUFBTSxDQUFDLEdBQUdXLE1BQU0sQ0FBQ3pCLE9BQU8sQ0FBQztJQUN0QyxDQUFDLE1BQU07TUFDSFksUUFBUSxDQUFDRSxNQUFNLENBQUMsR0FBR2QsT0FBTztJQUM5QjtFQUNKLENBQUM7RUFFRGEsUUFBUSxDQUFDYixPQUFPLEVBQUUsR0FBRyxDQUFDO0VBRXRCLElBQUkwQixNQUFNLEdBQUcsRUFBRTtFQUVmSixPQUFPLENBQUNWLFFBQVEsRUFBRSxVQUFVSixDQUFDLEVBQUVVLENBQUMsRUFBRTtJQUM5QlEsTUFBTSxDQUFDZixJQUFJLENBQUMsQ0FBQ08sQ0FBQyxFQUFFVixDQUFDLENBQUMsQ0FBQztFQUN2QixDQUFDLENBQUM7RUFFRmtCLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDLFVBQVVDLENBQUMsRUFBRUMsQ0FBQyxFQUFFO0lBQ3hCLE9BQU9ELENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBR0MsQ0FBQyxDQUFDLENBQUMsQ0FBQztFQUN0QixDQUFDLENBQUM7RUFFRixJQUFJQyxJQUFJLEdBQUd6QixJQUFJLENBQUNDLFNBQVMsQ0FBQ29CLE1BQU0sQ0FBQztFQUVqQyxJQUFJekIsU0FBUyxFQUFFO0lBQ1gsSUFBSThCLE1BQU0sR0FBR0MsSUFBSSxDQUFDQSxJQUFJLENBQUNGLElBQUksQ0FBQztJQUM1QixPQUFPQyxNQUFNO0VBQ2pCLENBQUMsTUFBTTtJQUNILE9BQU9ELElBQUk7RUFDZjtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNHLFVBQVVBLENBQUNMLENBQUMsRUFBRUMsQ0FBQyxFQUFFO0VBQ3RCLE9BQU85QixJQUFJLENBQUM2QixDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUk3QixJQUFJLENBQUM4QixDQUFDLEVBQUUsS0FBSyxDQUFDO0FBQzNDOzs7Ozs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNLLEtBQUtBLENBQUNDLFNBQVMsRUFBRTtFQUN0QjtFQUNBLE1BQU1DLGdCQUFnQixHQUFJLFlBQVc7SUFDakMsSUFBSSxDQUFDRixLQUFLLENBQUNHLGlCQUFpQixFQUFFO01BQzFCSCxLQUFLLENBQUNHLGlCQUFpQixHQUFHLElBQUlDLE9BQU8sQ0FBQyxDQUFDO0lBQzNDO0lBQ0EsT0FBT0osS0FBSyxDQUFDRyxpQkFBaUI7RUFDbEMsQ0FBQyxDQUFFLENBQUM7RUFFSixNQUFNRSxjQUFjLEdBQUksWUFBVztJQUMvQixJQUFJLENBQUNMLEtBQUssQ0FBQ00sZUFBZSxFQUFFO01BQ3hCTixLQUFLLENBQUNNLGVBQWUsR0FBRyxJQUFJQyxHQUFHLENBQUMsQ0FBQztJQUNyQztJQUNBLE9BQU9QLEtBQUssQ0FBQ00sZUFBZTtFQUNoQyxDQUFDLENBQUUsQ0FBQzs7RUFFSjtBQUNKO0FBQ0E7RUFDSSxTQUFTRSxrQkFBa0JBLENBQUNDLFFBQVEsRUFBRUMsV0FBVyxFQUFFO0lBQy9DLElBQUlDLGNBQWMsR0FBR1QsZ0JBQWdCLENBQUNVLEdBQUcsQ0FBQ0gsUUFBUSxDQUFDO0lBQ25ELElBQUksQ0FBQ0UsY0FBYyxFQUFFO01BQ2pCQSxjQUFjLEdBQUcsSUFBSUosR0FBRyxDQUFDLENBQUM7TUFDMUJMLGdCQUFnQixDQUFDVyxHQUFHLENBQUNKLFFBQVEsRUFBRUUsY0FBYyxDQUFDO0lBQ2xEO0lBRUEsSUFBSUcsVUFBVSxHQUFHSCxjQUFjLENBQUNDLEdBQUcsQ0FBQ0YsV0FBVyxDQUFDO0lBQ2hELElBQUksQ0FBQ0ksVUFBVSxFQUFFO01BQ2JBLFVBQVUsR0FBRztRQUFFQyxNQUFNLEVBQUUsS0FBSztRQUFFQyxLQUFLLEVBQUU7TUFBRyxDQUFDO01BQ3pDTCxjQUFjLENBQUNFLEdBQUcsQ0FBQ0gsV0FBVyxFQUFFSSxVQUFVLENBQUM7SUFDL0M7SUFFQSxPQUFPQSxVQUFVO0VBQ3JCOztFQUVBO0FBQ0o7QUFDQTtFQUNJLFNBQVNHLGdCQUFnQkEsQ0FBQ2xGLEVBQUUsRUFBRTtJQUMxQixJQUFJK0UsVUFBVSxHQUFHVCxjQUFjLENBQUNPLEdBQUcsQ0FBQzdFLEVBQUUsQ0FBQztJQUN2QyxJQUFJLENBQUMrRSxVQUFVLEVBQUU7TUFDYkEsVUFBVSxHQUFHO1FBQUVDLE1BQU0sRUFBRSxLQUFLO1FBQUVDLEtBQUssRUFBRTtNQUFHLENBQUM7TUFDekNYLGNBQWMsQ0FBQ1EsR0FBRyxDQUFDOUUsRUFBRSxFQUFFK0UsVUFBVSxDQUFDO0lBQ3RDO0lBQ0EsT0FBT0EsVUFBVTtFQUNyQjs7RUFFQTtBQUNKO0FBQ0E7RUFDSSxTQUFTSSxhQUFhQSxDQUFDSixVQUFVLEVBQUU7SUFDL0IsSUFBSUEsVUFBVSxDQUFDQyxNQUFNLElBQUlELFVBQVUsQ0FBQ0UsS0FBSyxDQUFDM0YsTUFBTSxLQUFLLENBQUMsRUFBRTtNQUNwRDtJQUNKO0lBRUEsTUFBTTtNQUFFOEYsRUFBRTtNQUFFQyxPQUFPO01BQUVDO0lBQU8sQ0FBQyxHQUFHUCxVQUFVLENBQUNFLEtBQUssQ0FBQ00sS0FBSyxDQUFDLENBQUM7SUFDeERSLFVBQVUsQ0FBQ0MsTUFBTSxHQUFHLElBQUk7SUFFeEJRLE9BQU8sQ0FBQ0gsT0FBTyxDQUFDLENBQUMsQ0FDWkksSUFBSSxDQUFDTCxFQUFFLENBQUMsQ0FDUkssSUFBSSxDQUFDSixPQUFPLEVBQUVDLE1BQU0sQ0FBQyxDQUNyQkksT0FBTyxDQUFDLE1BQU07TUFDWFgsVUFBVSxDQUFDQyxNQUFNLEdBQUcsS0FBSztNQUN6QkcsYUFBYSxDQUFDSixVQUFVLENBQUM7SUFDN0IsQ0FBQyxDQUFDO0VBQ1Y7O0VBRUE7QUFDSjtBQUNBO0VBQ0ksU0FBU1ksWUFBWUEsQ0FBQ1osVUFBVSxFQUFFSyxFQUFFLEVBQUU7SUFDbEMsT0FBTyxJQUFJSSxPQUFPLENBQUMsQ0FBQ0gsT0FBTyxFQUFFQyxNQUFNLEtBQUs7TUFDcENQLFVBQVUsQ0FBQ0UsS0FBSyxDQUFDdkMsSUFBSSxDQUFDO1FBQUUwQyxFQUFFO1FBQUVDLE9BQU87UUFBRUM7TUFBTyxDQUFDLENBQUM7TUFDOUNILGFBQWEsQ0FBQ0osVUFBVSxDQUFDO0lBQzdCLENBQUMsQ0FBQztFQUNOOztFQUVBO0VBQ0EsSUFBSSxPQUFPYixTQUFTLEtBQUssUUFBUSxFQUFFO0lBQy9CLE9BQU8sVUFBU3pHLE1BQU0sRUFBRTZFLEdBQUcsRUFBRXNELFVBQVUsRUFBRTtNQUNyQyxNQUFNQyxlQUFlLEdBQUdELFVBQVUsQ0FBQ3hKLEtBQUs7TUFFeEMsSUFBSSxPQUFPeUosZUFBZSxLQUFLLFVBQVUsRUFBRTtRQUN2QyxNQUFNLElBQUkzRSxLQUFLLENBQUMsNERBQTREb0IsR0FBRyxHQUFHLENBQUM7TUFDdkY7TUFFQXNELFVBQVUsQ0FBQ3hKLEtBQUssR0FBRyxZQUFrQjtRQUFBLFNBQUEwSixJQUFBLEdBQUE5RSxTQUFBLENBQUExQixNQUFBLEVBQU55RyxJQUFJLE9BQUFDLEtBQUEsQ0FBQUYsSUFBQSxHQUFBRyxJQUFBLE1BQUFBLElBQUEsR0FBQUgsSUFBQSxFQUFBRyxJQUFBO1VBQUpGLElBQUksQ0FBQUUsSUFBQSxJQUFBakYsU0FBQSxDQUFBaUYsSUFBQTtRQUFBO1FBQy9CLE1BQU1sQixVQUFVLEdBQUdHLGdCQUFnQixDQUFDaEIsU0FBUyxDQUFDO1FBQzlDLE9BQU95QixZQUFZLENBQUNaLFVBQVUsRUFBRSxNQUFNYyxlQUFlLENBQUNLLEtBQUssQ0FBQyxJQUFJLEVBQUVILElBQUksQ0FBQyxDQUFDO01BQzVFLENBQUM7TUFFRCxPQUFPSCxVQUFVO0lBQ3JCLENBQUM7RUFDTDs7RUFFQTtFQUNBLE1BQU1uSSxNQUFNLEdBQUd5RyxTQUFTLENBQUMsQ0FBRTtFQUMzQixNQUFNNUIsR0FBRyxHQUFHdEIsU0FBUyxDQUFDLENBQUMsQ0FBQztFQUN4QixNQUFNNEUsVUFBVSxHQUFHNUUsU0FBUyxDQUFDLENBQUMsQ0FBQztFQUUvQixNQUFNNkUsZUFBZSxHQUFHRCxVQUFVLENBQUN4SixLQUFLO0VBRXhDLElBQUksT0FBT3lKLGVBQWUsS0FBSyxVQUFVLEVBQUU7SUFDdkMsTUFBTSxJQUFJM0UsS0FBSyxDQUFDLDREQUE0RG9CLEdBQUcsR0FBRyxDQUFDO0VBQ3ZGO0VBRUFzRCxVQUFVLENBQUN4SixLQUFLLEdBQUcsWUFBa0I7SUFBQSxTQUFBK0osS0FBQSxHQUFBbkYsU0FBQSxDQUFBMUIsTUFBQSxFQUFOeUcsSUFBSSxPQUFBQyxLQUFBLENBQUFHLEtBQUEsR0FBQUMsS0FBQSxNQUFBQSxLQUFBLEdBQUFELEtBQUEsRUFBQUMsS0FBQTtNQUFKTCxJQUFJLENBQUFLLEtBQUEsSUFBQXBGLFNBQUEsQ0FBQW9GLEtBQUE7SUFBQTtJQUMvQixNQUFNckIsVUFBVSxHQUFHTixrQkFBa0IsQ0FBQyxJQUFJLEVBQUVuQyxHQUFHLENBQUM7SUFDaEQsT0FBT3FELFlBQVksQ0FBQ1osVUFBVSxFQUFFLE1BQU1jLGVBQWUsQ0FBQ0ssS0FBSyxDQUFDLElBQUksRUFBRUgsSUFBSSxDQUFDLENBQUM7RUFDNUUsQ0FBQztFQUVELE9BQU9ILFVBQVU7QUFDckI7Ozs7OztBQzlIQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU1MsS0FBS0EsQ0FBQSxFQUFtQjtFQUFBLElBQWxCQyxZQUFZLEdBQUF0RixTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLENBQUM7RUFDM0IsT0FBTyxJQUFJd0UsT0FBTyxDQUFFSCxPQUFPLElBQUs7SUFDNUIsSUFBSWlCLFlBQVksSUFBSSxDQUFDLElBQUlDLHFCQUFxQixFQUFFO01BQzVDQSxxQkFBcUIsQ0FBQ2xCLE9BQU8sQ0FBQztJQUNsQyxDQUFDLE1BQU07TUFDSG1CLFVBQVUsQ0FBQ25CLE9BQU8sRUFBRWlCLFlBQVksQ0FBQztJQUNyQztFQUNKLENBQUMsQ0FBQztBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTRyxRQUFRQSxDQUFDQyxpQkFBaUIsRUFBRUMsS0FBSyxFQUFxQjtFQUFBLElBQW5CQyxTQUFTLEdBQUE1RixTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLEtBQUs7RUFDekQ7RUFDQTtFQUNBLElBQUksT0FBTzBGLGlCQUFpQixLQUFLLFFBQVEsRUFBRTtJQUN2QyxNQUFNRyxlQUFlLEdBQUdILGlCQUFpQjtJQUN6QyxNQUFNSSxtQkFBbUIsR0FBR0gsS0FBSyxJQUFJLEtBQUs7O0lBRTFDO0lBQ0EsT0FBTyxVQUFVdkssS0FBSyxFQUFFMkssT0FBTyxFQUFFO01BQzdCLElBQUlBLE9BQU8sQ0FBQ0MsSUFBSSxLQUFLLFFBQVEsRUFBRTtRQUMzQixPQUFPQyxhQUFhLENBQUM3SyxLQUFLLEVBQUV5SyxlQUFlLEVBQUVDLG1CQUFtQixDQUFDO01BQ3JFO0lBQ0osQ0FBQztFQUNMOztFQUVBO0VBQ0E7RUFDQSxNQUFNM0gsUUFBUSxHQUFHdUgsaUJBQWlCO0VBQ2xDLE9BQU9PLGFBQWEsQ0FBQzlILFFBQVEsRUFBRXdILEtBQUssRUFBRUMsU0FBUyxDQUFDO0FBQ3BEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0ssYUFBYUEsQ0FBQzlILFFBQVEsRUFBRXdILEtBQUssRUFBcUI7RUFBQSxJQUFuQkMsU0FBUyxHQUFBNUYsU0FBQSxDQUFBMUIsTUFBQSxRQUFBMEIsU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBRyxLQUFLO0VBQ3JELElBQUlrRyxPQUFPLEdBQUcsS0FBSztFQUNuQixJQUFJQyxNQUFNLEdBQUcsS0FBSztFQUNsQixJQUFJQyxhQUFhLEdBQUcsQ0FBQyxDQUFDLENBQUM7RUFDdkIsSUFBSUMsS0FBSyxHQUFHLElBQUk7RUFFaEIsSUFBSUMsU0FBUyxHQUFHLEVBQUU7RUFDbEIsSUFBSUMsWUFBWSxHQUFHLElBQUk7RUFDdkIsSUFBSUMsYUFBYSxHQUFHLEVBQUU7RUFDdEIsSUFBSUMsWUFBWSxHQUFHLEVBQUU7RUFFckIsTUFBTUMsWUFBWSxHQUFHLE1BQUFBLENBQUEsS0FBWTtJQUM3QixNQUFNQyxjQUFjLEdBQUdILGFBQWE7SUFDcEMsTUFBTUksYUFBYSxHQUFHSCxZQUFZO0lBQ2xDLE1BQU0xQixJQUFJLEdBQUd1QixTQUFTO0lBQ3RCLE1BQU1QLE9BQU8sR0FBR1EsWUFBWTtJQUU1QkMsYUFBYSxHQUFHLEVBQUU7SUFDbEJDLFlBQVksR0FBRyxFQUFFO0lBQ2pCSCxTQUFTLEdBQUcsRUFBRTtJQUNkQyxZQUFZLEdBQUcsSUFBSTtJQUNuQkosTUFBTSxHQUFHLEtBQUs7SUFDZEQsT0FBTyxHQUFHLElBQUk7SUFFZCxJQUFJO01BQ0EsTUFBTVcsTUFBTSxHQUFHLE1BQU0xSSxRQUFRLENBQUMrRyxLQUFLLENBQUNhLE9BQU8sRUFBRWhCLElBQUksQ0FBQztNQUNsRCxLQUFLLE1BQU1WLE9BQU8sSUFBSXNDLGNBQWMsRUFBRXRDLE9BQU8sQ0FBQ3dDLE1BQU0sQ0FBQztJQUN6RCxDQUFDLENBQUMsT0FBT0MsR0FBRyxFQUFFO01BQ1YsS0FBSyxNQUFNeEMsTUFBTSxJQUFJc0MsYUFBYSxFQUFFdEMsTUFBTSxDQUFDd0MsR0FBRyxDQUFDO0lBQ25ELENBQUMsU0FBUztNQUNOWixPQUFPLEdBQUcsS0FBSztNQUNmRSxhQUFhLEdBQUdoSCxJQUFJLENBQUMySCxHQUFHLENBQUMsQ0FBQztNQUMxQixJQUFJWixNQUFNLEVBQUU7UUFDUmEsWUFBWSxDQUFDWCxLQUFLLENBQUM7UUFDbkJBLEtBQUssR0FBR2IsVUFBVSxDQUFDa0IsWUFBWSxFQUFFakosSUFBSSxDQUFDQyxHQUFHLENBQUNpSSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7TUFDeEQsQ0FBQyxNQUFNO1FBQ0hVLEtBQUssR0FBRyxJQUFJO01BQ2hCO0lBQ0o7RUFDSixDQUFDO0VBRUQsT0FBTyxZQUFtQjtJQUFBLFNBQUF2QixJQUFBLEdBQUE5RSxTQUFBLENBQUExQixNQUFBLEVBQU55RyxJQUFJLE9BQUFDLEtBQUEsQ0FBQUYsSUFBQSxHQUFBRyxJQUFBLE1BQUFBLElBQUEsR0FBQUgsSUFBQSxFQUFBRyxJQUFBO01BQUpGLElBQUksQ0FBQUUsSUFBQSxJQUFBakYsU0FBQSxDQUFBaUYsSUFBQTtJQUFBO0lBQ3BCcUIsU0FBUyxHQUFHdkIsSUFBSTtJQUNoQndCLFlBQVksR0FBRyxJQUFJO0lBRW5CLE9BQU8sSUFBSS9CLE9BQU8sQ0FBQyxDQUFDSCxPQUFPLEVBQUVDLE1BQU0sS0FBSztNQUNwQ2tDLGFBQWEsQ0FBQzlFLElBQUksQ0FBQzJDLE9BQU8sQ0FBQztNQUMzQm9DLFlBQVksQ0FBQy9FLElBQUksQ0FBQzRDLE1BQU0sQ0FBQzs7TUFFekI7TUFDQSxJQUFJLENBQUM0QixPQUFPLElBQUksQ0FBQ0csS0FBSyxFQUFFO1FBQ3BCLE1BQU1ZLFVBQVUsR0FBR2IsYUFBYSxLQUFLLENBQUM7UUFFdEMsSUFBSVIsU0FBUyxJQUFJcUIsVUFBVSxFQUFFO1VBQ3pCUCxZQUFZLENBQUMsQ0FBQztVQUNkO1FBQ0o7UUFFQSxNQUFNUSxLQUFLLEdBQUdELFVBQVUsR0FBR0UsUUFBUSxHQUFHL0gsSUFBSSxDQUFDMkgsR0FBRyxDQUFDLENBQUMsR0FBR1gsYUFBYTtRQUNoRSxJQUFJYyxLQUFLLElBQUl2QixLQUFLLEVBQUU7VUFDaEJlLFlBQVksQ0FBQyxDQUFDO1FBQ2xCLENBQUMsTUFBTTtVQUNILE1BQU1VLElBQUksR0FBRzNKLElBQUksQ0FBQ0MsR0FBRyxDQUFDaUksS0FBSyxHQUFHdUIsS0FBSyxFQUFFLENBQUMsQ0FBQztVQUN2Q0YsWUFBWSxDQUFDWCxLQUFLLENBQUM7VUFDbkJBLEtBQUssR0FBR2IsVUFBVSxDQUFDa0IsWUFBWSxFQUFFVSxJQUFJLENBQUM7UUFDMUM7UUFDQTtNQUNKOztNQUVBO01BQ0E7TUFDQWpCLE1BQU0sR0FBRyxJQUFJO0lBQ2pCLENBQUMsQ0FBQztFQUNOLENBQUM7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTa0IsTUFBTUEsQ0FBQ3hHLElBQUksRUFBRXlHLEVBQUUsRUFBRTtFQUN0QixPQUFPQyxhQUFhLENBQUNDLE9BQU8sQ0FBQzNHLElBQUksRUFBRXlHLEVBQUUsQ0FBQztBQUMxQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNHLFdBQVdBLENBQUM1RyxJQUFJLEVBQUV5RyxFQUFFLEVBQUU7RUFDM0IsT0FBT0MsYUFBYSxDQUFDRyxZQUFZLENBQUM3RyxJQUFJLEVBQUV5RyxFQUFFLENBQUM7QUFDL0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTSyxtQkFBbUJBLENBQUM5RyxJQUFJLEVBQUU7RUFDL0IwRyxhQUFhLENBQUNLLFlBQVksQ0FBQy9HLElBQUksQ0FBQztBQUNwQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU2dILGNBQWNBLENBQUNoSCxJQUFJLEVBQUU7RUFDMUIsT0FBTzBHLGFBQWEsQ0FBQ08sT0FBTyxDQUFDakgsSUFBSSxDQUFDO0FBQ3RDOzs7Ozs7QUNwTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE1BQU1qQixLQUFLLEdBQUcsV0FBVzs7QUFFekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU3lDLE9BQU9BLENBQUMwRixHQUFHLEVBQUU1SixRQUFRLEVBQUU7RUFDNUIsTUFBTTZKLE9BQU8sR0FBRyxFQUFFO0VBRWxCLElBQUloRCxLQUFLLENBQUNpRCxPQUFPLENBQUNGLEdBQUcsQ0FBQyxFQUFFO0lBQ3BCQSxHQUFHLENBQUNHLE9BQU8sQ0FBQyxDQUFDOU0sS0FBSyxFQUFFK00sS0FBSyxLQUFLO01BQzFCSCxPQUFPLENBQUN0RyxJQUFJLENBQUN2RCxRQUFRLENBQUMvQyxLQUFLLEVBQUUrTSxLQUFLLENBQUMsQ0FBQztJQUN4QyxDQUFDLENBQUM7RUFDTixDQUFDLE1BQU0sSUFBSUosR0FBRyxJQUFJLE9BQU9BLEdBQUcsS0FBSyxRQUFRLEVBQUU7SUFDdkMsS0FBSyxJQUFJekcsR0FBRyxJQUFJeUcsR0FBRyxFQUFFO01BQ2pCLElBQUlBLEdBQUcsQ0FBQzdGLGNBQWMsQ0FBQ1osR0FBRyxDQUFDLEVBQUU7UUFDekIwRyxPQUFPLENBQUN0RyxJQUFJLENBQUN2RCxRQUFRLENBQUM0SixHQUFHLENBQUN6RyxHQUFHLENBQUMsRUFBRUEsR0FBRyxDQUFDLENBQUM7TUFDekM7SUFDSjtFQUNKOztFQUVBO0VBQ0EsTUFBTThHLFFBQVEsR0FBR0osT0FBTyxDQUFDSyxNQUFNLENBQUV4QixNQUFNLElBQUtBLE1BQU0sSUFBSSxPQUFPQSxNQUFNLENBQUNwQyxJQUFJLEtBQUssVUFBVSxDQUFDOztFQUV4RjtFQUNBLElBQUkyRCxRQUFRLENBQUM5SixNQUFNLEdBQUcsQ0FBQyxFQUFFO0lBQ3JCLE9BQU9rRyxPQUFPLENBQUM4RCxHQUFHLENBQUNGLFFBQVEsQ0FBQztFQUNoQzs7RUFFQTtFQUNBLE9BQU9uSSxTQUFTO0FBQ3BCOztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU3NDLFVBQVVBLENBQUNnRyxDQUFDLEVBQUU7RUFDbkIsT0FBTyxDQUFDQyxLQUFLLENBQUNDLFVBQVUsQ0FBQ0YsQ0FBQyxDQUFDLENBQUMsSUFBSUcsUUFBUSxDQUFDSCxDQUFDLENBQUM7QUFDL0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNJLFNBQVNBLENBQUNDLENBQUMsRUFBRTtFQUNsQixPQUFPLE9BQU9BLENBQUMsSUFBSSxRQUFRO0FBQy9COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyxVQUFVQSxDQUFDTixDQUFDLEVBQUU7RUFDbkIsT0FBT08sTUFBTSxDQUFDQyxTQUFTLENBQUNSLENBQUMsQ0FBQztBQUM5Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU1MsVUFBVUEsQ0FBQ2pCLEdBQUcsRUFBRTtFQUNyQixPQUFPLE9BQU9BLEdBQUcsSUFBSSxRQUFRLElBQUksT0FBT0EsR0FBRyxDQUFDdEQsSUFBSSxJQUFJLFVBQVU7QUFDbEU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVN0QyxRQUFRQSxDQUFDNEYsR0FBRyxFQUFFO0VBQ25CLE9BQU8vQyxLQUFLLENBQUNpRCxPQUFPLENBQUNGLEdBQUcsQ0FBQztBQUM3Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU2hHLFNBQVNBLENBQUNnRyxHQUFHLEVBQUU7RUFDcEIsT0FBTyxPQUFPQSxHQUFHLEtBQUssUUFBUSxJQUFJQSxHQUFHLEtBQUssSUFBSTtBQUNsRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU3pGLFdBQVdBLENBQUMyRyxpQkFBaUIsRUFBRTtFQUNwQyxPQUFPQSxpQkFBaUIsSUFBSSxDQUFDLENBQUMsQ0FBQ0MsUUFBUSxDQUFDQyxJQUFJLENBQUNGLGlCQUFpQixDQUFDLEtBQUssbUJBQW1CO0FBQzNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNHLFFBQVFBLENBQUNDLEtBQUssRUFBRTtFQUNyQixJQUFJLENBQUNWLFNBQVMsQ0FBQ1UsS0FBSyxDQUFDLEVBQUU7SUFDbkIsT0FBTyxLQUFLO0VBQ2hCO0VBQ0EsTUFBTUMsS0FBSyxHQUFHLDBJQUEwSTtFQUN4SixPQUFPQSxLQUFLLENBQUNoTyxJQUFJLENBQUMrTixLQUFLLENBQUM7QUFDNUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNFLEtBQUtBLENBQUNuTyxLQUFLLEVBQUU7RUFDbEIsT0FBTyxPQUFPQSxLQUFLLElBQUl3RSxLQUFLO0FBQ2hDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTNEosS0FBS0EsQ0FBQ0MsTUFBTSxFQUFFO0VBQ25CLElBQUksT0FBT0EsTUFBTSxJQUFJN0osS0FBSyxFQUFFO0lBQ3hCLE9BQU8sSUFBSTtFQUNmO0VBQ0EsSUFBSTZKLE1BQU0sS0FBSyxJQUFJLEVBQUU7SUFDakIsT0FBTyxJQUFJO0VBQ2Y7RUFDQSxJQUFJLE9BQU9BLE1BQU0sSUFBSSxRQUFRLElBQUlBLE1BQU0sSUFBSSxFQUFFLEVBQUU7SUFDM0MsT0FBTyxJQUFJO0VBQ2Y7RUFDQSxJQUFJLE9BQU9BLE1BQU0sSUFBSSxRQUFRLEVBQUU7SUFDM0IsT0FBT0EsTUFBTSxJQUFJLENBQUM7RUFDdEI7RUFDQSxJQUFJekUsS0FBSyxDQUFDaUQsT0FBTyxDQUFDd0IsTUFBTSxDQUFDLEVBQUU7SUFDdkIsT0FBTyxDQUFDQSxNQUFNLENBQUNuTCxNQUFNO0VBQ3pCO0VBQ0EsSUFBSSxPQUFPbUwsTUFBTSxJQUFJLFVBQVUsRUFBRTtJQUM3QixPQUFPLEtBQUs7RUFDaEI7RUFDQSxLQUFLLElBQUluSSxHQUFHLElBQUltSSxNQUFNLEVBQUU7SUFDcEIsSUFBSUEsTUFBTSxDQUFDdkgsY0FBYyxDQUFDWixHQUFHLENBQUMsRUFBRTtNQUM1QixPQUFPLEtBQUs7SUFDaEI7RUFDSjtFQUNBLE9BQU8sSUFBSTtBQUNmOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTb0ksS0FBS0EsQ0FBQ0MsR0FBRyxFQUFFO0VBQ2hCO0VBQ0EsSUFBSUEsR0FBRyxLQUFLLElBQUksSUFBSUEsR0FBRyxLQUFLMUosU0FBUyxJQUFJMEosR0FBRyxLQUFLLEVBQUUsRUFBRTtJQUNqRCxPQUFPLEdBQUc7RUFDZDs7RUFFQTtFQUNBLE1BQU1DLE1BQU0sR0FBR25CLFVBQVUsQ0FBQ2tCLEdBQUcsQ0FBQzs7RUFFOUI7RUFDQSxPQUFPbkIsS0FBSyxDQUFDb0IsTUFBTSxDQUFDLEdBQUcsR0FBRyxHQUFHQSxNQUFNO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNDLEdBQUdBLENBQUNGLEdBQUcsRUFBRTtFQUNkO0VBQ0EsSUFBSUEsR0FBRyxLQUFLLElBQUksSUFBSUEsR0FBRyxLQUFLMUosU0FBUyxJQUFJMEosR0FBRyxLQUFLLEVBQUUsRUFBRTtJQUNqRCxPQUFPLENBQUM7RUFDWjs7RUFFQTtFQUNBLE1BQU1DLE1BQU0sR0FBR0UsUUFBUSxDQUFDSCxHQUFHLEVBQUUsRUFBRSxDQUFDOztFQUVoQztFQUNBLE9BQU9uQixLQUFLLENBQUNvQixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUdBLE1BQU07QUFDckM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU2xLLEdBQUdBLENBQUNpSyxHQUFHLEVBQUU7RUFDZDtFQUNBLElBQUlBLEdBQUcsS0FBSyxJQUFJLElBQUlBLEdBQUcsS0FBSzFKLFNBQVMsRUFBRTtJQUNuQyxPQUFPLEVBQUU7RUFDYjs7RUFFQTtFQUNBLE9BQU91QyxNQUFNLENBQUNtSCxHQUFHLENBQUM7QUFDdEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTSSw4Q0FBOENBLENBQUNKLEdBQUcsRUFBRTtFQUN6RDtFQUNBLElBQUksT0FBT0EsR0FBRyxLQUFLLFFBQVEsRUFBRTtJQUN6QixPQUFPQSxHQUFHO0VBQ2Q7O0VBRUE7RUFDQSxJQUFJaEIsU0FBUyxDQUFDZ0IsR0FBRyxDQUFDLElBQUlwSCxVQUFVLENBQUNvSCxHQUFHLENBQUMsRUFBRTtJQUNuQztJQUNBLE9BQU9sQixVQUFVLENBQUNrQixHQUFHLENBQUM7RUFDMUI7O0VBRUE7RUFDQSxPQUFPQSxHQUFHO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTSyxJQUFJQSxDQUFDdEssR0FBRyxFQUFFO0VBQ2YsT0FBT3VLLENBQUMsQ0FBQ0MsTUFBTSxDQUFDeEssR0FBRyxDQUFDO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTeUssS0FBS0EsQ0FBQ3pLLEdBQUcsRUFBRTtFQUNoQixJQUFJLE9BQU9BLEdBQUcsS0FBS0UsS0FBSyxJQUFJRixHQUFHLEtBQUssSUFBSSxFQUFFO0lBQ3RDLE9BQU8sRUFBRTtFQUNiO0VBQ0EsT0FBTyxDQUFDQSxHQUFHLEdBQUcsRUFBRSxFQUFFVCxPQUFPLENBQUMsK0JBQStCLEVBQUUsWUFBWSxDQUFDO0FBQzVFOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTbUwsTUFBTUEsQ0FBQzFLLEdBQUcsRUFBRTtFQUNqQixPQUFPeUssS0FBSyxDQUFDSCxJQUFJLENBQUN0SyxHQUFHLENBQUMsQ0FBQztBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzJLLFNBQVNBLENBQUMzSyxHQUFHLEVBQUU7RUFDcEIsT0FBTzRLLGtCQUFrQixDQUFDNUssR0FBRyxDQUFDO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTNkssU0FBU0EsQ0FBQzdLLEdBQUcsRUFBRTtFQUNwQixPQUFPOEssa0JBQWtCLENBQUM5SyxHQUFHLENBQUM7QUFDbEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMrSyxXQUFXQSxDQUFDclAsS0FBSyxFQUFFO0VBQ3hCLE9BQU9nRyxJQUFJLENBQUNDLFNBQVMsQ0FBQ2pHLEtBQUssQ0FBQztBQUNoQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU3NQLFdBQVdBLENBQUNoTCxHQUFHLEVBQUU7RUFDdEIsT0FBTzBCLElBQUksQ0FBQ3VKLEtBQUssQ0FBQ2pMLEdBQUcsQ0FBQztBQUMxQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTbkMsYUFBYUEsQ0FBQ3FOLE9BQU8sRUFBYTtFQUFBLFNBQUE5RixJQUFBLEdBQUE5RSxTQUFBLENBQUExQixNQUFBLEVBQVJ1TSxNQUFNLE9BQUE3RixLQUFBLENBQUFGLElBQUEsT0FBQUEsSUFBQSxXQUFBRyxJQUFBLE1BQUFBLElBQUEsR0FBQUgsSUFBQSxFQUFBRyxJQUFBO0lBQU40RixNQUFNLENBQUE1RixJQUFBLFFBQUFqRixTQUFBLENBQUFpRixJQUFBO0VBQUE7RUFDckMzSCxRQUFRLENBQUNDLGFBQWEsQ0FBQ3FOLE9BQU8sRUFBRSxHQUFHQyxNQUFNLENBQUM7QUFDOUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyxXQUFXQSxDQUFDQyxNQUFNLEVBQUVDLE1BQU0sRUFBRS9MLE9BQU8sRUFBRTtFQUMxQyxJQUFJLENBQUMwSixTQUFTLENBQUNvQyxNQUFNLENBQUMsRUFBRTtJQUNwQkEsTUFBTSxHQUFHQSxNQUFNLEdBQUcsRUFBRTtFQUN4QjtFQUNBLE9BQU9BLE1BQU0sQ0FBQzFLLEtBQUssQ0FBQzJLLE1BQU0sQ0FBQyxDQUFDQyxJQUFJLENBQUNoTSxPQUFPLENBQUM7QUFDN0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNpTSxPQUFPQSxDQUFDQyxLQUFLLEVBQUU7RUFDcEIsT0FBT0EsS0FBSyxDQUNQOUssS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUNWK0ssR0FBRyxDQUFFQyxJQUFJLElBQUtBLElBQUksQ0FBQ0MsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDQyxXQUFXLENBQUMsQ0FBQyxHQUFHRixJQUFJLENBQUNHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUMzRFAsSUFBSSxDQUFDLEdBQUcsQ0FBQztBQUNsQjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNRLEtBQUtBLENBQUNDLENBQUMsRUFBRTtFQUNkLElBQUlDLENBQUMsR0FBRyxDQUFDO0VBQ1QsS0FBSyxNQUFNMUosQ0FBQyxJQUFJeUosQ0FBQyxFQUFFO0lBQ2YsSUFBSUEsQ0FBQyxDQUFDeEosY0FBYyxDQUFDRCxDQUFDLENBQUMsRUFBRTtNQUNyQixFQUFFMEosQ0FBQztJQUNQO0VBQ0o7RUFDQSxPQUFPQSxDQUFDO0FBQ1o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNDLEtBQUtBLENBQUM3RCxHQUFHLEVBQUU7RUFDaEIsSUFBSSxPQUFPOEQsUUFBUSxDQUFDQyxTQUFTLENBQUNDLE9BQU8sSUFBSW5NLEtBQUssRUFBRTtJQUM1Q2lNLFFBQVEsQ0FBQ0MsU0FBUyxDQUFDQyxPQUFPLEdBQUcsWUFBWTtNQUNyQztNQUNBLE1BQU1DLElBQUksR0FBRyxJQUFJO01BQ2pCLElBQUlDLElBQUksR0FBRyxTQUFTQyxNQUFNQSxDQUFBLEVBQUc7UUFDekIsT0FBT0YsSUFBSSxDQUFDOUcsS0FBSyxDQUFDLElBQUksRUFBRWxGLFNBQVMsQ0FBQztNQUN0QyxDQUFDO01BQ0QsS0FBSyxJQUFJc0IsR0FBRyxJQUFJLElBQUksRUFBRTtRQUNsQixJQUFJLElBQUksQ0FBQ1ksY0FBYyxDQUFDWixHQUFHLENBQUMsRUFBRTtVQUMxQjJLLElBQUksQ0FBQzNLLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQ0EsR0FBRyxDQUFDO1FBQ3pCO01BQ0o7TUFDQSxPQUFPMkssSUFBSTtJQUNmLENBQUM7RUFDTDtFQUVBLElBQUksT0FBT2xFLEdBQUcsSUFBSSxVQUFVLEVBQUU7SUFDMUIsT0FBT0EsR0FBRyxDQUFDZ0UsT0FBTyxDQUFDLENBQUM7RUFDeEIsQ0FBQyxNQUFNLElBQUloRSxHQUFHLENBQUNvRSxXQUFXLElBQUlwRSxHQUFHLENBQUNvRSxXQUFXLElBQUluSCxLQUFLLEVBQUU7SUFDcEQsT0FBTytDLEdBQUcsQ0FBQ3lELEtBQUssQ0FBQyxDQUFDLENBQUM7RUFDdkIsQ0FBQyxNQUFNO0lBQ0g7SUFDQSxPQUFPWSxNQUFNLENBQUNDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRXRFLEdBQUcsQ0FBQztFQUNqQztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTdUUsUUFBUUEsQ0FBQSxFQUFHO0VBQ2hCLElBQUl2SCxJQUFJLEdBQUdDLEtBQUssQ0FBQ3VILElBQUksQ0FBQ3ZNLFNBQVMsQ0FBQztFQUNoQyxJQUFJd00sVUFBVSxHQUFHLElBQUk7RUFDckJ6SCxJQUFJLENBQUNtRCxPQUFPLENBQUMsVUFBVXVFLEdBQUcsRUFBRTtJQUN4QixJQUFJRCxVQUFVLEtBQUssSUFBSSxJQUFJLE9BQU9DLEdBQUcsSUFBSTdNLEtBQUssSUFBSTZNLEdBQUcsS0FBSyxJQUFJLEVBQUU7TUFDNURELFVBQVUsR0FBR0MsR0FBRztJQUNwQjtFQUNKLENBQUMsQ0FBQztFQUNGLE9BQU9ELFVBQVU7QUFDckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0UsaUJBQWlCQSxDQUFDQyxPQUFPLEVBQUU7RUFDaEMsTUFBTUMsS0FBSyxHQUFHRCxPQUFPLENBQUN0TSxLQUFLLENBQUMsR0FBRyxDQUFDO0VBQ2hDLE1BQU13TSxHQUFHLEdBQUcsRUFBRTtFQUNkeEssT0FBTyxDQUFDdUssS0FBSyxFQUFHRSxJQUFJLElBQUs7SUFDckJELEdBQUcsQ0FBQ25MLElBQUksQ0FBQ29MLElBQUksQ0FBQ0MsSUFBSSxDQUFDLENBQUMsQ0FBQztFQUN6QixDQUFDLENBQUM7RUFDRixPQUFPRixHQUFHO0FBQ2Q7Ozs7OztBQzVjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1HLFFBQVEsQ0FBQztFQUNYO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT0MsT0FBT0EsQ0FBQ0MsS0FBSyxFQUFFO0lBQ2xCO0lBQ0EsSUFBSSxPQUFPRixRQUFRLENBQUNHLFFBQVEsS0FBSyxXQUFXLEVBQUU7TUFDMUNILFFBQVEsQ0FBQ0csUUFBUSxHQUFHLENBQUMsQ0FBQztJQUMxQjs7SUFFQTtJQUNBRCxLQUFLLENBQUNoRixPQUFPLENBQUVrRixJQUFJLElBQUs7TUFDcEIsSUFBSUMsWUFBWSxHQUFHRCxJQUFJLENBQUMsQ0FBQyxDQUFDO01BQzFCLElBQUlFLFVBQVUsR0FBR0YsSUFBSSxDQUFDLENBQUMsQ0FBQztNQUN4QixJQUFJRyxhQUFhLEdBQUdILElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJO01BQ25DLElBQUlJLFVBQVUsR0FBR0osSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUk7O01BRWhDO01BQ0FKLFFBQVEsQ0FBQ0csUUFBUSxDQUFDRyxVQUFVLENBQUMsR0FBRztRQUM1QkcsS0FBSyxFQUFFSixZQUFZO1FBQ25CeE0sSUFBSSxFQUFFeU0sVUFBVTtRQUNoQkksT0FBTyxFQUFFSCxhQUFhO1FBQ3RCQyxVQUFVLEVBQUVBLFVBQVUsQ0FBRztNQUM3QixDQUFDOztNQUVEO01BQ0FILFlBQVksQ0FBQ00sS0FBSyxHQUFHTCxVQUFVO01BQy9CRCxZQUFZLENBQUNPLFFBQVEsR0FBR0wsYUFBYTtNQUNyQ0YsWUFBWSxDQUFDUSxXQUFXLEdBQUdMLFVBQVU7SUFDekMsQ0FBQyxDQUFDOztJQUVGO0lBQ0FSLFFBQVEsQ0FBQ2MscUJBQXFCLENBQUMsQ0FBQztFQUNwQzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0EscUJBQXFCQSxDQUFBLEVBQUc7SUFDM0I7SUFDQWQsUUFBUSxDQUFDZSxlQUFlLEdBQUcsQ0FBQyxDQUFDOztJQUU3QjtJQUNBLEtBQUssSUFBSVQsVUFBVSxJQUFJTixRQUFRLENBQUNHLFFBQVEsRUFBRTtNQUN0QyxNQUFNYSxTQUFTLEdBQUdoQixRQUFRLENBQUNHLFFBQVEsQ0FBQ0csVUFBVSxDQUFDO01BQy9DLElBQUlXLGtCQUFrQixHQUFHWCxVQUFVO01BQ25DLElBQUlZLGlCQUFpQixHQUFHRixTQUFTOztNQUVqQztNQUNBLE9BQU9FLGlCQUFpQixFQUFFO1FBQ3RCLE1BQU1DLFlBQVksR0FBR0QsaUJBQWlCLENBQUNSLE9BQU87UUFFOUMsSUFBSVMsWUFBWSxFQUFFO1VBQ2Q7VUFDQSxJQUFJLENBQUNuQixRQUFRLENBQUNlLGVBQWUsQ0FBQ0ksWUFBWSxDQUFDLEVBQUU7WUFDekNuQixRQUFRLENBQUNlLGVBQWUsQ0FBQ0ksWUFBWSxDQUFDLEdBQUcsRUFBRTtVQUMvQzs7VUFFQTtVQUNBLElBQUksQ0FBQ25CLFFBQVEsQ0FBQ2UsZUFBZSxDQUFDSSxZQUFZLENBQUMsQ0FBQ0MsUUFBUSxDQUFDZCxVQUFVLENBQUMsRUFBRTtZQUM5RE4sUUFBUSxDQUFDZSxlQUFlLENBQUNJLFlBQVksQ0FBQyxDQUFDek0sSUFBSSxDQUFDNEwsVUFBVSxDQUFDO1VBQzNEOztVQUVBO1VBQ0EsSUFBSU4sUUFBUSxDQUFDRyxRQUFRLENBQUNnQixZQUFZLENBQUMsRUFBRTtZQUNqQ0QsaUJBQWlCLEdBQUdsQixRQUFRLENBQUNHLFFBQVEsQ0FBQ2dCLFlBQVksQ0FBQztVQUN2RCxDQUFDLE1BQU07WUFDSDtZQUNBRCxpQkFBaUIsR0FBRyxJQUFJO1VBQzVCO1FBQ0osQ0FBQyxNQUFNO1VBQ0g7VUFDQUEsaUJBQWlCLEdBQUcsSUFBSTtRQUM1QjtNQUNKO0lBQ0o7RUFDSjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0csYUFBYUEsQ0FBQ0MsVUFBVSxFQUFFO0lBQzdCLElBQUksQ0FBQ3RCLFFBQVEsQ0FBQ0csUUFBUSxFQUFFO01BQ3BCLE9BQU8sRUFBRTtJQUNiOztJQUVBO0lBQ0EsSUFBSW9CLGlCQUFpQixHQUFHRCxVQUFVO0lBQ2xDLElBQUksT0FBT0EsVUFBVSxLQUFLLFFBQVEsRUFBRTtNQUNoQ0MsaUJBQWlCLEdBQUd2QixRQUFRLENBQUN3QixpQkFBaUIsQ0FBQ0YsVUFBVSxDQUFDO01BQzFELElBQUksQ0FBQ0MsaUJBQWlCLEVBQUU7UUFDcEIsTUFBTSxJQUFJck8sS0FBSyxDQUFDLHlCQUF5Qm9PLFVBQVUsRUFBRSxDQUFDO01BQzFEO0lBQ0o7SUFFQSxNQUFNRyxPQUFPLEdBQUcsRUFBRTtJQUVsQixLQUFLLElBQUluQixVQUFVLElBQUlOLFFBQVEsQ0FBQ0csUUFBUSxFQUFFO01BQ3RDLE1BQU1hLFNBQVMsR0FBR2hCLFFBQVEsQ0FBQ0csUUFBUSxDQUFDRyxVQUFVLENBQUM7TUFDL0MsSUFBSU4sUUFBUSxDQUFDMEIsaUJBQWlCLENBQUNWLFNBQVMsQ0FBQ1AsS0FBSyxFQUFFYyxpQkFBaUIsQ0FBQyxFQUFFO1FBQ2hFRSxPQUFPLENBQUMvTSxJQUFJLENBQUM7VUFDVDRMLFVBQVUsRUFBRUEsVUFBVTtVQUN0QkQsWUFBWSxFQUFFVyxTQUFTLENBQUNQO1FBQzVCLENBQUMsQ0FBQztNQUNOO0lBQ0o7O0lBRUE7SUFDQWdCLE9BQU8sQ0FBQy9MLElBQUksQ0FBQyxDQUFDQyxDQUFDLEVBQUVDLENBQUMsS0FBS0QsQ0FBQyxDQUFDMkssVUFBVSxDQUFDcUIsYUFBYSxDQUFDL0wsQ0FBQyxDQUFDMEssVUFBVSxDQUFDLENBQUM7SUFFaEUsT0FBT21CLE9BQU87RUFDbEI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPQyxpQkFBaUJBLENBQUNFLFFBQVEsRUFBRUMsVUFBVSxFQUFFO0lBQzNDO0lBQ0EsSUFBSUMsZUFBZSxHQUFHRixRQUFRO0lBQzlCLElBQUksT0FBT0EsUUFBUSxLQUFLLFFBQVEsRUFBRTtNQUM5QkUsZUFBZSxHQUFHOUIsUUFBUSxDQUFDd0IsaUJBQWlCLENBQUNJLFFBQVEsQ0FBQztNQUN0RCxJQUFJLENBQUNFLGVBQWUsRUFBRTtRQUNsQjtRQUNBLE9BQU8sS0FBSztNQUNoQjtJQUNKO0lBRUEsSUFBSUMsaUJBQWlCLEdBQUdGLFVBQVU7SUFDbEMsSUFBSSxPQUFPQSxVQUFVLEtBQUssUUFBUSxFQUFFO01BQ2hDRSxpQkFBaUIsR0FBRy9CLFFBQVEsQ0FBQ3dCLGlCQUFpQixDQUFDSyxVQUFVLENBQUM7TUFDMUQsSUFBSSxDQUFDRSxpQkFBaUIsRUFBRTtRQUNwQjtRQUNBLE1BQU0sSUFBSTdPLEtBQUssQ0FBQyxxQ0FBcUMyTyxVQUFVLEVBQUUsQ0FBQztNQUN0RTtJQUNKOztJQUVBO0lBQ0EsSUFBSUMsZUFBZSxLQUFLQyxpQkFBaUIsRUFBRTtNQUN2QyxPQUFPLEtBQUs7SUFDaEI7O0lBRUE7SUFDQSxJQUFJQyxhQUFhLEdBQUdGLGVBQWU7SUFDbkMsT0FBT0UsYUFBYSxFQUFFO01BQ2xCLElBQUlBLGFBQWEsS0FBS0QsaUJBQWlCLEVBQUU7UUFDckMsT0FBTyxJQUFJO01BQ2Y7TUFDQTtNQUNBLElBQUlDLGFBQWEsQ0FBQ3BCLFFBQVEsRUFBRTtRQUN4QjtRQUNBLElBQUksT0FBT29CLGFBQWEsQ0FBQ3BCLFFBQVEsS0FBSyxRQUFRLEVBQUU7VUFDNUNvQixhQUFhLEdBQUdoQyxRQUFRLENBQUN3QixpQkFBaUIsQ0FBQ1EsYUFBYSxDQUFDcEIsUUFBUSxDQUFDO1FBQ3RFLENBQUMsTUFBTTtVQUNIb0IsYUFBYSxHQUFHQSxhQUFhLENBQUNwQixRQUFRO1FBQzFDO01BQ0osQ0FBQyxNQUFNO1FBQ0hvQixhQUFhLEdBQUcsSUFBSTtNQUN4QjtJQUNKO0lBRUEsT0FBTyxLQUFLO0VBQ2hCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPUixpQkFBaUJBLENBQUNsQixVQUFVLEVBQUU7SUFDakMsSUFBSSxDQUFDTixRQUFRLENBQUNHLFFBQVEsSUFBSSxDQUFDSCxRQUFRLENBQUNHLFFBQVEsQ0FBQ0csVUFBVSxDQUFDLEVBQUU7TUFDdEQsT0FBTyxJQUFJO0lBQ2Y7SUFFQSxPQUFPTixRQUFRLENBQUNHLFFBQVEsQ0FBQ0csVUFBVSxDQUFDLENBQUNHLEtBQUs7RUFDOUM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7RUFDSSxPQUFPd0IsZUFBZUEsQ0FBQSxFQUFHO0lBQ3JCLElBQUksQ0FBQ2pDLFFBQVEsQ0FBQ0csUUFBUSxFQUFFO01BQ3BCLE9BQU8sRUFBRTtJQUNiO0lBRUEsTUFBTW5GLE9BQU8sR0FBRyxFQUFFO0lBQ2xCLEtBQUssSUFBSXNGLFVBQVUsSUFBSU4sUUFBUSxDQUFDRyxRQUFRLEVBQUU7TUFDdEMsTUFBTWEsU0FBUyxHQUFHaEIsUUFBUSxDQUFDRyxRQUFRLENBQUNHLFVBQVUsQ0FBQztNQUMvQ3RGLE9BQU8sQ0FBQ3RHLElBQUksQ0FBQztRQUNUNEwsVUFBVSxFQUFFVSxTQUFTLENBQUNuTixJQUFJO1FBQzFCd00sWUFBWSxFQUFFVyxTQUFTLENBQUNQLEtBQUs7UUFDN0JDLE9BQU8sRUFBRU0sU0FBUyxDQUFDTjtNQUN2QixDQUFDLENBQUM7SUFDTjs7SUFFQTtJQUNBMUYsT0FBTyxDQUFDdEYsSUFBSSxDQUFDLENBQUNDLENBQUMsRUFBRUMsQ0FBQyxLQUFLRCxDQUFDLENBQUMySyxVQUFVLENBQUNxQixhQUFhLENBQUMvTCxDQUFDLENBQUMwSyxVQUFVLENBQUMsQ0FBQztJQUVoRSxPQUFPdEYsT0FBTztFQUNsQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU9rSCxTQUFTQSxDQUFBLEVBQUc7SUFDZixJQUFJeFQsTUFBTSxDQUFDeVQsTUFBTSxJQUFJelQsTUFBTSxDQUFDeVQsTUFBTSxDQUFDRCxTQUFTLEVBQUU7TUFDMUMsT0FBT3hULE1BQU0sQ0FBQ3lULE1BQU0sQ0FBQ0QsU0FBUztJQUNsQztJQUNBLE9BQU8sU0FBUztFQUNwQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPRSxjQUFjQSxDQUFDOUIsVUFBVSxFQUFFM0osV0FBVyxFQUFFO0lBQzNDO0lBQ0EsSUFBSSxPQUFPMkosVUFBVSxLQUFLLFFBQVEsRUFBRTtNQUNoQ0EsVUFBVSxHQUFHQSxVQUFVLENBQUNLLEtBQUssSUFBSUwsVUFBVSxDQUFDek0sSUFBSTtJQUNwRDtJQUVBLE1BQU13TyxVQUFVLEdBQUdyQyxRQUFRLENBQUNHLFFBQVEsQ0FBQ0csVUFBVSxDQUFDO0lBQ2hELElBQUksQ0FBQytCLFVBQVUsSUFBSSxDQUFDQSxVQUFVLENBQUM3QixVQUFVLElBQUksQ0FBQzZCLFVBQVUsQ0FBQzdCLFVBQVUsQ0FBQzdKLFdBQVcsQ0FBQyxFQUFFO01BQzlFLE9BQU8sSUFBSTtJQUNmOztJQUVBO0lBQ0EsT0FBT3FKLFFBQVEsQ0FBQ3NDLHFCQUFxQixDQUFDRCxVQUFVLENBQUM3QixVQUFVLENBQUM3SixXQUFXLENBQUMsQ0FBQztFQUM3RTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBTzRMLGtCQUFrQkEsQ0FBQ2pDLFVBQVUsRUFBRTtJQUNsQztJQUNBLElBQUksT0FBT0EsVUFBVSxLQUFLLFFBQVEsRUFBRTtNQUNoQ0EsVUFBVSxHQUFHQSxVQUFVLENBQUNLLEtBQUssSUFBSUwsVUFBVSxDQUFDek0sSUFBSTtJQUNwRDtJQUVBLE1BQU13TyxVQUFVLEdBQUdyQyxRQUFRLENBQUNHLFFBQVEsQ0FBQ0csVUFBVSxDQUFDO0lBQ2hELElBQUksQ0FBQytCLFVBQVUsSUFBSSxDQUFDQSxVQUFVLENBQUM3QixVQUFVLEVBQUU7TUFDdkMsT0FBTyxDQUFDLENBQUM7SUFDYjs7SUFFQTtJQUNBLE1BQU0zRyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2pCLEtBQUssSUFBSWxELFdBQVcsSUFBSTBMLFVBQVUsQ0FBQzdCLFVBQVUsRUFBRTtNQUMzQzNHLE1BQU0sQ0FBQ2xELFdBQVcsQ0FBQyxHQUFHcUosUUFBUSxDQUFDc0MscUJBQXFCLENBQUNELFVBQVUsQ0FBQzdCLFVBQVUsQ0FBQzdKLFdBQVcsQ0FBQyxDQUFDO0lBQzVGO0lBQ0EsT0FBT2tELE1BQU07RUFDakI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT3lJLHFCQUFxQkEsQ0FBQ0Usa0JBQWtCLEVBQUU7SUFDN0MsSUFBSSxDQUFDeEssS0FBSyxDQUFDaUQsT0FBTyxDQUFDdUgsa0JBQWtCLENBQUMsRUFBRTtNQUNwQyxPQUFPLEVBQUU7SUFDYjtJQUVBLE9BQU9BLGtCQUFrQixDQUFDcEUsR0FBRyxDQUFDalEsU0FBUyxJQUFJO01BQ3ZDLElBQUk2SixLQUFLLENBQUNpRCxPQUFPLENBQUM5TSxTQUFTLENBQUMsSUFBSUEsU0FBUyxDQUFDbUQsTUFBTSxJQUFJLENBQUMsRUFBRTtRQUNuRCxPQUFPO1VBQ0h1QyxJQUFJLEVBQUUxRixTQUFTLENBQUMsQ0FBQyxDQUFDO1VBQ2xCNkUsU0FBUyxFQUFFN0UsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJO1FBQy9CLENBQUM7TUFDTDtNQUNBO01BQ0EsT0FBTztRQUNIMEYsSUFBSSxFQUFFLFNBQVM7UUFDZmIsU0FBUyxFQUFFO01BQ2YsQ0FBQztJQUNMLENBQUMsQ0FBQztFQUNOOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT3lQLGFBQWFBLENBQUNuQyxVQUFVLEVBQUUzSixXQUFXLEVBQUUrTCxjQUFjLEVBQUU7SUFDMUQsTUFBTWxDLFVBQVUsR0FBR1IsUUFBUSxDQUFDb0MsY0FBYyxDQUFDOUIsVUFBVSxFQUFFM0osV0FBVyxDQUFDO0lBQ25FLElBQUksQ0FBQzZKLFVBQVUsRUFBRTtNQUNiLE9BQU8sS0FBSztJQUNoQjtJQUVBLE9BQU9BLFVBQVUsQ0FBQ21DLElBQUksQ0FBQ0MsQ0FBQyxJQUFJQSxDQUFDLENBQUMvTyxJQUFJLEtBQUs2TyxjQUFjLENBQUM7RUFDMUQ7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0csb0JBQW9CQSxDQUFDdkIsVUFBVSxFQUFFO0lBQ3BDO0lBQ0EsSUFBSSxDQUFDdEIsUUFBUSxDQUFDZSxlQUFlLEVBQUU7TUFDM0JmLFFBQVEsQ0FBQ2MscUJBQXFCLENBQUMsQ0FBQztJQUNwQzs7SUFFQTtJQUNBLElBQUlnQyxlQUFlLEdBQUd4QixVQUFVO0lBQ2hDLElBQUksT0FBT0EsVUFBVSxLQUFLLFFBQVEsRUFBRTtNQUNoQ3dCLGVBQWUsR0FBR3hCLFVBQVUsQ0FBQ1gsS0FBSyxJQUFJVyxVQUFVLENBQUN6TixJQUFJO0lBQ3pEOztJQUVBO0lBQ0EsSUFBSSxDQUFDbU0sUUFBUSxDQUFDRyxRQUFRLENBQUMyQyxlQUFlLENBQUMsRUFBRTtNQUNyQztNQUNBLE9BQU8sRUFBRTtJQUNiOztJQUVBO0lBQ0EsTUFBTUMsY0FBYyxHQUFHL0MsUUFBUSxDQUFDZSxlQUFlLENBQUMrQixlQUFlLENBQUMsSUFBSSxFQUFFOztJQUV0RTtJQUNBLE1BQU1FLGdCQUFnQixHQUFHLEVBQUU7SUFDM0IsS0FBSyxJQUFJQyxhQUFhLElBQUlGLGNBQWMsRUFBRTtNQUN0QyxNQUFNL0IsU0FBUyxHQUFHaEIsUUFBUSxDQUFDRyxRQUFRLENBQUM4QyxhQUFhLENBQUM7TUFDbERELGdCQUFnQixDQUFDdE8sSUFBSSxDQUFDc00sU0FBUyxDQUFDUCxLQUFLLENBQUM7SUFDMUM7O0lBRUE7SUFDQXVDLGdCQUFnQixDQUFDdE4sSUFBSSxDQUFDLENBQUNDLENBQUMsRUFBRUMsQ0FBQyxLQUFLO01BQzVCLE1BQU1zTixNQUFNLEdBQUd2TixDQUFDLENBQUNnTCxLQUFLLElBQUloTCxDQUFDLENBQUM5QixJQUFJO01BQ2hDLE1BQU1zUCxNQUFNLEdBQUd2TixDQUFDLENBQUMrSyxLQUFLLElBQUkvSyxDQUFDLENBQUMvQixJQUFJO01BQ2hDLE9BQU9xUCxNQUFNLENBQUN2QixhQUFhLENBQUN3QixNQUFNLENBQUM7SUFDdkMsQ0FBQyxDQUFDO0lBRUYsT0FBT0gsZ0JBQWdCO0VBQzNCO0FBQ0o7O0FBRUE7Ozs7OztBQ3hXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1JLGFBQWEsQ0FBQztFQUNoQixPQUFPQyx1QkFBdUJBLENBQUEsRUFBRztJQUM3QkQsYUFBYSxDQUFDRSxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ2pERixhQUFhLENBQUNHLGlCQUFpQixDQUFDLENBQUM7RUFDckM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPRCxpQ0FBaUNBLENBQUEsRUFBRztJQUN2QyxPQUFPLENBQUM7O0lBRVI7SUFDQTtJQUNBN1UsQ0FBQyxDQUFDK1UsUUFBUSxDQUFDLENBQUNDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsY0FBYyxFQUFFLFVBQVVDLENBQUMsRUFBRTtNQUNyRCxNQUFNQyxLQUFLLEdBQUdsVixDQUFDLENBQUMsSUFBSSxDQUFDO01BQ3JCLE1BQU1tVixJQUFJLEdBQUdELEtBQUssQ0FBQ0UsSUFBSSxDQUFDLE1BQU0sQ0FBQzs7TUFFL0I7TUFDQSxJQUFJSCxDQUFDLENBQUNJLGtCQUFrQixDQUFDLENBQUMsRUFBRTtRQUN4QjtNQUNKOztNQUVBO01BQ0EsSUFBSUgsS0FBSyxDQUFDSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtRQUM5QjtNQUNKOztNQUVBO01BQ0EsSUFBSUgsSUFBSSxLQUFLLEdBQUcsRUFBRTtRQUNkRixDQUFDLENBQUNNLGNBQWMsQ0FBQyxDQUFDO1FBQ2xCTixDQUFDLENBQUNPLHdCQUF3QixDQUFDLENBQUM7UUFDNUIsT0FBTyxLQUFLO01BQ2hCOztNQUVBO01BQ0EsSUFBSUwsSUFBSSxDQUFDTSxVQUFVLENBQUMsY0FBYyxDQUFDLEVBQUU7UUFDakNSLENBQUMsQ0FBQ00sY0FBYyxDQUFDLENBQUM7UUFDbEJOLENBQUMsQ0FBQ08sd0JBQXdCLENBQUMsQ0FBQztRQUM1QixPQUFPLEtBQUs7TUFDaEI7O01BRUE7TUFDQSxNQUFNRSxRQUFRLEdBQUdQLElBQUksQ0FBQ1EsU0FBUyxDQUFDLENBQUMsQ0FBQztNQUNsQyxJQUFJRCxRQUFRLEVBQUU7UUFDVjtRQUNBLE1BQU1FLFlBQVksR0FBR2IsUUFBUSxDQUFDYyxjQUFjLENBQUNILFFBQVEsQ0FBQyxLQUFLLElBQUksSUFBSVgsUUFBUSxDQUFDZSxhQUFhLENBQUMsVUFBVUosUUFBUSxJQUFJLENBQUMsS0FBSyxJQUFJO1FBRTFILElBQUksQ0FBQ0UsWUFBWSxFQUFFO1VBQ2Y7VUFDQVgsQ0FBQyxDQUFDTSxjQUFjLENBQUMsQ0FBQztVQUNsQk4sQ0FBQyxDQUFDTyx3QkFBd0IsQ0FBQyxDQUFDO1VBQzVCLE9BQU8sS0FBSztRQUNoQjtRQUNBO01BQ0o7SUFDSixDQUFDLENBQUM7RUFDTjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT1YsaUJBQWlCQSxDQUFBLEVBQUc7SUFDdkJDLFFBQVEsQ0FBQ2dCLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxVQUFVQyxLQUFLLEVBQUU7TUFDL0M7TUFDQSxJQUFJQSxLQUFLLENBQUNDLFFBQVEsRUFBRTtNQUVwQixJQUFJQyxTQUFTLEdBQUdqVyxNQUFNLENBQUNrVyxZQUFZLENBQUMsQ0FBQztNQUNyQyxJQUFJQyxhQUFhLEdBQUdGLFNBQVMsQ0FBQ3pJLFFBQVEsQ0FBQyxDQUFDOztNQUV4QztNQUNBLElBQUksQ0FBQzJJLGFBQWEsRUFBRTs7TUFFcEI7TUFDQSxJQUFJQyxTQUFTLEdBQUdILFNBQVMsQ0FBQ0ksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDQyx1QkFBdUI7TUFDL0QsSUFBSUYsU0FBUyxDQUFDRyxRQUFRLEtBQUssQ0FBQyxFQUFFSCxTQUFTLEdBQUdBLFNBQVMsQ0FBQ0ksVUFBVSxDQUFDLENBQUM7TUFDaEUsSUFBSUosU0FBUyxDQUFDSyxPQUFPLENBQUMsNERBQTRELENBQUMsRUFBRTtNQUVyRixJQUFJQyxZQUFZLEdBQUdQLGFBQWEsQ0FBQzlFLElBQUksQ0FBQyxDQUFDOztNQUV2QztNQUNBLElBQUlxRixZQUFZLEtBQUtQLGFBQWEsSUFBSU8sWUFBWSxDQUFDOVQsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUMzRG1ULEtBQUssQ0FBQ1QsY0FBYyxDQUFDLENBQUM7UUFDdEJTLEtBQUssQ0FBQ1ksYUFBYSxDQUFDQyxPQUFPLENBQUMsWUFBWSxFQUFFRixZQUFZLENBQUM7UUFDdkQxUixPQUFPLENBQUM2UixHQUFHLENBQUMseUNBQXlDLENBQUM7TUFDMUQ7SUFDSixDQUFDLENBQUM7RUFDTjtBQUNKOzs7Ozs7QUMzR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTUMsU0FBUyxDQUFDO0VBQ1osT0FBT0MsY0FBY0EsQ0FBQSxFQUFHO0lBQ3BCQyxVQUFVLENBQUNDLE9BQU8sR0FBRztNQUNqQkMsTUFBTSxFQUFFLENBQUMsQ0FBQztNQUNWbFAsUUFBUSxFQUFFLENBQUM7SUFDZixDQUFDO0lBRURnUCxVQUFVLENBQUNHLFdBQVcsR0FBRyxDQUFDO0VBQzlCOztFQUVBO0VBQ0EsT0FBT2hQLEdBQUdBLENBQUN2QyxHQUFHLEVBQUU7SUFDWixPQUFPa1IsU0FBUyxDQUFDTSxZQUFZLENBQUN4UixHQUFHLENBQUM7RUFDdEM7O0VBRUE7RUFDQTtFQUNBO0VBQ0EsT0FBT3dSLFlBQVlBLENBQUN4UixHQUFHLEVBQUU7SUFDckIsSUFBSXlSLElBQUksQ0FBQ0MsS0FBSyxDQUFDLGNBQWMsQ0FBQyxFQUFFO01BQzVCLE9BQU8sSUFBSTtJQUNmO0lBRUEsSUFBSUMsV0FBVyxHQUFHVCxTQUFTLENBQUNVLFVBQVUsQ0FBQzVSLEdBQUcsQ0FBQztJQUUzQyxJQUFJLE9BQU9vUixVQUFVLENBQUNDLE9BQU8sQ0FBQ2pQLFFBQVEsQ0FBQ3VQLFdBQVcsQ0FBQyxJQUFJclQsS0FBSyxFQUFFO01BQzFELE9BQU93QixJQUFJLENBQUN1SixLQUFLLENBQUMrSCxVQUFVLENBQUNDLE9BQU8sQ0FBQ2pQLFFBQVEsQ0FBQ3VQLFdBQVcsQ0FBQyxDQUFDO0lBQy9EO0lBRUEsT0FBTyxJQUFJO0VBQ2Y7O0VBRUE7RUFDQTtFQUNBLE9BQU9FLFVBQVVBLENBQUM3UixHQUFHLEVBQUU7SUFDbkIsSUFBSXlSLElBQUksQ0FBQ0MsS0FBSyxDQUFDLGNBQWMsQ0FBQyxFQUFFO01BQzVCLE9BQU8sSUFBSTtJQUNmO0lBRUEsSUFBSUMsV0FBVyxHQUFHVCxTQUFTLENBQUNVLFVBQVUsQ0FBQzVSLEdBQUcsQ0FBQztJQUUzQyxJQUFJLE9BQU9vUixVQUFVLENBQUNDLE9BQU8sQ0FBQ0MsTUFBTSxDQUFDSyxXQUFXLENBQUMsSUFBSXJULEtBQUssRUFBRTtNQUN4RCxPQUFPd0IsSUFBSSxDQUFDdUosS0FBSyxDQUFDK0gsVUFBVSxDQUFDQyxPQUFPLENBQUNDLE1BQU0sQ0FBQ0ssV0FBVyxDQUFDLENBQUM7SUFDN0Q7SUFFQSxPQUFPLElBQUk7RUFDZjs7RUFFQTtFQUNBLE9BQU9uUCxHQUFHQSxDQUFDeEMsR0FBRyxFQUFFbEcsS0FBSyxFQUFFO0lBQ25CLElBQUkyWCxJQUFJLENBQUNDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRTtNQUM1QjtJQUNKO0lBRUEsSUFBSTVYLEtBQUssS0FBSyxJQUFJLEVBQUU7TUFDaEI7SUFDSjtJQUVBLElBQUlBLEtBQUssQ0FBQ2tELE1BQU0sR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFO01BQzFCaEIsUUFBUSxDQUFDQyxhQUFhLENBQUMsT0FBTyxFQUFFLHlDQUF5QyxFQUFFK0QsR0FBRyxDQUFDO01BQy9FO0lBQ0o7SUFFQSxJQUFJMlIsV0FBVyxHQUFHVCxTQUFTLENBQUNVLFVBQVUsQ0FBQzVSLEdBQUcsQ0FBQztJQUUzQ29SLFVBQVUsQ0FBQ0MsT0FBTyxDQUFDQyxNQUFNLENBQUNLLFdBQVcsQ0FBQyxHQUFHN1IsSUFBSSxDQUFDQyxTQUFTLENBQUNqRyxLQUFLLENBQUM7SUFDOURzWCxVQUFVLENBQUNDLE9BQU8sQ0FBQ2pQLFFBQVEsQ0FBQ3VQLFdBQVcsQ0FBQyxHQUFHN1IsSUFBSSxDQUFDQyxTQUFTLENBQUNqRyxLQUFLLENBQUM7O0lBRWhFOztJQUVBc1gsVUFBVSxDQUFDRyxXQUFXLEVBQUU7O0lBRXhCO0lBQ0EsSUFBSUgsVUFBVSxDQUFDRyxXQUFXLEdBQUcsSUFBSSxFQUFFO01BQy9CO01BQ0FILFVBQVUsQ0FBQ0csV0FBVyxHQUFHcEgsS0FBSyxDQUFDaUgsVUFBVSxDQUFDQyxPQUFPLENBQUNDLE1BQU0sQ0FBQztNQUV6RCxJQUFJRixVQUFVLENBQUNHLFdBQVcsR0FBRyxJQUFJLEVBQUU7UUFDL0JILFVBQVUsQ0FBQ0MsT0FBTyxHQUFHO1VBQ2pCQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1VBQ1ZsUCxRQUFRLEVBQUUsQ0FBQztRQUNmLENBQUM7UUFDRGdQLFVBQVUsQ0FBQ0csV0FBVyxHQUFHLENBQUM7TUFDOUI7SUFDSjtFQUNKOztFQUVBO0VBQ0E7RUFDQSxPQUFPTyxXQUFXQSxDQUFDOVIsR0FBRyxFQUFFO0lBQ3BCLElBQUl5UixJQUFJLENBQUNDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRTtNQUM1QixPQUFPLElBQUk7SUFDZjtJQUVBLElBQUksQ0FBQ1IsU0FBUyxDQUFDYSxnQkFBZ0IsQ0FBQyxDQUFDLEVBQUU7TUFDL0IsT0FBTyxJQUFJO0lBQ2Y7SUFFQSxJQUFJSixXQUFXLEdBQUdULFNBQVMsQ0FBQ1UsVUFBVSxDQUFDNVIsR0FBRyxDQUFDO0lBRTNDLElBQUlnUyxFQUFFLEdBQUdDLGNBQWMsQ0FBQ0MsT0FBTyxDQUFDUCxXQUFXLENBQUM7SUFFNUMsSUFBSSxDQUFDekosS0FBSyxDQUFDOEosRUFBRSxDQUFDLEVBQUU7TUFDWixPQUFPbFMsSUFBSSxDQUFDdUosS0FBSyxDQUFDMkksRUFBRSxDQUFDO0lBQ3pCLENBQUMsTUFBTTtNQUNILE9BQU8sSUFBSTtJQUNmO0VBQ0o7O0VBRUE7RUFDQSxPQUFPRyxXQUFXQSxDQUFDblMsR0FBRyxFQUFFbEcsS0FBSyxFQUFvQjtJQUFBLElBQWxCc1ksU0FBUyxHQUFBMVQsU0FBQSxDQUFBMUIsTUFBQSxRQUFBMEIsU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBRyxJQUFJO0lBQzNDLElBQUkrUyxJQUFJLENBQUNDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRTtNQUM1QjtJQUNKO0lBRUEsSUFBSTVYLEtBQUssQ0FBQ2tELE1BQU0sR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFO01BQzFCaEIsUUFBUSxDQUFDQyxhQUFhLENBQUMsT0FBTyxFQUFFLHlDQUF5QyxFQUFFK0QsR0FBRyxDQUFDO01BQy9FO0lBQ0o7SUFFQSxJQUFJLENBQUNrUixTQUFTLENBQUNhLGdCQUFnQixDQUFDLENBQUMsRUFBRTtNQUMvQixPQUFPLElBQUk7SUFDZjtJQUVBLElBQUlKLFdBQVcsR0FBR1QsU0FBUyxDQUFDVSxVQUFVLENBQUM1UixHQUFHLENBQUM7SUFFM0MsSUFBSTtNQUNBaVMsY0FBYyxDQUFDSSxVQUFVLENBQUNWLFdBQVcsQ0FBQztNQUN0Q00sY0FBYyxDQUFDSyxPQUFPLENBQUNYLFdBQVcsRUFBRTdSLElBQUksQ0FBQ0MsU0FBUyxDQUFDakcsS0FBSyxDQUFDLENBQUM7SUFDOUQsQ0FBQyxDQUFDLE9BQU9zVixDQUFDLEVBQUU7TUFDUixJQUFJOEIsU0FBUyxDQUFDcUIsYUFBYSxDQUFDbkQsQ0FBQyxDQUFDLElBQUk2QyxjQUFjLENBQUNqVixNQUFNLEVBQUU7UUFDckRpVixjQUFjLENBQUNPLEtBQUssQ0FBQyxDQUFDO1FBQ3RCLElBQUlKLFNBQVMsRUFBRTtVQUNYaEIsVUFBVSxDQUFDZSxXQUFXLENBQUNuUyxHQUFHLEVBQUVsRyxLQUFLLEVBQUUsS0FBSyxDQUFDO1FBQzdDO01BQ0o7SUFDSjtFQUNKO0VBRUEsT0FBTzJZLE1BQU1BLENBQUEsRUFBRztJQUNackIsVUFBVSxDQUFDQyxPQUFPLENBQUNqUCxRQUFRLEdBQUcsQ0FBQyxDQUFDO0VBQ3BDOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT3dQLFVBQVVBLENBQUM1UixHQUFHLEVBQUU7SUFDbkIsTUFBTU8sTUFBTSxHQUFHLFFBQVE7O0lBRXZCO0lBQ0E7O0lBRUEsSUFBSThHLFNBQVMsQ0FBQ3JILEdBQUcsQ0FBQyxJQUFJQSxHQUFHLENBQUNoRCxNQUFNLEdBQUcsR0FBRyxJQUFJZ0QsR0FBRyxDQUFDakYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFO01BQzlELE9BQU93RixNQUFNLEdBQUdtTCxRQUFRLENBQUNrQyxTQUFTLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRzVOLEdBQUc7SUFDcEQsQ0FBQyxNQUFNO01BQ0gsT0FBT08sTUFBTSxHQUFHZixJQUFJLENBQUMsQ0FBQ2tNLFFBQVEsQ0FBQ2tDLFNBQVMsQ0FBQyxDQUFDLEVBQUU1TixHQUFHLENBQUMsQ0FBQztJQUNyRDtFQUNKOztFQUVBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBLE9BQU8rUixnQkFBZ0JBLENBQUEsRUFBRztJQUN0QixJQUFJL1IsR0FBRyxHQUFHLGVBQWU7SUFDekIsSUFBSWxHLEtBQUssR0FBR2tHLEdBQUc7SUFFZixJQUFJa1IsU0FBUyxDQUFDd0IsaUJBQWlCLEtBQUsvVCxTQUFTLEVBQUU7TUFDM0MsT0FBT3VTLFNBQVMsQ0FBQ3dCLGlCQUFpQjtJQUN0Qzs7SUFFQTtJQUNBO0lBQ0EsSUFBSTtNQUNBLElBQUksQ0FBQ1QsY0FBYyxFQUFFO1FBQ2pCLE9BQU8sS0FBSztNQUNoQjtJQUNKLENBQUMsQ0FBQyxPQUFPVSxFQUFFLEVBQUU7TUFDVCxPQUFPLEtBQUs7SUFDaEI7SUFFQSxJQUFJO01BQ0FWLGNBQWMsQ0FBQ0ssT0FBTyxDQUFDdFMsR0FBRyxFQUFFbEcsS0FBSyxDQUFDO01BQ2xDbVksY0FBYyxDQUFDSSxVQUFVLENBQUNyUyxHQUFHLENBQUM7TUFDOUJrUixTQUFTLENBQUN3QixpQkFBaUIsR0FBRyxJQUFJO0lBQ3RDLENBQUMsQ0FBQyxPQUFPdEQsQ0FBQyxFQUFFO01BQ1I7TUFDQSxJQUFJOEIsU0FBUyxDQUFDcUIsYUFBYSxDQUFDbkQsQ0FBQyxDQUFDLElBQUk2QyxjQUFjLENBQUNqVixNQUFNLEVBQUU7UUFDckRrVSxTQUFTLENBQUN3QixpQkFBaUIsR0FBRyxJQUFJLENBQUMsQ0FBQztNQUN4QyxDQUFDLE1BQU07UUFDSHhCLFNBQVMsQ0FBQ3dCLGlCQUFpQixHQUFHLEtBQUs7TUFDdkM7SUFDSjtJQUVBLE9BQU94QixTQUFTLENBQUN3QixpQkFBaUI7RUFDdEM7O0VBRUE7RUFDQSxPQUFPSCxhQUFhQSxDQUFDbkQsQ0FBQyxFQUFFO0lBQ3BCLE9BQU9BLENBQUMsS0FBS0EsQ0FBQyxDQUFDN1AsSUFBSSxLQUFLLG9CQUFvQixJQUFJNlAsQ0FBQyxDQUFDN1AsSUFBSSxLQUFLLDRCQUE0QixJQUFJNlAsQ0FBQyxDQUFDN1AsSUFBSSxLQUFLLG9CQUFvQixDQUFDO0VBQy9IO0FBQ0o7Ozs7OztBQ2pOQTtBQUNBO0FBQ0E7QUFDQSxNQUFNcVQsUUFBUSxDQUFDO0VBQ1g7QUFDSjtBQUNBO0FBQ0E7RUFDSSxPQUFPN0QsdUJBQXVCQSxDQUFBLEVBQUc7SUFDN0IsSUFBSSxDQUFDOEQsR0FBRyxDQUFDQyxPQUFPLENBQUMsQ0FBQyxFQUFFO01BQ2hCRixRQUFRLENBQUNHLG9CQUFvQixDQUFDLENBQUM7SUFDbkM7RUFDSjs7RUFFQTtBQUNKO0FBQ0E7RUFDSSxPQUFPQSxvQkFBb0JBLENBQUEsRUFBRztJQUMxQjtJQUNBLE1BQU1DLE9BQU8sR0FBRzlELFFBQVEsQ0FBQytELG9CQUFvQixDQUFDLFFBQVEsQ0FBQztJQUV2RCxLQUFLLElBQUluUyxDQUFDLEdBQUcsQ0FBQyxFQUFFQSxDQUFDLEdBQUdrUyxPQUFPLENBQUNoVyxNQUFNLEVBQUU4RCxDQUFDLEVBQUUsRUFBRTtNQUNyQyxNQUFNb1MsTUFBTSxHQUFHRixPQUFPLENBQUNsUyxDQUFDLENBQUM7O01BRXpCO01BQ0EsSUFBSSxDQUFDb1MsTUFBTSxDQUFDM1YsR0FBRyxFQUFFO1FBQ2I7TUFDSjs7TUFFQTtNQUNBLElBQUksQ0FBQzJWLE1BQU0sQ0FBQ0MsS0FBSyxFQUFFO1FBQ2YsTUFBTTVWLEdBQUcsR0FBRzJWLE1BQU0sQ0FBQzNWLEdBQUcsSUFBSSxpQkFBaUI7UUFDM0MsTUFBTTZWLE1BQU0sR0FBRyxvR0FBb0c3VixHQUFHLEVBQUU7O1FBRXhIO1FBQ0FzVixHQUFHLENBQUNRLG1CQUFtQixDQUFDRCxNQUFNLENBQUM7O1FBRS9CO1FBQ0FoVSxPQUFPLENBQUNqQixLQUFLLENBQUMsc0JBQXNCaVYsTUFBTSxFQUFFLENBQUM7O1FBRTdDO1FBQ0E7TUFDSjtJQUNKO0VBQ0o7QUFDSjs7Ozs7O0FDN0NBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1FLFlBQVksQ0FBQztFQUNmO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSXpJLFdBQVdBLENBQUEsRUFBWTtJQUFBLElBQVg0RSxJQUFJLEdBQUEvUSxTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLENBQUMsQ0FBQztJQUNqQjtJQUNBO0lBQ0E7O0lBRUE7SUFDQTtJQUNBLE1BQU07TUFBRTZVLE9BQU87TUFBRSxHQUFHQztJQUFVLENBQUMsR0FBRy9ELElBQUk7SUFDdEMzRSxNQUFNLENBQUNDLE1BQU0sQ0FBQyxJQUFJLEVBQUV5SSxTQUFTLENBQUM7RUFDbEM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxhQUFhQyxLQUFLQSxDQUFDL1YsRUFBRSxFQUFFO0lBQ25CLE1BQU1nVyxZQUFZLEdBQUcsSUFBSTtJQUN6QjtJQUNBLE1BQU1DLFNBQVMsR0FBR0QsWUFBWSxDQUFDblUsSUFBSTtJQUVuQyxNQUFNcVUsUUFBUSxHQUFHLE1BQU16WixDQUFDLENBQUMwWixJQUFJLENBQUM7TUFDMUJDLEdBQUcsRUFBRSxXQUFXSCxTQUFTLEVBQUU7TUFDM0JJLE1BQU0sRUFBRSxNQUFNO01BQ2R0RSxJQUFJLEVBQUU7UUFBRS9SLEVBQUUsRUFBRUE7TUFBRyxDQUFDO01BQ2hCc1csUUFBUSxFQUFFO0lBQ2QsQ0FBQyxDQUFDOztJQUVGO0lBQ0EsSUFBSUosUUFBUSxLQUFLLEtBQUssRUFBRTtNQUNwQixPQUFPLEtBQUs7SUFDaEI7O0lBRUE7SUFDQTtJQUNBLE9BQU9OLFlBQVksQ0FBQ1csNkJBQTZCLENBQUNMLFFBQVEsQ0FBQztFQUMvRDs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPTSxZQUFZQSxDQUFBLEVBQUc7SUFDbEIsTUFBTVIsWUFBWSxHQUFHLElBQUk7SUFDekIsT0FBT0EsWUFBWSxDQUFDblUsSUFBSTtFQUM1Qjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksTUFBTTRVLE9BQU9BLENBQUEsRUFBRztJQUNaLE1BQU16SixJQUFJLEdBQUcsSUFBSTtJQUNqQixJQUFJLENBQUNBLElBQUksQ0FBQ2hOLEVBQUUsRUFBRTtNQUNWYyxlQUFlLENBQUMsMENBQTBDLENBQUM7SUFDL0Q7SUFFQSxNQUFNNFYsS0FBSyxHQUFHLE1BQU0xSixJQUFJLENBQUNHLFdBQVcsQ0FBQzRJLEtBQUssQ0FBQy9JLElBQUksQ0FBQ2hOLEVBQUUsQ0FBQztJQUVuRCxJQUFJMFcsS0FBSyxLQUFLLEtBQUssRUFBRTtNQUNqQixPQUFPLEtBQUs7SUFDaEI7O0lBRUE7SUFDQXRKLE1BQU0sQ0FBQ0MsTUFBTSxDQUFDTCxJQUFJLEVBQUUwSixLQUFLLENBQUM7SUFDMUIsT0FBTzFKLElBQUk7RUFDZjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSTJKLFFBQVFBLENBQUEsRUFBRztJQUNQLE1BQU0zSixJQUFJLEdBQUcsSUFBSTtJQUNqQixNQUFNakUsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUNkLEtBQUssTUFBTXpHLEdBQUcsSUFBSTBLLElBQUksRUFBRTtNQUNwQixJQUFJQSxJQUFJLENBQUM5SixjQUFjLENBQUNaLEdBQUcsQ0FBQyxJQUFJLE9BQU8wSyxJQUFJLENBQUMxSyxHQUFHLENBQUMsS0FBSyxVQUFVLEVBQUU7UUFDN0R5RyxHQUFHLENBQUN6RyxHQUFHLENBQUMsR0FBRzBLLElBQUksQ0FBQzFLLEdBQUcsQ0FBQztNQUN4QjtJQUNKO0lBQ0EsT0FBT3lHLEdBQUc7RUFDZDs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0k2TixNQUFNQSxDQUFBLEVBQUc7SUFDTCxNQUFNNUosSUFBSSxHQUFHLElBQUk7SUFDakIsT0FBTzVLLElBQUksQ0FBQ0MsU0FBUyxDQUFDMkssSUFBSSxDQUFDMkosUUFBUSxDQUFDLENBQUMsQ0FBQztFQUMxQzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPSiw2QkFBNkJBLENBQUN4RSxJQUFJLEVBQUU7SUFDdkM7SUFDQTtJQUNBOztJQUVBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQSxJQUFJQSxJQUFJLEtBQUssSUFBSSxJQUFJQSxJQUFJLEtBQUs5USxTQUFTLEVBQUU7TUFDckMsT0FBTzhRLElBQUk7SUFDZjs7SUFFQTtJQUNBLElBQUkvTCxLQUFLLENBQUNpRCxPQUFPLENBQUM4SSxJQUFJLENBQUMsRUFBRTtNQUNyQixPQUFPQSxJQUFJLENBQUMzRixHQUFHLENBQUVnQyxJQUFJLElBQUt3SCxZQUFZLENBQUNXLDZCQUE2QixDQUFDbkksSUFBSSxDQUFDLENBQUM7SUFDL0U7O0lBRUE7SUFDQSxJQUFJLE9BQU8yRCxJQUFJLEtBQUssUUFBUSxFQUFFO01BQzFCO01BQ0EsSUFBSUEsSUFBSSxDQUFDOEQsT0FBTyxJQUFJLE9BQU85RCxJQUFJLENBQUM4RCxPQUFPLEtBQUssUUFBUSxFQUFFO1FBQ2xEO1FBQ0EsTUFBTWdCLFVBQVUsR0FBR25hLE1BQU0sQ0FBQ3FWLElBQUksQ0FBQzhELE9BQU8sQ0FBQzs7UUFFdkM7UUFDQTtRQUNBLElBQUlnQixVQUFVLElBQUlBLFVBQVUsQ0FBQy9KLFNBQVMsWUFBWThJLFlBQVksRUFBRTtVQUM1RCxPQUFPLElBQUlpQixVQUFVLENBQUM5RSxJQUFJLENBQUM7UUFDL0I7TUFDSjs7TUFFQTtNQUNBLE1BQU1sSyxNQUFNLEdBQUcsQ0FBQyxDQUFDO01BQ2pCLEtBQUssTUFBTXZGLEdBQUcsSUFBSXlQLElBQUksRUFBRTtRQUNwQixJQUFJQSxJQUFJLENBQUM3TyxjQUFjLENBQUNaLEdBQUcsQ0FBQyxFQUFFO1VBQzFCdUYsTUFBTSxDQUFDdkYsR0FBRyxDQUFDLEdBQUdzVCxZQUFZLENBQUNXLDZCQUE2QixDQUFDeEUsSUFBSSxDQUFDelAsR0FBRyxDQUFDLENBQUM7UUFDdkU7TUFDSjtNQUNBLE9BQU91RixNQUFNO0lBQ2pCOztJQUVBO0lBQ0EsT0FBT2tLLElBQUk7RUFDZjtBQUNKOzs7Ozs7QUN4TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0rRSxvQkFBb0IsQ0FBQztFQUN2QjtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU96Rix1QkFBdUJBLENBQUEsRUFBRztJQUM3QjtJQUNBLElBQUksQ0FBQ0csUUFBUSxDQUFDdUYsbUJBQW1CLEVBQUU7TUFDL0J4WSxhQUFhLENBQUMsa0JBQWtCLEVBQUUsOENBQThDLENBQUM7TUFDakY7SUFDSjs7SUFFQTtJQUNBdVksb0JBQW9CLENBQUNFLHNCQUFzQixDQUFDLENBQUM7RUFDakQ7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9BLHNCQUFzQkEsQ0FBQSxFQUFHO0lBQzVCLE1BQU1DLEtBQUssR0FBR3pGLFFBQVEsQ0FBQzBGLGFBQWEsQ0FBQyxPQUFPLENBQUM7SUFFN0NELEtBQUssQ0FBQ0UsV0FBVyxHQUFHO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztJQUVEM0YsUUFBUSxDQUFDNEYsSUFBSSxDQUFDQyxXQUFXLENBQUNKLEtBQUssQ0FBQztFQUNwQztBQUNKOzs7Ozs7OztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0xTyxhQUFhLENBQUM7RUFzRGhCO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0MsT0FBT0EsQ0FBQzNHLElBQUksRUFBRXlHLEVBQUUsRUFBRTtJQUNyQixPQUFPLElBQUk5QyxPQUFPLENBQUMsQ0FBQ0gsT0FBTyxFQUFFQyxNQUFNLEtBQUs7TUFDcEMsTUFBTXNFLENBQUMsR0FBRzBOLDBCQUFBLENBL0RoQi9PLGFBQWEsRUErREcsSUFBSSxFQUFDZ1Asa0JBQVEsQ0FBQyxDQUFBcE4sSUFBQSxDQUFkLElBQUksRUFBV3RJLElBQUksQ0FBQztNQUM5QitILENBQUMsQ0FBQzROLFFBQVEsQ0FBQzlVLElBQUksQ0FBQztRQUFFNEYsRUFBRTtRQUFFakQsT0FBTztRQUFFQztNQUFPLENBQUMsQ0FBQztNQUN4Q2dTLDBCQUFBLENBakVOL08sYUFBYSxFQWlFUCxJQUFJLEVBQUNrUCxrQkFBUSxDQUFDLENBQUF0TixJQUFBLENBQWQsSUFBSSxFQUFXdEksSUFBSTtJQUN2QixDQUFDLENBQUM7RUFDTjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU82RyxZQUFZQSxDQUFDN0csSUFBSSxFQUFFeUcsRUFBRSxFQUFFO0lBQzFCLE9BQU8sSUFBSTlDLE9BQU8sQ0FBQyxDQUFDSCxPQUFPLEVBQUVDLE1BQU0sS0FBSztNQUNwQyxNQUFNc0UsQ0FBQyxHQUFHME4sMEJBQUEsQ0E5RWhCL08sYUFBYSxFQThFRyxJQUFJLEVBQUNnUCxrQkFBUSxDQUFDLENBQUFwTixJQUFBLENBQWQsSUFBSSxFQUFXdEksSUFBSSxDQUFDO01BQzlCLElBQUkrSCxDQUFDLENBQUM4TixhQUFhLElBQUk5TixDQUFDLENBQUM0TixRQUFRLENBQUNsWSxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQzFDc0ssQ0FBQyxDQUFDK04sUUFBUSxDQUFDalYsSUFBSSxDQUFDO1VBQUU0RixFQUFFO1VBQUVqRCxPQUFPO1VBQUVDO1FBQU8sQ0FBQyxDQUFDO1FBQ3hDLE9BQU9nUywwQkFBQSxDQWpGakIvTyxhQUFhLEVBaUZJLElBQUksRUFBQ2tQLGtCQUFRLENBQUMsQ0FBQXROLElBQUEsQ0FBZCxJQUFJLEVBQVd0SSxJQUFJO01BQzlCO01BQ0ErSCxDQUFDLENBQUNnTyxPQUFPLElBQUksQ0FBQztNQUNkcFMsT0FBTyxDQUFDSCxPQUFPLENBQUMsQ0FBQyxDQUNaSSxJQUFJLENBQUM2QyxFQUFFLENBQUMsQ0FDUjdDLElBQUksQ0FBQ0osT0FBTyxFQUFFQyxNQUFNLENBQUMsQ0FDckJJLE9BQU8sQ0FBQyxNQUFNO1FBQ1hrRSxDQUFDLENBQUNnTyxPQUFPLElBQUksQ0FBQztRQUNkLElBQUloTyxDQUFDLENBQUNnTyxPQUFPLEtBQUssQ0FBQyxFQUFFTiwwQkFBQSxDQXpGbkMvTyxhQUFhLEVBeUZzQixJQUFJLEVBQUNrUCxrQkFBUSxDQUFDLENBQUF0TixJQUFBLENBQWQsSUFBSSxFQUFXdEksSUFBSTtNQUM1QyxDQUFDLENBQUM7SUFDVixDQUFDLENBQUM7RUFDTjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBTytHLFlBQVlBLENBQUMvRyxJQUFJLEVBQUU7SUFDdEJ5ViwwQkFBQSxDQXBHRi9PLGFBQWEsRUFvR1gsSUFBSSxFQUFDc1AsTUFBTSxFQUFBNU0sQ0FBQSxDQUFDNk0sTUFBTSxDQUFDalcsSUFBSSxDQUFDO0VBQzVCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPaUgsT0FBT0EsQ0FBQ2pILElBQUksRUFBRTtJQUNqQixNQUFNK0gsQ0FBQyxHQUFHME4sMEJBQUEsQ0E3R1ovTyxhQUFhLEVBNkdELElBQUksRUFBQ3NQLE1BQU0sRUFBQTVNLENBQUEsQ0FBQ3BHLEdBQUcsQ0FBQ2hELElBQUksQ0FBQztJQUMvQixJQUFJLENBQUMrSCxDQUFDLEVBQUUsT0FBTztNQUFFZ08sT0FBTyxFQUFFLENBQUM7TUFBRUYsYUFBYSxFQUFFLEtBQUs7TUFBRUMsUUFBUSxFQUFFLENBQUM7TUFBRUgsUUFBUSxFQUFFO0lBQUUsQ0FBQztJQUM3RSxPQUFPO01BQ0hJLE9BQU8sRUFBRWhPLENBQUMsQ0FBQ2dPLE9BQU87TUFDbEJGLGFBQWEsRUFBRTlOLENBQUMsQ0FBQzhOLGFBQWE7TUFDOUJDLFFBQVEsRUFBRS9OLENBQUMsQ0FBQytOLFFBQVEsQ0FBQ3JZLE1BQU07TUFDM0JrWSxRQUFRLEVBQUU1TixDQUFDLENBQUM0TixRQUFRLENBQUNsWTtJQUN6QixDQUFDO0VBQ0w7QUFDSjtBQUFDeVksdUJBQUEsR0F0SEt4UCxhQUFhO0FBR2Y7QUFDSjtBQUNBO0FBQ0E7QUFISSxTQUFBZ1AsbUJBSWlCMVYsSUFBSSxFQUFFO0VBQ25CLElBQUkrSCxDQUFDLEdBQUcwTiwwQkFBQSxDQVJWL08sdUJBQWEsRUFRSCxJQUFJLEVBQUNzUCxNQUFNLEVBQUE1TSxDQUFBLENBQUNwRyxHQUFHLENBQUNoRCxJQUFJLENBQUM7RUFDN0IsSUFBSSxDQUFDK0gsQ0FBQyxFQUFFO0lBQ0pBLENBQUMsR0FBRztNQUFFZ08sT0FBTyxFQUFFLENBQUM7TUFBRUYsYUFBYSxFQUFFLEtBQUs7TUFBRUMsUUFBUSxFQUFFLEVBQUU7TUFBRUgsUUFBUSxFQUFFO0lBQUcsQ0FBQztJQUNwRUYsMEJBQUEsQ0FYTi9PLHVCQUFhLEVBV1AsSUFBSSxFQUFDc1AsTUFBTSxFQUFBNU0sQ0FBQSxDQUFDbkcsR0FBRyxDQUFDakQsSUFBSSxFQUFFK0gsQ0FBQyxDQUFDO0VBQzVCO0VBQ0EsT0FBT0EsQ0FBQztBQUNaO0FBRUE7QUFDSjtBQUNBO0FBQ0E7QUFISSxTQUFBNk4sbUJBSWlCNVYsSUFBSSxFQUFFO0VBQ25CLE1BQU0rSCxDQUFDLEdBQUcwTiwwQkFBQSxDQXJCWi9PLHVCQUFhLEVBcUJELElBQUksRUFBQ2dQLGtCQUFRLENBQUMsQ0FBQXBOLElBQUEsQ0FBZCxJQUFJLEVBQVd0SSxJQUFJLENBQUM7RUFDOUIsSUFBSStILENBQUMsQ0FBQzhOLGFBQWEsSUFBSTlOLENBQUMsQ0FBQ2dPLE9BQU8sR0FBRyxDQUFDLEVBQUU7O0VBRXRDO0VBQ0EsSUFBSWhPLENBQUMsQ0FBQzROLFFBQVEsQ0FBQ2xZLE1BQU0sR0FBRyxDQUFDLEVBQUU7SUFDdkIsTUFBTTtNQUFFZ0osRUFBRTtNQUFFakQsT0FBTztNQUFFQztJQUFPLENBQUMsR0FBR3NFLENBQUMsQ0FBQzROLFFBQVEsQ0FBQ2pTLEtBQUssQ0FBQyxDQUFDO0lBQ2xEcUUsQ0FBQyxDQUFDOE4sYUFBYSxHQUFHLElBQUk7SUFDdEJsUyxPQUFPLENBQUNILE9BQU8sQ0FBQyxDQUFDLENBQ1pJLElBQUksQ0FBQzZDLEVBQUUsQ0FBQyxDQUNSN0MsSUFBSSxDQUFDSixPQUFPLEVBQUVDLE1BQU0sQ0FBQyxDQUNyQkksT0FBTyxDQUFDLE1BQU07TUFDWGtFLENBQUMsQ0FBQzhOLGFBQWEsR0FBRyxLQUFLO01BQ3ZCSiwwQkFBQSxDQWpDZC9PLHVCQUFhLEVBaUNDLElBQUksRUFBQ2tQLGtCQUFRLENBQUMsQ0FBQXROLElBQUEsQ0FBZCxJQUFJLEVBQVd0SSxJQUFJO0lBQ3ZCLENBQUMsQ0FBQztJQUNOO0VBQ0o7O0VBRUE7RUFDQSxJQUFJK0gsQ0FBQyxDQUFDK04sUUFBUSxDQUFDclksTUFBTSxHQUFHLENBQUMsRUFBRTtJQUN2QixNQUFNMFksS0FBSyxHQUFHcE8sQ0FBQyxDQUFDK04sUUFBUSxDQUFDTSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ2xDck8sQ0FBQyxDQUFDZ08sT0FBTyxJQUFJSSxLQUFLLENBQUMxWSxNQUFNO0lBQ3pCLEtBQUssTUFBTTtNQUFFZ0osRUFBRTtNQUFFakQsT0FBTztNQUFFQztJQUFPLENBQUMsSUFBSTBTLEtBQUssRUFBRTtNQUN6Q3hTLE9BQU8sQ0FBQ0gsT0FBTyxDQUFDLENBQUMsQ0FDWkksSUFBSSxDQUFDNkMsRUFBRSxDQUFDLENBQ1I3QyxJQUFJLENBQUNKLE9BQU8sRUFBRUMsTUFBTSxDQUFDLENBQ3JCSSxPQUFPLENBQUMsTUFBTTtRQUNYa0UsQ0FBQyxDQUFDZ08sT0FBTyxJQUFJLENBQUM7UUFDZCxJQUFJaE8sQ0FBQyxDQUFDZ08sT0FBTyxLQUFLLENBQUMsRUFBRU4sMEJBQUEsQ0FoRHZDL08sdUJBQWEsRUFnRDBCLElBQUksRUFBQ2tQLGtCQUFRLENBQUMsQ0FBQXROLElBQUEsQ0FBZCxJQUFJLEVBQVd0SSxJQUFJO01BQzVDLENBQUMsQ0FBQztJQUNWO0VBQ0o7QUFDSjtBQUFDLElBQUFnVyxNQUFBO0VBQUE1TSxDQUFBLEVBbkRlLElBQUl6RyxHQUFHLENBQUM7QUFBQzs7Ozs7O0FDTDdCO0FBQ0E7QUFDQTtBQUNBLE1BQU0wVCxVQUFVLENBQUM7RUFDYjtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0MseUJBQXlCQSxDQUFBLEVBQWM7SUFBQSxJQUFiQyxNQUFNLEdBQUFwWCxTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLENBQUMsQ0FBQztJQUN4Q3ZFLENBQUMsQ0FBQzJJLEVBQUUsQ0FBQ2lULFdBQVcsR0FBRyxZQUF1QjtNQUFBLElBQWRDLE9BQU8sR0FBQXRYLFNBQUEsQ0FBQTFCLE1BQUEsUUFBQTBCLFNBQUEsUUFBQUMsU0FBQSxHQUFBRCxTQUFBLE1BQUcsQ0FBQyxDQUFDO01BQ3BDLE1BQU11WCxRQUFRLEdBQUc5YixDQUFDLENBQUMsSUFBSSxDQUFDO01BRXhCLElBQUksQ0FBQzhiLFFBQVEsQ0FBQ0MsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1FBQ3RCLE1BQU0sSUFBSXRYLEtBQUssQ0FBQyxtREFBbUQsQ0FBQztNQUN4RTtNQUVBLE1BQU1rVixHQUFHLEdBQUdtQyxRQUFRLENBQUMxRyxJQUFJLENBQUMsUUFBUSxDQUFDO01BQ25DLElBQUksQ0FBQ3VFLEdBQUcsRUFBRTtRQUNOLE1BQU0sSUFBSWxWLEtBQUssQ0FBQyxvQ0FBb0MsQ0FBQztNQUN6RDtNQUVBLE1BQU07UUFBRXVYLFVBQVU7UUFBRUM7TUFBTyxDQUFDLEdBQUdDLElBQUksQ0FBQ0MsNkJBQTZCLENBQUN4QyxHQUFHLENBQUM7TUFFdEUsT0FBTzhCLFVBQVUsQ0FBQ0csV0FBVyxDQUFDRSxRQUFRLEVBQUVFLFVBQVUsRUFBRUMsTUFBTSxFQUFFSixPQUFPLENBQUM7SUFDeEUsQ0FBQztFQUNMOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT08saUJBQWlCQSxDQUFDQyxlQUFlLEVBQUVDLE1BQU0sRUFBRTtJQUM5Q3JYLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQ3NZLE1BQU0sQ0FBQztJQUVyQixNQUFNcGIsT0FBTyxHQUFHbEIsQ0FBQyxDQUFDcWMsZUFBZSxDQUFDOztJQUVsQztJQUNBWixVQUFVLENBQUNjLGlCQUFpQixDQUFDRixlQUFlLENBQUM7O0lBRTdDO0lBQ0EsTUFBTUcsVUFBVSxHQUFHZixVQUFVLENBQUNnQixpQkFBaUIsQ0FBQ0gsTUFBTSxDQUFDO0lBRXZELE9BQU8sSUFBSXZULE9BQU8sQ0FBRUgsT0FBTyxJQUFLO01BQzVCLElBQUk4VCxVQUFVLEdBQUcsRUFBRTtNQUVuQixJQUFJRixVQUFVLENBQUNHLElBQUksS0FBSyxRQUFRLEVBQUU7UUFDOUI7UUFDQUQsVUFBVSxHQUFHakIsVUFBVSxDQUFDbUIscUJBQXFCLENBQUMxYixPQUFPLEVBQUVzYixVQUFVLENBQUNsSCxJQUFJLENBQUM7TUFDM0UsQ0FBQyxNQUFNLElBQUlrSCxVQUFVLENBQUNHLElBQUksS0FBSyxPQUFPLEVBQUU7UUFDcEM7UUFDQSxNQUFNRSxZQUFZLEdBQUdwQixVQUFVLENBQUNxQixtQkFBbUIsQ0FBQ04sVUFBVSxDQUFDbEgsSUFBSSxDQUFDO1FBQ3BFb0gsVUFBVSxHQUFHakIsVUFBVSxDQUFDbUIscUJBQXFCLENBQUMxYixPQUFPLEVBQUUyYixZQUFZLENBQUM7TUFDeEUsQ0FBQyxNQUFNLElBQUlMLFVBQVUsQ0FBQ0csSUFBSSxLQUFLLFFBQVEsRUFBRTtRQUNyQztRQUNBLE1BQU12UixNQUFNLEdBQUdxUSxVQUFVLENBQUNzQixtQkFBbUIsQ0FBQzdiLE9BQU8sRUFBRXNiLFVBQVUsQ0FBQ2xILElBQUksQ0FBQztRQUN2RW9ILFVBQVUsR0FBR3RSLE1BQU0sQ0FBQ3NSLFVBQVU7O1FBRTlCO1FBQ0EsTUFBTU0sYUFBYSxHQUFHck0sTUFBTSxDQUFDc00sSUFBSSxDQUFDVCxVQUFVLENBQUNsSCxJQUFJLENBQUMsQ0FBQ3pTLE1BQU0sR0FBRzhOLE1BQU0sQ0FBQ3NNLElBQUksQ0FBQzdSLE1BQU0sQ0FBQzhSLFNBQVMsQ0FBQyxDQUFDcmEsTUFBTTtRQUNoRyxNQUFNc2Esc0JBQXNCLEdBQUcxQixVQUFVLENBQUNxQixtQkFBbUIsQ0FBQzFSLE1BQU0sQ0FBQzhSLFNBQVMsQ0FBQztRQUMvRSxNQUFNRSxlQUFlLEdBQUd6TSxNQUFNLENBQUNzTSxJQUFJLENBQUNFLHNCQUFzQixDQUFDLENBQUN0YSxNQUFNOztRQUVsRTtRQUNBLElBQUltYSxhQUFhLEdBQUcsQ0FBQyxJQUFJSSxlQUFlLEdBQUcsQ0FBQyxFQUFFO1VBQzFDO1VBQ0EsSUFBSUMsV0FBVyxHQUFHLEVBQUU7VUFDcEIsSUFBSUwsYUFBYSxHQUFHLENBQUMsRUFBRTtZQUNuQkssV0FBVyxHQUFHTCxhQUFhLEtBQUssQ0FBQyxHQUMzQiw2Q0FBNkMsR0FDN0MsOENBQThDO1VBQ3hEOztVQUVBO1VBQ0EsSUFBSUksZUFBZSxHQUFHLENBQUMsRUFBRTtZQUNyQixNQUFNRSxrQkFBa0IsR0FBRzdCLFVBQVUsQ0FBQzhCLHFCQUFxQixDQUFDcmMsT0FBTyxFQUFFbWMsV0FBVyxFQUFFRixzQkFBc0IsQ0FBQztZQUN6R1QsVUFBVSxDQUFDelcsSUFBSSxDQUFDLEdBQUdxWCxrQkFBa0IsQ0FBQztVQUMxQyxDQUFDLE1BQU07WUFDSDtZQUNBLE1BQU1BLGtCQUFrQixHQUFHN0IsVUFBVSxDQUFDbUIscUJBQXFCLENBQUMxYixPQUFPLEVBQUVtYyxXQUFXLENBQUM7WUFDakZYLFVBQVUsQ0FBQ3pXLElBQUksQ0FBQyxHQUFHcVgsa0JBQWtCLENBQUM7VUFDMUM7UUFDSjtNQUNKOztNQUVBO01BQ0F2VSxPQUFPLENBQUM4RCxHQUFHLENBQUM2UCxVQUFVLENBQUMsQ0FBQzFULElBQUksQ0FBQyxNQUFNO1FBQy9CO1FBQ0EsTUFBTXdVLGdCQUFnQixHQUFHdGMsT0FBTyxDQUFDdWMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUNDLEtBQUssQ0FBQyxDQUFDO1FBQzVFLElBQUlGLGdCQUFnQixDQUFDM2EsTUFBTSxHQUFHLENBQUMsRUFBRTtVQUM3QixNQUFNOGEsYUFBYSxHQUFHSCxnQkFBZ0IsQ0FBQ25iLE1BQU0sQ0FBQyxDQUFDLENBQUNmLEdBQUc7O1VBRW5EO1VBQ0EsTUFBTXNjLG1CQUFtQixHQUFHbkMsVUFBVSxDQUFDb0Msd0JBQXdCLENBQUMsQ0FBQzs7VUFFakU7VUFDQSxNQUFNQyxhQUFhLEdBQUdILGFBQWEsR0FBR0MsbUJBQW1CLEdBQUcsRUFBRTtVQUM5RDVkLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQ3dDLE9BQU8sQ0FBQztZQUNwQmpCLFNBQVMsRUFBRXVjO1VBQ2YsQ0FBQyxFQUFFLEdBQUcsQ0FBQztRQUNYO1FBRUFsVixPQUFPLENBQUMsQ0FBQztNQUNiLENBQUMsQ0FBQztJQUNOLENBQUMsQ0FBQztFQUNOOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT21WLEtBQUtBLENBQUNDLGFBQWEsRUFBRTtJQUN4QixNQUFNQyxLQUFLLEdBQUcsT0FBT0QsYUFBYSxLQUFLLFFBQVEsR0FBR2hlLENBQUMsQ0FBQ2dlLGFBQWEsQ0FBQyxHQUFHQSxhQUFhO0lBRWxGdkMsVUFBVSxDQUFDYyxpQkFBaUIsQ0FBQ3lCLGFBQWEsQ0FBQztJQUMzQ0MsS0FBSyxDQUFDQyxPQUFPLENBQUMsT0FBTyxDQUFDO0VBQzFCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9DLFNBQVNBLENBQUNILGFBQWEsRUFBRTtJQUM1QixNQUFNQyxLQUFLLEdBQUcsT0FBT0QsYUFBYSxLQUFLLFFBQVEsR0FBR2hlLENBQUMsQ0FBQ2dlLGFBQWEsQ0FBQyxHQUFHQSxhQUFhO0lBQ2xGLE1BQU0xSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBRWYySSxLQUFLLENBQUNHLGNBQWMsQ0FBQyxDQUFDLENBQUMzUixPQUFPLENBQUVrRixJQUFJLElBQUs7TUFDckMyRCxJQUFJLENBQUMzRCxJQUFJLENBQUN2TSxJQUFJLENBQUMsR0FBR3VNLElBQUksQ0FBQ2hTLEtBQUs7SUFDaEMsQ0FBQyxDQUFDO0lBRUYsT0FBTzJWLElBQUk7RUFDZjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksYUFBYXNHLFdBQVdBLENBQUNvQyxhQUFhLEVBQUVoQyxVQUFVLEVBQUVDLE1BQU0sRUFBZ0I7SUFBQSxJQUFkSixPQUFPLEdBQUF0WCxTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLENBQUMsQ0FBQztJQUNwRSxNQUFNMFosS0FBSyxHQUFHLE9BQU9ELGFBQWEsS0FBSyxRQUFRLEdBQUdoZSxDQUFDLENBQUNnZSxhQUFhLENBQUMsR0FBR0EsYUFBYTtJQUNsRixNQUFNSyxTQUFTLEdBQUc1QyxVQUFVLENBQUMwQyxTQUFTLENBQUNGLEtBQUssQ0FBQztJQUU3Q3hDLFVBQVUsQ0FBQ2MsaUJBQWlCLENBQUN5QixhQUFhLENBQUM7SUFFM0MsSUFBSTtNQUNBLE1BQU12RSxRQUFRLEdBQUcsTUFBTXlDLElBQUksQ0FBQ3hPLElBQUksQ0FBQ3NPLFVBQVUsRUFBRUMsTUFBTSxFQUFFb0MsU0FBUyxDQUFDO01BRS9ELElBQUl4QyxPQUFPLENBQUN5QyxVQUFVLEVBQUU7UUFDcEJ6QyxPQUFPLENBQUN5QyxVQUFVLENBQUM3RSxRQUFRLENBQUM7TUFDaEM7TUFFQSxPQUFPQSxRQUFRO0lBQ25CLENBQUMsQ0FBQyxPQUFPelYsS0FBSyxFQUFFO01BQ1osSUFBSUEsS0FBSyxDQUFDMlksSUFBSSxLQUFLLFlBQVksSUFBSTNZLEtBQUssQ0FBQ3VhLE9BQU8sRUFBRTtRQUM5QyxNQUFNOUMsVUFBVSxDQUFDVyxpQkFBaUIsQ0FBQzRCLGFBQWEsRUFBRWhhLEtBQUssQ0FBQ3VhLE9BQU8sQ0FBQztNQUNwRSxDQUFDLE1BQU07UUFDSCxNQUFNOUMsVUFBVSxDQUFDVyxpQkFBaUIsQ0FBQzRCLGFBQWEsRUFBRWhhLEtBQUssQ0FBQ00sT0FBTyxJQUFJLG1CQUFtQixDQUFDO01BQzNGO01BRUEsSUFBSXVYLE9BQU8sQ0FBQzJDLFFBQVEsRUFBRTtRQUNsQjNDLE9BQU8sQ0FBQzJDLFFBQVEsQ0FBQ3hhLEtBQUssQ0FBQztNQUMzQjtNQUVBLE1BQU1BLEtBQUs7SUFDZjtFQUNKOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT3VZLGlCQUFpQkEsQ0FBQ0YsZUFBZSxFQUFFO0lBQ3RDLE1BQU1uYixPQUFPLEdBQUdsQixDQUFDLENBQUNxYyxlQUFlLENBQUM7O0lBRWxDO0lBQ0FyYyxDQUFDLENBQUMsaUJBQWlCLENBQUMsQ0FBQ3llLE1BQU0sQ0FBQyxDQUFDOztJQUU3QjtJQUNBdmQsT0FBTyxDQUFDdWMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDZ0IsTUFBTSxDQUFDLENBQUM7O0lBRXRDO0lBQ0F2ZCxPQUFPLENBQUN1YyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUNpQixXQUFXLENBQUMsWUFBWSxDQUFDO0lBQ3JEeGQsT0FBTyxDQUFDdWMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUNnQixNQUFNLENBQUMsQ0FBQztFQUM5Qzs7RUFFQTs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPaEMsaUJBQWlCQSxDQUFDSCxNQUFNLEVBQUU7SUFDN0I7SUFDQSxJQUFJLENBQUNBLE1BQU0sRUFBRTtNQUNULE9BQU87UUFBRUssSUFBSSxFQUFFLFFBQVE7UUFBRXJILElBQUksRUFBRTtNQUF3QixDQUFDO0lBQzVEOztJQUVBO0lBQ0EsSUFBSSxPQUFPZ0gsTUFBTSxLQUFLLFFBQVEsRUFBRTtNQUM1QixPQUFPO1FBQUVLLElBQUksRUFBRSxRQUFRO1FBQUVySCxJQUFJLEVBQUVnSDtNQUFPLENBQUM7SUFDM0M7O0lBRUE7SUFDQSxJQUFJL1MsS0FBSyxDQUFDaUQsT0FBTyxDQUFDOFAsTUFBTSxDQUFDLEVBQUU7TUFDdkI7TUFDQSxJQUFJQSxNQUFNLENBQUNxQyxLQUFLLENBQUUxSixDQUFDLElBQUssT0FBT0EsQ0FBQyxLQUFLLFFBQVEsQ0FBQyxFQUFFO1FBQzVDLE9BQU87VUFBRTBILElBQUksRUFBRSxPQUFPO1VBQUVySCxJQUFJLEVBQUVnSDtRQUFPLENBQUM7TUFDMUM7TUFDQTtNQUNBLElBQUlBLE1BQU0sQ0FBQ3paLE1BQU0sR0FBRyxDQUFDLElBQUksT0FBT3laLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDcEQsT0FBT2IsVUFBVSxDQUFDZ0IsaUJBQWlCLENBQUNILE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztNQUNsRDtNQUNBO01BQ0EsT0FBTztRQUFFSyxJQUFJLEVBQUUsT0FBTztRQUFFckgsSUFBSSxFQUFFO01BQUcsQ0FBQztJQUN0Qzs7SUFFQTtJQUNBLElBQUksT0FBT2dILE1BQU0sS0FBSyxRQUFRLEVBQUU7TUFDNUI7TUFDQSxNQUFNc0MsU0FBUyxHQUFHdEMsTUFBTSxDQUFDQSxNQUFNLElBQUlBLE1BQU0sQ0FBQ3RZLEtBQUs7TUFDL0MsSUFBSTRhLFNBQVMsRUFBRTtRQUNYLE9BQU9uRCxVQUFVLENBQUNnQixpQkFBaUIsQ0FBQ21DLFNBQVMsQ0FBQztNQUNsRDs7TUFFQTtNQUNBLE1BQU1wQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO01BQ3JCLEtBQUssTUFBTXFDLEtBQUssSUFBSXZDLE1BQU0sRUFBRTtRQUN4QixJQUFJQSxNQUFNLENBQUM3VixjQUFjLENBQUNvWSxLQUFLLENBQUMsRUFBRTtVQUM5QixNQUFNbGYsS0FBSyxHQUFHMmMsTUFBTSxDQUFDdUMsS0FBSyxDQUFDO1VBQzNCLElBQUl0VixLQUFLLENBQUNpRCxPQUFPLENBQUM3TSxLQUFLLENBQUMsSUFBSUEsS0FBSyxDQUFDa0QsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUMxQzJaLFVBQVUsQ0FBQ3FDLEtBQUssQ0FBQyxHQUFHbGYsS0FBSyxDQUFDLENBQUMsQ0FBQztVQUNoQyxDQUFDLE1BQU0sSUFBSSxPQUFPQSxLQUFLLEtBQUssUUFBUSxFQUFFO1lBQ2xDNmMsVUFBVSxDQUFDcUMsS0FBSyxDQUFDLEdBQUdsZixLQUFLO1VBQzdCLENBQUMsTUFBTTtZQUNINmMsVUFBVSxDQUFDcUMsS0FBSyxDQUFDLEdBQUc5WCxNQUFNLENBQUNwSCxLQUFLLENBQUM7VUFDckM7UUFDSjtNQUNKO01BRUEsT0FBTztRQUFFZ2QsSUFBSSxFQUFFLFFBQVE7UUFBRXJILElBQUksRUFBRWtIO01BQVcsQ0FBQztJQUMvQzs7SUFFQTtJQUNBLE9BQU87TUFBRUcsSUFBSSxFQUFFLFFBQVE7TUFBRXJILElBQUksRUFBRXZPLE1BQU0sQ0FBQ3VWLE1BQU07SUFBRSxDQUFDO0VBQ25EOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9RLG1CQUFtQkEsQ0FBQ1IsTUFBTSxFQUFFO0lBQy9CLElBQUkvUyxLQUFLLENBQUNpRCxPQUFPLENBQUM4UCxNQUFNLENBQUMsRUFBRTtNQUN2QixPQUFPLENBQUMsR0FBRyxJQUFJd0MsR0FBRyxDQUFDeEMsTUFBTSxDQUFDLENBQUM7SUFDL0I7SUFFQSxJQUFJLE9BQU9BLE1BQU0sS0FBSyxRQUFRLEVBQUU7TUFDNUIsTUFBTXlDLElBQUksR0FBRyxJQUFJRCxHQUFHLENBQUMsQ0FBQztNQUN0QixNQUFNMVQsTUFBTSxHQUFHLENBQUMsQ0FBQztNQUNqQixLQUFLLE1BQU12RixHQUFHLElBQUl5VyxNQUFNLEVBQUU7UUFDdEIsTUFBTTNjLEtBQUssR0FBRzJjLE1BQU0sQ0FBQ3pXLEdBQUcsQ0FBQztRQUN6QixJQUFJLENBQUNrWixJQUFJLENBQUNDLEdBQUcsQ0FBQ3JmLEtBQUssQ0FBQyxFQUFFO1VBQ2xCb2YsSUFBSSxDQUFDRSxHQUFHLENBQUN0ZixLQUFLLENBQUM7VUFDZnlMLE1BQU0sQ0FBQ3ZGLEdBQUcsQ0FBQyxHQUFHbEcsS0FBSztRQUN2QjtNQUNKO01BQ0EsT0FBT3lMLE1BQU07SUFDakI7SUFFQSxPQUFPa1IsTUFBTTtFQUNqQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9TLG1CQUFtQkEsQ0FBQzdiLE9BQU8sRUFBRWdlLFlBQVksRUFBRTtJQUM5QyxNQUFNeEMsVUFBVSxHQUFHLEVBQUU7SUFDckIsTUFBTVEsU0FBUyxHQUFHLENBQUMsQ0FBQztJQUVwQixLQUFLLE1BQU1pQyxVQUFVLElBQUlELFlBQVksRUFBRTtNQUNuQyxNQUFNRSxhQUFhLEdBQUdGLFlBQVksQ0FBQ0MsVUFBVSxDQUFDO01BQzlDLE1BQU1FLE1BQU0sR0FBR25lLE9BQU8sQ0FBQ3VjLElBQUksQ0FBQyxVQUFVMEIsVUFBVSxJQUFJLENBQUM7TUFFckQsSUFBSSxDQUFDRSxNQUFNLENBQUN4YyxNQUFNLEVBQUU7UUFDaEJxYSxTQUFTLENBQUNpQyxVQUFVLENBQUMsR0FBR0MsYUFBYTtRQUNyQztNQUNKO01BRUEsTUFBTUUsTUFBTSxHQUFHdGYsQ0FBQyxDQUFDLHNDQUFzQyxDQUFDLENBQUN1TyxJQUFJLENBQUM2USxhQUFhLENBQUM7TUFDNUUsTUFBTW5lLE9BQU8sR0FBR29lLE1BQU0sQ0FBQzNJLE9BQU8sQ0FBQyx3Q0FBd0MsQ0FBQztNQUV4RSxJQUFJLENBQUN6VixPQUFPLENBQUM0QixNQUFNLEVBQUU7UUFDakJxYSxTQUFTLENBQUNpQyxVQUFVLENBQUMsR0FBR0MsYUFBYTtRQUNyQztNQUNKO01BRUFDLE1BQU0sQ0FBQ0UsUUFBUSxDQUFDLFlBQVksQ0FBQztNQUM3QkQsTUFBTSxDQUFDRSxRQUFRLENBQUN2ZSxPQUFPLENBQUM7TUFDeEJ5YixVQUFVLENBQUN6VyxJQUFJLENBQUNxWixNQUFNLENBQUNHLElBQUksQ0FBQyxDQUFDLENBQUNDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQ0MsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUN4RDtJQUVBLE9BQU87TUFBRWpELFVBQVU7TUFBRVE7SUFBVSxDQUFDO0VBQ3BDOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPSyxxQkFBcUJBLENBQUNyYyxPQUFPLEVBQUVtYyxXQUFXLEVBQUV1QyxnQkFBZ0IsRUFBRTtJQUNqRSxNQUFNbEQsVUFBVSxHQUFHLEVBQUU7SUFDckIsTUFBTWMsZ0JBQWdCLEdBQUd0YyxPQUFPLENBQUN1YyxJQUFJLENBQUMsNkJBQTZCLENBQUMsQ0FBQ0MsS0FBSyxDQUFDLENBQUM7SUFDNUUsTUFBTXpjLE9BQU8sR0FBR3VjLGdCQUFnQixDQUFDM2EsTUFBTSxHQUFHLENBQUMsR0FBRzJhLGdCQUFnQixHQUFHdGMsT0FBTzs7SUFFeEU7SUFDQSxNQUFNMmUsTUFBTSxHQUFHN2YsQ0FBQyxDQUFDLHFEQUFxRCxDQUFDOztJQUV2RTtJQUNBLElBQUlxZCxXQUFXLEVBQUU7TUFDYnJkLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDOGYsSUFBSSxDQUFDekMsV0FBVyxDQUFDLENBQUNtQyxRQUFRLENBQUNLLE1BQU0sQ0FBQztJQUNoRTs7SUFFQTtJQUNBLElBQUlsUCxNQUFNLENBQUNzTSxJQUFJLENBQUMyQyxnQkFBZ0IsQ0FBQyxDQUFDL2MsTUFBTSxHQUFHLENBQUMsRUFBRTtNQUMxQyxNQUFNa2QsS0FBSyxHQUFHL2YsQ0FBQyxDQUFDLHdCQUF3QixDQUFDO01BQ3pDLEtBQUssTUFBTW1mLFVBQVUsSUFBSVMsZ0JBQWdCLEVBQUU7UUFDdkMsTUFBTUksU0FBUyxHQUFHSixnQkFBZ0IsQ0FBQ1QsVUFBVSxDQUFDO1FBQzlDbmYsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDdU8sSUFBSSxDQUFDeVIsU0FBUyxDQUFDLENBQUNSLFFBQVEsQ0FBQ08sS0FBSyxDQUFDO01BQ2xEO01BQ0FBLEtBQUssQ0FBQ1AsUUFBUSxDQUFDSyxNQUFNLENBQUM7SUFDMUI7SUFFQSxJQUFJckMsZ0JBQWdCLENBQUMzYSxNQUFNLEdBQUcsQ0FBQyxFQUFFO01BQzdCNlosVUFBVSxDQUFDelcsSUFBSSxDQUFDNFosTUFBTSxDQUFDSixJQUFJLENBQUMsQ0FBQyxDQUFDRCxRQUFRLENBQUN2ZSxPQUFPLENBQUMsQ0FBQ3llLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQ0MsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMxRSxDQUFDLE1BQU07TUFDSGpELFVBQVUsQ0FBQ3pXLElBQUksQ0FBQzRaLE1BQU0sQ0FBQ0osSUFBSSxDQUFDLENBQUMsQ0FBQ1EsU0FBUyxDQUFDaGYsT0FBTyxDQUFDLENBQUN5ZSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUNDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDM0U7SUFFQSxPQUFPakQsVUFBVTtFQUNyQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9FLHFCQUFxQkEsQ0FBQzFiLE9BQU8sRUFBRWdmLFFBQVEsRUFBRTtJQUM1QyxNQUFNeEQsVUFBVSxHQUFHLEVBQUU7O0lBRXJCO0lBQ0EsTUFBTWMsZ0JBQWdCLEdBQUd0YyxPQUFPLENBQUN1YyxJQUFJLENBQUMsNkJBQTZCLENBQUMsQ0FBQ0MsS0FBSyxDQUFDLENBQUM7SUFDNUUsTUFBTXpjLE9BQU8sR0FBR3VjLGdCQUFnQixDQUFDM2EsTUFBTSxHQUFHLENBQUMsR0FBRzJhLGdCQUFnQixHQUFHdGMsT0FBTztJQUV4RSxJQUFJLE9BQU9nZixRQUFRLEtBQUssUUFBUSxFQUFFO01BQzlCO01BQ0EsTUFBTUwsTUFBTSxHQUFHN2YsQ0FBQyxDQUFDLHFEQUFxRCxDQUFDLENBQUM4ZixJQUFJLENBQUNJLFFBQVEsQ0FBQztNQUN0RixJQUFJMUMsZ0JBQWdCLENBQUMzYSxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQzdCNlosVUFBVSxDQUFDelcsSUFBSSxDQUFDNFosTUFBTSxDQUFDSixJQUFJLENBQUMsQ0FBQyxDQUFDRCxRQUFRLENBQUN2ZSxPQUFPLENBQUMsQ0FBQ3llLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQ0MsT0FBTyxDQUFDLENBQUMsQ0FBQztNQUMxRSxDQUFDLE1BQU07UUFDSGpELFVBQVUsQ0FBQ3pXLElBQUksQ0FBQzRaLE1BQU0sQ0FBQ0osSUFBSSxDQUFDLENBQUMsQ0FBQ1EsU0FBUyxDQUFDaGYsT0FBTyxDQUFDLENBQUN5ZSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUNDLE9BQU8sQ0FBQyxDQUFDLENBQUM7TUFDM0U7SUFDSixDQUFDLE1BQU0sSUFBSXBXLEtBQUssQ0FBQ2lELE9BQU8sQ0FBQzBULFFBQVEsQ0FBQyxJQUFJQSxRQUFRLENBQUNyZCxNQUFNLEdBQUcsQ0FBQyxFQUFFO01BQ3ZEO01BQ0EsTUFBTWdkLE1BQU0sR0FBRzdmLENBQUMsQ0FBQywyRUFBMkUsQ0FBQztNQUM3RixNQUFNK2YsS0FBSyxHQUFHRixNQUFNLENBQUNwQyxJQUFJLENBQUMsSUFBSSxDQUFDO01BRS9CeUMsUUFBUSxDQUFDelQsT0FBTyxDQUFFMFQsR0FBRyxJQUFLO1FBQ3RCLE1BQU1MLElBQUksR0FBRyxDQUFDSyxHQUFHLEdBQUcsRUFBRSxFQUFFN08sSUFBSSxDQUFDLENBQUMsSUFBSSx1QkFBdUI7UUFDekR0UixDQUFDLENBQUMsV0FBVyxDQUFDLENBQUN1TyxJQUFJLENBQUN1UixJQUFJLENBQUMsQ0FBQ04sUUFBUSxDQUFDTyxLQUFLLENBQUM7TUFDN0MsQ0FBQyxDQUFDO01BRUYsSUFBSXZDLGdCQUFnQixDQUFDM2EsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUM3QjZaLFVBQVUsQ0FBQ3pXLElBQUksQ0FBQzRaLE1BQU0sQ0FBQ0osSUFBSSxDQUFDLENBQUMsQ0FBQ0QsUUFBUSxDQUFDdmUsT0FBTyxDQUFDLENBQUN5ZSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUNDLE9BQU8sQ0FBQyxDQUFDLENBQUM7TUFDMUUsQ0FBQyxNQUFNO1FBQ0hqRCxVQUFVLENBQUN6VyxJQUFJLENBQUM0WixNQUFNLENBQUNKLElBQUksQ0FBQyxDQUFDLENBQUNRLFNBQVMsQ0FBQ2hmLE9BQU8sQ0FBQyxDQUFDeWUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDQyxPQUFPLENBQUMsQ0FBQyxDQUFDO01BQzNFO0lBQ0osQ0FBQyxNQUFNLElBQUksT0FBT08sUUFBUSxLQUFLLFFBQVEsSUFBSSxDQUFDM1csS0FBSyxDQUFDaUQsT0FBTyxDQUFDMFQsUUFBUSxDQUFDLEVBQUU7TUFDakU7TUFDQSxNQUFNRSxVQUFVLEdBQUd6UCxNQUFNLENBQUN2QixNQUFNLENBQUM4USxRQUFRLENBQUMsQ0FDckN2USxHQUFHLENBQUU3SixDQUFDLElBQUtpQixNQUFNLENBQUNqQixDQUFDLENBQUMsQ0FBQ3dMLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FDNUIxRSxNQUFNLENBQUU5RyxDQUFDLElBQUtBLENBQUMsQ0FBQztNQUNyQixJQUFJc2EsVUFBVSxDQUFDdmQsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUN2QixPQUFPNFksVUFBVSxDQUFDbUIscUJBQXFCLENBQUMxYixPQUFPLEVBQUVrZixVQUFVLENBQUM7TUFDaEU7SUFDSjtJQUVBLE9BQU8xRCxVQUFVO0VBQ3JCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPbUIsd0JBQXdCQSxDQUFBLEVBQUc7SUFDOUIsSUFBSXdDLFlBQVksR0FBRyxDQUFDOztJQUVwQjtJQUNBcmdCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQytDLElBQUksQ0FBQyxZQUFXO01BQ25CLE1BQU11ZCxHQUFHLEdBQUd0Z0IsQ0FBQyxDQUFDLElBQUksQ0FBQztNQUNuQixNQUFNcUIsUUFBUSxHQUFHaWYsR0FBRyxDQUFDQyxHQUFHLENBQUMsVUFBVSxDQUFDOztNQUVwQztNQUNBLElBQUlsZixRQUFRLEtBQUssT0FBTyxJQUFJQSxRQUFRLEtBQUssUUFBUSxFQUFFO1FBQy9DO01BQ0o7O01BRUE7TUFDQSxNQUFNQyxHQUFHLEdBQUcrTSxRQUFRLENBQUNpUyxHQUFHLENBQUNDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUM7TUFDekMsSUFBSWpmLEdBQUcsR0FBRyxFQUFFLEVBQUU7UUFDVixPQUFPLENBQUM7TUFDWjs7TUFFQTtNQUNBLElBQUksQ0FBQ2dmLEdBQUcsQ0FBQ3ZFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUNyQjtNQUNKOztNQUVBO01BQ0EsTUFBTTdiLEtBQUssR0FBR29nQixHQUFHLENBQUNFLFVBQVUsQ0FBQyxDQUFDO01BQzlCLE1BQU1DLGNBQWMsR0FBR3pnQixDQUFDLENBQUNDLE1BQU0sQ0FBQyxDQUFDQyxLQUFLLENBQUMsQ0FBQztNQUN4QyxJQUFJQSxLQUFLLEdBQUd1Z0IsY0FBYyxHQUFHLEdBQUcsRUFBRTtRQUM5QixPQUFPLENBQUM7TUFDWjs7TUFFQTtNQUNBSixZQUFZLElBQUlDLEdBQUcsQ0FBQzdlLFdBQVcsQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQztJQUVGLE9BQU80ZSxZQUFZO0VBQ3ZCO0FBQ0o7Ozs7Ozs7OztBQ3JkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU14ZSxRQUFRLENBQUM7RUFvQlg7QUFDSjtBQUNBO0FBQ0E7RUFDSSxPQUFPK1MsdUJBQXVCQSxDQUFBLEVBQUc7SUFDN0I7SUFDQSxJQUFJM1UsTUFBTSxDQUFDeVQsTUFBTSxJQUFJelQsTUFBTSxDQUFDeVQsTUFBTSxDQUFDZ04sa0JBQWtCLEVBQUU7TUFDbkQ7TUFDQXpnQixNQUFNLENBQUM4VixnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsVUFBVUMsS0FBSyxFQUFFO1FBQzlDblUsUUFBUSxDQUFDOGUscUJBQXFCLENBQUM7VUFDM0JyYyxPQUFPLEVBQUUwUixLQUFLLENBQUMxUixPQUFPO1VBQ3RCc2MsUUFBUSxFQUFFNUssS0FBSyxDQUFDNEssUUFBUTtVQUN4QkMsTUFBTSxFQUFFN0ssS0FBSyxDQUFDNkssTUFBTTtVQUNwQkMsS0FBSyxFQUFFOUssS0FBSyxDQUFDOEssS0FBSztVQUNsQnBjLEtBQUssRUFBRXNSLEtBQUssQ0FBQ2hTLEtBQUssR0FBR2dTLEtBQUssQ0FBQ2hTLEtBQUssQ0FBQ1UsS0FBSyxHQUFHLElBQUk7VUFDN0NpWSxJQUFJLEVBQUU7UUFDVixDQUFDLENBQUM7TUFDTixDQUFDLENBQUM7O01BRUY7TUFDQTFjLE1BQU0sQ0FBQzhWLGdCQUFnQixDQUFDLG9CQUFvQixFQUFFLFVBQVVDLEtBQUssRUFBRTtRQUMzRG5VLFFBQVEsQ0FBQzhlLHFCQUFxQixDQUFDO1VBQzNCcmMsT0FBTyxFQUFFMFIsS0FBSyxDQUFDaUQsTUFBTSxHQUFHakQsS0FBSyxDQUFDaUQsTUFBTSxDQUFDM1UsT0FBTyxJQUFJeUMsTUFBTSxDQUFDaVAsS0FBSyxDQUFDaUQsTUFBTSxDQUFDLEdBQUcsNkJBQTZCO1VBQ3BHdlUsS0FBSyxFQUFFc1IsS0FBSyxDQUFDaUQsTUFBTSxJQUFJakQsS0FBSyxDQUFDaUQsTUFBTSxDQUFDdlUsS0FBSyxHQUFHc1IsS0FBSyxDQUFDaUQsTUFBTSxDQUFDdlUsS0FBSyxHQUFHLElBQUk7VUFDckVpWSxJQUFJLEVBQUU7UUFDVixDQUFDLENBQUM7TUFDTixDQUFDLENBQUM7SUFDTjs7SUFFQTtJQUNBakUsR0FBRyxDQUFDMUQsRUFBRSxDQUFDLFNBQVMsRUFBRW5ULFFBQVEsQ0FBQ2tmLFVBQVUsQ0FBQztFQUMxQzs7RUFFQTtFQUNBLE9BQU9BLFVBQVVBLENBQUEsRUFBRztJQUNoQixJQUFJLENBQUNySSxHQUFHLENBQUNDLE9BQU8sQ0FBQyxDQUFDLEVBQUU7TUFDaEI7TUFDQTtNQUNBO01BQ0E7TUFDQTtNQUNBO0lBQUE7RUFFUjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU83VyxhQUFhQSxDQUFDcU4sT0FBTyxFQUFhO0lBQ3JDO0lBQ0EsSUFBSSxDQUFDbFAsTUFBTSxDQUFDeVQsTUFBTSxJQUFJLENBQUN6VCxNQUFNLENBQUN5VCxNQUFNLENBQUM1UixhQUFhLElBQUksQ0FBQzdCLE1BQU0sQ0FBQ3lULE1BQU0sQ0FBQzVSLGFBQWEsQ0FBQ2tmLE9BQU8sRUFBRTtNQUN4RjtJQUNKO0lBRUEsTUFBTUMsTUFBTSxHQUFHaGhCLE1BQU0sQ0FBQ3lULE1BQU0sQ0FBQzVSLGFBQWE7O0lBRTFDO0lBQ0FxTixPQUFPLEdBQUdwSSxNQUFNLENBQUNvSSxPQUFPLENBQUMsQ0FDcEJXLFdBQVcsQ0FBQyxDQUFDLENBQ2J0TSxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQzs7SUFFM0I7SUFDQSxJQUFJeWQsTUFBTSxDQUFDQyxXQUFXLEtBQUssVUFBVSxFQUFFO01BQ25DLE1BQU1DLFFBQVEsR0FBR0YsTUFBTSxDQUFDRyxnQkFBZ0I7TUFDeEMsSUFBSUQsUUFBUSxFQUFFO1FBQ1Y7UUFDQSxNQUFNRSxRQUFRLEdBQUdGLFFBQVEsQ0FBQ3ZjLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQytLLEdBQUcsQ0FBRU8sQ0FBQyxJQUFLQSxDQUFDLENBQUNvQixJQUFJLENBQUMsQ0FBQyxDQUFDeEIsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUN2RSxJQUFJLENBQUN1UixRQUFRLENBQUMxTyxRQUFRLENBQUN4RCxPQUFPLENBQUMsRUFBRTtVQUM3QjtRQUNKO01BQ0o7SUFDSixDQUFDLE1BQU0sSUFBSThSLE1BQU0sQ0FBQ0MsV0FBVyxLQUFLLFdBQVcsRUFBRTtNQUMzQyxNQUFNSSxTQUFTLEdBQUcsQ0FBQ0wsTUFBTSxDQUFDTSxlQUFlLElBQUksRUFBRSxFQUFFNVIsR0FBRyxDQUFFTyxDQUFDLElBQUtBLENBQUMsQ0FBQ0osV0FBVyxDQUFDLENBQUMsQ0FBQztNQUM1RSxJQUFJLENBQUN3UixTQUFTLENBQUMzTyxRQUFRLENBQUN4RCxPQUFPLENBQUMsRUFBRTtRQUM5QjtNQUNKO0lBQ0osQ0FBQyxNQUFNLElBQUk4UixNQUFNLENBQUNDLFdBQVcsS0FBSyxXQUFXLEVBQUU7TUFDM0MsTUFBTU0sU0FBUyxHQUFHLENBQUNQLE1BQU0sQ0FBQ00sZUFBZSxJQUFJLEVBQUUsRUFBRTVSLEdBQUcsQ0FBRU8sQ0FBQyxJQUFLQSxDQUFDLENBQUNKLFdBQVcsQ0FBQyxDQUFDLENBQUM7TUFDNUUsSUFBSTBSLFNBQVMsQ0FBQzdPLFFBQVEsQ0FBQ3hELE9BQU8sQ0FBQyxFQUFFO1FBQzdCO01BQ0o7SUFDSjs7SUFFQTtJQUFBLFNBQUE5RixJQUFBLEdBQUE5RSxTQUFBLENBQUExQixNQUFBLEVBbkM2QnVNLE1BQU0sT0FBQTdGLEtBQUEsQ0FBQUYsSUFBQSxPQUFBQSxJQUFBLFdBQUFHLElBQUEsTUFBQUEsSUFBQSxHQUFBSCxJQUFBLEVBQUFHLElBQUE7TUFBTjRGLE1BQU0sQ0FBQTVGLElBQUEsUUFBQWpGLFNBQUEsQ0FBQWlGLElBQUE7SUFBQTtJQW9DbkMsSUFBSWxGLE9BQU8sR0FBRztNQUNWNkssT0FBTyxFQUFFQSxPQUFPO01BQ2hCQyxNQUFNLEVBQUVBLE1BQU07TUFDZHFTLFNBQVMsRUFBRSxJQUFJOWQsSUFBSSxDQUFDLENBQUMsQ0FBQytkLFdBQVcsQ0FBQztJQUN0QyxDQUFDOztJQUVEO0lBQ0EsSUFBSVQsTUFBTSxDQUFDVSxnQkFBZ0IsSUFBSVYsTUFBTSxDQUFDVyxpQkFBaUIsRUFBRTtNQUNyRCxNQUFNNWQsS0FBSyxHQUFHLElBQUlTLEtBQUssQ0FBQyxDQUFDO01BQ3pCLE1BQU1DLEtBQUssR0FBR1YsS0FBSyxDQUFDVSxLQUFLLElBQUksRUFBRTtNQUMvQixNQUFNQyxVQUFVLEdBQUdELEtBQUssQ0FBQ0UsS0FBSyxDQUFDLElBQUksQ0FBQztNQUVwQyxJQUFJcWMsTUFBTSxDQUFDVSxnQkFBZ0IsSUFBSWhkLFVBQVUsQ0FBQzlCLE1BQU0sR0FBRyxDQUFDLEVBQUU7UUFDbEQ7UUFDQSxNQUFNaUMsVUFBVSxHQUFHSCxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRTtRQUN0QyxNQUFNSSxLQUFLLEdBQUdELFVBQVUsQ0FBQ0MsS0FBSyxDQUFDLGtDQUFrQyxDQUFDLElBQUlELFVBQVUsQ0FBQ0MsS0FBSyxDQUFDLHdCQUF3QixDQUFDO1FBQ2hILElBQUlBLEtBQUssRUFBRTtVQUNQVCxPQUFPLENBQUN1ZCxRQUFRLEdBQUcsR0FBRzljLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSUEsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ2hEO01BQ0o7TUFFQSxJQUFJa2MsTUFBTSxDQUFDVyxpQkFBaUIsRUFBRTtRQUMxQjtRQUNBdGQsT0FBTyxDQUFDd2QsU0FBUyxHQUFHbmQsVUFBVSxDQUN6Qm9MLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQ1hKLEdBQUcsQ0FBRW9TLElBQUksSUFBS0EsSUFBSSxDQUFDelEsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUMxQjFFLE1BQU0sQ0FBRW1WLElBQUksSUFBS0EsSUFBSSxDQUFDO01BQy9CO0lBQ0o7O0lBRUE7SUFDQSxJQUFJZCxNQUFNLENBQUNlLE9BQU8sSUFBSWYsTUFBTSxDQUFDZSxPQUFPLENBQUNDLE9BQU8sRUFBRTtNQUMxQyxNQUFNN2IsTUFBTSxHQUFHNmEsTUFBTSxDQUFDaUIsaUJBQWlCLEdBQUcsSUFBSXJnQixRQUFRLENBQUNzZ0IsZ0JBQWdCLENBQUMsQ0FBQyxJQUFJLEdBQUcsRUFBRTtNQUNsRixNQUFNQyxhQUFhLEdBQUcsSUFBSWpULE9BQU8sR0FBRzs7TUFFcEM7TUFDQSxJQUFJa1QsYUFBYSxHQUFHLEtBQUs7TUFDekIsSUFBSWxULE9BQU8sQ0FBQ3dELFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTBQLGFBQWEsR0FBRyxPQUFPLENBQUMsS0FDbEQsSUFBSWxULE9BQU8sQ0FBQ3dELFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRTBQLGFBQWEsR0FBRyxNQUFNLENBQUMsS0FDckQsSUFBSWxULE9BQU8sQ0FBQ3dELFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRTBQLGFBQWEsR0FBRyxNQUFNO01BRXpEcGQsT0FBTyxDQUFDb2QsYUFBYSxDQUFDLENBQUNqYyxNQUFNLEdBQUdnYyxhQUFhLEVBQUUsR0FBR2hULE1BQU0sQ0FBQztJQUM3RDs7SUFFQTtJQUNBLElBQUk2UixNQUFNLENBQUNlLE9BQU8sSUFBSWYsTUFBTSxDQUFDZSxPQUFPLENBQUNNLFdBQVcsRUFBRTtNQUM5Q3pnQixRQUFRLENBQUMwZ0Isc0JBQXNCLENBQUNqZSxPQUFPLENBQUM7SUFDNUM7RUFDSjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU9rZSxTQUFTQSxDQUFDeGUsS0FBSyxFQUFFO0lBQ3BCO0lBQ0EsSUFBSSxDQUFDL0QsTUFBTSxDQUFDeVQsTUFBTSxJQUFJLENBQUN6VCxNQUFNLENBQUN5VCxNQUFNLENBQUNnTixrQkFBa0IsRUFBRTtNQUNyRDtJQUNKOztJQUVBO0lBQ0EsSUFBSStCLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFDbEIsSUFBSSxPQUFPemUsS0FBSyxLQUFLLFFBQVEsRUFBRTtNQUMzQnllLFNBQVMsQ0FBQ25lLE9BQU8sR0FBR04sS0FBSztNQUN6QnllLFNBQVMsQ0FBQzlGLElBQUksR0FBRyxRQUFRO0lBQzdCLENBQUMsTUFBTSxJQUFJM1ksS0FBSyxZQUFZUyxLQUFLLEVBQUU7TUFDL0JnZSxTQUFTLENBQUNuZSxPQUFPLEdBQUdOLEtBQUssQ0FBQ00sT0FBTztNQUNqQ21lLFNBQVMsQ0FBQy9kLEtBQUssR0FBR1YsS0FBSyxDQUFDVSxLQUFLO01BQzdCK2QsU0FBUyxDQUFDOUYsSUFBSSxHQUFHLFdBQVc7SUFDaEMsQ0FBQyxNQUFNLElBQUkzWSxLQUFLLElBQUksT0FBT0EsS0FBSyxLQUFLLFFBQVEsRUFBRTtNQUMzQ3llLFNBQVMsR0FBR3plLEtBQUs7TUFDakIsSUFBSSxDQUFDeWUsU0FBUyxDQUFDOUYsSUFBSSxFQUFFO1FBQ2pCOEYsU0FBUyxDQUFDOUYsSUFBSSxHQUFHLFFBQVE7TUFDN0I7SUFDSjtJQUVBOWEsUUFBUSxDQUFDOGUscUJBQXFCLENBQUM4QixTQUFTLENBQUM7RUFDN0M7O0VBRUE7QUFDSjtBQUNBO0VBQ0ksT0FBTzlCLHFCQUFxQkEsQ0FBQzhCLFNBQVMsRUFBRTtJQUNwQztJQUNBLElBQUk1Z0IsUUFBUSxDQUFDNmdCLFlBQVksSUFBSTdnQixRQUFRLENBQUM4Z0IsbUJBQW1CLEVBQUU7TUFDdkQ7SUFDSjtJQUNBLElBQUk5Z0IsUUFBUSxDQUFDK2dCLGtCQUFrQixJQUFJL2dCLFFBQVEsQ0FBQ2doQixpQkFBaUIsRUFBRTtNQUMzRDtJQUNKO0lBRUFoaEIsUUFBUSxDQUFDNmdCLFlBQVksRUFBRTs7SUFFdkI7SUFDQUQsU0FBUyxDQUFDOUksR0FBRyxHQUFHMVosTUFBTSxDQUFDNGhCLFFBQVEsQ0FBQzFNLElBQUk7SUFDcENzTixTQUFTLENBQUMxaUIsU0FBUyxHQUFHRCxTQUFTLENBQUNDLFNBQVM7SUFDekMwaUIsU0FBUyxDQUFDaEIsU0FBUyxHQUFHLElBQUk5ZCxJQUFJLENBQUMsQ0FBQyxDQUFDK2QsV0FBVyxDQUFDLENBQUM7O0lBRTlDO0lBQ0E3ZixRQUFRLENBQUNpaEIsWUFBWSxDQUFDN2MsSUFBSSxDQUFDd2MsU0FBUyxDQUFDOztJQUVyQztJQUNBLElBQUk1Z0IsUUFBUSxDQUFDa2hCLFlBQVksRUFBRTtNQUN2QnhYLFlBQVksQ0FBQzFKLFFBQVEsQ0FBQ2toQixZQUFZLENBQUM7SUFDdkM7O0lBRUE7SUFDQWxoQixRQUFRLENBQUNraEIsWUFBWSxHQUFHaFosVUFBVSxDQUFDLE1BQU07TUFDckNsSSxRQUFRLENBQUNtaEIsa0JBQWtCLENBQUMsQ0FBQztJQUNqQyxDQUFDLEVBQUVuaEIsUUFBUSxDQUFDb2hCLFdBQVcsQ0FBQztFQUM1Qjs7RUFFQTtBQUNKO0FBQ0E7RUFDSSxPQUFPVixzQkFBc0JBLENBQUNqZSxPQUFPLEVBQUU7SUFDbkN6QyxRQUFRLENBQUNxaEIsY0FBYyxDQUFDamQsSUFBSSxDQUFDM0IsT0FBTyxDQUFDOztJQUVyQztJQUNBLElBQUl6QyxRQUFRLENBQUNzaEIsY0FBYyxFQUFFO01BQ3pCNVgsWUFBWSxDQUFDMUosUUFBUSxDQUFDc2hCLGNBQWMsQ0FBQztJQUN6Qzs7SUFFQTtJQUNBdGhCLFFBQVEsQ0FBQ3NoQixjQUFjLEdBQUdwWixVQUFVLENBQUMsTUFBTTtNQUN2Q2xJLFFBQVEsQ0FBQ3VoQixvQkFBb0IsQ0FBQyxDQUFDO0lBQ25DLENBQUMsRUFBRXZoQixRQUFRLENBQUNvaEIsV0FBVyxDQUFDO0VBQzVCOztFQUVBO0FBQ0o7QUFDQTtFQUNJLGFBQWFHLG9CQUFvQkEsQ0FBQSxFQUFHO0lBQ2hDLElBQUl2aEIsUUFBUSxDQUFDcWhCLGNBQWMsQ0FBQ3JnQixNQUFNLEtBQUssQ0FBQyxFQUFFO01BQ3RDO0lBQ0o7SUFFQSxNQUFNcWQsUUFBUSxHQUFHcmUsUUFBUSxDQUFDcWhCLGNBQWM7SUFDeENyaEIsUUFBUSxDQUFDcWhCLGNBQWMsR0FBRyxFQUFFO0lBQzVCcmhCLFFBQVEsQ0FBQ3NoQixjQUFjLEdBQUcsSUFBSTtJQUU5QixJQUFJO01BQ0EsT0FBT2pILElBQUksQ0FBQ3hPLElBQUksQ0FBQ2dMLEdBQUcsQ0FBQzJLLEtBQUssQ0FBQyxxQkFBcUIsRUFBRSxzQkFBc0IsQ0FBQyxFQUFFO1FBQUVuRCxRQUFRLEVBQUVBO01BQVMsQ0FBQyxDQUFDO0lBQ3RHLENBQUMsQ0FBQyxPQUFPbGMsS0FBSyxFQUFFO01BQ1o7TUFDQWlCLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyxrREFBa0QsRUFBRUEsS0FBSyxDQUFDO0lBQzVFO0VBQ0o7O0VBRUE7QUFDSjtBQUNBO0VBQ0ksYUFBYWdmLGtCQUFrQkEsQ0FBQSxFQUFHO0lBQzlCLElBQUluaEIsUUFBUSxDQUFDaWhCLFlBQVksQ0FBQ2pnQixNQUFNLEtBQUssQ0FBQyxFQUFFO01BQ3BDO0lBQ0o7SUFFQSxNQUFNeVosTUFBTSxHQUFHemEsUUFBUSxDQUFDaWhCLFlBQVk7SUFDcENqaEIsUUFBUSxDQUFDaWhCLFlBQVksR0FBRyxFQUFFO0lBQzFCamhCLFFBQVEsQ0FBQ2toQixZQUFZLEdBQUcsSUFBSTtJQUM1QmxoQixRQUFRLENBQUMrZ0Isa0JBQWtCLEVBQUU7SUFFN0IsSUFBSTtNQUNBLE9BQU8xRyxJQUFJLENBQUN4TyxJQUFJLENBQUNnTCxHQUFHLENBQUMySyxLQUFLLENBQUMscUJBQXFCLEVBQUUsb0JBQW9CLENBQUMsRUFBRTtRQUFFL0csTUFBTSxFQUFFQTtNQUFPLENBQUMsQ0FBQztJQUNoRyxDQUFDLENBQUMsT0FBT3RZLEtBQUssRUFBRTtNQUNaO01BQ0FpQixPQUFPLENBQUNqQixLQUFLLENBQUMsMENBQTBDLEVBQUVBLEtBQUssQ0FBQztJQUNwRTtFQUNKOztFQUVBO0FBQ0o7QUFDQTtFQUNJLE9BQU9tZSxnQkFBZ0JBLENBQUEsRUFBRztJQUN0QixNQUFNN1csR0FBRyxHQUFHM0gsSUFBSSxDQUFDMkgsR0FBRyxDQUFDLENBQUM7SUFDdEIsSUFBSSxDQUFDekosUUFBUSxDQUFDeWhCLFdBQVcsRUFBRTtNQUN2QnpoQixRQUFRLENBQUN5aEIsV0FBVyxHQUFHaFksR0FBRztJQUM5QjtJQUNBLE1BQU1pWSxPQUFPLEdBQUdqWSxHQUFHLEdBQUd6SixRQUFRLENBQUN5aEIsV0FBVztJQUMxQyxPQUFPLENBQUNDLE9BQU8sR0FBRyxJQUFJLEVBQUVDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHO0VBQzVDO0FBQ0o7QUE3Ukk7QUFBQUMsd0JBQUEsQ0FERTVoQixRQUFRLG9CQUVjLEVBQUU7QUFBQTRoQix3QkFBQSxDQUZ4QjVoQixRQUFRLG9CQUdjLElBQUk7QUFBQTRoQix3QkFBQSxDQUgxQjVoQixRQUFRLDBCQUlvQixDQUFDO0FBRS9CO0FBQUE0aEIsd0JBQUEsQ0FORTVoQixRQUFRLGtCQU9ZLEVBQUU7QUFBQTRoQix3QkFBQSxDQVB0QjVoQixRQUFRLGtCQVFZLElBQUk7QUFBQTRoQix3QkFBQSxDQVJ4QjVoQixRQUFRLGtCQVNZLENBQUM7QUFBQTRoQix3QkFBQSxDQVRyQjVoQixRQUFRLHdCQVVrQixDQUFDO0FBRTdCO0FBQUE0aEIsd0JBQUEsQ0FaRTVoQixRQUFRLGlCQWFXLElBQUk7QUFBQTRoQix3QkFBQSxDQWJ2QjVoQixRQUFRLHlCQWNtQixFQUFFO0FBQUE0aEIsd0JBQUEsQ0FkN0I1aEIsUUFBUSx1QkFlaUIsQ0FBQztBQUU1QjtBQUFBNGhCLHdCQUFBLENBakJFNWhCLFFBQVEsaUJBa0JXLElBQUk7Ozs7OztBQ3RCN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTZoQixjQUFjLENBQUM7RUFDakI7QUFDSjtBQUNBO0FBQ0E7RUFDSSxPQUFPaEkseUJBQXlCQSxDQUFBLEVBQUc7SUFDL0I7SUFDQTFiLENBQUMsQ0FBQzJJLEVBQUUsQ0FBQ2diLE1BQU0sR0FBRyxZQUFZO01BQ3RCLE9BQU8sSUFBSSxDQUFDOWdCLE1BQU0sR0FBRyxDQUFDO0lBQzFCLENBQUM7O0lBRUQ7SUFDQTdDLENBQUMsQ0FBQzJJLEVBQUUsQ0FBQ2liLFVBQVUsR0FBRyxZQUFZO01BQzFCLE9BQU8sSUFBSSxDQUFDN0gsRUFBRSxDQUFDLFVBQVUsQ0FBQztJQUM5QixDQUFDOztJQUVEO0lBQ0E7SUFDQS9iLENBQUMsQ0FBQzJJLEVBQUUsQ0FBQ2tiLFlBQVksR0FBRyxZQUFxQjtNQUFBLElBQVhDLEtBQUssR0FBQXZmLFNBQUEsQ0FBQTFCLE1BQUEsUUFBQTBCLFNBQUEsUUFBQUMsU0FBQSxHQUFBRCxTQUFBLE1BQUcsQ0FBQztNQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDb2YsTUFBTSxDQUFDLENBQUMsRUFBRTtRQUNoQjtRQUNBO01BQ0o7TUFFQSxJQUFJLENBQUMsSUFBSSxDQUFDSSxTQUFTLENBQUMsQ0FBQyxFQUFFO1FBQ25CO1FBQ0E7TUFDSjtNQUVBLElBQUlDLEtBQUssR0FBR2hpQixJQUFJLENBQUMwQixLQUFLLENBQUMsSUFBSSxDQUFDckIsTUFBTSxDQUFDLENBQUMsQ0FBQ2YsR0FBRyxDQUFDO01BQ3pDLElBQUkyaUIsS0FBSyxHQUFHamtCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQ3VCLFNBQVMsQ0FBQyxDQUFDO01BQ2pDLElBQUl5aUIsS0FBSyxHQUFHLENBQUMsRUFBRTtRQUNYLElBQUloakIsTUFBTSxHQUFHaWpCLEtBQUssR0FBR0QsS0FBSztRQUMxQmhrQixDQUFDLENBQUMsWUFBWSxDQUFDLENBQUN3QyxPQUFPLENBQ25CO1VBQ0lqQixTQUFTLEVBQUVQO1FBQ2YsQ0FBQyxFQUNEOGlCLEtBQ0osQ0FBQztNQUNMO0lBQ0osQ0FBQzs7SUFFRDtJQUNBOWpCLENBQUMsQ0FBQ2trQixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUNDLEtBQUssR0FBRyxVQUFVQyxJQUFJLEVBQUU7TUFDaEMsT0FBT0EsSUFBSSxLQUFLclAsUUFBUSxDQUFDc1AsYUFBYSxLQUFLRCxJQUFJLENBQUN6SCxJQUFJLElBQUl5SCxJQUFJLENBQUNqUCxJQUFJLENBQUM7SUFDdEUsQ0FBQzs7SUFFRDtJQUNBblYsQ0FBQyxDQUFDMkksRUFBRSxDQUFDMmIsYUFBYSxHQUFHdGtCLENBQUMsQ0FBQzJJLEVBQUUsQ0FBQzRiLEtBQUs7O0lBRS9CO0lBQ0E7SUFDQXZrQixDQUFDLENBQUMySSxFQUFFLENBQUM0YixLQUFLLEdBQUcsVUFBVUMsT0FBTyxFQUFFO01BQzVCO01BQ0EsSUFBSSxPQUFPQSxPQUFPLEtBQUssV0FBVyxFQUFFO1FBQ2hDLE9BQU8sSUFBSSxDQUFDRixhQUFhLENBQUMsQ0FBQztNQUMvQjs7TUFFQTtNQUNBLE9BQU8sSUFBSSxDQUFDdFAsRUFBRSxDQUFDLE9BQU8sRUFBRSxVQUFVQyxDQUFDLEVBQUU7UUFDakM7UUFDQSxNQUFNd1AsdUJBQXVCLEdBQUd4UCxDQUFDLENBQUNNLGNBQWMsQ0FBQ21QLElBQUksQ0FBQ3pQLENBQUMsQ0FBQzs7UUFFeEQ7UUFDQUEsQ0FBQyxDQUFDTSxjQUFjLEdBQUcsWUFBVztVQUMxQnRRLE9BQU8sQ0FBQzBmLElBQUksQ0FBQyxnR0FBZ0csQ0FBQztVQUM5RyxPQUFPRix1QkFBdUIsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7O1FBRUQ7UUFDQUEsdUJBQXVCLENBQUMsQ0FBQztRQUV6QixPQUFPRCxPQUFPLENBQUM5VyxJQUFJLENBQUMsSUFBSSxFQUFFdUgsQ0FBQyxDQUFDO01BQ2hDLENBQUMsQ0FBQztJQUNOLENBQUM7O0lBRUQ7SUFDQWpWLENBQUMsQ0FBQzJJLEVBQUUsQ0FBQ2ljLG1CQUFtQixHQUFHLFVBQVVKLE9BQU8sRUFBRTtNQUMxQyxJQUFJLE9BQU9BLE9BQU8sS0FBSyxXQUFXLEVBQUU7UUFDaEMsT0FBTyxJQUFJLENBQUNGLGFBQWEsQ0FBQyxDQUFDO01BQy9CO01BQ0EsT0FBTyxJQUFJLENBQUNBLGFBQWEsQ0FBQ0UsT0FBTyxDQUFDO0lBQ3RDLENBQUM7O0lBRUQ7SUFDQXhrQixDQUFDLENBQUMySSxFQUFFLENBQUNvYixTQUFTLEdBQUcsWUFBWTtNQUN6QixJQUFJakksUUFBUSxHQUFHLElBQUk7TUFDbkIsSUFBSStJLFNBQVMsR0FBRyxTQUFBQSxDQUFVQyxPQUFPLEVBQUU7UUFDL0IsT0FBT0EsT0FBTyxDQUFDQyxhQUFhLEVBQUU7VUFDMUJELE9BQU8sR0FBR0EsT0FBTyxDQUFDQyxhQUFhO1FBQ25DO1FBQ0EsT0FBT0QsT0FBTztNQUNsQixDQUFDO01BQ0QsT0FBT0QsU0FBUyxDQUFDL0ksUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUsvRyxRQUFRLENBQUNpUSxlQUFlO0lBQzlELENBQUM7O0lBRUQ7SUFDQWhsQixDQUFDLENBQUMySSxFQUFFLENBQUNzYyxjQUFjLEdBQUcsWUFBWTtNQUM5QixJQUFJQyxTQUFTLEdBQUdsbEIsQ0FBQyxDQUFDQyxNQUFNLENBQUMsQ0FBQ3NCLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHdkIsQ0FBQyxDQUFDQyxNQUFNLENBQUMsQ0FBQ3NCLFNBQVMsQ0FBQyxDQUFDLEdBQUd2QixDQUFDLENBQUMsTUFBTSxDQUFDLENBQUN1QixTQUFTLENBQUMsQ0FBQztNQUV6RixJQUFJdWEsUUFBUSxHQUFHLElBQUk7TUFFbkIsTUFBTXFKLGNBQWMsR0FBR3JKLFFBQVEsQ0FBQ3paLE1BQU0sQ0FBQyxDQUFDLENBQUNmLEdBQUc7TUFDNUMsTUFBTThqQixpQkFBaUIsR0FBR3RKLFFBQVEsQ0FBQ3paLE1BQU0sQ0FBQyxDQUFDLENBQUNmLEdBQUcsR0FBR3dhLFFBQVEsQ0FBQ3JhLFdBQVcsQ0FBQyxDQUFDO01BQ3hFLE1BQU00akIsZ0JBQWdCLEdBQUdILFNBQVMsR0FBR2xsQixDQUFDLENBQUNDLE1BQU0sQ0FBQyxDQUFDcWxCLFdBQVcsQ0FBQyxDQUFDO01BQzVELE1BQU1DLGFBQWEsR0FBR0wsU0FBUztNQUUvQixJQUFJRyxnQkFBZ0IsR0FBR0YsY0FBYyxJQUFJSSxhQUFhLEdBQUdILGlCQUFpQixFQUFFO1FBQ3hFLE9BQU8sSUFBSTtNQUNmLENBQUMsTUFBTTtRQUNILE9BQU8sS0FBSztNQUNoQjtJQUNKLENBQUM7O0lBRUQ7SUFDQXBsQixDQUFDLENBQUMySSxFQUFFLENBQUM2YyxPQUFPLEdBQUcsWUFBWTtNQUN2QixPQUFPLElBQUksQ0FBQ0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDQyxXQUFXLENBQUMsQ0FBQztJQUM3QyxDQUFDOztJQUVEO0lBQ0ExbEIsQ0FBQyxDQUFDMkksRUFBRSxDQUFDZ2QsV0FBVyxHQUFHLFlBQVk7TUFDM0IsTUFBTUMsSUFBSSxHQUFHM2xCLE1BQU0sQ0FBQzRoQixRQUFRLENBQUMrRCxJQUFJO01BQ2pDLE1BQU1DLElBQUksR0FBRzdsQixDQUFDLENBQUMsS0FBSyxFQUFFO1FBQ2xCbVYsSUFBSSxFQUFFLElBQUksQ0FBQ0MsSUFBSSxDQUFDLE1BQU07TUFDMUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMwUSxRQUFRO01BQ2QsT0FBT0QsSUFBSSxLQUFLRCxJQUFJO0lBQ3hCLENBQUM7O0lBRUQ7SUFDQTVsQixDQUFDLENBQUMySSxFQUFFLENBQUNvZCxhQUFhLEdBQUcsWUFBWTtNQUM3QixJQUFJLElBQUksQ0FBQ2xqQixNQUFNLEtBQUssQ0FBQyxFQUFFLE9BQU8sS0FBSztNQUNuQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQ2tqQixhQUFhLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQvbEIsQ0FBQyxDQUFDMkksRUFBRSxDQUFDcWQsY0FBYyxHQUFHLFlBQVk7TUFDOUIsSUFBSSxJQUFJLENBQUNuakIsTUFBTSxLQUFLLENBQUMsRUFBRSxPQUFPLEtBQUs7TUFDbkMsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUNtakIsY0FBYyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVEaG1CLENBQUMsQ0FBQzJJLEVBQUUsQ0FBQ3NkLGFBQWEsR0FBRyxZQUFZO01BQzdCLElBQUksSUFBSSxDQUFDcGpCLE1BQU0sS0FBSyxDQUFDLEVBQUUsT0FBTyxJQUFJO01BQ2xDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQ29qQixhQUFhLENBQUMsQ0FBQztNQUN2QixPQUFPLElBQUk7SUFDZixDQUFDOztJQUVEO0lBQ0E7SUFDQWptQixDQUFDLENBQUMySSxFQUFFLENBQUN1ZCxlQUFlLEdBQUcsVUFBVUMsUUFBUSxFQUFFO01BQ3ZDLElBQUlDLFFBQVEsR0FBRyxJQUFJO01BQ25CLElBQUlsbEIsT0FBTyxHQUFHa2xCLFFBQVEsQ0FBQ2psQixNQUFNLENBQUMsQ0FBQzs7TUFFL0I7TUFDQSxPQUFPRCxPQUFPLENBQUMyQixNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMzQixPQUFPLENBQUM2YSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDOUM7UUFDQSxJQUFJc0ssTUFBTSxHQUFHbmxCLE9BQU8sQ0FBQ3VjLElBQUksQ0FBQzBJLFFBQVEsQ0FBQztRQUNuQyxJQUFJRSxNQUFNLENBQUN4akIsTUFBTSxHQUFHLENBQUMsRUFBRTtVQUNuQixPQUFPd2pCLE1BQU07UUFDakI7O1FBRUE7UUFDQW5sQixPQUFPLEdBQUdBLE9BQU8sQ0FBQ0MsTUFBTSxDQUFDLENBQUM7TUFDOUI7O01BRUE7TUFDQSxJQUFJRCxPQUFPLENBQUM2YSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDcEIsSUFBSXNLLE1BQU0sR0FBR25sQixPQUFPLENBQUN1YyxJQUFJLENBQUMwSSxRQUFRLENBQUM7UUFDbkMsSUFBSUUsTUFBTSxDQUFDeGpCLE1BQU0sR0FBRyxDQUFDLEVBQUU7VUFDbkIsT0FBT3dqQixNQUFNO1FBQ2pCO01BQ0o7O01BRUE7TUFDQSxPQUFPcm1CLENBQUMsQ0FBQyxDQUFDO0lBQ2QsQ0FBQzs7SUFFRDtJQUNBO0lBQ0EsTUFBTXNtQixXQUFXLEdBQUd0bUIsQ0FBQyxDQUFDMFosSUFBSTtJQUMxQjFaLENBQUMsQ0FBQzBaLElBQUksR0FBRyxVQUFVQyxHQUFHLEVBQUVrQyxPQUFPLEVBQUU7TUFDN0I7TUFDQSxJQUFJMEssUUFBUTtNQUNaLElBQUksT0FBTzVNLEdBQUcsS0FBSyxRQUFRLEVBQUU7UUFDekI0TSxRQUFRLEdBQUcxSyxPQUFPLElBQUksQ0FBQyxDQUFDO1FBQ3hCMEssUUFBUSxDQUFDNU0sR0FBRyxHQUFHQSxHQUFHO01BQ3RCLENBQUMsTUFBTTtRQUNINE0sUUFBUSxHQUFHNU0sR0FBRyxJQUFJLENBQUMsQ0FBQztNQUN4Qjs7TUFFQTtNQUNBLE1BQU02TSxXQUFXLEdBQUdELFFBQVEsQ0FBQzVNLEdBQUcsSUFBSSxFQUFFO01BQ3RDLE1BQU04TSxXQUFXLEdBQUcsQ0FBQ0QsV0FBVyxDQUFDemhCLEtBQUssQ0FBQyxjQUFjLENBQUM7TUFDdEQsTUFBTTJoQixjQUFjLEdBQUdGLFdBQVcsQ0FBQy9RLFVBQVUsQ0FBQ3hWLE1BQU0sQ0FBQzRoQixRQUFRLENBQUM4RSxNQUFNLENBQUM7TUFDckUsTUFBTUMsZ0JBQWdCLEdBQUdILFdBQVcsSUFBSUMsY0FBYzs7TUFFdEQ7TUFDQSxJQUFJSCxRQUFRLENBQUNNLG1CQUFtQixLQUFLLElBQUksRUFBRTtRQUN2QyxPQUFPUCxXQUFXLENBQUM1WSxJQUFJLENBQUMsSUFBSSxFQUFFNlksUUFBUSxDQUFDO01BQzNDOztNQUVBO01BQ0EsTUFBTU8sY0FBYyxHQUFHTixXQUFXLEtBQUssVUFBVSxJQUFJQSxXQUFXLENBQUNPLFFBQVEsQ0FBQyxVQUFVLENBQUM7TUFDckYsSUFBSUQsY0FBYyxFQUFFO1FBQ2hCLE9BQU9SLFdBQVcsQ0FBQzVZLElBQUksQ0FBQyxJQUFJLEVBQUU2WSxRQUFRLENBQUM7TUFDM0M7O01BRUE7TUFDQSxJQUFJSyxnQkFBZ0IsRUFBRTtRQUNsQjtRQUNBLElBQUlJLGVBQWUsR0FBRyxJQUFJO1FBQzFCLElBQUlDLFdBQVcsR0FBRyxJQUFJO1FBQ3RCLE1BQU1DLFNBQVMsR0FBR1YsV0FBVyxDQUFDemhCLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQztRQUN2RSxJQUFJbWlCLFNBQVMsRUFBRTtVQUNYRixlQUFlLEdBQUdFLFNBQVMsQ0FBQyxDQUFDLENBQUM7VUFDOUJELFdBQVcsR0FBR0MsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUM5QjtRQUVBLElBQUk5SCxhQUFhLEdBQUcsNkRBQTZEO1FBRWpGLElBQUk0SCxlQUFlLElBQUlDLFdBQVcsRUFBRTtVQUNoQzdILGFBQWEsSUFBSSxlQUFlO1VBQ2hDQSxhQUFhLElBQUksbUJBQW1Cb0gsV0FBVyxjQUFjO1VBQzdEcEgsYUFBYSxJQUFJLFFBQVE7VUFDekJBLGFBQWEsSUFBSSxXQUFXNEgsZUFBZSxJQUFJQyxXQUFXLGtCQUFrQjtRQUNoRixDQUFDLE1BQU07VUFDSDdILGFBQWEsSUFBSSxrQ0FBa0M7VUFDbkRBLGFBQWEsSUFBSSxxREFBcUQ7UUFDMUU7UUFFQUEsYUFBYSxJQUFJLGlFQUFpRTtRQUVsRi9hLGVBQWUsQ0FBQythLGFBQWEsQ0FBQztNQUNsQzs7TUFFQTtNQUNBLE9BQU9rSCxXQUFXLENBQUM1WSxJQUFJLENBQUMsSUFBSSxFQUFFNlksUUFBUSxDQUFDO0lBQzNDLENBQUM7RUFDTDtBQUNKOzs7Ozs7Ozs7QUNuUEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNN04sR0FBRyxDQUFDO0VBSU47RUFDQSxPQUFPeU8sWUFBWUEsQ0FBQSxFQUFHO0lBQ2xCLElBQUksT0FBT3pPLEdBQUcsQ0FBQzBPLGVBQWUsS0FBSyxXQUFXLEVBQUU7TUFDNUMxTyxHQUFHLENBQUMwTyxlQUFlLEdBQUcsQ0FBQyxDQUFDO0lBQzVCO0lBQ0EsSUFBSSxPQUFPMU8sR0FBRyxDQUFDMk8saUJBQWlCLEtBQUssV0FBVyxFQUFFO01BQzlDM08sR0FBRyxDQUFDMk8saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0lBQzlCO0VBQ0o7O0VBRUE7RUFDQSxPQUFPclMsRUFBRUEsQ0FBQ2dCLEtBQUssRUFBRXRULFFBQVEsRUFBRTtJQUN2QmdXLEdBQUcsQ0FBQ3lPLFlBQVksQ0FBQyxDQUFDO0lBRWxCLElBQUksT0FBT3prQixRQUFRLEtBQUssVUFBVSxFQUFFO01BQ2hDLE1BQU0sSUFBSStCLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQztJQUNsRDtJQUVBLElBQUksQ0FBQ2lVLEdBQUcsQ0FBQzBPLGVBQWUsQ0FBQ3BSLEtBQUssQ0FBQyxFQUFFO01BQzdCMEMsR0FBRyxDQUFDME8sZUFBZSxDQUFDcFIsS0FBSyxDQUFDLEdBQUcsRUFBRTtJQUNuQztJQUVBMEMsR0FBRyxDQUFDME8sZUFBZSxDQUFDcFIsS0FBSyxDQUFDLENBQUMvUCxJQUFJLENBQUN2RCxRQUFRLENBQUM7O0lBRXpDO0lBQ0EsSUFBSWdXLEdBQUcsQ0FBQzJPLGlCQUFpQixDQUFDclIsS0FBSyxDQUFDLEVBQUU7TUFDOUJsVSxhQUFhLENBQUMsVUFBVSxFQUFFLGFBQWEsR0FBR2tVLEtBQUssR0FBRywrQkFBK0IsQ0FBQztNQUNsRnRULFFBQVEsQ0FBQ2dXLEdBQUcsQ0FBQzJPLGlCQUFpQixDQUFDclIsS0FBSyxDQUFDLENBQUM7SUFDMUM7RUFDSjs7RUFFQTtFQUNBLE9BQU9rSSxPQUFPQSxDQUFDbEksS0FBSyxFQUFhO0lBQUEsSUFBWFYsSUFBSSxHQUFBL1EsU0FBQSxDQUFBMUIsTUFBQSxRQUFBMEIsU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBRyxDQUFDLENBQUM7SUFDM0JtVSxHQUFHLENBQUN5TyxZQUFZLENBQUMsQ0FBQzs7SUFFbEI7SUFDQXpPLEdBQUcsQ0FBQzJPLGlCQUFpQixDQUFDclIsS0FBSyxDQUFDLEdBQUdWLElBQUk7SUFFbkMsSUFBSSxDQUFDb0QsR0FBRyxDQUFDME8sZUFBZSxDQUFDcFIsS0FBSyxDQUFDLEVBQUU7TUFDN0I7SUFDSjtJQUVBbFUsYUFBYSxDQUFDLFVBQVUsRUFBRSxhQUFhLEdBQUdrVSxLQUFLLEdBQUcsT0FBTyxHQUFHMEMsR0FBRyxDQUFDME8sZUFBZSxDQUFDcFIsS0FBSyxDQUFDLENBQUNuVCxNQUFNLEdBQUcsWUFBWSxDQUFDOztJQUU3RztJQUNBLEtBQUssTUFBTUgsUUFBUSxJQUFJZ1csR0FBRyxDQUFDME8sZUFBZSxDQUFDcFIsS0FBSyxDQUFDLEVBQUU7TUFDL0N0VCxRQUFRLENBQUM0UyxJQUFJLENBQUM7SUFDbEI7RUFDSjs7RUFFQTtFQUNBO0VBQ0EsT0FBT2dTLGVBQWVBLENBQUEsRUFBRztJQUNyQjtJQUNBLElBQUksQ0FBQ3BKLE9BQU8sQ0FBQyxTQUFTLENBQUM7RUFDM0I7O0VBRUE7RUFDQSxPQUFPcEgsR0FBR0EsQ0FBQzZGLElBQUksRUFBc0I7SUFBQSxJQUFwQnJZLE9BQU8sR0FBQUMsU0FBQSxDQUFBMUIsTUFBQSxRQUFBMEIsU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBRyxRQUFRO0lBQy9CZ2pCLFFBQVEsQ0FBQ3pRLEdBQUcsQ0FBQzZGLElBQUksRUFBRXJZLE9BQU8sQ0FBQztFQUMvQjs7RUFFQTtFQUNBO0VBQ0EsT0FBT2tqQixNQUFNQSxDQUFBLEVBQUc7SUFDWixPQUFPdm5CLE1BQU0sQ0FBQ3lULE1BQU0sQ0FBQzZELEtBQUs7RUFDOUI7RUFFQSxPQUFPb0IsT0FBT0EsQ0FBQSxFQUFHO0lBQ2IsT0FBTyxDQUFDMVksTUFBTSxDQUFDeVQsTUFBTSxDQUFDNkQsS0FBSztFQUMvQjs7RUFFQTtFQUNBLE9BQU9rUSxHQUFHQSxDQUFBLEVBQUc7SUFDVCxJQUFJLE9BQU8vTyxHQUFHLENBQUNnUCxJQUFJLElBQUl2akIsS0FBSyxFQUFFO01BQzFCdVUsR0FBRyxDQUFDZ1AsSUFBSSxHQUFHLENBQUM7SUFDaEI7SUFDQSxPQUFPaFAsR0FBRyxDQUFDZ1AsSUFBSSxFQUFFO0VBQ3JCOztFQUVBOztFQUdBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT0MsY0FBY0EsQ0FBQ0MsTUFBTSxFQUFFO0lBQzFCO0lBQ0EsS0FBSyxNQUFNL1YsVUFBVSxJQUFJK1YsTUFBTSxFQUFFO01BQzdCLElBQUksQ0FBQ2xQLEdBQUcsQ0FBQ21QLE9BQU8sQ0FBQ2hXLFVBQVUsQ0FBQyxFQUFFO1FBQzFCNkcsR0FBRyxDQUFDbVAsT0FBTyxDQUFDaFcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO01BQ2hDO01BQ0EsS0FBSyxNQUFNM0osV0FBVyxJQUFJMGYsTUFBTSxDQUFDL1YsVUFBVSxDQUFDLEVBQUU7UUFDMUM2RyxHQUFHLENBQUNtUCxPQUFPLENBQUNoVyxVQUFVLENBQUMsQ0FBQzNKLFdBQVcsQ0FBQyxHQUFHMGYsTUFBTSxDQUFDL1YsVUFBVSxDQUFDLENBQUMzSixXQUFXLENBQUM7TUFDMUU7SUFDSjtFQUNKOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9tYixLQUFLQSxDQUFDeFIsVUFBVSxFQUF3QztJQUFBLElBQXRDb1YsV0FBVyxHQUFBMWlCLFNBQUEsQ0FBQTFCLE1BQUEsUUFBQTBCLFNBQUEsUUFBQUMsU0FBQSxHQUFBRCxTQUFBLE1BQUcsT0FBTztJQUFBLElBQUVvWCxNQUFNLEdBQUFwWCxTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLElBQUk7SUFDekQ7SUFDQSxJQUFJdWpCLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDbkIsSUFBSSxPQUFPbk0sTUFBTSxLQUFLLFFBQVEsRUFBRTtNQUM1Qm1NLFVBQVUsR0FBRztRQUFFdmtCLEVBQUUsRUFBRW9ZO01BQU8sQ0FBQztJQUMvQixDQUFDLE1BQU0sSUFBSUEsTUFBTSxJQUFJLE9BQU9BLE1BQU0sS0FBSyxRQUFRLEVBQUU7TUFDN0NtTSxVQUFVLEdBQUduTSxNQUFNO0lBQ3ZCLENBQUMsTUFBTSxJQUFJQSxNQUFNLEtBQUssSUFBSSxJQUFJQSxNQUFNLEtBQUtuWCxTQUFTLEVBQUU7TUFDaEQsTUFBTSxJQUFJQyxLQUFLLENBQUMsd0NBQXdDLENBQUM7SUFDN0Q7O0lBRUE7SUFDQSxJQUFJd2lCLFdBQVcsQ0FBQ3hSLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRTtNQUM3QixPQUFPLEdBQUc7SUFDZDs7SUFFQTtJQUNBLElBQUlzUyxPQUFPO0lBQ1gsSUFBSXJQLEdBQUcsQ0FBQ21QLE9BQU8sQ0FBQ2hXLFVBQVUsQ0FBQyxJQUFJNkcsR0FBRyxDQUFDbVAsT0FBTyxDQUFDaFcsVUFBVSxDQUFDLENBQUNvVixXQUFXLENBQUMsRUFBRTtNQUNqRWMsT0FBTyxHQUFHclAsR0FBRyxDQUFDbVAsT0FBTyxDQUFDaFcsVUFBVSxDQUFDLENBQUNvVixXQUFXLENBQUM7SUFDbEQsQ0FBQyxNQUFNO01BQ0g7TUFDQWMsT0FBTyxHQUFHLE1BQU1sVyxVQUFVLElBQUlvVixXQUFXLEVBQUU7SUFDL0M7O0lBRUE7SUFDQSxPQUFPdk8sR0FBRyxDQUFDc1AsMEJBQTBCLENBQUNELE9BQU8sRUFBRUQsVUFBVSxDQUFDO0VBQzlEOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0UsMEJBQTBCQSxDQUFDRCxPQUFPLEVBQUVwTSxNQUFNLEVBQUU7SUFDL0M7SUFDQSxNQUFNc00sZUFBZSxHQUFHLEVBQUU7SUFDMUIsTUFBTUMsT0FBTyxHQUFHSCxPQUFPLENBQUNoakIsS0FBSyxDQUFDLDRCQUE0QixDQUFDO0lBQzNELElBQUltakIsT0FBTyxFQUFFO01BQ1Q7TUFDQSxLQUFLLE1BQU1uakIsS0FBSyxJQUFJbWpCLE9BQU8sRUFBRTtRQUN6QkQsZUFBZSxDQUFDaGlCLElBQUksQ0FBQ2xCLEtBQUssQ0FBQzRRLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztNQUM1QztJQUNKOztJQUVBO0lBQ0EsTUFBTXdTLE9BQU8sR0FBRyxFQUFFO0lBQ2xCLEtBQUssTUFBTUMsUUFBUSxJQUFJSCxlQUFlLEVBQUU7TUFDcEMsSUFBSSxFQUFFRyxRQUFRLElBQUl6TSxNQUFNLENBQUMsRUFBRTtRQUN2QndNLE9BQU8sQ0FBQ2xpQixJQUFJLENBQUNtaUIsUUFBUSxDQUFDO01BQzFCO0lBQ0o7SUFFQSxJQUFJRCxPQUFPLENBQUN0bEIsTUFBTSxHQUFHLENBQUMsRUFBRTtNQUNwQixNQUFNLElBQUk0QixLQUFLLENBQUMsd0JBQXdCMGpCLE9BQU8sQ0FBQzNZLElBQUksQ0FBQyxJQUFJLENBQUMsMkJBQTJCdVksT0FBTyxFQUFFLENBQUM7SUFDbkc7O0lBRUE7SUFDQSxJQUFJcE8sR0FBRyxHQUFHb08sT0FBTztJQUNqQixNQUFNTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO0lBRXRCLEtBQUssTUFBTUMsVUFBVSxJQUFJTCxlQUFlLEVBQUU7TUFDdEMsTUFBTXRvQixLQUFLLEdBQUdnYyxNQUFNLENBQUMyTSxVQUFVLENBQUM7TUFDaEM7TUFDQSxNQUFNQyxhQUFhLEdBQUcxWixrQkFBa0IsQ0FBQ2xQLEtBQUssQ0FBQztNQUMvQ2dhLEdBQUcsR0FBR0EsR0FBRyxDQUFDblcsT0FBTyxDQUFDLEdBQUcsR0FBRzhrQixVQUFVLEVBQUVDLGFBQWEsQ0FBQztNQUNsREYsV0FBVyxDQUFDQyxVQUFVLENBQUMsR0FBRyxJQUFJO0lBQ2xDOztJQUVBO0lBQ0EsTUFBTUUsWUFBWSxHQUFHLENBQUMsQ0FBQztJQUN2QixLQUFLLE1BQU0zaUIsR0FBRyxJQUFJOFYsTUFBTSxFQUFFO01BQ3RCLElBQUksQ0FBQzBNLFdBQVcsQ0FBQ3hpQixHQUFHLENBQUMsRUFBRTtRQUNuQjJpQixZQUFZLENBQUMzaUIsR0FBRyxDQUFDLEdBQUc4VixNQUFNLENBQUM5VixHQUFHLENBQUM7TUFDbkM7SUFDSjs7SUFFQTtJQUNBLElBQUk4SyxNQUFNLENBQUNzTSxJQUFJLENBQUN1TCxZQUFZLENBQUMsQ0FBQzNsQixNQUFNLEdBQUcsQ0FBQyxFQUFFO01BQ3RDLE1BQU00bEIsWUFBWSxHQUFHOVgsTUFBTSxDQUFDK1gsT0FBTyxDQUFDRixZQUFZLENBQUMsQ0FDNUM3WSxHQUFHLENBQUNnWixJQUFBO1FBQUEsSUFBQyxDQUFDOWlCLEdBQUcsRUFBRWxHLEtBQUssQ0FBQyxHQUFBZ3BCLElBQUE7UUFBQSxPQUFLLEdBQUc5WixrQkFBa0IsQ0FBQ2hKLEdBQUcsQ0FBQyxJQUFJZ0osa0JBQWtCLENBQUNsUCxLQUFLLENBQUMsRUFBRTtNQUFBLEVBQUMsQ0FDaEY2UCxJQUFJLENBQUMsR0FBRyxDQUFDO01BQ2RtSyxHQUFHLElBQUksR0FBRyxHQUFHOE8sWUFBWTtJQUM3QjtJQUVBLE9BQU85TyxHQUFHO0VBQ2Q7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksYUFBYWlQLHFCQUFxQkEsQ0FBQzFnQixXQUFXLEVBQUU7SUFDNUMsTUFBTTJnQixXQUFXLEdBQUd0WCxRQUFRLENBQUNpQyxlQUFlLENBQUMsQ0FBQztJQUM5QyxNQUFNc1YsbUJBQW1CLEdBQUcsRUFBRTtJQUM5QixNQUFNQyxZQUFZLEdBQUcsRUFBRTtJQUV2QixLQUFLLE1BQU1uVixVQUFVLElBQUlpVixXQUFXLEVBQUU7TUFDbEMsTUFBTWpYLFlBQVksR0FBR2dDLFVBQVUsQ0FBQ2hDLFlBQVk7TUFDNUMsTUFBTUMsVUFBVSxHQUFHK0IsVUFBVSxDQUFDL0IsVUFBVTs7TUFFeEM7TUFDQSxJQUFJLE9BQU9ELFlBQVksQ0FBQzFKLFdBQVcsQ0FBQyxLQUFLLFVBQVUsRUFBRTtRQUNqRDRnQixtQkFBbUIsQ0FBQzdpQixJQUFJLENBQUM0TCxVQUFVLENBQUM7UUFDcEMsTUFBTW1YLFlBQVksR0FBRyxNQUFNcFgsWUFBWSxDQUFDMUosV0FBVyxDQUFDLENBQUMsQ0FBQzs7UUFFdEQ7UUFDQSxJQUFJOGdCLFlBQVksWUFBWWpnQixPQUFPLEVBQUU7VUFDakNnZ0IsWUFBWSxDQUFDOWlCLElBQUksQ0FBQytpQixZQUFZLENBQUM7UUFDbkMsQ0FBQyxNQUFNLElBQUl6ZixLQUFLLENBQUNpRCxPQUFPLENBQUN3YyxZQUFZLENBQUMsRUFBRTtVQUNwQyxLQUFLLE1BQU1yWCxJQUFJLElBQUlxWCxZQUFZLEVBQUU7WUFDN0IsSUFBSXJYLElBQUksWUFBWTVJLE9BQU8sRUFBRTtjQUN6QmdnQixZQUFZLENBQUM5aUIsSUFBSSxDQUFDMEwsSUFBSSxDQUFDO1lBQzNCO1VBQ0o7UUFDSjtRQUVBLElBQUkrRyxHQUFHLENBQUN1USxTQUFTLEVBQUU7VUFDZjtRQUNKO01BQ0o7SUFDSjtJQUVBLElBQUlILG1CQUFtQixDQUFDam1CLE1BQU0sR0FBRyxDQUFDLEVBQUU7TUFDaENmLGFBQWEsQ0FBQyxVQUFVLEVBQUUsR0FBR29HLFdBQVcsS0FBSzRnQixtQkFBbUIsQ0FBQ2ptQixNQUFNLFVBQVUsQ0FBQztJQUN0Rjs7SUFFQTtJQUNBLElBQUlrbUIsWUFBWSxDQUFDbG1CLE1BQU0sR0FBRyxDQUFDLEVBQUU7TUFDekJmLGFBQWEsQ0FBQyxVQUFVLEVBQUUsR0FBR29HLFdBQVcsY0FBYzZnQixZQUFZLENBQUNsbUIsTUFBTSxXQUFXLENBQUM7TUFDckYsTUFBTWtHLE9BQU8sQ0FBQzhELEdBQUcsQ0FBQ2tjLFlBQVksQ0FBQztJQUNuQztFQUNKOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxhQUFhRyxjQUFjQSxDQUFBLEVBQUc7SUFDMUIsSUFBSXhRLEdBQUcsQ0FBQ3lRLFFBQVEsRUFBRTtNQUNkbGtCLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQztNQUN6RDtJQUNKO0lBRUEwVSxHQUFHLENBQUN5USxRQUFRLEdBQUcsSUFBSTs7SUFFbkI7SUFDQSxNQUFNTixXQUFXLEdBQUd0WCxRQUFRLENBQUNpQyxlQUFlLENBQUMsQ0FBQztJQUU5QzFSLGFBQWEsQ0FBQyxVQUFVLEVBQUUsZ0NBQWdDK21CLFdBQVcsQ0FBQ2htQixNQUFNLFVBQVUsQ0FBQztJQUV2RixJQUFJLENBQUNnbUIsV0FBVyxJQUFJQSxXQUFXLENBQUNobUIsTUFBTSxLQUFLLENBQUMsRUFBRTtNQUMxQztNQUNBd0IsZUFBZSxDQUFDLG1GQUFtRixDQUFDO01BQ3BHO0lBQ0o7O0lBRUE7SUFDQSxNQUFNK2tCLE1BQU0sR0FBRyxDQUNYO01BQUVwVCxLQUFLLEVBQUUsdUJBQXVCO01BQUU0RCxNQUFNLEVBQUU7SUFBNEIsQ0FBQyxFQUN2RTtNQUFFNUQsS0FBSyxFQUFFLDBCQUEwQjtNQUFFNEQsTUFBTSxFQUFFO0lBQStCLENBQUMsRUFDN0U7TUFBRTVELEtBQUssRUFBRSxxQkFBcUI7TUFBRTRELE1BQU0sRUFBRTtJQUEwQixDQUFDLEVBQ25FO01BQUU1RCxLQUFLLEVBQUUsb0JBQW9CO01BQUU0RCxNQUFNLEVBQUU7SUFBd0IsQ0FBQyxFQUNoRTtNQUFFNUQsS0FBSyxFQUFFLFlBQVk7TUFBRTRELE1BQU0sRUFBRTtJQUFnQixDQUFDLEVBQ2hEO01BQUU1RCxLQUFLLEVBQUUsd0JBQXdCO01BQUU0RCxNQUFNLEVBQUU7SUFBNkIsQ0FBQyxFQUN6RTtNQUFFNUQsS0FBSyxFQUFFLGtCQUFrQjtNQUFFNEQsTUFBTSxFQUFFO0lBQXNCLENBQUMsRUFDNUQ7TUFBRTVELEtBQUssRUFBRSxVQUFVO01BQUU0RCxNQUFNLEVBQUU7SUFBYyxDQUFDLEVBQzVDO01BQUU1RCxLQUFLLEVBQUUsV0FBVztNQUFFNEQsTUFBTSxFQUFFO0lBQWUsQ0FBQyxDQUNqRDs7SUFFRDtJQUNBLEtBQUssTUFBTXlQLEtBQUssSUFBSUQsTUFBTSxFQUFFO01BQ3hCLE1BQU0xUSxHQUFHLENBQUNrUSxxQkFBcUIsQ0FBQ1MsS0FBSyxDQUFDelAsTUFBTSxDQUFDO01BRTdDLElBQUlsQixHQUFHLENBQUN1USxTQUFTLEVBQUU7UUFDZjtNQUNKO01BRUF2USxHQUFHLENBQUN3RixPQUFPLENBQUNtTCxLQUFLLENBQUNyVCxLQUFLLENBQUM7SUFDNUI7O0lBRUE7SUFDQTBDLEdBQUcsQ0FBQzRPLGVBQWUsQ0FBQyxDQUFDOztJQUVyQjtJQUNBeGxCLGFBQWEsQ0FBQyxVQUFVLEVBQUUseUJBQXlCLENBQUM7O0lBRXBEOztJQUVBO0lBQ0E7SUFDQTtJQUNBNFcsR0FBRyxDQUFDd0YsT0FBTyxDQUFDLGNBQWMsQ0FBQztFQUMvQjs7RUFFQTtFQUNBLGFBQWFoRixtQkFBbUJBLENBQUNELE1BQU0sRUFBRTtJQUNyQ2hVLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQ2lWLE1BQU0sQ0FBQztJQUNyQlAsR0FBRyxDQUFDdVEsU0FBUyxHQUFHLElBQUk7RUFDeEI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT0ssV0FBV0EsQ0FBQSxFQUFHO0lBQ2pCLE1BQU1qa0IsSUFBSSxHQUFHcEYsTUFBTSxDQUFDNGhCLFFBQVEsQ0FBQ3hjLElBQUk7SUFDakMsSUFBSSxDQUFDQSxJQUFJLElBQUlBLElBQUksS0FBSyxHQUFHLEVBQUU7TUFDdkIsT0FBTyxDQUFDLENBQUM7SUFDYjs7SUFFQTtJQUNBLE1BQU1ra0IsV0FBVyxHQUFHbGtCLElBQUksQ0FBQ3NRLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDckMsTUFBTWdHLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFFakIsTUFBTTZOLEtBQUssR0FBR0QsV0FBVyxDQUFDM2tCLEtBQUssQ0FBQyxHQUFHLENBQUM7SUFDcEMsS0FBSyxNQUFNNmtCLElBQUksSUFBSUQsS0FBSyxFQUFFO01BQ3RCLE1BQU0sQ0FBQzNqQixHQUFHLEVBQUVsRyxLQUFLLENBQUMsR0FBRzhwQixJQUFJLENBQUM3a0IsS0FBSyxDQUFDLEdBQUcsQ0FBQztNQUNwQyxJQUFJaUIsR0FBRyxFQUFFO1FBQ0w4VixNQUFNLENBQUM1TSxrQkFBa0IsQ0FBQ2xKLEdBQUcsQ0FBQyxDQUFDLEdBQUdsRyxLQUFLLEdBQUdvUCxrQkFBa0IsQ0FBQ3BQLEtBQUssQ0FBQyxHQUFHLEVBQUU7TUFDNUU7SUFDSjtJQUVBLE9BQU9nYyxNQUFNO0VBQ2pCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBTytOLGVBQWVBLENBQUMvTixNQUFNLEVBQUU7SUFDM0IsTUFBTTZOLEtBQUssR0FBRyxFQUFFO0lBQ2hCLEtBQUssTUFBTTNqQixHQUFHLElBQUk4VixNQUFNLEVBQUU7TUFDdEIsTUFBTWhjLEtBQUssR0FBR2djLE1BQU0sQ0FBQzlWLEdBQUcsQ0FBQztNQUN6QixJQUFJbEcsS0FBSyxLQUFLLElBQUksSUFBSUEsS0FBSyxLQUFLNkUsU0FBUyxJQUFJN0UsS0FBSyxLQUFLLEVBQUUsRUFBRTtRQUN2RDZwQixLQUFLLENBQUN2akIsSUFBSSxDQUFDLEdBQUc0SSxrQkFBa0IsQ0FBQ2hKLEdBQUcsQ0FBQyxJQUFJZ0osa0JBQWtCLENBQUNsUCxLQUFLLENBQUMsRUFBRSxDQUFDO01BQ3pFO0lBQ0o7SUFFQSxPQUFPNnBCLEtBQUssQ0FBQzNtQixNQUFNLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRzJtQixLQUFLLENBQUNoYSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtFQUN4RDs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT21hLGtCQUFrQkEsQ0FBQSxFQUFHO0lBQ3hCLE9BQU9qUixHQUFHLENBQUM0USxXQUFXLENBQUMsQ0FBQztFQUM1Qjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPTSxjQUFjQSxDQUFDL2pCLEdBQUcsRUFBRTtJQUFBLElBQUFna0IsVUFBQTtJQUN2QixNQUFNQyxLQUFLLEdBQUdwUixHQUFHLENBQUM0USxXQUFXLENBQUMsQ0FBQztJQUMvQixRQUFBTyxVQUFBLEdBQU9DLEtBQUssQ0FBQ2prQixHQUFHLENBQUMsY0FBQWdrQixVQUFBLGNBQUFBLFVBQUEsR0FBSSxJQUFJO0VBQzdCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPRSxjQUFjQSxDQUFDbGtCLEdBQUcsRUFBRWxHLEtBQUssRUFBRTtJQUM5QixNQUFNbXFCLEtBQUssR0FBR3BSLEdBQUcsQ0FBQzRRLFdBQVcsQ0FBQyxDQUFDOztJQUUvQjtJQUNBLElBQUkzcEIsS0FBSyxLQUFLLElBQUksSUFBSUEsS0FBSyxLQUFLNkUsU0FBUyxJQUFJN0UsS0FBSyxLQUFLLEVBQUUsRUFBRTtNQUN2RCxPQUFPbXFCLEtBQUssQ0FBQ2prQixHQUFHLENBQUM7SUFDckIsQ0FBQyxNQUFNO01BQ0hpa0IsS0FBSyxDQUFDamtCLEdBQUcsQ0FBQyxHQUFHa0IsTUFBTSxDQUFDcEgsS0FBSyxDQUFDO0lBQzlCOztJQUVBO0lBQ0EsTUFBTXFxQixRQUFRLEdBQUd0UixHQUFHLENBQUNnUixlQUFlLENBQUNJLEtBQUssQ0FBQztJQUMzQyxNQUFNblEsR0FBRyxHQUFHMVosTUFBTSxDQUFDNGhCLFFBQVEsQ0FBQ29JLFFBQVEsR0FBR2hxQixNQUFNLENBQUM0aEIsUUFBUSxDQUFDdFMsTUFBTSxHQUFHeWEsUUFBUTtJQUN4RUUsT0FBTyxDQUFDQyxZQUFZLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRXhRLEdBQUcsQ0FBQztFQUN2Qzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBT3lRLGtCQUFrQkEsQ0FBQ0MsU0FBUyxFQUFFO0lBQ2pDLE1BQU1QLEtBQUssR0FBR3BSLEdBQUcsQ0FBQzRRLFdBQVcsQ0FBQyxDQUFDOztJQUUvQjtJQUNBLEtBQUssTUFBTXpqQixHQUFHLElBQUl3a0IsU0FBUyxFQUFFO01BQ3pCLE1BQU0xcUIsS0FBSyxHQUFHMHFCLFNBQVMsQ0FBQ3hrQixHQUFHLENBQUM7TUFDNUIsSUFBSWxHLEtBQUssS0FBSyxJQUFJLElBQUlBLEtBQUssS0FBSzZFLFNBQVMsSUFBSTdFLEtBQUssS0FBSyxFQUFFLEVBQUU7UUFDdkQsT0FBT21xQixLQUFLLENBQUNqa0IsR0FBRyxDQUFDO01BQ3JCLENBQUMsTUFBTTtRQUNIaWtCLEtBQUssQ0FBQ2prQixHQUFHLENBQUMsR0FBR2tCLE1BQU0sQ0FBQ3BILEtBQUssQ0FBQztNQUM5QjtJQUNKOztJQUVBO0lBQ0EsTUFBTXFxQixRQUFRLEdBQUd0UixHQUFHLENBQUNnUixlQUFlLENBQUNJLEtBQUssQ0FBQztJQUMzQyxNQUFNblEsR0FBRyxHQUFHMVosTUFBTSxDQUFDNGhCLFFBQVEsQ0FBQ29JLFFBQVEsR0FBR2hxQixNQUFNLENBQUM0aEIsUUFBUSxDQUFDdFMsTUFBTSxHQUFHeWEsUUFBUTtJQUN4RUUsT0FBTyxDQUFDQyxZQUFZLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRXhRLEdBQUcsQ0FBQztFQUN2Qzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPMlEsWUFBWUEsQ0FBQ3RtQixLQUFLLEVBQUVxUyxTQUFTLEVBQUU7SUFDbEMsTUFBTWtVLFVBQVUsR0FBR3ZxQixDQUFDLENBQUNxVyxTQUFTLENBQUM7SUFFL0IsSUFBSSxDQUFDa1UsVUFBVSxDQUFDNUcsTUFBTSxDQUFDLENBQUMsRUFBRTtNQUN0QjFlLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyx1Q0FBdUMsRUFBRXFTLFNBQVMsQ0FBQztNQUNqRTtJQUNKOztJQUVBO0lBQ0FrVSxVQUFVLENBQUN4YyxLQUFLLENBQUMsQ0FBQztJQUVsQixJQUFJUSxJQUFJLEdBQUcsRUFBRTs7SUFFYjtJQUNBLElBQUl2SyxLQUFLLENBQUMyWSxJQUFJLEtBQUssT0FBTyxJQUFJM1ksS0FBSyxDQUFDdWEsT0FBTyxFQUFFO01BQ3pDO01BQ0EsTUFBTUEsT0FBTyxHQUFHdmEsS0FBSyxDQUFDdWEsT0FBTztNQUM3QixNQUFNaU0sSUFBSSxHQUFHak0sT0FBTyxDQUFDaU0sSUFBSSxJQUFJLGNBQWM7TUFDM0MsTUFBTXpJLElBQUksR0FBR3hELE9BQU8sQ0FBQ3dELElBQUksSUFBSSxHQUFHO01BQ2hDLE1BQU16ZCxPQUFPLEdBQUdpYSxPQUFPLENBQUN2YSxLQUFLLElBQUlBLEtBQUssQ0FBQ00sT0FBTyxJQUFJLHNCQUFzQjtNQUV4RWlLLElBQUksR0FBRztBQUNuQjtBQUNBLGtEQUFrRGljLElBQUksSUFBSXpJLElBQUk7QUFDOUQsc0NBQXNDckosR0FBRyxDQUFDK1IsWUFBWSxDQUFDbm1CLE9BQU8sQ0FBQztBQUMvRDtBQUNBLGFBQWE7SUFDTCxDQUFDLE1BQU0sSUFBSU4sS0FBSyxDQUFDMlksSUFBSSxLQUFLLFlBQVksSUFBSTNZLEtBQUssQ0FBQ3VhLE9BQU8sRUFBRTtNQUNyRDtNQUNBO01BQ0EsTUFBTWpDLE1BQU0sR0FBR3RZLEtBQUssQ0FBQ3VhLE9BQU87TUFDNUIsTUFBTTZCLFVBQVUsR0FBRyxFQUFFO01BRXJCLEtBQUssTUFBTXZCLEtBQUssSUFBSXZDLE1BQU0sRUFBRTtRQUN4QjhELFVBQVUsQ0FBQ25hLElBQUksQ0FBQ3FXLE1BQU0sQ0FBQ3VDLEtBQUssQ0FBQyxDQUFDO01BQ2xDO01BRUEsSUFBSXVCLFVBQVUsQ0FBQ3ZkLE1BQU0sR0FBRyxDQUFDLEVBQUU7UUFDdkIwTCxJQUFJLEdBQUc7QUFDdkI7QUFDQTtBQUNBO0FBQ0EsOEJBQThCNlIsVUFBVSxDQUFDelEsR0FBRyxDQUFDdEUsR0FBRyxJQUFJLE9BQU9xTixHQUFHLENBQUMrUixZQUFZLENBQUNwZixHQUFHLENBQUMsT0FBTyxDQUFDLENBQUNtRSxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQ2pHO0FBQ0E7QUFDQSxpQkFBaUI7TUFDTDtJQUNKLENBQUMsTUFBTSxJQUFJeEwsS0FBSyxDQUFDMlksSUFBSSxLQUFLLGVBQWUsSUFBSTNZLEtBQUssQ0FBQzJZLElBQUksS0FBSyxjQUFjLEVBQUU7TUFDeEU7TUFDQSxNQUFNclksT0FBTyxHQUFHTixLQUFLLENBQUNNLE9BQU8sSUFBSSx5QkFBeUI7TUFDMURpSyxJQUFJLEdBQUc7QUFDbkI7QUFDQSxzQ0FBc0NtSyxHQUFHLENBQUMrUixZQUFZLENBQUNubUIsT0FBTyxDQUFDO0FBQy9EO0FBQ0EsYUFBYTtJQUNMLENBQUMsTUFBTSxJQUFJTixLQUFLLENBQUMyWSxJQUFJLEtBQUssU0FBUyxFQUFFO01BQ2pDO01BQ0EsTUFBTXJZLE9BQU8sR0FBR04sS0FBSyxDQUFDTSxPQUFPLElBQUksdURBQXVEO01BQ3hGaUssSUFBSSxHQUFHO0FBQ25CO0FBQ0Esc0NBQXNDbUssR0FBRyxDQUFDK1IsWUFBWSxDQUFDbm1CLE9BQU8sQ0FBQztBQUMvRDtBQUNBLGFBQWE7SUFDTCxDQUFDLE1BQU07TUFDSDtNQUNBLE1BQU1BLE9BQU8sR0FBR04sS0FBSyxDQUFDTSxPQUFPLElBQUlOLEtBQUssQ0FBQ3lKLFFBQVEsQ0FBQyxDQUFDLElBQUksMkJBQTJCO01BQ2hGYyxJQUFJLEdBQUc7QUFDbkI7QUFDQSxzQ0FBc0NtSyxHQUFHLENBQUMrUixZQUFZLENBQUNubUIsT0FBTyxDQUFDO0FBQy9EO0FBQ0EsYUFBYTtJQUNMO0lBRUFpbUIsVUFBVSxDQUFDaGMsSUFBSSxDQUFDQSxJQUFJLENBQUM7RUFDekI7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7RUFDSSxPQUFPa2MsWUFBWUEsQ0FBQzNLLElBQUksRUFBRTtJQUN0QixNQUFNNEssR0FBRyxHQUFHM1YsUUFBUSxDQUFDMEYsYUFBYSxDQUFDLEtBQUssQ0FBQztJQUN6Q2lRLEdBQUcsQ0FBQ2hRLFdBQVcsR0FBR29GLElBQUk7SUFDdEIsT0FBTzRLLEdBQUcsQ0FBQ0MsU0FBUztFQUN4QjtBQUNKO0FBcmxCSTtBQUFBQyx3QkFBQSxDQURFbFMsR0FBRyxlQUVjLEtBQUs7QUFBQWtTLHdCQUFBLENBRnRCbFMsR0FBRyxhQXFGWSxDQUFDLENBQUM7Ozs7OztBQ3JJdkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTXdELElBQUksQ0FBQztFQUNQO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT3RILHVCQUF1QkEsQ0FBQSxFQUFHO0lBQzdCO0lBQ0FzSCxJQUFJLENBQUMyTyxjQUFjLEdBQUcsQ0FBQyxDQUFDOztJQUV4QjtJQUNBM08sSUFBSSxDQUFDNE8sY0FBYyxHQUFHLElBQUk7O0lBRTFCO0lBQ0E1TyxJQUFJLENBQUM2TyxhQUFhLEdBQUcsQ0FBQzs7SUFFdEI7SUFDQTdPLElBQUksQ0FBQzhPLGNBQWMsR0FBRyxFQUFFOztJQUV4QjtJQUNBOU8sSUFBSSxDQUFDK0csV0FBVyxHQUFHLENBQUM7O0lBRXBCO0lBQ0EvRyxJQUFJLENBQUMrTyxpQkFBaUIsR0FBRyxJQUFJQyxPQUFPLENBQUMsQ0FBQzs7SUFFdEM7SUFDQWpyQixNQUFNLENBQUM4VixnQkFBZ0IsQ0FBQyxvQkFBb0IsRUFBRSxNQUFPQyxLQUFLLElBQUs7TUFDM0Q7TUFDQSxJQUFJa0csSUFBSSxDQUFDK08saUJBQWlCLENBQUNqTSxHQUFHLENBQUNoSixLQUFLLENBQUMySixPQUFPLENBQUMsRUFBRTtRQUMzQzNKLEtBQUssQ0FBQ1QsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDOztRQUV4QixNQUFNdlIsS0FBSyxHQUFHZ1MsS0FBSyxDQUFDaUQsTUFBTTtRQUMxQmhVLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyxzQkFBc0IsRUFBRUEsS0FBSyxDQUFDOztRQUU1QztRQUNBLElBQUksT0FBT21uQixLQUFLLEtBQUssV0FBVyxJQUFJQSxLQUFLLENBQUNubkIsS0FBSyxFQUFFO1VBQzdDLE1BQU1tbkIsS0FBSyxDQUFDbm5CLEtBQUssQ0FBQ0EsS0FBSyxFQUFFLHFCQUFxQixDQUFDO1FBQ25EO01BQ0o7SUFDSixDQUFDLENBQUM7RUFDTjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDSSxhQUFhMEosSUFBSUEsQ0FBQ2lNLEdBQUcsRUFBZTtJQUFBLElBQWJnQyxNQUFNLEdBQUFwWCxTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLENBQUMsQ0FBQztJQUM5QjtJQUNBLElBQUlvVixHQUFHLElBQUksT0FBT0EsR0FBRyxLQUFLLFFBQVEsSUFBSUEsR0FBRyxDQUFDeVIsSUFBSSxFQUFFO01BQzVDelIsR0FBRyxHQUFHQSxHQUFHLENBQUN5UixJQUFJO0lBQ2xCLENBQUMsTUFBTSxJQUFJelIsR0FBRyxJQUFJLE9BQU9BLEdBQUcsS0FBSyxVQUFVLElBQUlBLEdBQUcsQ0FBQ3lSLElBQUksRUFBRTtNQUNyRHpSLEdBQUcsR0FBR0EsR0FBRyxDQUFDeVIsSUFBSTtJQUNsQjs7SUFFQTtJQUNBLElBQUksT0FBT3pSLEdBQUcsS0FBSyxRQUFRLElBQUlBLEdBQUcsQ0FBQzlXLE1BQU0sS0FBSyxDQUFDLEVBQUU7TUFDN0MsTUFBTSxJQUFJNEIsS0FBSyxDQUFDLHlGQUF5RixDQUFDO0lBQzlHOztJQUVBO0lBQ0EsTUFBTTtNQUFFdVgsVUFBVTtNQUFFQztJQUFPLENBQUMsR0FBR0MsSUFBSSxDQUFDQyw2QkFBNkIsQ0FBQ3hDLEdBQUcsQ0FBQztJQUV0RTFVLE9BQU8sQ0FBQzZSLEdBQUcsQ0FBQyxPQUFPLEVBQUVrRixVQUFVLEVBQUVDLE1BQU0sRUFBRU4sTUFBTSxDQUFDOztJQUVoRDtJQUNBLElBQUlnRSxPQUFPO0lBQ1gsSUFBSTFmLE1BQU0sQ0FBQ3lULE1BQU0sSUFBSXpULE1BQU0sQ0FBQ3lULE1BQU0sQ0FBQzJYLHFCQUFxQixFQUFFO01BQ3REMUwsT0FBTyxHQUFHekQsSUFBSSxDQUFDb1AsWUFBWSxDQUFDdFAsVUFBVSxFQUFFQyxNQUFNLEVBQUVOLE1BQU0sQ0FBQztJQUMzRCxDQUFDLE1BQU07TUFDSGdFLE9BQU8sR0FBR3pELElBQUksQ0FBQ3FQLFdBQVcsQ0FBQ3ZQLFVBQVUsRUFBRUMsTUFBTSxFQUFFTixNQUFNLENBQUM7SUFDMUQ7O0lBRUE7SUFDQU8sSUFBSSxDQUFDK08saUJBQWlCLENBQUNoTSxHQUFHLENBQUNVLE9BQU8sQ0FBQztJQUVuQyxPQUFPQSxPQUFPO0VBQ2xCOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBTzRMLFdBQVdBLENBQUN2UCxVQUFVLEVBQUVDLE1BQU0sRUFBZTtJQUFBLElBQWJOLE1BQU0sR0FBQXBYLFNBQUEsQ0FBQTFCLE1BQUEsUUFBQTBCLFNBQUEsUUFBQUMsU0FBQSxHQUFBRCxTQUFBLE1BQUcsQ0FBQyxDQUFDO0lBQzlDVSxPQUFPLENBQUM2UixHQUFHLENBQUMsYUFBYSxFQUFFa0YsVUFBVSxFQUFFQyxNQUFNLEVBQUVOLE1BQU0sQ0FBQztJQUV0RCxPQUFPLElBQUk1UyxPQUFPLENBQUMsQ0FBQ0gsT0FBTyxFQUFFQyxNQUFNLEtBQUs7TUFDcEM7TUFDQSxNQUFNMmlCLFFBQVEsR0FBR3RQLElBQUksQ0FBQ3VQLGtCQUFrQixDQUFDelAsVUFBVSxFQUFFQyxNQUFNLEVBQUVOLE1BQU0sQ0FBQzs7TUFFcEU7TUFDQSxJQUFJTyxJQUFJLENBQUMyTyxjQUFjLENBQUNXLFFBQVEsQ0FBQyxFQUFFO1FBQy9CLE1BQU1FLGFBQWEsR0FBR3hQLElBQUksQ0FBQzJPLGNBQWMsQ0FBQ1csUUFBUSxDQUFDOztRQUVuRDtRQUNBLElBQUlFLGFBQWEsQ0FBQ0MsV0FBVyxFQUFFO1VBQzNCLElBQUlELGFBQWEsQ0FBQ0UsUUFBUSxFQUFFO1lBQ3hCL2lCLE1BQU0sQ0FBQzZpQixhQUFhLENBQUMxbkIsS0FBSyxDQUFDO1VBQy9CLENBQUMsTUFBTTtZQUNINEUsT0FBTyxDQUFDOGlCLGFBQWEsQ0FBQ3RnQixNQUFNLENBQUM7VUFDakM7VUFDQTtRQUNKOztRQUVBO1FBQ0FzZ0IsYUFBYSxDQUFDRyxTQUFTLENBQUM1bEIsSUFBSSxDQUFDO1VBQUUyQyxPQUFPO1VBQUVDO1FBQU8sQ0FBQyxDQUFDO1FBQ2pEO01BQ0o7O01BRUE7TUFDQSxNQUFNaWpCLE9BQU8sR0FBRzVQLElBQUksQ0FBQzZPLGFBQWEsRUFBRTtNQUNwQyxNQUFNZ0IsWUFBWSxHQUFHO1FBQ2pCRCxPQUFPLEVBQUVBLE9BQU87UUFDaEJOLFFBQVEsRUFBRUEsUUFBUTtRQUNsQnhQLFVBQVUsRUFBRUEsVUFBVTtRQUN0QkMsTUFBTSxFQUFFQSxNQUFNO1FBQ2ROLE1BQU0sRUFBRUEsTUFBTTtRQUNka1EsU0FBUyxFQUFFLENBQUM7VUFBRWpqQixPQUFPO1VBQUVDO1FBQU8sQ0FBQyxDQUFDO1FBQ2hDOGlCLFdBQVcsRUFBRSxLQUFLO1FBQ2xCQyxRQUFRLEVBQUUsS0FBSztRQUNmeGdCLE1BQU0sRUFBRSxJQUFJO1FBQ1pwSCxLQUFLLEVBQUU7TUFDWCxDQUFDOztNQUVEO01BQ0FrWSxJQUFJLENBQUMyTyxjQUFjLENBQUNXLFFBQVEsQ0FBQyxHQUFHTyxZQUFZOztNQUU1QztNQUNBLE1BQU1DLGFBQWEsR0FBR3JiLE1BQU0sQ0FBQ3NNLElBQUksQ0FBQ2YsSUFBSSxDQUFDMk8sY0FBYyxDQUFDLENBQUNqZSxNQUFNLENBQUUvRyxHQUFHLElBQUssQ0FBQ3FXLElBQUksQ0FBQzJPLGNBQWMsQ0FBQ2hsQixHQUFHLENBQUMsQ0FBQzhsQixXQUFXLENBQUMsQ0FBQzlvQixNQUFNOztNQUVwSDtNQUNBLElBQUltcEIsYUFBYSxJQUFJOVAsSUFBSSxDQUFDOE8sY0FBYyxFQUFFO1FBQ3RDemYsWUFBWSxDQUFDMlEsSUFBSSxDQUFDNE8sY0FBYyxDQUFDO1FBQ2pDNU8sSUFBSSxDQUFDNE8sY0FBYyxHQUFHLElBQUk7UUFDMUI1TyxJQUFJLENBQUMrUCxvQkFBb0IsQ0FBQyxDQUFDO01BQy9CLENBQUMsTUFBTTtRQUNIO1FBQ0ExZ0IsWUFBWSxDQUFDMlEsSUFBSSxDQUFDNE8sY0FBYyxDQUFDO1FBQ2pDNU8sSUFBSSxDQUFDNE8sY0FBYyxHQUFHL2dCLFVBQVUsQ0FBQyxNQUFNO1VBQ25DbVMsSUFBSSxDQUFDK1Asb0JBQW9CLENBQUMsQ0FBQztRQUMvQixDQUFDLEVBQUUvUCxJQUFJLENBQUMrRyxXQUFXLENBQUM7TUFDeEI7SUFDSixDQUFDLENBQUM7RUFDTjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtFQUNJLGFBQWFxSSxZQUFZQSxDQUFDdFAsVUFBVSxFQUFFQyxNQUFNLEVBQWU7SUFBQSxJQUFiTixNQUFNLEdBQUFwWCxTQUFBLENBQUExQixNQUFBLFFBQUEwQixTQUFBLFFBQUFDLFNBQUEsR0FBQUQsU0FBQSxNQUFHLENBQUMsQ0FBQztJQUNyRDtJQUNBLE1BQU1vVixHQUFHLEdBQUcsVUFBVXFDLFVBQVUsSUFBSUMsTUFBTSxFQUFFOztJQUU1QztJQUNBLElBQUksT0FBT3BhLFFBQVEsS0FBSyxXQUFXLElBQUlBLFFBQVEsQ0FBQ0MsYUFBYSxFQUFFO01BQzNERCxRQUFRLENBQUNDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsV0FBV2thLFVBQVUsSUFBSUMsTUFBTSxjQUFjLEVBQUVOLE1BQU0sQ0FBQztJQUN6RjtJQUVBLE9BQU8sSUFBSTVTLE9BQU8sQ0FBQyxDQUFDSCxPQUFPLEVBQUVDLE1BQU0sS0FBSztNQUNwQzdJLENBQUMsQ0FBQzBaLElBQUksQ0FBQztRQUNIQyxHQUFHLEVBQUVBLEdBQUc7UUFDUkMsTUFBTSxFQUFFLE1BQU07UUFDZHRFLElBQUksRUFBRXFHLE1BQU07UUFDWjlCLFFBQVEsRUFBRSxNQUFNO1FBQ2hCZ04sbUJBQW1CLEVBQUUsSUFBSTtRQUFFO1FBQzNCcUYsT0FBTyxFQUFHelMsUUFBUSxJQUFLO1VBQ25CO1VBQ0EsSUFBSUEsUUFBUSxDQUFDM1gsYUFBYSxJQUFJeUgsS0FBSyxDQUFDaUQsT0FBTyxDQUFDaU4sUUFBUSxDQUFDM1gsYUFBYSxDQUFDLEVBQUU7WUFDakUyWCxRQUFRLENBQUMzWCxhQUFhLENBQUMySyxPQUFPLENBQUUwVCxHQUFHLElBQUs7Y0FDcEMsSUFBSSxDQUFDNVcsS0FBSyxDQUFDaUQsT0FBTyxDQUFDMlQsR0FBRyxDQUFDLElBQUlBLEdBQUcsQ0FBQ3RkLE1BQU0sS0FBSyxDQUFDLEVBQUU7Z0JBQ3pDLE1BQU0sSUFBSTRCLEtBQUssQ0FBQyx3RUFBd0UsQ0FBQztjQUM3RjtjQUNBLE1BQU0sQ0FBQzBLLE9BQU8sRUFBRTdGLElBQUksQ0FBQyxHQUFHNlcsR0FBRztjQUMzQmxiLE9BQU8sQ0FBQzZSLEdBQUcsQ0FBQzNILE9BQU8sRUFBRSxHQUFHN0YsSUFBSSxDQUFDO1lBQ2pDLENBQUMsQ0FBQztVQUNOOztVQUVBO1VBQ0EsSUFBSW1RLFFBQVEsQ0FBQzBTLFFBQVEsS0FBSyxJQUFJLEVBQUU7WUFDNUI7WUFDQSxNQUFNQyxlQUFlLEdBQUdqVCxZQUFZLENBQUNXLDZCQUE2QixDQUFDTCxRQUFRLENBQUM0UyxrQkFBa0IsQ0FBQztZQUMvRnpqQixPQUFPLENBQUN3akIsZUFBZSxDQUFDO1VBQzVCLENBQUMsTUFBTTtZQUNIO1lBQ0EsTUFBTUUsVUFBVSxHQUFHN1MsUUFBUSxDQUFDNlMsVUFBVSxJQUFJLGVBQWU7WUFDekQsTUFBTXJULE1BQU0sR0FBR1EsUUFBUSxDQUFDUixNQUFNLElBQUksd0JBQXdCO1lBQzFELE1BQU1zRixPQUFPLEdBQUc5RSxRQUFRLENBQUM4RSxPQUFPLElBQUksQ0FBQyxDQUFDOztZQUV0QztZQUNBLFFBQVErTixVQUFVO2NBQ2QsS0FBSyxPQUFPO2dCQUNSO2dCQUNBLE1BQU1DLGdCQUFnQixHQUFHOVMsUUFBUSxDQUFDelYsS0FBSyxJQUFJLENBQUMsQ0FBQztnQkFDN0MsTUFBTW9iLGFBQWEsR0FBR21OLGdCQUFnQixDQUFDdm9CLEtBQUssSUFBSSxzQkFBc0I7Z0JBRXRFaUIsT0FBTyxDQUFDakIsS0FBSyxDQUFDLGtDQUFrQyxFQUFFeVYsUUFBUSxDQUFDelYsS0FBSyxDQUFDO2dCQUVqRSxNQUFNd29CLFdBQVcsR0FBRyxJQUFJL25CLEtBQUssQ0FBQzJhLGFBQWEsQ0FBQztnQkFDNUNvTixXQUFXLENBQUM3UCxJQUFJLEdBQUcsT0FBTztnQkFDMUI2UCxXQUFXLENBQUNqTyxPQUFPLEdBQUc5RSxRQUFRLENBQUN6VixLQUFLOztnQkFFcEM7Z0JBQ0FuQyxRQUFRLENBQUMyZ0IsU0FBUyxDQUFDO2tCQUNmbGUsT0FBTyxFQUFFLHFCQUFxQjhhLGFBQWEsRUFBRTtrQkFDN0N6QyxJQUFJLEVBQUUsWUFBWTtrQkFDbEI4UCxRQUFRLEVBQUU5UyxHQUFHO2tCQUNiNEUsT0FBTyxFQUFFOUUsUUFBUSxDQUFDelY7Z0JBQ3RCLENBQUMsQ0FBQztnQkFFRjZFLE1BQU0sQ0FBQzJqQixXQUFXLENBQUM7Z0JBQ25CO2NBRUosS0FBSyx3QkFBd0I7Z0JBQ3pCdm5CLE9BQU8sQ0FBQ2pCLEtBQUssQ0FDVCx5R0FDSixDQUFDO2dCQUNELE1BQU0wb0IsVUFBVSxHQUFHLElBQUlqb0IsS0FBSyxDQUFDd1UsTUFBTSxDQUFDO2dCQUNwQ3lULFVBQVUsQ0FBQy9QLElBQUksR0FBRyxlQUFlO2dCQUNqQytQLFVBQVUsQ0FBQ25PLE9BQU8sR0FBR0EsT0FBTztnQkFDNUIxVixNQUFNLENBQUM2akIsVUFBVSxDQUFDO2dCQUNsQjtjQUVKLEtBQUssdUJBQXVCO2dCQUN4QnpuQixPQUFPLENBQUNqQixLQUFLLENBQ1QscUhBQ0osQ0FBQztnQkFDRCxNQUFNMm9CLFlBQVksR0FBRyxJQUFJbG9CLEtBQUssQ0FBQ3dVLE1BQU0sQ0FBQztnQkFDdEMwVCxZQUFZLENBQUNoUSxJQUFJLEdBQUcsY0FBYztnQkFDbENnUSxZQUFZLENBQUNwTyxPQUFPLEdBQUdBLE9BQU87Z0JBQzlCMVYsTUFBTSxDQUFDOGpCLFlBQVksQ0FBQztnQkFDcEI7Y0FFSixLQUFLLHFCQUFxQjtnQkFDdEIsTUFBTUMsVUFBVSxHQUFHLElBQUlub0IsS0FBSyxDQUFDd1UsTUFBTSxDQUFDO2dCQUNwQzJULFVBQVUsQ0FBQ2pRLElBQUksR0FBRyxZQUFZO2dCQUM5QmlRLFVBQVUsQ0FBQ3JPLE9BQU8sR0FBR0EsT0FBTztnQkFDNUIxVixNQUFNLENBQUMrakIsVUFBVSxDQUFDO2dCQUNsQjtjQUVKO2dCQUNJLE1BQU1DLGFBQWEsR0FBRyxJQUFJcG9CLEtBQUssQ0FBQ3dVLE1BQU0sQ0FBQztnQkFDdkM0VCxhQUFhLENBQUNsUSxJQUFJLEdBQUcyUCxVQUFVO2dCQUMvQk8sYUFBYSxDQUFDdE8sT0FBTyxHQUFHQSxPQUFPO2dCQUMvQjFWLE1BQU0sQ0FBQ2drQixhQUFhLENBQUM7Z0JBQ3JCO1lBQ1I7VUFDSjtRQUNKLENBQUM7UUFDRDdvQixLQUFLLEVBQUVBLENBQUM4b0IsR0FBRyxFQUFFMW9CLE1BQU0sRUFBRUosS0FBSyxLQUFLO1VBQzNCLE1BQU1vYixhQUFhLEdBQUdsRCxJQUFJLENBQUM2USxzQkFBc0IsQ0FBQ0QsR0FBRyxDQUFDO1VBQ3RELE1BQU1FLGFBQWEsR0FBRyxJQUFJdm9CLEtBQUssQ0FBQzJhLGFBQWEsQ0FBQztVQUM5QzROLGFBQWEsQ0FBQ3JRLElBQUksR0FBRyxlQUFlO1VBQ3BDcVEsYUFBYSxDQUFDNW9CLE1BQU0sR0FBRzBvQixHQUFHLENBQUMxb0IsTUFBTTtVQUNqQzRvQixhQUFhLENBQUNDLFVBQVUsR0FBRzdvQixNQUFNOztVQUVqQztVQUNBLElBQUkwb0IsR0FBRyxDQUFDMW9CLE1BQU0sSUFBSSxHQUFHLEVBQUU7WUFDbkJ2QyxRQUFRLENBQUMyZ0IsU0FBUyxDQUFDO2NBQ2ZsZSxPQUFPLEVBQUUscUJBQXFCd29CLEdBQUcsQ0FBQzFvQixNQUFNLEtBQUtnYixhQUFhLEVBQUU7Y0FDNUR6QyxJQUFJLEVBQUUsbUJBQW1CO2NBQ3pCOFAsUUFBUSxFQUFFOVMsR0FBRztjQUNidlYsTUFBTSxFQUFFMG9CLEdBQUcsQ0FBQzFvQixNQUFNO2NBQ2xCNm9CLFVBQVUsRUFBRTdvQjtZQUNoQixDQUFDLENBQUM7VUFDTjtVQUVBeUUsTUFBTSxDQUFDbWtCLGFBQWEsQ0FBQztRQUN6QjtNQUNKLENBQUMsQ0FBQztJQUNOLENBQUMsQ0FBQztFQUNOOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksYUFBYWYsb0JBQW9CQSxDQUFBLEVBQUc7SUFDaEM7SUFDQSxNQUFNaUIsYUFBYSxHQUFHLEVBQUU7SUFDeEIsTUFBTUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7O0lBRXJCLEtBQUssTUFBTTNCLFFBQVEsSUFBSXRQLElBQUksQ0FBQzJPLGNBQWMsRUFBRTtNQUN4QyxNQUFNa0IsWUFBWSxHQUFHN1AsSUFBSSxDQUFDMk8sY0FBYyxDQUFDVyxRQUFRLENBQUM7TUFFbEQsSUFBSSxDQUFDTyxZQUFZLENBQUNKLFdBQVcsRUFBRTtRQUMzQnVCLGFBQWEsQ0FBQ2puQixJQUFJLENBQUM7VUFDZjZsQixPQUFPLEVBQUVDLFlBQVksQ0FBQ0QsT0FBTztVQUM3QjlQLFVBQVUsRUFBRStQLFlBQVksQ0FBQy9QLFVBQVU7VUFDbkNDLE1BQU0sRUFBRThQLFlBQVksQ0FBQzlQLE1BQU07VUFDM0JOLE1BQU0sRUFBRW9RLFlBQVksQ0FBQ3BRO1FBQ3pCLENBQUMsQ0FBQztRQUVGd1IsUUFBUSxDQUFDcEIsWUFBWSxDQUFDRCxPQUFPLENBQUMsR0FBR0MsWUFBWTtNQUNqRDtJQUNKOztJQUVBO0lBQ0EsSUFBSW1CLGFBQWEsQ0FBQ3JxQixNQUFNLEtBQUssQ0FBQyxFQUFFO01BQzVCO0lBQ0o7O0lBRUE7SUFDQSxJQUFJLE9BQU9oQixRQUFRLEtBQUssV0FBVyxJQUFJQSxRQUFRLENBQUNDLGFBQWEsRUFBRTtNQUMzREQsUUFBUSxDQUFDQyxhQUFhLENBQ2xCLFlBQVksRUFDWixvQkFBb0JvckIsYUFBYSxDQUFDcnFCLE1BQU0sUUFBUSxFQUNoRHFxQixhQUFhLENBQUN2ZCxHQUFHLENBQUVPLENBQUMsSUFBSyxHQUFHQSxDQUFDLENBQUM4TCxVQUFVLElBQUk5TCxDQUFDLENBQUMrTCxNQUFNLEVBQUUsQ0FDMUQsQ0FBQztJQUNMO0lBRUEsSUFBSTtNQUNBO01BQ0EsTUFBTXhDLFFBQVEsR0FBRyxNQUFNelosQ0FBQyxDQUFDMFosSUFBSSxDQUFDO1FBQzFCQyxHQUFHLEVBQUUsZUFBZTtRQUNwQkMsTUFBTSxFQUFFLE1BQU07UUFDZHRFLElBQUksRUFBRTtVQUFFOFgsV0FBVyxFQUFFem5CLElBQUksQ0FBQ0MsU0FBUyxDQUFDc25CLGFBQWE7UUFBRSxDQUFDO1FBQ3BEclQsUUFBUSxFQUFFLE1BQU07UUFDaEJnTixtQkFBbUIsRUFBRSxJQUFJLENBQUU7TUFDL0IsQ0FBQyxDQUFDOztNQUVGO01BQ0E7TUFDQSxLQUFLLE1BQU13RyxZQUFZLElBQUk1VCxRQUFRLEVBQUU7UUFDakMsSUFBSSxDQUFDNFQsWUFBWSxDQUFDNVgsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFO1VBQ2hDO1FBQ0o7UUFFQSxNQUFNcVcsT0FBTyxHQUFHemQsUUFBUSxDQUFDZ2YsWUFBWSxDQUFDMVgsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUN2RCxNQUFNMlgsYUFBYSxHQUFHN1QsUUFBUSxDQUFDNFQsWUFBWSxDQUFDO1FBQzVDLE1BQU10QixZQUFZLEdBQUdvQixRQUFRLENBQUNyQixPQUFPLENBQUM7UUFFdEMsSUFBSSxDQUFDQyxZQUFZLEVBQUU7VUFDZjltQixPQUFPLENBQUNqQixLQUFLLENBQUMsd0NBQXdDLEVBQUU4bkIsT0FBTyxDQUFDO1VBQ2hFO1FBQ0o7O1FBRUE7UUFDQSxJQUFJd0IsYUFBYSxDQUFDeHJCLGFBQWEsSUFBSXlILEtBQUssQ0FBQ2lELE9BQU8sQ0FBQzhnQixhQUFhLENBQUN4ckIsYUFBYSxDQUFDLEVBQUU7VUFDM0V3ckIsYUFBYSxDQUFDeHJCLGFBQWEsQ0FBQzJLLE9BQU8sQ0FBRTBULEdBQUcsSUFBSztZQUN6QyxJQUFJLENBQUM1VyxLQUFLLENBQUNpRCxPQUFPLENBQUMyVCxHQUFHLENBQUMsSUFBSUEsR0FBRyxDQUFDdGQsTUFBTSxLQUFLLENBQUMsRUFBRTtjQUN6QyxNQUFNLElBQUk0QixLQUFLLENBQUMsd0VBQXdFLENBQUM7WUFDN0Y7WUFDQSxNQUFNLENBQUMwSyxPQUFPLEVBQUU3RixJQUFJLENBQUMsR0FBRzZXLEdBQUc7WUFDM0JsYixPQUFPLENBQUM2UixHQUFHLENBQUMzSCxPQUFPLEVBQUUsR0FBRzdGLElBQUksQ0FBQztVQUNqQyxDQUFDLENBQUM7UUFDTjs7UUFFQTtRQUNBeWlCLFlBQVksQ0FBQ0osV0FBVyxHQUFHLElBQUk7O1FBRS9CO1FBQ0EsSUFBSTJCLGFBQWEsQ0FBQ25CLFFBQVEsS0FBSyxJQUFJLEVBQUU7VUFDakM7VUFDQSxNQUFNQyxlQUFlLEdBQUdqVCxZQUFZLENBQUNXLDZCQUE2QixDQUFDd1QsYUFBYSxDQUFDakIsa0JBQWtCLENBQUM7VUFDcEdOLFlBQVksQ0FBQzNnQixNQUFNLEdBQUdnaEIsZUFBZTs7VUFFckM7VUFDQUwsWUFBWSxDQUFDRixTQUFTLENBQUNwZixPQUFPLENBQUNrYyxJQUFBLElBQWlCO1lBQUEsSUFBaEI7Y0FBRS9mO1lBQVEsQ0FBQyxHQUFBK2YsSUFBQTtZQUN2Qy9mLE9BQU8sQ0FBQ3dqQixlQUFlLENBQUM7VUFDNUIsQ0FBQyxDQUFDO1FBQ04sQ0FBQyxNQUFNO1VBQ0g7VUFDQSxNQUFNRSxVQUFVLEdBQUdnQixhQUFhLENBQUNoQixVQUFVLElBQUksZUFBZTtVQUM5RCxJQUFJbE4sYUFBYTtVQUNqQixJQUFJbU8sYUFBYTtVQUVqQixJQUFJakIsVUFBVSxLQUFLLE9BQU8sSUFBSWdCLGFBQWEsQ0FBQ3RwQixLQUFLLEVBQUU7WUFDL0M7WUFDQSxNQUFNdW9CLGdCQUFnQixHQUFHZSxhQUFhLENBQUN0cEIsS0FBSztZQUM1Q29iLGFBQWEsR0FBR21OLGdCQUFnQixDQUFDdm9CLEtBQUssSUFBSSxzQkFBc0I7WUFDaEV1cEIsYUFBYSxHQUFHRCxhQUFhLENBQUN0cEIsS0FBSztZQUVuQ2lCLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyxrQ0FBa0MsRUFBRXNwQixhQUFhLENBQUN0cEIsS0FBSyxDQUFDO1VBQzFFLENBQUMsTUFBTTtZQUNIO1lBQ0FvYixhQUFhLEdBQUdrTyxhQUFhLENBQUNyVSxNQUFNLElBQUksd0JBQXdCO1lBQ2hFc1UsYUFBYSxHQUFHRCxhQUFhLENBQUMvTyxPQUFPLElBQUksQ0FBQyxDQUFDO1VBQy9DO1VBRUEsTUFBTXZhLEtBQUssR0FBRyxJQUFJUyxLQUFLLENBQUMyYSxhQUFhLENBQUM7VUFDdENwYixLQUFLLENBQUMyWSxJQUFJLEdBQUcyUCxVQUFVO1VBQ3ZCdG9CLEtBQUssQ0FBQ3VhLE9BQU8sR0FBR2dQLGFBQWE7VUFFN0J4QixZQUFZLENBQUNILFFBQVEsR0FBRyxJQUFJO1VBQzVCRyxZQUFZLENBQUMvbkIsS0FBSyxHQUFHQSxLQUFLOztVQUUxQjtVQUNBK25CLFlBQVksQ0FBQ0YsU0FBUyxDQUFDcGYsT0FBTyxDQUFDK2dCLEtBQUEsSUFBZ0I7WUFBQSxJQUFmO2NBQUUza0I7WUFBTyxDQUFDLEdBQUEya0IsS0FBQTtZQUN0QzNrQixNQUFNLENBQUM3RSxLQUFLLENBQUM7VUFDakIsQ0FBQyxDQUFDO1FBQ047TUFDSjtJQUNKLENBQUMsQ0FBQyxPQUFPeXBCLFNBQVMsRUFBRTtNQUNoQjtNQUNBLE1BQU1yTyxhQUFhLEdBQUdsRCxJQUFJLENBQUM2USxzQkFBc0IsQ0FBQ1UsU0FBUyxDQUFDO01BQzVELE1BQU16cEIsS0FBSyxHQUFHLElBQUlTLEtBQUssQ0FBQzJhLGFBQWEsQ0FBQztNQUN0Q3BiLEtBQUssQ0FBQzJZLElBQUksR0FBRyxlQUFlO01BRTVCLEtBQUssTUFBTW1QLE9BQU8sSUFBSXFCLFFBQVEsRUFBRTtRQUM1QixNQUFNcEIsWUFBWSxHQUFHb0IsUUFBUSxDQUFDckIsT0FBTyxDQUFDO1FBQ3RDQyxZQUFZLENBQUNKLFdBQVcsR0FBRyxJQUFJO1FBQy9CSSxZQUFZLENBQUNILFFBQVEsR0FBRyxJQUFJO1FBQzVCRyxZQUFZLENBQUMvbkIsS0FBSyxHQUFHQSxLQUFLO1FBRTFCK25CLFlBQVksQ0FBQ0YsU0FBUyxDQUFDcGYsT0FBTyxDQUFDaWhCLEtBQUEsSUFBZ0I7VUFBQSxJQUFmO1lBQUU3a0I7VUFBTyxDQUFDLEdBQUE2a0IsS0FBQTtVQUN0QzdrQixNQUFNLENBQUM3RSxLQUFLLENBQUM7UUFDakIsQ0FBQyxDQUFDO01BQ047TUFFQWlCLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyw0QkFBNEIsRUFBRW9iLGFBQWEsQ0FBQztJQUM5RDtFQUNKOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT3FNLGtCQUFrQkEsQ0FBQ3pQLFVBQVUsRUFBRUMsTUFBTSxFQUFFTixNQUFNLEVBQUU7SUFDbEQ7SUFDQTtJQUNBLE1BQU1nUyxhQUFhLEdBQUcsQ0FBQyxDQUFDO0lBQ3hCaGQsTUFBTSxDQUFDc00sSUFBSSxDQUFDdEIsTUFBTSxDQUFDLENBQ2QxVSxJQUFJLENBQUMsQ0FBQyxDQUNOd0YsT0FBTyxDQUFFNUcsR0FBRyxJQUFLO01BQ2Q4bkIsYUFBYSxDQUFDOW5CLEdBQUcsQ0FBQyxHQUFHOFYsTUFBTSxDQUFDOVYsR0FBRyxDQUFDO0lBQ3BDLENBQUMsQ0FBQztJQUVOLE9BQU8sR0FBR21XLFVBQVUsS0FBS0MsTUFBTSxLQUFLdFcsSUFBSSxDQUFDQyxTQUFTLENBQUMrbkIsYUFBYSxDQUFDLEVBQUU7RUFDdkU7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7RUFDSSxPQUFPWixzQkFBc0JBLENBQUNELEdBQUcsRUFBRTtJQUMvQixJQUFJQSxHQUFHLENBQUNjLFlBQVksSUFBSWQsR0FBRyxDQUFDYyxZQUFZLENBQUN0cEIsT0FBTyxFQUFFO01BQzlDLE9BQU93b0IsR0FBRyxDQUFDYyxZQUFZLENBQUN0cEIsT0FBTztJQUNuQyxDQUFDLE1BQU0sSUFBSXdvQixHQUFHLENBQUNlLFlBQVksRUFBRTtNQUN6QixJQUFJO1FBQ0EsTUFBTXBVLFFBQVEsR0FBRzlULElBQUksQ0FBQ3VKLEtBQUssQ0FBQzRkLEdBQUcsQ0FBQ2UsWUFBWSxDQUFDO1FBQzdDLElBQUlwVSxRQUFRLENBQUNuVixPQUFPLEVBQUU7VUFDbEIsT0FBT21WLFFBQVEsQ0FBQ25WLE9BQU87UUFDM0I7TUFDSixDQUFDLENBQUMsT0FBTzJRLENBQUMsRUFBRTtRQUNSO01BQUE7SUFFUjtJQUVBLE9BQU8sR0FBRzZYLEdBQUcsQ0FBQzFvQixNQUFNLEtBQUswb0IsR0FBRyxDQUFDRyxVQUFVLElBQUksZUFBZSxFQUFFO0VBQ2hFOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBTzlRLDZCQUE2QkEsQ0FBQ3hDLEdBQUcsRUFBRTtJQUN0QztJQUNBLElBQUlBLEdBQUcsSUFBSSxPQUFPQSxHQUFHLEtBQUssUUFBUSxJQUFJQSxHQUFHLENBQUN5UixJQUFJLEVBQUU7TUFDNUN6UixHQUFHLEdBQUdBLEdBQUcsQ0FBQ3lSLElBQUk7SUFDbEIsQ0FBQyxNQUFNLElBQUl6UixHQUFHLElBQUksT0FBT0EsR0FBRyxLQUFLLFVBQVUsSUFBSUEsR0FBRyxDQUFDeVIsSUFBSSxFQUFFO01BQ3JEelIsR0FBRyxHQUFHQSxHQUFHLENBQUN5UixJQUFJO0lBQ2xCOztJQUVBO0lBQ0EsSUFBSSxPQUFPelIsR0FBRyxLQUFLLFFBQVEsRUFBRTtNQUN6QixNQUFNLElBQUlsVixLQUFLLENBQUMsdURBQXVELE9BQU9rVixHQUFHLEVBQUUsQ0FBQztJQUN4RjtJQUVBLElBQUksQ0FBQ0EsR0FBRyxDQUFDbEUsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUNrRSxHQUFHLENBQUNsRSxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUU7TUFDckQsTUFBTSxJQUFJaFIsS0FBSyxDQUFDLDBDQUEwQ2tWLEdBQUcsRUFBRSxDQUFDO0lBQ3BFO0lBRUEsTUFBTXhJLEtBQUssR0FBR3dJLEdBQUcsQ0FBQy9VLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQ2dJLE1BQU0sQ0FBRXlFLElBQUksSUFBS0EsSUFBSSxLQUFLLEVBQUUsQ0FBQztJQUUxRCxJQUFJRixLQUFLLENBQUN0TyxNQUFNLEdBQUcsQ0FBQyxFQUFFO01BQ2xCLE1BQU0sSUFBSTRCLEtBQUssQ0FBQywrQkFBK0JrVixHQUFHLEVBQUUsQ0FBQztJQUN6RDtJQUVBLElBQUl4SSxLQUFLLENBQUN0TyxNQUFNLEdBQUcsQ0FBQyxFQUFFO01BQ2xCLE1BQU0sSUFBSTRCLEtBQUssQ0FBQyxtQ0FBbUNrVixHQUFHLEVBQUUsQ0FBQztJQUM3RDtJQUVBLE1BQU1xQyxVQUFVLEdBQUc3SyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzNCLE1BQU04SyxNQUFNLEdBQUc5SyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTztJQUVsQyxPQUFPO01BQUU2SyxVQUFVO01BQUVDO0lBQU8sQ0FBQztFQUNqQzs7RUFFQTtBQUNKO0FBQ0E7RUFDSSxPQUFPakYsY0FBY0EsQ0FBQSxFQUFHO0lBQ3BCa0YsSUFBSSxDQUFDdEgsdUJBQXVCLENBQUMsQ0FBQztFQUNsQztBQUNKOzs7Ozs7QUM1ZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNa1osZ0JBQWdCLFNBQVNDLHNCQUFzQixDQUFDOztBQUV0RDs7Ozs7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1DLGtCQUFrQixDQUFDO0VBQ3JCO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFPQyw0QkFBNEJBLENBQUEsRUFBRztJQUNsQyxJQUFJQyxpQkFBaUIsR0FBRzNjLFFBQVEsQ0FBQ3FCLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQztJQUVsRTlRLGFBQWEsQ0FBQyxhQUFhLEVBQUUsY0FBYyxHQUFHb3NCLGlCQUFpQixDQUFDcnJCLE1BQU0sR0FBRyxvQkFBb0IsQ0FBQztJQUU5RixLQUFLLElBQUlzckIsU0FBUyxJQUFJRCxpQkFBaUIsRUFBRTtNQUNyQ0UsTUFBTSxDQUFDQyxrQkFBa0IsQ0FBQ0YsU0FBUyxDQUFDdGMsVUFBVSxFQUFFc2MsU0FBUyxDQUFDdmMsWUFBWSxDQUFDO0lBQzNFO0VBQ0o7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0ksT0FBTzBjLDBCQUEwQkEsQ0FBQ0MsTUFBTSxFQUFFO0lBQ3RDLE1BQU1DLFlBQVksR0FBRyxDQUFDRCxNQUFNO0lBQzVCLE1BQU01aEIsUUFBUSxHQUFHLEVBQUU7SUFDbkIsTUFBTThoQix1QkFBdUIsR0FBRyxDQUFDRixNQUFNLElBQUl2dUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFeWQsSUFBSSxDQUFDLHdCQUF3QixDQUFDO0lBQ3BGLElBQUlnUix1QkFBdUIsQ0FBQzVyQixNQUFNLEdBQUcsQ0FBQyxFQUFFO01BQ3BDZixhQUFhLENBQUMsYUFBYSxFQUFFLGdCQUFnQjJzQix1QkFBdUIsQ0FBQzVyQixNQUFNLGlCQUFpQixDQUFDO0lBQ2pHO0lBRUE0ckIsdUJBQXVCLENBQUMxckIsSUFBSSxDQUFDLFlBQVk7TUFDckMsTUFBTStZLFFBQVEsR0FBRzliLENBQUMsQ0FBQyxJQUFJLENBQUM7O01BRXhCO01BQ0E7TUFDQSxJQUFJLENBQUMrVSxRQUFRLENBQUMyWixRQUFRLENBQUM1UyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUNqQztNQUNKOztNQUVBO01BQ0EsSUFBSTNhLE1BQU0sR0FBRzJhLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQ2lKLGFBQWE7TUFDdEMsT0FBTzVqQixNQUFNLEVBQUU7UUFDWCxJQUFJQSxNQUFNLENBQUN3dEIsU0FBUyxDQUFDRCxRQUFRLENBQUMsdUJBQXVCLENBQUMsRUFBRTtVQUNwRCxPQUFPLENBQUM7UUFDWjtRQUNBdnRCLE1BQU0sR0FBR0EsTUFBTSxDQUFDNGpCLGFBQWE7TUFDakM7TUFFQSxNQUFNNkosY0FBYyxHQUFHOVMsUUFBUSxDQUFDMUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDOztNQUVoRTtNQUNBLElBQUl5WixjQUFjLEdBQUcsQ0FBQyxDQUFDO01BQ3ZCLE1BQU1DLFdBQVcsR0FBR2hULFFBQVEsQ0FBQzFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQzs7TUFFeEQ7TUFDQTtNQUNBO01BQ0EwRyxRQUFRLENBQUNpVCxVQUFVLENBQUMsMEJBQTBCLENBQUM7TUFDL0NqVCxRQUFRLENBQUNpVCxVQUFVLENBQUMscUJBQXFCLENBQUM7TUFDMUNqVCxRQUFRLENBQUNrVCxVQUFVLENBQUMscUJBQXFCLENBQUM7TUFDMUNsVCxRQUFRLENBQUNrVCxVQUFVLENBQUMsZ0JBQWdCLENBQUM7TUFFckMsSUFBSUYsV0FBVyxFQUFFO1FBQ2IsSUFBSTtVQUNBRCxjQUFjLEdBQUdscEIsSUFBSSxDQUFDdUosS0FBSyxDQUFDNGYsV0FBVyxDQUFDO1FBQzVDLENBQUMsQ0FBQyxPQUFPN1osQ0FBQyxFQUFFO1VBQ1JoUSxPQUFPLENBQUNqQixLQUFLLENBQUMsMkRBQTJENHFCLGNBQWMsR0FBRyxFQUFFM1osQ0FBQyxDQUFDO1VBQzlGNFosY0FBYyxHQUFHLENBQUMsQ0FBQztRQUN2QjtNQUNKO01BRUEsSUFBSUQsY0FBYyxFQUFFO1FBQ2hCO1FBQ0EsSUFBSUssdUJBQXVCLEdBQUcsQ0FBQyxDQUFDO1FBQ2hDLEtBQUssTUFBTSxDQUFDcHBCLEdBQUcsRUFBRWxHLEtBQUssQ0FBQyxJQUFJZ1IsTUFBTSxDQUFDK1gsT0FBTyxDQUFDbUcsY0FBYyxDQUFDLEVBQUU7VUFDdkQ7VUFDQTtVQUNBO1VBQ0EsSUFBSWhwQixHQUFHLENBQUM0UCxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDekJ3Wix1QkFBdUIsQ0FBQ3BwQixHQUFHLENBQUM4UCxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBR2hXLEtBQUs7VUFDckQsQ0FBQyxNQUFNO1lBQ0hzdkIsdUJBQXVCLENBQUNwcEIsR0FBRyxDQUFDLEdBQUdsRyxLQUFLO1VBQ3hDO1FBQ0o7UUFFQSxJQUFJO1VBQ0E7VUFDQXN2Qix1QkFBdUIsQ0FBQ0MsV0FBVyxHQUFHcFQsUUFBUSxDQUFDdk4sSUFBSSxDQUFDLENBQUM7VUFDckR1TixRQUFRLENBQUMvTixLQUFLLENBQUMsQ0FBQzs7VUFFaEI7VUFDQStOLFFBQVEsQ0FBQzRDLFdBQVcsQ0FBQyx1QkFBdUIsQ0FBQzs7VUFFN0M7VUFDQSxNQUFNeVEsaUJBQWlCLEdBQUcsSUFBSXBtQixPQUFPLENBQUVILE9BQU8sSUFBSztZQUMvQztZQUNBO1lBQ0E7WUFDQSxJQUFJdWxCLFNBQVMsR0FBR3JTLFFBQVEsQ0FBQ3FTLFNBQVMsQ0FBQ1MsY0FBYyxFQUFFSyx1QkFBdUIsQ0FBQztZQUUzRWQsU0FBUyxDQUFDblosRUFBRSxDQUFDLFFBQVEsRUFBRSxZQUFZO2NBQy9COztjQUVBOztjQUVBLE1BQU1vYSxlQUFlLEdBQUdwQixrQkFBa0IsQ0FBQ00sMEJBQTBCLENBQUNILFNBQVMsQ0FBQ251QixDQUFDLENBQUM7Y0FDbEYyTSxRQUFRLENBQUMxRyxJQUFJLENBQUMsR0FBR21wQixlQUFlLENBQUM7O2NBRWpDO2NBQ0F4bUIsT0FBTyxDQUFDLENBQUM7WUFDYixDQUFDLENBQUMsQ0FBQzVJLENBQUM7VUFDUixDQUFDLENBQUM7VUFFRjJNLFFBQVEsQ0FBQzFHLElBQUksQ0FBQ2twQixpQkFBaUIsQ0FBQztRQUNwQyxDQUFDLENBQUMsT0FBT25yQixLQUFLLEVBQUU7VUFDWmlCLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyx1REFBdUQ0cUIsY0FBYyxHQUFHLEVBQUU1cUIsS0FBSyxDQUFDO1VBQzlGaUIsT0FBTyxDQUFDakIsS0FBSyxDQUFDLGdCQUFnQixFQUFFQSxLQUFLLENBQUNVLEtBQUssSUFBSVYsS0FBSyxDQUFDO1FBQ3pEO01BQ0o7SUFDSixDQUFDLENBQUM7O0lBRUY7SUFDQSxJQUFJd3FCLFlBQVksRUFBRTtNQUNkLENBQUMsWUFBWTtRQUNULE1BQU16bEIsT0FBTyxDQUFDOEQsR0FBRyxDQUFDRixRQUFRLENBQUM7UUFDM0IsTUFBTStMLEdBQUcsQ0FBQ2tRLHFCQUFxQixDQUFDLGlCQUFpQixDQUFDO1FBQ2xEbFEsR0FBRyxDQUFDd0YsT0FBTyxDQUFDLGNBQWMsQ0FBQztNQUMvQixDQUFDLEVBQUUsQ0FBQztNQUNKO0lBQ0o7O0lBRUE7SUFDQSxPQUFPdlIsUUFBUTtFQUNuQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU8waUIsbUJBQW1CQSxDQUFBLEVBQUc7SUFDekIsT0FBT2pCLE1BQU0sQ0FBQ2lCLG1CQUFtQixDQUFDLENBQUM7RUFDdkM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9DLGFBQWFBLENBQUNscUIsSUFBSSxFQUFFO0lBQ3ZCLE9BQU9ncEIsTUFBTSxDQUFDa0IsYUFBYSxDQUFDbHFCLElBQUksQ0FBQztFQUNyQztBQUNKOztBQUVBOzs7O0FDaktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRyIsImZpbGUiOiJidW5kbGVfb3V0cHV0X0Jvb3RzdHJhcDVfQnVuZGxlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTlBNIEltcG9ydCBEZWNsYXJhdGlvbnMgZm9yIEFwcCBCdW5kbGVcbi8vIEF1dG8tZ2VuZXJhdGVkIHRvIHByb3ZpZGUgTlBNIG1vZHVsZXMgdG8gYXBwIGJ1bmRsZSBzY29wZVxuLy8gQ2FjaGUga2V5OiA5NWE2ZjYwMmM5ODAzNzYxMWI2NDBiMGI1MzQyODMwYlxuXG5jb25zdCBqcWh0bWwgPSB3aW5kb3cuX3JzeF9ucG0uanFodG1sO1xuaWYgKCFqcWh0bWwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdSU1ggRnJhbWV3b3JrIEVycm9yOiBOUE0gbW9kdWxlIFwianFodG1sXCIgbm90IGZvdW5kLlxcbicgK1xuICAgICAgICAnRXhwZWN0ZWQgd2luZG93Ll9yc3hfbnBtLmpxaHRtbCB0byBiZSBkZWZpbmVkIGJ5IHRoZSB2ZW5kb3IgYnVuZGxlLidcbiAgICApO1xufVxuXG5jb25zdCBfQmFzZV9KcWh0bWxfQ29tcG9uZW50ID0gd2luZG93Ll9yc3hfbnBtLl9CYXNlX0pxaHRtbF9Db21wb25lbnQ7XG5pZiAoIV9CYXNlX0pxaHRtbF9Db21wb25lbnQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdSU1ggRnJhbWV3b3JrIEVycm9yOiBOUE0gbW9kdWxlIFwiX0Jhc2VfSnFodG1sX0NvbXBvbmVudFwiIG5vdCBmb3VuZC5cXG4nICtcbiAgICAgICAgJ0V4cGVjdGVkIHdpbmRvdy5fcnN4X25wbS5fQmFzZV9KcWh0bWxfQ29tcG9uZW50IHRvIGJlIGRlZmluZWQgYnkgdGhlIHZlbmRvciBidW5kbGUuJ1xuICAgICk7XG59XG5cbi8vIENsZWFuIHVwIE5QTSBjb250YWluZXIgdG8gcHJldmVudCBjb25zb2xlIGFjY2Vzc1xuZGVsZXRlIHdpbmRvdy5fcnN4X25wbTtcbiIsIi8qKlxuICogRGVjb3JhdG9yIGZ1bmN0aW9uIHRoYXQgbWFya3MgYSBmdW5jdGlvbiBhcyBhIGRlY29yYXRvciBpbXBsZW1lbnRhdGlvbi5cbiAqXG4gKiBXaGVuIGEgZnVuY3Rpb24gaGFzIEBkZWNvcmF0b3IgaW4gaXRzIEpTRG9jIGNvbW1lbnQsIGl0IHdoaXRlbGlzdHMgdGhhdCBmdW5jdGlvblxuICogdG8gYmUgdXNlZCBhcyBhIGRlY29yYXRvciBvbiBvdGhlciBtZXRob2RzIHRocm91Z2hvdXQgdGhlIGNvZGViYXNlLlxuICpcbiAqIFRoZSBmdW5jdGlvbiBpdHNlbGYgcGVyZm9ybXMgbm8gb3BlcmF0aW9uIC0gaXQgc2ltcGx5IHJldHVybnMgaXRzIGlucHV0IHVuY2hhbmdlZC5cbiAqIEl0cyBwdXJwb3NlIGlzIHB1cmVseSBhcyBhIG1hcmtlciBmb3IgdGhlIG1hbmlmZXN0IHZhbGlkYXRpb24gc3lzdGVtLlxuICpcbiAqIFVzYWdlOlxuICogICAvLyAvKipcbiAqICAgLy8gICogTXkgY3VzdG9tIGRlY29yYXRvciBpbXBsZW1lbnRhdGlvblxuICogICAvLyAgKiBAZGVjb3JhdG9yXG4gKiAgIC8vICAqXFwvXG4gKiAgIGZ1bmN0aW9uIG15X2N1c3RvbV9kZWNvcmF0b3IodGFyZ2V0LCBrZXksIGRlc2NyaXB0b3IpIHtcbiAqICAgICAgIC8vIERlY29yYXRvciBpbXBsZW1lbnRhdGlvblxuICogICB9XG4gKlxuICogVGhpcyBhbGxvd3MgbXlfY3VzdG9tX2RlY29yYXRvciB0byBiZSB1c2VkIGFzIEBteV9jdXN0b21fZGVjb3JhdG9yIG9uIHN0YXRpYyBtZXRob2RzLlxuICpcbiAqIFRPRE86IFRoaXMgaXMgcHJvYmFibHkgbm8gbG9uZ2VyIG5lY2Vzc2FyeT8gbWF5YmU/XG4gKi9cbmZ1bmN0aW9uIGRlY29yYXRvcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbn1cbiIsIi8qXG4gKiBCcm93c2VyIGFuZCBET00gdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBSU3BhZGUgZnJhbWV3b3JrLlxuICogVGhlc2UgZnVuY3Rpb25zIGhhbmRsZSBicm93c2VyIGRldGVjdGlvbiwgdmlld3BvcnQgdXRpbGl0aWVzLCBhbmQgRE9NIG1hbmlwdWxhdGlvbi5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBCUk9XU0VSIERFVEVDVElPTlxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIERldGVjdHMgaWYgdXNlciBpcyBvbiBhIG1vYmlsZSBkZXZpY2Ugb3IgdXNpbmcgbW9iaWxlIHZpZXdwb3J0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBtb2JpbGUgZGV2aWNlIG9yIHZpZXdwb3J0IDwgOTkycHhcbiAqIEB0b2RvIEltcHJvdmUgdXNlciBhZ2VudCBkZXRlY3Rpb24gZm9yIGFsbCBtb2JpbGUgZGV2aWNlc1xuICovXG5mdW5jdGlvbiBpc19tb2JpbGUoKSB7XG4gICAgaWYgKC9BbmRyb2lkfHdlYk9TfGlQaG9uZXxpUGFkfGlQb2R8QmxhY2tCZXJyeXxJRU1vYmlsZXxPcGVyYSBNaW5pL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKCQod2luZG93KS53aWR0aCgpIDwgOTkyKSB7XG4gICAgICAgIC8vIDk5MnB4ID0gYm9vdHN0cmFwIDQgY29sLW1kLVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuXG4vKipcbiAqIERldGVjdHMgaWYgdXNlciBpcyBvbiBkZXNrdG9wIChub3QgbW9iaWxlKVxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgbm90IG1vYmlsZSBkZXZpY2Uvdmlld3BvcnRcbiAqL1xuZnVuY3Rpb24gaXNfZGVza3RvcCgpIHtcbiAgICByZXR1cm4gIWlzX21vYmlsZSgpO1xufVxuXG4vKipcbiAqIERldGVjdHMgdGhlIHVzZXIncyBvcGVyYXRpbmcgc3lzdGVtXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBPUyBuYW1lOiAnTWFjIE9TJywgJ2lQaG9uZScsICdpUGFkJywgJ1dpbmRvd3MnLCAnQW5kcm9pZC1QaG9uZScsICdBbmRyb2lkLVRhYmxldCcsICdMaW51eCcsIG9yICdVbmtub3duJ1xuICovXG5mdW5jdGlvbiBnZXRfb3MoKSB7XG4gICAgbGV0IHVzZXJfYWdlbnQgPSB3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgcGxhdGZvcm0gPSB3aW5kb3cubmF2aWdhdG9yLnBsYXRmb3JtLFxuICAgICAgICBtYWNvc19wbGF0Zm9ybXMgPSBbJ01hY2ludG9zaCcsICdNYWNJbnRlbCcsICdNYWNQUEMnLCAnTWFjNjhLJ10sXG4gICAgICAgIHdpbmRvd3NfcGxhdGZvcm1zID0gWydXaW4zMicsICdXaW42NCcsICdXaW5kb3dzJywgJ1dpbkNFJ10sXG4gICAgICAgIGlvc19wbGF0Zm9ybXMgPSBbJ2lQaG9uZScsICdpUGFkJywgJ2lQb2QnXSxcbiAgICAgICAgb3MgPSBudWxsO1xuXG4gICAgbGV0IGlzX21vYmlsZV9kZXZpY2UgPSBpc19tb2JpbGUoKTtcblxuICAgIGlmIChtYWNvc19wbGF0Zm9ybXMuaW5kZXhPZihwbGF0Zm9ybSkgIT09IC0xKSB7XG4gICAgICAgIG9zID0gJ01hYyBPUyc7XG4gICAgfSBlbHNlIGlmIChpb3NfcGxhdGZvcm1zLmluZGV4T2YocGxhdGZvcm0pICE9PSAtMSAmJiBpc19tb2JpbGVfZGV2aWNlKSB7XG4gICAgICAgIG9zID0gJ2lQaG9uZSc7XG4gICAgfSBlbHNlIGlmIChpb3NfcGxhdGZvcm1zLmluZGV4T2YocGxhdGZvcm0pICE9PSAtMSAmJiAhaXNfbW9iaWxlX2RldmljZSkge1xuICAgICAgICBvcyA9ICdpUGFkJztcbiAgICB9IGVsc2UgaWYgKHdpbmRvd3NfcGxhdGZvcm1zLmluZGV4T2YocGxhdGZvcm0pICE9PSAtMSkge1xuICAgICAgICBvcyA9ICdXaW5kb3dzJztcbiAgICB9IGVsc2UgaWYgKC9BbmRyb2lkLy50ZXN0KHVzZXJfYWdlbnQpICYmIGlzX21vYmlsZV9kZXZpY2UpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZC1QaG9uZSc7XG4gICAgfSBlbHNlIGlmICgvQW5kcm9pZC8udGVzdCh1c2VyX2FnZW50KSAmJiAhaXNfbW9iaWxlX2RldmljZSkge1xuICAgICAgICBvcyA9ICdBbmRyb2lkLVRhYmxldCc7XG4gICAgfSBlbHNlIGlmICghb3MgJiYgL0xpbnV4Ly50ZXN0KHBsYXRmb3JtKSkge1xuICAgICAgICBvcyA9ICdMaW51eCc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3MgPSAnVW5rbm93bic7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9zO1xufVxuXG4vKipcbiAqIERldGVjdHMgaWYgdGhlIHVzZXIgYWdlbnQgaXMgYSB3ZWIgY3Jhd2xlci9ib3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHVzZXIgYWdlbnQgYXBwZWFycyB0byBiZSBhIGJvdC9jcmF3bGVyXG4gKi9cbmZ1bmN0aW9uIGlzX2NyYXdsZXIoKSB7XG4gICAgbGV0IHVzZXJfYWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICAgIGxldCBib3RfcGF0dGVybiA9IC9ib3R8c3BpZGVyfGNyYXdsfHNsdXJwfGFyY2hpdmVyfHBpbmd8c2VhcmNofGRpZ3x0cmFja2VyfG1vbml0b3J8c25vb3B5fHlhaG9vfGJhaWR1fG1zbnxhc2t8dGVvbWF8YXhpb3MvaTtcblxuICAgIHJldHVybiBib3RfcGF0dGVybi50ZXN0KHVzZXJfYWdlbnQpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBET00gU0NST0xMSU5HIFVUSUxJVElFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFNjcm9sbHMgcGFyZW50IGNvbnRhaW5lciB0byBtYWtlIHRhcmdldCBlbGVtZW50IHZpc2libGUgaWYgbmVlZGVkXG4gKiBAcGFyYW0ge3N0cmluZ3xIVE1MRWxlbWVudHxqUXVlcnl9IHRhcmdldCAtIFRhcmdldCBlbGVtZW50IHRvIHNjcm9sbCBpbnRvIHZpZXdcbiAqL1xuZnVuY3Rpb24gc2Nyb2xsX2ludG9fdmlld19pZl9uZWVkZWQodGFyZ2V0KSB7XG4gICAgY29uc3QgJHRhcmdldCA9ICQodGFyZ2V0KTtcblxuICAgIC8vIEZpbmQgdGhlIGNsb3Nlc3QgcGFyZW50IHdpdGggb3ZlcmZsb3cteTogYXV0b1xuICAgIGNvbnN0ICRwYXJlbnQgPSAkdGFyZ2V0LnBhcmVudCgpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBhYnNvbHV0ZSB0b3AgcG9zaXRpb24gb2YgdGhlIHRhcmdldFxuICAgIGNvbnN0IHRhcmdldF90b3AgPSAkdGFyZ2V0LnBvc2l0aW9uKCkudG9wICsgJHBhcmVudC5zY3JvbGxUb3AoKTtcblxuICAgIGNvbnN0IHRhcmdldF9oZWlnaHQgPSAkdGFyZ2V0Lm91dGVySGVpZ2h0KCk7XG4gICAgY29uc3QgcGFyZW50X2hlaWdodCA9ICRwYXJlbnQuaGVpZ2h0KCk7XG4gICAgY29uc3Qgc2Nyb2xsX3Bvc2l0aW9uID0gJHBhcmVudC5zY3JvbGxUb3AoKTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB0YXJnZXQgaXMgb3V0IG9mIHZpZXdcbiAgICBpZiAodGFyZ2V0X3RvcCA8IHNjcm9sbF9wb3NpdGlvbiB8fCB0YXJnZXRfdG9wICsgdGFyZ2V0X2hlaWdodCA+IHNjcm9sbF9wb3NpdGlvbiArIHBhcmVudF9oZWlnaHQpIHtcbiAgICAgICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZygnVUknLCAnU2Nyb2xsaW5nIScsIHRhcmdldF90b3ApO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbmV3IHNjcm9sbCBwb3NpdGlvbiB0byBjZW50ZXIgdGhlIHRhcmdldFxuICAgICAgICBsZXQgbmV3X3Njcm9sbF9wb3NpdGlvbiA9IHRhcmdldF90b3AgKyB0YXJnZXRfaGVpZ2h0IC8gMiAtIHBhcmVudF9oZWlnaHQgLyAyO1xuXG4gICAgICAgIC8vIExpbWl0IHRoZSBzY3JvbGwgcG9zaXRpb24gYmV0d2VlbiAwIGFuZCB0aGUgbWF4aW11bSBzY3JvbGxhYmxlIGhlaWdodFxuICAgICAgICBuZXdfc2Nyb2xsX3Bvc2l0aW9uID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obmV3X3Njcm9sbF9wb3NpdGlvbiwgJHBhcmVudFswXS5zY3JvbGxIZWlnaHQgLSBwYXJlbnRfaGVpZ2h0KSk7XG5cbiAgICAgICAgLy8gU2Nyb2xsIHRoZSBwYXJlbnQgdG8gdGhlIG5ldyBzY3JvbGwgcG9zaXRpb25cbiAgICAgICAgJHBhcmVudC5zY3JvbGxUb3AobmV3X3Njcm9sbF9wb3NpdGlvbik7XG4gICAgfVxufVxuXG4vKipcbiAqIFNjcm9sbHMgcGFnZSB0byBtYWtlIHRhcmdldCBlbGVtZW50IHZpc2libGUgaWYgbmVlZGVkICh3aXRoIGFuaW1hdGlvbilcbiAqIEBwYXJhbSB7c3RyaW5nfEhUTUxFbGVtZW50fGpRdWVyeX0gdGFyZ2V0IC0gVGFyZ2V0IGVsZW1lbnQgdG8gc2Nyb2xsIGludG8gdmlld1xuICovXG5mdW5jdGlvbiBzY3JvbGxfcGFnZV9pbnRvX3ZpZXdfaWZfbmVlZGVkKHRhcmdldCkge1xuICAgIGNvbnN0ICR0YXJnZXQgPSAkKHRhcmdldCk7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGFic29sdXRlIHRvcCBwb3NpdGlvbiBvZiB0aGUgdGFyZ2V0IHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudFxuICAgIGNvbnN0IHRhcmdldF90b3AgPSAkdGFyZ2V0Lm9mZnNldCgpLnRvcDtcblxuICAgIGNvbnN0IHRhcmdldF9oZWlnaHQgPSAkdGFyZ2V0Lm91dGVySGVpZ2h0KCk7XG4gICAgY29uc3Qgd2luZG93X2hlaWdodCA9ICQod2luZG93KS5oZWlnaHQoKTtcbiAgICBjb25zdCB3aW5kb3dfc2Nyb2xsX3Bvc2l0aW9uID0gJCh3aW5kb3cpLnNjcm9sbFRvcCgpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHRhcmdldCBpcyBvdXQgb2Ygdmlld1xuICAgIGlmICh0YXJnZXRfdG9wIDwgd2luZG93X3Njcm9sbF9wb3NpdGlvbiB8fCB0YXJnZXRfdG9wICsgdGFyZ2V0X2hlaWdodCA+IHdpbmRvd19zY3JvbGxfcG9zaXRpb24gKyB3aW5kb3dfaGVpZ2h0KSB7XG4gICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoJ1VJJywgJ1Njcm9sbGluZyEnLCB0YXJnZXRfdG9wKTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG5ldyBzY3JvbGwgcG9zaXRpb24gdG8gY2VudGVyIHRoZSB0YXJnZXRcbiAgICAgICAgY29uc3QgbmV3X3Njcm9sbF9wb3NpdGlvbiA9IHRhcmdldF90b3AgKyB0YXJnZXRfaGVpZ2h0IC8gMiAtIHdpbmRvd19oZWlnaHQgLyAyO1xuXG4gICAgICAgIC8vIEFuaW1hdGUgdGhlIHNjcm9sbCB0byB0aGUgbmV3IHBvc2l0aW9uXG4gICAgICAgICQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHNjcm9sbFRvcDogbmV3X3Njcm9sbF9wb3NpdGlvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAxMDAwXG4gICAgICAgICk7IC8vIGR1cmF0aW9uIG9mIHRoZSBzY3JvbGwgYW5pbWF0aW9uIGluIG1pbGxpc2Vjb25kc1xuICAgIH1cbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRE9NIFVUSUxJVElFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFdhaXRzIGZvciBhbGwgaW1hZ2VzIG9uIHRoZSBwYWdlIHRvIGxvYWRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIC0gRnVuY3Rpb24gdG8gY2FsbCB3aGVuIGFsbCBpbWFnZXMgYXJlIGxvYWRlZFxuICovXG5mdW5jdGlvbiB3YWl0X2Zvcl9pbWFnZXMoY2FsbGJhY2spIHtcbiAgICBjb25zdCAkaW1hZ2VzID0gJCgnaW1nJyk7IC8vIEdldCBhbGwgaW1nIHRhZ3NcbiAgICBjb25zdCB0b3RhbF9pbWFnZXMgPSAkaW1hZ2VzLmxlbmd0aDtcbiAgICBsZXQgaW1hZ2VzX2xvYWRlZCA9IDA7XG5cbiAgICBpZiAodG90YWxfaW1hZ2VzID09PSAwKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7IC8vIGlmIHRoZXJlIGFyZSBubyBpbWFnZXMsIGltbWVkaWF0ZWx5IGNhbGwgdGhlIGNhbGxiYWNrXG4gICAgfVxuXG4gICAgJGltYWdlcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7XG4gICAgICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpbWFnZXNfbG9hZGVkKys7XG4gICAgICAgICAgICBpZiAoaW1hZ2VzX2xvYWRlZCA9PT0gdG90YWxfaW1hZ2VzKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTsgLy8gY2FsbCB0aGUgY2FsbGJhY2sgd2hlbiBhbGwgaW1hZ2VzIGFyZSBsb2FkZWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaW1nLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpbWFnZXNfbG9hZGVkKys7XG4gICAgICAgICAgICBpZiAoaW1hZ2VzX2xvYWRlZCA9PT0gdG90YWxfaW1hZ2VzKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTsgLy8gYWxzbyBjYWxsIHRoZSBjYWxsYmFjayBpZiBhbiBpbWFnZSBmYWlscyB0byBsb2FkXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGltZy5zcmMgPSB0aGlzLnNyYzsgLy8gdGhpcyB0cmlnZ2VycyB0aGUgbG9hZGluZ1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBqUXVlcnkgZWxlbWVudCBjb250YWluaW5nIGEgbm9uLWJyZWFraW5nIHNwYWNlXG4gKiBAcmV0dXJucyB7alF1ZXJ5fSBqUXVlcnkgc3BhbiBlbGVtZW50IHdpdGggJm5ic3A7XG4gKi9cbmZ1bmN0aW9uICRuYnNwKCkge1xuICAgIHJldHVybiAkKCc8c3Bhbj4mbmJzcDs8L3NwYW4+Jyk7XG59XG5cbi8qKlxuICogRXNjYXBlcyBzcGVjaWFsIGNoYXJhY3RlcnMgaW4gYSBqUXVlcnkgc2VsZWN0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIEVsZW1lbnQgSUQgdG8gZXNjYXBlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBqUXVlcnkgc2VsZWN0b3Igc3RyaW5nIHdpdGggZXNjYXBlZCBzcGVjaWFsIGNoYXJhY3RlcnNcbiAqIEB3YXJuaW5nIE5vdCBzYWZlIGZvciBzZWN1cml0eS1jcml0aWNhbCBvcGVyYXRpb25zXG4gKi9cbmZ1bmN0aW9uIGVzY2FwZV9qcV9zZWxlY3RvcihpZCkge1xuICAgIHJldHVybiAnIycgKyBpZC5yZXBsYWNlKC8oOnxcXC58XFxbfFxcXXwsfD18QCkvZywgJ1xcXFwkMScpO1xufSIsIi8qXG4gKiBEYXRlIGFuZCB0aW1lIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgZGF0ZS90aW1lIGNvbnZlcnNpb25zIGFuZCBVbml4IHRpbWVzdGFtcHMuXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gREFURS9USU1FIFVUSUxJVElFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgVW5peCB0aW1lc3RhbXAgKHNlY29uZHMgc2luY2UgZXBvY2gpXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBDdXJyZW50IFVuaXggdGltZXN0YW1wIGluIHNlY29uZHNcbiAqIEB0b2RvIENhbGN1bGF0ZSBiYXNlZCBvbiBzZXJ2ZXIgdGltZSBhdCBwYWdlIHJlbmRlclxuICogQHRvZG8gTW92ZSB0byBhIGRhdGUgbGlicmFyeVxuICovXG5mdW5jdGlvbiB1bml4X3RpbWUoKSB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIGRhdGUgc3RyaW5nIHRvIFVuaXggdGltZXN0YW1wXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyX2RhdGUgLSBEYXRlIHN0cmluZyAoWS1tLWQgSDppOnMgZm9ybWF0KVxuICogQHJldHVybnMge251bWJlcn0gVW5peCB0aW1lc3RhbXAgaW4gc2Vjb25kc1xuICovXG5mdW5jdGlvbiB5bWRoaXNfdG9fdW5peChzdHJfZGF0ZSkge1xuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShzdHJfZGF0ZSk7XG4gICAgcmV0dXJuIGRhdGUuZ2V0VGltZSgpIC8gMTAwMDtcbn0iLCIvKlxuICogRXJyb3IgaGFuZGxpbmcgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBSU3BhZGUgZnJhbWV3b3JrLlxuICogVGhlc2UgZnVuY3Rpb25zIGhhbmRsZSBlcnJvciBjcmVhdGlvbiBhbmQgZGVidWdnaW5nIHV0aWxpdGllcy5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFUlJPUiBIQU5ETElOR1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gZXJyb3Igb2JqZWN0IGZyb20gYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfE9iamVjdH0gc3RyIC0gRXJyb3IgbWVzc2FnZSBvciBleGlzdGluZyBlcnJvciBvYmplY3RcbiAqIEBwYXJhbSB7bnVtYmVyfSBbZXJyb3JfY29kZV0gLSBPcHRpb25hbCBlcnJvciBzdGF0dXMgY29kZVxuICogQHJldHVybnMge09iamVjdH0gRXJyb3Igb2JqZWN0IHdpdGggZXJyb3IgYW5kIHN0YXR1cyBwcm9wZXJ0aWVzXG4gKi9cbmZ1bmN0aW9uIGVycm9yKHN0ciwgZXJyb3JfY29kZSkge1xuICAgIGlmICh0eXBlb2Ygc3RyLmVycm9yICE9IHVuZGVmKSB7XG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvcl9jb2RlID09IHVuZGVmKSB7XG4gICAgICAgICAgICByZXR1cm4geyBlcnJvcjogc3RyLCBzdGF0dXM6IG51bGwgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB7IGVycm9yOiBzdHIsIHN0YXR1czogZXJyb3JfY29kZSB9O1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFNhbml0eSBjaGVjayBmYWlsdXJlIGhhbmRsZXIgZm9yIEphdmFTY3JpcHRcbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHNob3VsZCBiZSBjYWxsZWQgd2hlbiBhIHNhbml0eSBjaGVjayBmYWlscyAtIGkuZS4sIHdoZW4gdGhlIGNvZGVcbiAqIGVuY291bnRlcnMgYSBjb25kaXRpb24gdGhhdCBcInNob3VsZG4ndCBoYXBwZW5cIiBpZiBldmVyeXRoaW5nIGlzIHdvcmtpbmcgY29ycmVjdGx5LlxuICpcbiAqIFVubGlrZSBQSFAsIHdlIGNhbid0IHN0b3AgSmF2YVNjcmlwdCBleGVjdXRpb24sIGJ1dCB3ZSBjYW46XG4gKiAxLiBUaHJvdyBhbiBlcnJvciB0aGF0IHdpbGwgYmUgY2F1Z2h0IGJ5IGVycm9yIGhhbmRsZXJzXG4gKiAyLiBMb2cgYSBjbGVhciBlcnJvciB0byB0aGUgY29uc29sZVxuICogMy4gUHJvdmlkZSBzdGFjayB0cmFjZSBmb3IgZGVidWdnaW5nXG4gKlxuICogVXNlIHRoaXMgaW5zdGVhZCBvZiBzaWxlbnRseSByZXR1cm5pbmcgb3IgY29udGludWluZyB3aGVuIGVuY291bnRlcmluZyB1bmV4cGVjdGVkIGNvbmRpdGlvbnMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgT3B0aW9uYWwgc3BlY2lmaWMgbWVzc2FnZSBhYm91dCB3aGF0IHNob3VsZG4ndCBoYXZlIGhhcHBlbmVkXG4gKiBAdGhyb3dzIHtFcnJvcn0gQWx3YXlzIHRocm93cyB3aXRoIGxvY2F0aW9uIGFuZCBjb250ZXh0IGluZm9ybWF0aW9uXG4gKi9cbmZ1bmN0aW9uIHNob3VsZG50X2hhcHBlbihtZXNzYWdlID0gbnVsbCkge1xuICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKCk7XG4gICAgY29uc3Qgc3RhY2sgPSBlcnJvci5zdGFjayB8fCAnJztcbiAgICBjb25zdCBzdGFja0xpbmVzID0gc3RhY2suc3BsaXQoJ1xcbicpO1xuXG4gICAgLy8gR2V0IHRoZSBjYWxsZXIgbG9jYXRpb24gKHNraXAgdGhlIEVycm9yIGxpbmUgYW5kIHRoaXMgZnVuY3Rpb24pXG4gICAgbGV0IGNhbGxlckluZm8gPSAndW5rbm93biBsb2NhdGlvbic7XG4gICAgaWYgKHN0YWNrTGluZXMubGVuZ3RoID4gMikge1xuICAgICAgICBjb25zdCBjYWxsZXJMaW5lID0gc3RhY2tMaW5lc1syXSB8fCBzdGFja0xpbmVzWzFdIHx8ICcnO1xuICAgICAgICAvLyBFeHRyYWN0IGZpbGUgYW5kIGxpbmUgbnVtYmVyIGZyb20gc3RhY2sgdHJhY2VcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBjYWxsZXJMaW5lLm1hdGNoKC9hdFxccysuKj9cXHMrXFwoKC4qPyk6KFxcZCspOihcXGQrKVxcKS8pIHx8IGNhbGxlckxpbmUubWF0Y2goL2F0XFxzKyguKj8pOihcXGQrKTooXFxkKykvKTtcbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICBjYWxsZXJJbmZvID0gYCR7bWF0Y2hbMV19OiR7bWF0Y2hbMl19YDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxldCBlcnJvck1lc3NhZ2UgPSBgRmF0YWw6IHNob3VsZG50X2hhcHBlbigpIHdhcyBjYWxsZWQgYXQgJHtjYWxsZXJJbmZvfVxcbmA7XG4gICAgZXJyb3JNZXNzYWdlICs9ICdUaGlzIGluZGljYXRlcyBhIHNhbml0eSBjaGVjayBmYWlsZWQgLSB0aGUgY29kZSBpcyBub3QgYmVoYXZpbmcgYXMgZXhwZWN0ZWQuXFxuJztcblxuICAgIGlmIChtZXNzYWdlKSB7XG4gICAgICAgIGVycm9yTWVzc2FnZSArPSBgRGV0YWlsczogJHttZXNzYWdlfVxcbmA7XG4gICAgfVxuXG4gICAgZXJyb3JNZXNzYWdlICs9ICdQbGVhc2UgdGhvcm91Z2hseSByZXZpZXcgdGhlIHJlbGF0ZWQgY29kZSB0byBkZXRlcm1pbmUgd2h5IHRoaXMgZXJyb3Igb2NjdXJyZWQuJztcblxuICAgIC8vIExvZyB0byBjb25zb2xlIHdpdGggZnVsbCB2aXNpYmlsaXR5XG4gICAgY29uc29sZS5lcnJvcignPScucmVwZWF0KDgwKSk7XG4gICAgY29uc29sZS5lcnJvcignU0FOSVRZIENIRUNLIEZBSUxVUkUnKTtcbiAgICBjb25zb2xlLmVycm9yKCc9Jy5yZXBlYXQoODApKTtcbiAgICBjb25zb2xlLmVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgY29uc29sZS5lcnJvcignU3RhY2sgdHJhY2U6Jywgc3RhY2spO1xuICAgIGNvbnNvbGUuZXJyb3IoJz0nLnJlcGVhdCg4MCkpO1xuXG4gICAgLy8gVGhyb3cgZXJyb3IgdG8gc3RvcCBleGVjdXRpb24gZmxvd1xuICAgIGNvbnN0IGZhdGFsRXJyb3IgPSBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgICBmYXRhbEVycm9yLm5hbWUgPSAnU2FuaXR5Q2hlY2tGYWlsdXJlJztcbiAgICB0aHJvdyBmYXRhbEVycm9yO1xufSIsIi8qXG4gKiBIYXNoaW5nIGFuZCBjb21wYXJpc29uIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgb2JqZWN0IGhhc2hpbmcgYW5kIGRlZXAgY29tcGFyaXNvbi5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBIQVNISU5HIEFORCBDT01QQVJJU09OXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgdW5pcXVlIGhhc2ggZm9yIGFueSB2YWx1ZSAoaGFuZGxlcyBvYmplY3RzLCBhcnJheXMsIGNpcmN1bGFyIHJlZmVyZW5jZXMpXG4gKiBAcGFyYW0geyp9IHRoZV92YXIgLSBWYWx1ZSB0byBoYXNoXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtjYWxjX3NoYTE9dHJ1ZV0gLSBJZiB0cnVlLCByZXR1cm5zIFNIQTEgaGFzaDsgaWYgZmFsc2UsIHJldHVybnMgSlNPTlxuICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBbaWdub3JlZF9rZXlzPW51bGxdIC0gS2V5cyB0byBpZ25vcmUgd2hlbiBoYXNoaW5nIG9iamVjdHNcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFNIQTEgaGFzaCBvciBKU09OIHN0cmluZyBvZiB0aGUgdmFsdWVcbiAqL1xuZnVuY3Rpb24gaGFzaCh0aGVfdmFyLCBjYWxjX3NoYTEgPSB0cnVlLCBpZ25vcmVkX2tleXMgPSBudWxsKSB7XG4gICAgaWYgKHR5cGVvZiB0aGVfdmFyID09IHVuZGVmKSB7XG4gICAgICAgIHRoZV92YXIgPSAnX191bmRlZmluZWRfXyc7XG4gICAgfVxuXG4gICAgaWYgKGlnbm9yZWRfa2V5cyA9PT0gbnVsbCkge1xuICAgICAgICBpZ25vcmVkX2tleXMgPSBbJyQnXTtcbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0cyB2YWx1ZSB0byBqc29uLCBkaXNjYXJkaW5nIGNpcmN1bGFyIHJlZmVyZW5jZXNcbiAgICBsZXQganNvbl9zdHJpbmdpZnlfbm9jaXJjID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGNhY2hlID0gW107XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSwgZnVuY3Rpb24gKGtleSwgdikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB2ID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgdGhlX3Zhci5fY2FjaGVfa2V5ID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhlX3Zhci5faGFzaF9rZXkoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHYgPT09ICdvYmplY3QnICYmIHYgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoY2FjaGUuaW5kZXhPZih2KSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRHVwbGljYXRlIHJlZmVyZW5jZSBmb3VuZCwgZGlzY2FyZCBrZXlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWNoZS5wdXNoKHYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyBUdXJuIGV2ZXJ5IHByb3BlcnR5IGFuZCBhbGwgaXRzIGNoaWxkcmVuIGludG8gYSBzaW5nbGUgZGVwdGggYXJyYXkgb2YgdmFsdWVzIHRoYXQgd2UgY2FuIHRoZW5cbiAgICAvLyBzb3J0IGFuZCBoYXNoIGFzIGEgd2hvbGVcbiAgICBsZXQgZmxhdF92YXIgPSB7fTtcbiAgICBsZXQgX2ZsYXR0ZW4gPSBmdW5jdGlvbiAodGhlX3ZhciwgcHJlZml4LCBkZXB0aCA9IDApIHtcbiAgICAgICAgLy8gSWYgYSBjbGFzcyBvYmplY3QgaXMgcHJvdmlkZWQsIGNpcmN1bGFyIHJlZmVyZW5jZXMgY2FuIG1ha2UgdGhlIGNhbGwgc3RhY2sgcmVjdXJzaXZlLlxuICAgICAgICAvLyBGb3IgdGhlIHB1cnBvc2VzIG9mIGhvdyB0aGUgaGFzaCBmdW5jdGlvbiBpcyBjYWxsZWQsIHRoaXMgc2hvdWxkIGJlIHN1ZmZpY2llbnQuXG4gICAgICAgIGlmIChkZXB0aCA+IDEwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEb2VzIG5vdCBhY2NvdW50IGZvciBkYXRlcyBpIHRoaW5rLi4uXG5cbiAgICAgICAgaWYgKGlzX29iamVjdCh0aGVfdmFyKSAmJiB0eXBlb2YgdGhlX3Zhci5fY2FjaGVfa2V5ID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIC8vIFVzZSBfY2FjaGVfa2V5IHRvIGhhc2ggY29tcG9uZW50c1xuICAgICAgICAgICAgZmxhdF92YXJbcHJlZml4XSA9IHRoZV92YXIuX2hhc2hfa2V5KCk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNfb2JqZWN0KHRoZV92YXIpICYmIHR5cGVvZiBBYnN0cmFjdCAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhlX3ZhciBpbnN0YW5jZW9mIEFic3RyYWN0KSB7XG4gICAgICAgICAgICAvLyBTdHJpbmdpZnkgYWxsIGNsYXNzIG9iamVjdHNcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSBqc29uX3N0cmluZ2lmeV9ub2NpcmModGhlX3Zhcik7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNfb2JqZWN0KHRoZV92YXIpKSB7XG4gICAgICAgICAgICAvLyBJdGVyYXRlIG90aGVyIG9iamVjdHNcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSB7fTtcbiAgICAgICAgICAgIGZvciAobGV0IGsgaW4gdGhlX3Zhcikge1xuICAgICAgICAgICAgICAgIGlmICh0aGVfdmFyLmhhc093blByb3BlcnR5KGspICYmIGlnbm9yZWRfa2V5cy5pbmRleE9mKGspID09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIF9mbGF0dGVuKHRoZV92YXJba10sIHByZWZpeCArICcuLicgKyBrLCBkZXB0aCArIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChpc19hcnJheSh0aGVfdmFyKSkge1xuICAgICAgICAgICAgLy8gSXRlcmF0ZSBhcnJheXNcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSBbXTtcbiAgICAgICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgICAgIGZvcmVhY2godGhlX3ZhciwgKHYpID0+IHtcbiAgICAgICAgICAgICAgICBfZmxhdHRlbih2LCBwcmVmaXggKyAnLi4nICsgaSwgZGVwdGggKyAxKTtcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChpc19mdW5jdGlvbih0aGVfdmFyKSkge1xuICAgICAgICAgICAgLy8gbm90aGluZ1xuICAgICAgICB9IGVsc2UgaWYgKCFpc19udW1lcmljKHRoZV92YXIpKSB7XG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0gU3RyaW5nKHRoZV92YXIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZmxhdF92YXJbcHJlZml4XSA9IHRoZV92YXI7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgX2ZsYXR0ZW4odGhlX3ZhciwgJ18nKTtcblxuICAgIGxldCBzb3J0ZXIgPSBbXTtcblxuICAgIGZvcmVhY2goZmxhdF92YXIsIGZ1bmN0aW9uICh2LCBrKSB7XG4gICAgICAgIHNvcnRlci5wdXNoKFtrLCB2XSk7XG4gICAgfSk7XG5cbiAgICBzb3J0ZXIuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gYVswXSA+IGJbMF07XG4gICAgfSk7XG5cbiAgICBsZXQganNvbiA9IEpTT04uc3RyaW5naWZ5KHNvcnRlcik7XG5cbiAgICBpZiAoY2FsY19zaGExKSB7XG4gICAgICAgIGxldCBoYXNoZWQgPSBzaGExLnNoYTEoanNvbik7XG4gICAgICAgIHJldHVybiBoYXNoZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGpzb247XG4gICAgfVxufVxuXG4vKipcbiAqIERlZXAgY29tcGFyaXNvbiBvZiB0d28gdmFsdWVzIChpZ25vcmVzIHByb3BlcnR5IG9yZGVyIGFuZCBmdW5jdGlvbnMpXG4gKiBAcGFyYW0geyp9IGEgLSBGaXJzdCB2YWx1ZSB0byBjb21wYXJlXG4gKiBAcGFyYW0geyp9IGIgLSBTZWNvbmQgdmFsdWUgdG8gY29tcGFyZVxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWVzIGFyZSBkZWVwbHkgZXF1YWxcbiAqL1xuZnVuY3Rpb24gZGVlcF9lcXVhbChhLCBiKSB7XG4gICAgcmV0dXJuIGhhc2goYSwgZmFsc2UpID09IGhhc2goYiwgZmFsc2UpO1xufSIsIi8qKlxuICogTXV0ZXggZGVjb3JhdG9yIGZvciBleGNsdXNpdmUgbWV0aG9kIGV4ZWN1dGlvblxuICpcbiAqIFdpdGhvdXQgYXJndW1lbnRzOiBQZXItaW5zdGFuY2UgbG9ja2luZyAoZWFjaCBvYmplY3QgaGFzIGl0cyBvd24gbG9jayBwZXIgbWV0aG9kKVxuICogICBAbXV0ZXhcbiAqICAgYXN5bmMgbXlfbWV0aG9kKCkgeyAuLi4gfVxuICpcbiAqIFdpdGggSUQgYXJndW1lbnQ6IEdsb2JhbCBsb2NraW5nIGJ5IElEIChhbGwgaW5zdGFuY2VzIHNoYXJlIHRoZSBsb2NrKVxuICogICBAbXV0ZXgoJ29wZXJhdGlvbl9uYW1lJylcbiAqICAgYXN5bmMgbXlfbWV0aG9kKCkgeyAuLi4gfVxuICpcbiAqIEBkZWNvcmF0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBbZ2xvYmFsX2lkXSAtIE9wdGlvbmFsIGdsb2JhbCBtdXRleCBJRCBmb3IgY3Jvc3MtaW5zdGFuY2UgbG9ja2luZ1xuICovXG5mdW5jdGlvbiBtdXRleChnbG9iYWxfaWQpIHtcbiAgICAvLyBTdG9yYWdlICh1c2luZyBJSUZFcyB0byBrZWVwIFdlYWtNYXAvTWFwIGluIGNsb3N1cmUgc2NvcGUpXG4gICAgY29uc3QgaW5zdGFuY2VfbXV0ZXhlcyA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCFtdXRleC5faW5zdGFuY2Vfc3RvcmFnZSkge1xuICAgICAgICAgICAgbXV0ZXguX2luc3RhbmNlX3N0b3JhZ2UgPSBuZXcgV2Vha01hcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtdXRleC5faW5zdGFuY2Vfc3RvcmFnZTtcbiAgICB9KSgpO1xuXG4gICAgY29uc3QgZ2xvYmFsX211dGV4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghbXV0ZXguX2dsb2JhbF9zdG9yYWdlKSB7XG4gICAgICAgICAgICBtdXRleC5fZ2xvYmFsX3N0b3JhZ2UgPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG11dGV4Ll9nbG9iYWxfc3RvcmFnZTtcbiAgICB9KSgpO1xuXG4gICAgLyoqXG4gICAgICogR2V0IG9yIGNyZWF0ZSBhIG11dGV4IGZvciBhIHNwZWNpZmljIGluc3RhbmNlIGFuZCBtZXRob2RcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRfaW5zdGFuY2VfbXV0ZXgoaW5zdGFuY2UsIG1ldGhvZF9uYW1lKSB7XG4gICAgICAgIGxldCBpbnN0YW5jZV9sb2NrcyA9IGluc3RhbmNlX211dGV4ZXMuZ2V0KGluc3RhbmNlKTtcbiAgICAgICAgaWYgKCFpbnN0YW5jZV9sb2Nrcykge1xuICAgICAgICAgICAgaW5zdGFuY2VfbG9ja3MgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICBpbnN0YW5jZV9tdXRleGVzLnNldChpbnN0YW5jZSwgaW5zdGFuY2VfbG9ja3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxvY2tfc3RhdGUgPSBpbnN0YW5jZV9sb2Nrcy5nZXQobWV0aG9kX25hbWUpO1xuICAgICAgICBpZiAoIWxvY2tfc3RhdGUpIHtcbiAgICAgICAgICAgIGxvY2tfc3RhdGUgPSB7IGFjdGl2ZTogZmFsc2UsIHF1ZXVlOiBbXSB9O1xuICAgICAgICAgICAgaW5zdGFuY2VfbG9ja3Muc2V0KG1ldGhvZF9uYW1lLCBsb2NrX3N0YXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBsb2NrX3N0YXRlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBvciBjcmVhdGUgYSBnbG9iYWwgbXV0ZXggYnkgSURcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRfZ2xvYmFsX211dGV4KGlkKSB7XG4gICAgICAgIGxldCBsb2NrX3N0YXRlID0gZ2xvYmFsX211dGV4ZXMuZ2V0KGlkKTtcbiAgICAgICAgaWYgKCFsb2NrX3N0YXRlKSB7XG4gICAgICAgICAgICBsb2NrX3N0YXRlID0geyBhY3RpdmU6IGZhbHNlLCBxdWV1ZTogW10gfTtcbiAgICAgICAgICAgIGdsb2JhbF9tdXRleGVzLnNldChpZCwgbG9ja19zdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxvY2tfc3RhdGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZSB0aGUgbmV4dCBxdWV1ZWQgb3BlcmF0aW9uIGZvciBhIG11dGV4XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2NoZWR1bGVfbmV4dChsb2NrX3N0YXRlKSB7XG4gICAgICAgIGlmIChsb2NrX3N0YXRlLmFjdGl2ZSB8fCBsb2NrX3N0YXRlLnF1ZXVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBmbiwgcmVzb2x2ZSwgcmVqZWN0IH0gPSBsb2NrX3N0YXRlLnF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgIGxvY2tfc3RhdGUuYWN0aXZlID0gdHJ1ZTtcblxuICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oZm4pXG4gICAgICAgICAgICAudGhlbihyZXNvbHZlLCByZWplY3QpXG4gICAgICAgICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9ja19zdGF0ZS5hY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBzY2hlZHVsZV9uZXh0KGxvY2tfc3RhdGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWNxdWlyZSBhIG11dGV4IGxvY2sgYW5kIGV4ZWN1dGUgY2FsbGJhY2tcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhY3F1aXJlX2xvY2sobG9ja19zdGF0ZSwgZm4pIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGxvY2tfc3RhdGUucXVldWUucHVzaCh7IGZuLCByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICBzY2hlZHVsZV9uZXh0KGxvY2tfc3RhdGUpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBJZiBjYWxsZWQgd2l0aCBhbiBJRCBhcmd1bWVudDogQG11dGV4KCdpZCcpXG4gICAgaWYgKHR5cGVvZiBnbG9iYWxfaWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbih0YXJnZXQsIGtleSwgZGVzY3JpcHRvcikge1xuICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxfbWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcmlnaW5hbF9tZXRob2QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEBtdXRleCBjYW4gb25seSBiZSBhcHBsaWVkIHRvIG1ldGhvZHMgKHRyaWVkIHRvIGFwcGx5IHRvICR7a2V5fSlgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVzY3JpcHRvci52YWx1ZSA9IGZ1bmN0aW9uKC4uLmFyZ3MpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsb2NrX3N0YXRlID0gZ2V0X2dsb2JhbF9tdXRleChnbG9iYWxfaWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBhY3F1aXJlX2xvY2sobG9ja19zdGF0ZSwgKCkgPT4gb3JpZ2luYWxfbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIElmIGNhbGxlZCB3aXRob3V0IGFyZ3VtZW50czogQG11dGV4ICh0YXJnZXQgaXMgdGhlIGZpcnN0IGFyZ3VtZW50KVxuICAgIGNvbnN0IHRhcmdldCA9IGdsb2JhbF9pZDsgIC8vIEluIHRoaXMgY2FzZSwgZmlyc3QgYXJnIGlzIHRhcmdldFxuICAgIGNvbnN0IGtleSA9IGFyZ3VtZW50c1sxXTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gYXJndW1lbnRzWzJdO1xuXG4gICAgY29uc3Qgb3JpZ2luYWxfbWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgIGlmICh0eXBlb2Ygb3JpZ2luYWxfbWV0aG9kICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQG11dGV4IGNhbiBvbmx5IGJlIGFwcGxpZWQgdG8gbWV0aG9kcyAodHJpZWQgdG8gYXBwbHkgdG8gJHtrZXl9KWApO1xuICAgIH1cblxuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgICAgIGNvbnN0IGxvY2tfc3RhdGUgPSBnZXRfaW5zdGFuY2VfbXV0ZXgodGhpcywga2V5KTtcbiAgICAgICAgcmV0dXJuIGFjcXVpcmVfbG9jayhsb2NrX3N0YXRlLCAoKSA9PiBvcmlnaW5hbF9tZXRob2QuYXBwbHkodGhpcywgYXJncykpO1xuICAgIH07XG5cbiAgICByZXR1cm4gZGVzY3JpcHRvcjtcbn1cbiIsIi8qXG4gKiBBc3luYyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zLCBkZWxheXMsIGRlYm91bmNpbmcsIGFuZCBtdXRleGVzLlxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEFTWU5DIFVUSUxJVElFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFBhdXNlcyBleGVjdXRpb24gZm9yIHNwZWNpZmllZCBtaWxsaXNlY29uZHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBbbWlsbGlzZWNvbmRzPTBdIC0gRGVsYXkgaW4gbWlsbGlzZWNvbmRzICgwIHVzZXMgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKVxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IFByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciBkZWxheVxuICogQGV4YW1wbGUgYXdhaXQgc2xlZXAoMTAwMCk7IC8vIFdhaXQgMSBzZWNvbmRcbiAqL1xuZnVuY3Rpb24gc2xlZXAobWlsbGlzZWNvbmRzID0gMCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICBpZiAobWlsbGlzZWNvbmRzID09IDAgJiYgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKSB7XG4gICAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVzb2x2ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIG1pbGxpc2Vjb25kcyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVib3VuY2VkIGZ1bmN0aW9uIHdpdGggZXhjbHVzaXZpdHkgYW5kIHByb21pc2UgZmFuLWluXG4gKlxuICogVGhpcyBmdW5jdGlvbiwgd2hlbiBpbnZva2VkLCBpbW1lZGlhdGVseSBydW5zIHRoZSBjYWxsYmFjayBleGNsdXNpdmVseS5cbiAqIEZvciBzdWJzZXF1ZW50IGludm9jYXRpb25zLCBpdCBhcHBsaWVzIGEgZGVsYXkgYmVmb3JlIHJ1bm5pbmcgdGhlIGNhbGxiYWNrIGV4Y2x1c2l2ZWx5IGFnYWluLlxuICogVGhlIGRlbGF5IHN0YXJ0cyBhZnRlciB0aGUgY3VycmVudCBhc3luY2hyb25vdXMgb3BlcmF0aW9uIHJlc29sdmVzLlxuICpcbiAqIElmICdkZWxheScgaXMgc2V0IHRvIDAsIHRoZSBmdW5jdGlvbiB3aWxsIG9ubHkgcHJldmVudCBlbnF1ZXVlaW5nIG11bHRpcGxlIGV4ZWN1dGlvbnMgb2YgdGhlXG4gKiBzYW1lIG1ldGhvZCBtb3JlIHRoYW4gb25jZSwgYnV0IHdpbGwgc3RpbGwgcnVuIHRoZW0gaW1tZWRpYXRlbHkgaW4gYW4gZXhjbHVzaXZlIHNlcXVlbnRpYWwgbWFubmVyLlxuICpcbiAqIFRoZSBtb3N0IHJlY2VudCBpbnZvY2F0aW9uIG9mIHRoZSBmdW5jdGlvbiB3aWxsIGJlIHRoZSBwYXJhbWV0ZXJzIHRoYXQgZ2V0IHBhc3NlZCB0byB0aGUgZnVuY3Rpb25cbiAqIHdoZW4gaXQgaW52b2tlcy5cbiAqXG4gKiBUaGUgZnVuY3Rpb24gcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBuZXh0IGV4Y2x1c2l2ZSBleGVjdXRpb24gY29tcGxldGVzLlxuICpcbiAqIFVzYWdlIGFzIGZ1bmN0aW9uOlxuICogICBjb25zdCBkZWJvdW5jZWRGbiA9IGRlYm91bmNlKG15RnVuY3Rpb24sIDI1MCk7XG4gKlxuICogVXNhZ2UgYXMgZGVjb3JhdG9yOlxuICogICBAZGVib3VuY2UoMjUwKVxuICogICBteU1ldGhvZCgpIHsgLi4uIH1cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufG51bWJlcn0gY2FsbGJhY2tfb3JfZGVsYXkgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIE9SIGRlbGF5IHdoZW4gdXNlZCBhcyBkZWNvcmF0b3JcbiAqIEBwYXJhbSB7bnVtYmVyfSBkZWxheSBUaGUgZGVsYXkgaW4gbWlsbGlzZWNvbmRzIGJlZm9yZSBzdWJzZXF1ZW50IGludm9jYXRpb25zXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGltbWVkaWF0ZSBpZiB0cnVlLCB0aGUgZmlyc3QgdGltZSB0aGUgYWN0aW9uIGlzIGNhbGxlZCwgdGhlIGNhbGxiYWNrIGV4ZWN1dGVzIGltbWVkaWF0ZWx5XG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IEEgZnVuY3Rpb24gdGhhdCB3aGVuIGludm9rZWQsIHJ1bnMgdGhlIGNhbGxiYWNrIGltbWVkaWF0ZWx5IGFuZCBleGNsdXNpdmVseSxcbiAqXG4gKiBAZGVjb3JhdG9yXG4gKi9cbmZ1bmN0aW9uIGRlYm91bmNlKGNhbGxiYWNrX29yX2RlbGF5LCBkZWxheSwgaW1tZWRpYXRlID0gZmFsc2UpIHtcbiAgICAvLyBEZWNvcmF0b3IgdXNhZ2U6IEBkZWJvdW5jZSgyNTApIG9yIEBkZWJvdW5jZSgyNTAsIHRydWUpXG4gICAgLy8gRmlyc3QgYXJndW1lbnQgaXMgYSBudW1iZXIgKHRoZSBkZWxheSksIHJldHVybnMgZGVjb3JhdG9yIGZ1bmN0aW9uXG4gICAgaWYgKHR5cGVvZiBjYWxsYmFja19vcl9kZWxheSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgY29uc3QgZGVjb3JhdG9yX2RlbGF5ID0gY2FsbGJhY2tfb3JfZGVsYXk7XG4gICAgICAgIGNvbnN0IGRlY29yYXRvcl9pbW1lZGlhdGUgPSBkZWxheSB8fCBmYWxzZTtcblxuICAgICAgICAvLyBUQzM5IGRlY29yYXRvciBmb3JtOiByZWNlaXZlcyAodmFsdWUsIGNvbnRleHQpXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGNvbnRleHQpIHtcbiAgICAgICAgICAgIGlmIChjb250ZXh0LmtpbmQgPT09ICdtZXRob2QnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlYm91bmNlX2ltcGwodmFsdWUsIGRlY29yYXRvcl9kZWxheSwgZGVjb3JhdG9yX2ltbWVkaWF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRnVuY3Rpb24gdXNhZ2U6IGRlYm91bmNlKGZuLCAyNTApXG4gICAgLy8gRmlyc3QgYXJndW1lbnQgaXMgYSBmdW5jdGlvbiAodGhlIGNhbGxiYWNrKVxuICAgIGNvbnN0IGNhbGxiYWNrID0gY2FsbGJhY2tfb3JfZGVsYXk7XG4gICAgcmV0dXJuIGRlYm91bmNlX2ltcGwoY2FsbGJhY2ssIGRlbGF5LCBpbW1lZGlhdGUpO1xufVxuXG4vKipcbiAqIEludGVybmFsIGltcGxlbWVudGF0aW9uIG9mIGRlYm91bmNlIGxvZ2ljXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBkZWJvdW5jZV9pbXBsKGNhbGxiYWNrLCBkZWxheSwgaW1tZWRpYXRlID0gZmFsc2UpIHtcbiAgICBsZXQgcnVubmluZyA9IGZhbHNlO1xuICAgIGxldCBxdWV1ZWQgPSBmYWxzZTtcbiAgICBsZXQgbGFzdF9lbmRfdGltZSA9IDA7IC8vIHRpbWVzdGFtcCBvZiBsYXN0IGNvbXBsZXRlZCBydW5cbiAgICBsZXQgdGltZXIgPSBudWxsO1xuXG4gICAgbGV0IG5leHRfYXJncyA9IFtdO1xuICAgIGxldCBuZXh0X2NvbnRleHQgPSBudWxsO1xuICAgIGxldCByZXNvbHZlX3F1ZXVlID0gW107XG4gICAgbGV0IHJlamVjdF9xdWV1ZSA9IFtdO1xuXG4gICAgY29uc3QgcnVuX2Z1bmN0aW9uID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCB0aGVzZV9yZXNvbHZlcyA9IHJlc29sdmVfcXVldWU7XG4gICAgICAgIGNvbnN0IHRoZXNlX3JlamVjdHMgPSByZWplY3RfcXVldWU7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBuZXh0X2FyZ3M7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSBuZXh0X2NvbnRleHQ7XG5cbiAgICAgICAgcmVzb2x2ZV9xdWV1ZSA9IFtdO1xuICAgICAgICByZWplY3RfcXVldWUgPSBbXTtcbiAgICAgICAgbmV4dF9hcmdzID0gW107XG4gICAgICAgIG5leHRfY29udGV4dCA9IG51bGw7XG4gICAgICAgIHF1ZXVlZCA9IGZhbHNlO1xuICAgICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY2FsbGJhY2suYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlc29sdmUgb2YgdGhlc2VfcmVzb2x2ZXMpIHJlc29sdmUocmVzdWx0KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlamVjdCBvZiB0aGVzZV9yZWplY3RzKSByZWplY3QoZXJyKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGxhc3RfZW5kX3RpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgaWYgKHF1ZXVlZCkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgICAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KHJ1bl9mdW5jdGlvbiwgTWF0aC5tYXgoZGVsYXksIDApKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGltZXIgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICBuZXh0X2FyZ3MgPSBhcmdzO1xuICAgICAgICBuZXh0X2NvbnRleHQgPSB0aGlzO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlX3F1ZXVlLnB1c2gocmVzb2x2ZSk7XG4gICAgICAgICAgICByZWplY3RfcXVldWUucHVzaChyZWplY3QpO1xuXG4gICAgICAgICAgICAvLyBOb3RoaW5nIHJ1bm5pbmcgYW5kIG5vdGhpbmcgc2NoZWR1bGVkXG4gICAgICAgICAgICBpZiAoIXJ1bm5pbmcgJiYgIXRpbWVyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlyc3RfY2FsbCA9IGxhc3RfZW5kX3RpbWUgPT09IDA7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW1tZWRpYXRlICYmIGZpcnN0X2NhbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcnVuX2Z1bmN0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzaW5jZSA9IGZpcnN0X2NhbGwgPyBJbmZpbml0eSA6IERhdGUubm93KCkgLSBsYXN0X2VuZF90aW1lO1xuICAgICAgICAgICAgICAgIGlmIChzaW5jZSA+PSBkZWxheSkge1xuICAgICAgICAgICAgICAgICAgICBydW5fZnVuY3Rpb24oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB3YWl0ID0gTWF0aC5tYXgoZGVsYXkgLSBzaW5jZSwgMCk7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyID0gc2V0VGltZW91dChydW5fZnVuY3Rpb24sIHdhaXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIHdlJ3JlIGFscmVhZHkgcnVubmluZyBvciBhIHRpbWVyIGV4aXN0cywganVzdCBtYXJrIHF1ZXVlZC5cbiAgICAgICAgICAgIC8vIFRoZSBmaW5hbGx5e30gb2YgcnVuX2Z1bmN0aW9uIGhhbmRsZXMgc2NoZWR1bGluZyBhZnRlciBmdWxsIGRlbGF5LlxuICAgICAgICAgICAgcXVldWVkID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUkVBRC1XUklURSBMT0NLIEZVTkNUSU9OUyAtIERlbGVnYXRlZCB0byBSZWFkV3JpdGVMb2NrIGNsYXNzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQWNxdWlyZSBhbiBleGNsdXNpdmUgd3JpdGUgbG9jayBieSBuYW1lLlxuICogT25seSBvbmUgd3JpdGVyIHJ1bnMgYXQgYSB0aW1lOyBibG9ja3MgcmVhZGVycyB1bnRpbCBmaW5pc2hlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0geygpID0+IGFueXxQcm9taXNlPGFueT59IGNiXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxhbnk+fVxuICovXG5mdW5jdGlvbiByd2xvY2sobmFtZSwgY2IpIHtcbiAgICByZXR1cm4gUmVhZFdyaXRlTG9jay5hY3F1aXJlKG5hbWUsIGNiKTtcbn1cblxuLyoqXG4gKiBBY3F1aXJlIGEgc2hhcmVkIHJlYWQgbG9jayBieSBuYW1lLlxuICogTXVsdGlwbGUgcmVhZGVycyBydW4gaW4gcGFyYWxsZWwsIGJ1dCByZWFkZXJzIGFyZSBibG9ja2VkIGJ5IHF1ZXVlZC9hY3RpdmUgd3JpdGVycy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0geygpID0+IGFueXxQcm9taXNlPGFueT59IGNiXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxhbnk+fVxuICovXG5mdW5jdGlvbiByd2xvY2tfcmVhZChuYW1lLCBjYikge1xuICAgIHJldHVybiBSZWFkV3JpdGVMb2NrLmFjcXVpcmVfcmVhZChuYW1lLCBjYik7XG59XG5cbi8qKlxuICogRm9yY2VmdWxseSBjbGVhciBhbGwgbG9ja3MgYW5kIHF1ZXVlcyBmb3IgYSBnaXZlbiBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqL1xuZnVuY3Rpb24gcndsb2NrX2ZvcmNlX3VubG9jayhuYW1lKSB7XG4gICAgUmVhZFdyaXRlTG9jay5mb3JjZV91bmxvY2sobmFtZSk7XG59XG5cbi8qKlxuICogSW5zcGVjdCBsb2NrIHN0YXRlIGZvciBkZWJ1Z2dpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHJldHVybnMge3tyZWFkZXJzOm51bWJlciwgd3JpdGVyX2FjdGl2ZTpib29sZWFuLCByZWFkZXJfcTpudW1iZXIsIHdyaXRlcl9xOm51bWJlcn19XG4gKi9cbmZ1bmN0aW9uIHJ3bG9ja19wZW5kaW5nKG5hbWUpIHtcbiAgICByZXR1cm4gUmVhZFdyaXRlTG9jay5wZW5kaW5nKG5hbWUpO1xufVxuIiwiLypcbiAqIENvcmUgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBSU3BhZGUgZnJhbWV3b3JrLlxuICogVGhlc2UgZnVuY3Rpb25zIGhhbmRsZSB0eXBlIGNoZWNraW5nLCB0eXBlIGNvbnZlcnNpb24sIHN0cmluZyBtYW5pcHVsYXRpb24sXG4gKiBhbmQgb2JqZWN0L2FycmF5IHV0aWxpdGllcy4gVGhleSBtaXJyb3IgZnVuY3Rpb25hbGl0eSBmcm9tIFBIUCBmdW5jdGlvbnMuXG4gKlxuICogT3RoZXIgdXRpbGl0eSBmdW5jdGlvbnMgYXJlIG9yZ2FuaXplZCBpbjpcbiAqIC0gYXN5bmMuanM6IEFzeW5jIHV0aWxpdGllcyAoc2xlZXAsIGRlYm91bmNlLCBtdXRleClcbiAqIC0gYnJvd3Nlci5qczogQnJvd3Nlci9ET00gdXRpbGl0aWVzIChpc19tb2JpbGUsIHNjcm9sbCBmdW5jdGlvbnMpXG4gKiAtIGRhdGV0aW1lLmpzOiBEYXRlL3RpbWUgdXRpbGl0aWVzXG4gKiAtIGhhc2guanM6IEhhc2hpbmcgYW5kIGNvbXBhcmlzb25cbiAqIC0gZXJyb3IuanM6IEVycm9yIGhhbmRsaW5nXG4gKi9cblxuLy8gVG9kbzogdGVzdCB0aGF0IHByb2QgYnVpbGQgaWRlbnRpZmllcyBhbmQgcmVtb3ZlcyB1bmNhbGxlZCBmdW5jdGlvbnMgZnJvbSB0aGUgZmluYWwgYnVuZGxlLlxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDT05TVEFOVFMgQU5EIEhFTFBFUlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLy8gRGVmaW5lIGNvbW1vbmx5IHVzZWQgY29uc3RhbnRzXG5jb25zdCB1bmRlZiA9ICd1bmRlZmluZWQnO1xuXG4vKipcbiAqIEl0ZXJhdGVzIG92ZXIgYXJyYXlzIG9yIG9iamVjdHMgd2l0aCBwcm9taXNlIHN1cHBvcnRcbiAqXG4gKiBXb3JrcyB3aXRoIGJvdGggc3luY2hyb25vdXMgYW5kIGFzeW5jaHJvbm91cyBjYWxsYmFja3MuIElmIHRoZSBjYWxsYmFja1xuICogcmV0dXJucyBwcm9taXNlcywgdGhleSBhcmUgZXhlY3V0ZWQgaW4gcGFyYWxsZWwgYW5kIHRoaXMgZnVuY3Rpb24gcmV0dXJuc1xuICogYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgcGFyYWxsZWwgdGFza3MgY29tcGxldGUuXG4gKlxuICogQHBhcmFtIHtBcnJheXxPYmplY3R9IG9iaiAtIENvbGxlY3Rpb24gdG8gaXRlcmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgLSBGdW5jdGlvbiB0byBjYWxsIGZvciBlYWNoIGl0ZW0gKHZhbHVlLCBrZXkpIC0gY2FuIGJlIGFzeW5jXG4gKiBAcmV0dXJucyB7UHJvbWlzZXx1bmRlZmluZWR9IFByb21pc2UgaWYgYW55IGNhbGxiYWNrcyByZXR1cm4gcHJvbWlzZXMsIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU3luY2hyb25vdXMgdXNhZ2VcbiAqIGZvcmVhY2goWzEsMiwzXSwgKHZhbCkgPT4gY29uc29sZS5sb2codmFsKSk7XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEFzeW5jaHJvbm91cyB1c2FnZSAtIHdhaXRzIGZvciBhbGwgdG8gY29tcGxldGVcbiAqIGF3YWl0IGZvcmVhY2goWzEsMiwzXSwgYXN5bmMgKHZhbCkgPT4ge1xuICogICAgIGF3YWl0IGZldGNoKCcvYXBpL3Byb2Nlc3MvJyArIHZhbCk7XG4gKiB9KTtcbiAqL1xuZnVuY3Rpb24gZm9yZWFjaChvYmosIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgcmVzdWx0cyA9IFtdO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICBvYmouZm9yRWFjaCgodmFsdWUsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goY2FsbGJhY2sodmFsdWUsIGluZGV4KSk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAob2JqICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGZvciAobGV0IGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChjYWxsYmFjayhvYmpba2V5XSwga2V5KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGaWx0ZXIgZm9yIHByb21pc2VzXG4gICAgY29uc3QgcHJvbWlzZXMgPSByZXN1bHRzLmZpbHRlcigocmVzdWx0KSA9PiByZXN1bHQgJiYgdHlwZW9mIHJlc3VsdC50aGVuID09PSAnZnVuY3Rpb24nKTtcblxuICAgIC8vIElmIHRoZXJlIGFyZSBhbnkgcHJvbWlzZXMsIHJldHVybiBQcm9taXNlLmFsbCB0byB3YWl0IGZvciBhbGwgdG8gY29tcGxldGVcbiAgICBpZiAocHJvbWlzZXMubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgIH1cblxuICAgIC8vIE5vIHByb21pc2VzIHJldHVybmVkLCBzbyB3ZSdyZSBkb25lXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFIENIRUNLSU5HIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIG51bWVyaWNcbiAqIEBwYXJhbSB7Kn0gbiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYSBmaW5pdGUgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGlzX251bWVyaWMobikge1xuICAgIHJldHVybiAhaXNOYU4ocGFyc2VGbG9hdChuKSkgJiYgaXNGaW5pdGUobik7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgYSBzdHJpbmdcbiAqIEBwYXJhbSB7Kn0gcyAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYSBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gaXNfc3RyaW5nKHMpIHtcbiAgICByZXR1cm4gdHlwZW9mIHMgPT0gJ3N0cmluZyc7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgYW4gaW50ZWdlclxuICogQHBhcmFtIHsqfSBuIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhbiBpbnRlZ2VyXG4gKi9cbmZ1bmN0aW9uIGlzX2ludGVnZXIobikge1xuICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKG4pO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGEgcHJvbWlzZS1saWtlIG9iamVjdFxuICogQHBhcmFtIHsqfSBvYmogLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGhhcyBhIHRoZW4gbWV0aG9kXG4gKi9cbmZ1bmN0aW9uIGlzX3Byb21pc2Uob2JqKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBvYmogPT0gJ29iamVjdCcgJiYgdHlwZW9mIG9iai50aGVuID09ICdmdW5jdGlvbic7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgYW4gYXJyYXlcbiAqIEBwYXJhbSB7Kn0gb2JqIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhbiBhcnJheVxuICovXG5mdW5jdGlvbiBpc19hcnJheShvYmopIHtcbiAgICByZXR1cm4gQXJyYXkuaXNBcnJheShvYmopO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGFuIG9iamVjdCAoZXhjbHVkZXMgbnVsbClcbiAqIEBwYXJhbSB7Kn0gb2JqIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhbiBvYmplY3QgYW5kIG5vdCBudWxsXG4gKi9cbmZ1bmN0aW9uIGlzX29iamVjdChvYmopIHtcbiAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGEgZnVuY3Rpb25cbiAqIEBwYXJhbSB7Kn0gZnVuY3Rpb25fdG9fY2hlY2sgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGEgZnVuY3Rpb25cbiAqL1xuZnVuY3Rpb24gaXNfZnVuY3Rpb24oZnVuY3Rpb25fdG9fY2hlY2spIHtcbiAgICByZXR1cm4gZnVuY3Rpb25fdG9fY2hlY2sgJiYge30udG9TdHJpbmcuY2FsbChmdW5jdGlvbl90b19jaGVjaykgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgc3RyaW5nIGlzIGEgdmFsaWQgZW1haWwgYWRkcmVzc1xuICogVXNlcyBhIHByYWN0aWNhbCBSRkMgNTMyMiBjb21wbGlhbnQgcmVnZXggdGhhdCBtYXRjaGVzIDk5Ljk5JSBvZiByZWFsLXdvcmxkIGVtYWlsIGFkZHJlc3Nlc1xuICogQHBhcmFtIHtzdHJpbmd9IGVtYWlsIC0gRW1haWwgYWRkcmVzcyB0byB2YWxpZGF0ZVxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHN0cmluZyBpcyBhIHZhbGlkIGVtYWlsIGFkZHJlc3NcbiAqL1xuZnVuY3Rpb24gaXNfZW1haWwoZW1haWwpIHtcbiAgICBpZiAoIWlzX3N0cmluZyhlbWFpbCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCByZWdleCA9IC9eW2EtejAtOSEjJCUmJyorLz0/Xl9ge3x9fi1dKyg/OlxcLlthLXowLTkhIyQlJicqKy89P15fYHt8fX4tXSspKkAoPzpbYS16MC05XSg/OlthLXowLTktXSpbYS16MC05XSk/XFwuKStbYS16MC05XSg/OlthLXowLTktXSpbYS16MC05XSk/JC9pO1xuICAgIHJldHVybiByZWdleC50ZXN0KGVtYWlsKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBkZWZpbmVkIChub3QgdW5kZWZpbmVkKVxuICogQHBhcmFtIHsqfSB2YWx1ZSAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkXG4gKi9cbmZ1bmN0aW9uIGlzc2V0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSAhPSB1bmRlZjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBlbXB0eSAobnVsbCwgdW5kZWZpbmVkLCAwLCBcIlwiLCBlbXB0eSBhcnJheS9vYmplY3QpXG4gKiBAcGFyYW0geyp9IG9iamVjdCAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgY29uc2lkZXJlZCBlbXB0eVxuICovXG5mdW5jdGlvbiBlbXB0eShvYmplY3QpIHtcbiAgICBpZiAodHlwZW9mIG9iamVjdCA9PSB1bmRlZikge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKG9iamVjdCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT0gJ3N0cmluZycgJiYgb2JqZWN0ID09ICcnKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iamVjdCA9PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gb2JqZWN0ID09IDA7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuICFvYmplY3QubGVuZ3RoO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iamVjdCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChsZXQga2V5IGluIG9iamVjdCkge1xuICAgICAgICBpZiAob2JqZWN0Lmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRSBDT05WRVJTSU9OIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENvbnZlcnRzIGEgdmFsdWUgdG8gYSBmbG9hdGluZyBwb2ludCBudW1iZXJcbiAqIFJldHVybnMgMCBmb3IgbnVsbCwgdW5kZWZpbmVkLCBOYU4sIG9yIG5vbi1udW1lcmljIHZhbHVlc1xuICogQHBhcmFtIHsqfSB2YWwgLSBWYWx1ZSB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBGbG9hdGluZyBwb2ludCBudW1iZXJcbiAqL1xuZnVuY3Rpb24gZmxvYXQodmFsKSB7XG4gICAgLy8gSGFuZGxlIG51bGwsIHVuZGVmaW5lZCwgZW1wdHkgc3RyaW5nXG4gICAgaWYgKHZhbCA9PT0gbnVsbCB8fCB2YWwgPT09IHVuZGVmaW5lZCB8fCB2YWwgPT09ICcnKSB7XG4gICAgICAgIHJldHVybiAwLjA7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHRvIHBhcnNlIHRoZSB2YWx1ZVxuICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlRmxvYXQodmFsKTtcblxuICAgIC8vIENoZWNrIGZvciBOYU4gYW5kIHJldHVybiAwIGlmIHBhcnNpbmcgZmFpbGVkXG4gICAgcmV0dXJuIGlzTmFOKHBhcnNlZCkgPyAwLjAgOiBwYXJzZWQ7XG59XG5cbi8qKlxuICogQ29udmVydHMgYSB2YWx1ZSB0byBhbiBpbnRlZ2VyXG4gKiBSZXR1cm5zIDAgZm9yIG51bGwsIHVuZGVmaW5lZCwgTmFOLCBvciBub24tbnVtZXJpYyB2YWx1ZXNcbiAqIEBwYXJhbSB7Kn0gdmFsIC0gVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMge251bWJlcn0gSW50ZWdlciB2YWx1ZVxuICovXG5mdW5jdGlvbiBpbnQodmFsKSB7XG4gICAgLy8gSGFuZGxlIG51bGwsIHVuZGVmaW5lZCwgZW1wdHkgc3RyaW5nXG4gICAgaWYgKHZhbCA9PT0gbnVsbCB8fCB2YWwgPT09IHVuZGVmaW5lZCB8fCB2YWwgPT09ICcnKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIC8vIFRyeSB0byBwYXJzZSB0aGUgdmFsdWVcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUludCh2YWwsIDEwKTtcblxuICAgIC8vIENoZWNrIGZvciBOYU4gYW5kIHJldHVybiAwIGlmIHBhcnNpbmcgZmFpbGVkXG4gICAgcmV0dXJuIGlzTmFOKHBhcnNlZCkgPyAwIDogcGFyc2VkO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgdmFsdWUgdG8gYSBzdHJpbmdcbiAqIFJldHVybnMgZW1wdHkgc3RyaW5nIGZvciBudWxsIG9yIHVuZGVmaW5lZFxuICogQHBhcmFtIHsqfSB2YWwgLSBWYWx1ZSB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50YXRpb25cbiAqL1xuZnVuY3Rpb24gc3RyKHZhbCkge1xuICAgIC8vIEhhbmRsZSBudWxsIGFuZCB1bmRlZmluZWQgc3BlY2lhbGx5XG4gICAgaWYgKHZhbCA9PT0gbnVsbCB8fCB2YWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgLy8gQ29udmVydCB0byBzdHJpbmdcbiAgICByZXR1cm4gU3RyaW5nKHZhbCk7XG59XG5cbi8qKlxuICogQ29udmVydHMgbnVtZXJpYyBzdHJpbmdzIHRvIG51bWJlcnMsIHJldHVybnMgYWxsIG90aGVyIHZhbHVlcyB1bmNoYW5nZWRcbiAqIFVzZWQgd2hlbiB5b3UgbmVlZCB0byBlbnN1cmUgbnVtZXJpYyB0eXBlcyBidXQgZG9uJ3Qgd2FudCB0byBmb3JjZVxuICogY29udmVyc2lvbiBvZiBub24tbnVtZXJpYyB2YWx1ZXMgKHdoaWNoIHdvdWxkIGJlY29tZSAwKVxuICogQHBhcmFtIHsqfSB2YWwgLSBWYWx1ZSB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7Kn0gTnVtYmVyIGlmIGlucHV0IHdhcyBudW1lcmljIHN0cmluZywgb3RoZXJ3aXNlIHVuY2hhbmdlZFxuICovXG5mdW5jdGlvbiB2YWx1ZV91bmxlc3NfbnVtZXJpY19zdHJpbmdfdGhlbl9udW1lcmljX3ZhbHVlKHZhbCkge1xuICAgIC8vIElmIGl0J3MgYWxyZWFkeSBhIG51bWJlciwgcmV0dXJuIGl0XG4gICAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfVxuXG4gICAgLy8gSWYgaXQncyBhIHN0cmluZyBhbmQgbnVtZXJpYywgY29udmVydCBpdFxuICAgIGlmIChpc19zdHJpbmcodmFsKSAmJiBpc19udW1lcmljKHZhbCkpIHtcbiAgICAgICAgLy8gVXNlIHBhcnNlRmxvYXQgdG8gaGFuZGxlIGJvdGggaW50ZWdlcnMgYW5kIGZsb2F0c1xuICAgICAgICByZXR1cm4gcGFyc2VGbG9hdCh2YWwpO1xuICAgIH1cblxuICAgIC8vIFJldHVybiBldmVyeXRoaW5nIGVsc2UgdW5jaGFuZ2VkIChudWxsLCBvYmplY3RzLCBub24tbnVtZXJpYyBzdHJpbmdzLCBldGMuKVxuICAgIHJldHVybiB2YWw7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFNUUklORyBNQU5JUFVMQVRJT04gRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogRXNjYXBlcyBIVE1MIHNwZWNpYWwgY2hhcmFjdGVycyAodXNlcyBMb2Rhc2ggZXNjYXBlKVxuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byBlc2NhcGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEhUTUwtZXNjYXBlZCBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gaHRtbChzdHIpIHtcbiAgICByZXR1cm4gXy5lc2NhcGUoc3RyKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBuZXdsaW5lcyB0byBIVE1MIGxpbmUgYnJlYWtzXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gU3RyaW5nIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFN0cmluZyB3aXRoIG5ld2xpbmVzIHJlcGxhY2VkIGJ5IDxiciAvPlxuICovXG5mdW5jdGlvbiBubDJicihzdHIpIHtcbiAgICBpZiAodHlwZW9mIHN0ciA9PT0gdW5kZWYgfHwgc3RyID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIChzdHIgKyAnJykucmVwbGFjZSgvKFtePlxcclxcbl0/KShcXHJcXG58XFxuXFxyfFxccnxcXG4pL2csICckMTxiciAvPiQyJyk7XG59XG5cbi8qKlxuICogRXNjYXBlcyBIVE1MIGFuZCBjb252ZXJ0cyBuZXdsaW5lcyB0byA8YnIgLz5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gcHJvY2Vzc1xuICogQHJldHVybnMge3N0cmluZ30gSFRNTC1lc2NhcGVkIHN0cmluZyB3aXRoIGxpbmUgYnJlYWtzXG4gKi9cbmZ1bmN0aW9uIGh0bWxicihzdHIpIHtcbiAgICByZXR1cm4gbmwyYnIoaHRtbChzdHIpKTtcbn1cblxuLyoqXG4gKiBVUkwtZW5jb2RlcyBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byBlbmNvZGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFVSTC1lbmNvZGVkIHN0cmluZ1xuICovXG5mdW5jdGlvbiB1cmxlbmNvZGUoc3RyKSB7XG4gICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChzdHIpO1xufVxuXG4vKipcbiAqIFVSTC1kZWNvZGVzIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gU3RyaW5nIHRvIGRlY29kZVxuICogQHJldHVybnMge3N0cmluZ30gVVJMLWRlY29kZWQgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIHVybGRlY29kZShzdHIpIHtcbiAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0cik7XG59XG5cbi8qKlxuICogSlNPTi1lbmNvZGVzIGEgdmFsdWVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBWYWx1ZSB0byBlbmNvZGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEpTT04gc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIGpzb25fZW5jb2RlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbn1cblxuLyoqXG4gKiBKU09OLWRlY29kZXMgYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBKU09OIHN0cmluZyB0byBkZWNvZGVcbiAqIEByZXR1cm5zIHsqfSBEZWNvZGVkIHZhbHVlXG4gKi9cbmZ1bmN0aW9uIGpzb25fZGVjb2RlKHN0cikge1xuICAgIHJldHVybiBKU09OLnBhcnNlKHN0cik7XG59XG5cbi8qKlxuICogQ29uc29sZSBkZWJ1ZyBvdXRwdXQgd2l0aCBjaGFubmVsIGZpbHRlcmluZ1xuICogQWxpYXMgZm9yIERlYnVnZ2VyLmNvbnNvbGVfZGVidWdcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIC0gRGVidWcgY2hhbm5lbCBuYW1lXG4gKiBAcGFyYW0gey4uLip9IHZhbHVlcyAtIFZhbHVlcyB0byBsb2dcbiAqL1xuZnVuY3Rpb24gY29uc29sZV9kZWJ1ZyhjaGFubmVsLCAuLi52YWx1ZXMpIHtcbiAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKGNoYW5uZWwsIC4uLnZhbHVlcyk7XG59XG5cbi8qKlxuICogUmVwbGFjZXMgYWxsIG9jY3VycmVuY2VzIG9mIGEgc3Vic3RyaW5nIGluIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIC0gU3RyaW5nIHRvIHNlYXJjaCBpblxuICogQHBhcmFtIHtzdHJpbmd9IHNlYXJjaCAtIFN1YnN0cmluZyB0byBmaW5kXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVwbGFjZSAtIFJlcGxhY2VtZW50IHN1YnN0cmluZ1xuICogQHJldHVybnMge3N0cmluZ30gU3RyaW5nIHdpdGggYWxsIG9jY3VycmVuY2VzIHJlcGxhY2VkXG4gKi9cbmZ1bmN0aW9uIHJlcGxhY2VfYWxsKHN0cmluZywgc2VhcmNoLCByZXBsYWNlKSB7XG4gICAgaWYgKCFpc19zdHJpbmcoc3RyaW5nKSkge1xuICAgICAgICBzdHJpbmcgPSBzdHJpbmcgKyAnJztcbiAgICB9XG4gICAgcmV0dXJuIHN0cmluZy5zcGxpdChzZWFyY2gpLmpvaW4ocmVwbGFjZSk7XG59XG5cbi8qKlxuICogQ2FwaXRhbGl6ZXMgdGhlIGZpcnN0IGxldHRlciBvZiBlYWNoIHdvcmRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dCAtIFN0cmluZyB0byBjYXBpdGFsaXplXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgd2l0aCBmaXJzdCBsZXR0ZXIgb2YgZWFjaCB3b3JkIGNhcGl0YWxpemVkXG4gKi9cbmZ1bmN0aW9uIHVjd29yZHMoaW5wdXQpIHtcbiAgICByZXR1cm4gaW5wdXRcbiAgICAgICAgLnNwbGl0KCcgJylcbiAgICAgICAgLm1hcCgod29yZCkgPT4gd29yZC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHdvcmQuc2xpY2UoMSkpXG4gICAgICAgIC5qb2luKCcgJyk7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIE9CSkVDVCBBTkQgQVJSQVkgVVRJTElUSUVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQ291bnRzIHRoZSBudW1iZXIgb2YgcHJvcGVydGllcyBpbiBhbiBvYmplY3Qgb3IgZWxlbWVudHMgaW4gYW4gYXJyYXlcbiAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBvIC0gT2JqZWN0IG9yIGFycmF5IHRvIGNvdW50XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1iZXIgb2Ygb3duIHByb3BlcnRpZXMvZWxlbWVudHNcbiAqL1xuZnVuY3Rpb24gY291bnQobykge1xuICAgIGxldCBjID0gMDtcbiAgICBmb3IgKGNvbnN0IGsgaW4gbykge1xuICAgICAgICBpZiAoby5oYXNPd25Qcm9wZXJ0eShrKSkge1xuICAgICAgICAgICAgKytjO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBzaGFsbG93IGNsb25lIG9mIGFuIG9iamVjdCwgYXJyYXksIG9yIGZ1bmN0aW9uXG4gKiBAcGFyYW0geyp9IG9iaiAtIFZhbHVlIHRvIGNsb25lXG4gKiBAcmV0dXJucyB7Kn0gQ2xvbmVkIHZhbHVlXG4gKi9cbmZ1bmN0aW9uIGNsb25lKG9iaikge1xuICAgIGlmICh0eXBlb2YgRnVuY3Rpb24ucHJvdG90eXBlLl9fY2xvbmUgPT0gdW5kZWYpIHtcbiAgICAgICAgRnVuY3Rpb24ucHJvdG90eXBlLl9fY2xvbmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvL2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE4MzM1ODgvamF2YXNjcmlwdC1jbG9uZS1hLWZ1bmN0aW9uXG4gICAgICAgICAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICAgICAgICAgIGxldCB0ZW1wID0gZnVuY3Rpb24gY2xvbmVkKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm9yIChsZXQga2V5IGluIHRoaXMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbXBba2V5XSA9IHRoaXNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGVtcDtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9iaiA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBvYmouX19jbG9uZSgpO1xuICAgIH0gZWxzZSBpZiAob2JqLmNvbnN0cnVjdG9yICYmIG9iai5jb25zdHJ1Y3RvciA9PSBBcnJheSkge1xuICAgICAgICByZXR1cm4gb2JqLnNsaWNlKDApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzcyODM2MC9ob3ctZG8taS1jb3JyZWN0bHktY2xvbmUtYS1qYXZhc2NyaXB0LW9iamVjdC8zMDA0Mjk0OCMzMDA0Mjk0OFxuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgb2JqKTtcbiAgICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZmlyc3Qgbm9uLW51bGwvdW5kZWZpbmVkIHZhbHVlIGZyb20gYXJndW1lbnRzXG4gKiBAcGFyYW0gey4uLip9IGFyZ3VtZW50cyAtIFZhbHVlcyB0byBjaGVja1xuICogQHJldHVybnMgeyp9IEZpcnN0IG5vbi1udWxsL3VuZGVmaW5lZCB2YWx1ZSwgb3IgbnVsbCBpZiBub25lIGZvdW5kXG4gKi9cbmZ1bmN0aW9uIGNvYWxlc2NlKCkge1xuICAgIGxldCBhcmdzID0gQXJyYXkuZnJvbShhcmd1bWVudHMpO1xuICAgIGxldCByZXR1cm5fdmFsID0gbnVsbDtcbiAgICBhcmdzLmZvckVhY2goZnVuY3Rpb24gKGFyZykge1xuICAgICAgICBpZiAocmV0dXJuX3ZhbCA9PT0gbnVsbCAmJiB0eXBlb2YgYXJnICE9IHVuZGVmICYmIGFyZyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuX3ZhbCA9IGFyZztcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXR1cm5fdmFsO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIENTViBzdHJpbmcgdG8gYXJyYXksIHRyaW1taW5nIGVhY2ggZWxlbWVudFxuICogQHBhcmFtIHtzdHJpbmd9IHN0cl9jc3YgLSBDU1Ygc3RyaW5nIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHtBcnJheTxzdHJpbmc+fSBBcnJheSBvZiB0cmltbWVkIHZhbHVlc1xuICogQHRvZG8gSGFuZGxlIHF1b3RlZC9lc2NhcGVkIGNoYXJhY3RlcnNcbiAqL1xuZnVuY3Rpb24gY3N2X3RvX2FycmF5X3RyaW0oc3RyX2Nzdikge1xuICAgIGNvbnN0IHBhcnRzID0gc3RyX2Nzdi5zcGxpdCgnLCcpO1xuICAgIGNvbnN0IHJldCA9IFtdO1xuICAgIGZvcmVhY2gocGFydHMsIChwYXJ0KSA9PiB7XG4gICAgICAgIHJldC5wdXNoKHBhcnQudHJpbSgpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmV0O1xufVxuIiwiLyoqXG4gKiBNYW5pZmVzdCAtIEphdmFTY3JpcHQgY2xhc3MgcmVnaXN0cnkgYW5kIG1ldGFkYXRhIHN5c3RlbVxuICpcbiAqIFRoaXMgY2xhc3MgbWFpbnRhaW5zIGEgcmVnaXN0cnkgb2YgYWxsIEphdmFTY3JpcHQgY2xhc3NlcyBpbiB0aGUgYnVuZGxlLFxuICogdHJhY2tpbmcgdGhlaXIgbmFtZXMgYW5kIGluaGVyaXRhbmNlIHJlbGF0aW9uc2hpcHMuIEl0IHByb3ZpZGVzIHV0aWxpdGllc1xuICogZm9yIHdvcmtpbmcgd2l0aCBjbGFzcyBoaWVyYXJjaGllcyBhbmQgY2FsbGluZyBpbml0aWFsaXphdGlvbiBtZXRob2RzLlxuICovXG5jbGFzcyBNYW5pZmVzdCB7XG4gICAgLyoqXG4gICAgICogRGVmaW5lIGNsYXNzZXMgaW4gdGhlIG1hbmlmZXN0IChmcmFtZXdvcmsgaW50ZXJuYWwpXG4gICAgICogQHBhcmFtIHtBcnJheX0gaXRlbXMgLSBBcnJheSBvZiBjbGFzcyBkZWZpbml0aW9ucyBbW0NsYXNzLCBcIkNsYXNzTmFtZVwiLCBQYXJlbnRDbGFzcywgZGVjb3JhdG9yc10sIC4uLl1cbiAgICAgKi9cbiAgICBzdGF0aWMgX2RlZmluZShpdGVtcykge1xuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBjbGFzc2VzIG9iamVjdCBpZiBub3QgYWxyZWFkeSBkZWZpbmVkXG4gICAgICAgIGlmICh0eXBlb2YgTWFuaWZlc3QuX2NsYXNzZXMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBNYW5pZmVzdC5fY2xhc3NlcyA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvY2VzcyBlYWNoIGNsYXNzIGRlZmluaXRpb25cbiAgICAgICAgaXRlbXMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgbGV0IGNsYXNzX29iamVjdCA9IGl0ZW1bMF07XG4gICAgICAgICAgICBsZXQgY2xhc3NfbmFtZSA9IGl0ZW1bMV07XG4gICAgICAgICAgICBsZXQgY2xhc3NfZXh0ZW5kcyA9IGl0ZW1bMl0gfHwgbnVsbDtcbiAgICAgICAgICAgIGxldCBkZWNvcmF0b3JzID0gaXRlbVszXSB8fCBudWxsO1xuXG4gICAgICAgICAgICAvLyBTdG9yZSB0aGUgY2xhc3MgaW5mb3JtYXRpb24gKHVzaW5nIG9iamVjdCB0byBhdm9pZCBkdXBsaWNhdGVzKVxuICAgICAgICAgICAgTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV0gPSB7XG4gICAgICAgICAgICAgICAgY2xhc3M6IGNsYXNzX29iamVjdCxcbiAgICAgICAgICAgICAgICBuYW1lOiBjbGFzc19uYW1lLFxuICAgICAgICAgICAgICAgIGV4dGVuZHM6IGNsYXNzX2V4dGVuZHMsXG4gICAgICAgICAgICAgICAgZGVjb3JhdG9yczogZGVjb3JhdG9ycywgIC8vIFN0b3JlIGNvbXBhY3QgZGVjb3JhdG9yIGRhdGFcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8vIEFkZCBtZXRhZGF0YSB0byB0aGUgY2xhc3Mgb2JqZWN0IGl0c2VsZlxuICAgICAgICAgICAgY2xhc3Nfb2JqZWN0Ll9uYW1lID0gY2xhc3NfbmFtZTtcbiAgICAgICAgICAgIGNsYXNzX29iamVjdC5fZXh0ZW5kcyA9IGNsYXNzX2V4dGVuZHM7XG4gICAgICAgICAgICBjbGFzc19vYmplY3QuX2RlY29yYXRvcnMgPSBkZWNvcmF0b3JzO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBCdWlsZCB0aGUgc3ViY2xhc3MgaW5kZXggYWZ0ZXIgYWxsIGNsYXNzZXMgYXJlIGRlZmluZWRcbiAgICAgICAgTWFuaWZlc3QuX2J1aWxkX3N1YmNsYXNzX2luZGV4KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQnVpbGQgYW4gaW5kZXggb2Ygc3ViY2xhc3NlcyBmb3IgZWZmaWNpZW50IGxvb2t1cHNcbiAgICAgKiBUaGlzIGNyZWF0ZXMgYSBtYXBwaW5nIHdoZXJlIGVhY2ggY2xhc3MgbmFtZSBwb2ludHMgdG8gYW4gYXJyYXkgb2YgYWxsIGl0cyBzdWJjbGFzc2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2J1aWxkX3N1YmNsYXNzX2luZGV4KCkge1xuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBzdWJjbGFzcyBpbmRleFxuICAgICAgICBNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXggPSB7fTtcblxuICAgICAgICAvLyBTdGVwIHRocm91Z2ggZWFjaCBjbGFzcyBhbmQgd2FsayB1cCBpdHMgcGFyZW50IGNoYWluXG4gICAgICAgIGZvciAobGV0IGNsYXNzX25hbWUgaW4gTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzZGF0YSA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRfY2xhc3NfbmFtZSA9IGNsYXNzX25hbWU7XG4gICAgICAgICAgICBsZXQgY3VycmVudF9jbGFzc2RhdGEgPSBjbGFzc2RhdGE7XG5cbiAgICAgICAgICAgIC8vIFdhbGsgdXAgdGhlIHBhcmVudCBjaGFpbiB1bnRpbCB3ZSByZWFjaCB0aGUgcm9vdFxuICAgICAgICAgICAgd2hpbGUgKGN1cnJlbnRfY2xhc3NkYXRhKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5kc19uYW1lID0gY3VycmVudF9jbGFzc2RhdGEuZXh0ZW5kcztcblxuICAgICAgICAgICAgICAgIGlmIChleHRlbmRzX25hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgcGFyZW50J3Mgc3ViY2xhc3MgYXJyYXkgaWYgbmVlZGVkXG4gICAgICAgICAgICAgICAgICAgIGlmICghTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtleHRlbmRzX25hbWVdID0gW107XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBBZGQgdGhpcyBjbGFzcyB0byBpdHMgcGFyZW50J3Mgc3ViY2xhc3MgbGlzdFxuICAgICAgICAgICAgICAgICAgICBpZiAoIU1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtleHRlbmRzX25hbWVdLmluY2x1ZGVzKGNsYXNzX25hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbZXh0ZW5kc19uYW1lXS5wdXNoKGNsYXNzX25hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTW92ZSB1cCB0byB0aGUgcGFyZW50J3MgbWV0YWRhdGEgKGlmIGl0IGV4aXN0cyBpbiBtYW5pZmVzdClcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1hbmlmZXN0Ll9jbGFzc2VzW2V4dGVuZHNfbmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbZXh0ZW5kc19uYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBhcmVudCBub3QgaW4gbWFuaWZlc3QgKGUuZy4sIG5hdGl2ZSBKYXZhU2NyaXB0IGNsYXNzKSwgc3RvcCBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzZGF0YSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBObyBwYXJlbnQsIHdlJ3ZlIHJlYWNoZWQgdGhlIHJvb3RcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzc2RhdGEgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgY2xhc3NlcyB0aGF0IGV4dGVuZCBhIGdpdmVuIGJhc2UgY2xhc3NcbiAgICAgKiBAcGFyYW0ge0NsYXNzfHN0cmluZ30gYmFzZV9jbGFzcyAtIFRoZSBiYXNlIGNsYXNzIChvYmplY3Qgb3IgbmFtZSBzdHJpbmcpIHRvIGNoZWNrIGZvclxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygb2JqZWN0cyB3aXRoIHtjbGFzc19uYW1lLCBjbGFzc19vYmplY3R9IGZvciBjbGFzc2VzIHRoYXQgZXh0ZW5kIHRoZSBiYXNlIGNsYXNzXG4gICAgICovXG4gICAgc3RhdGljIGdldF9leHRlbmRpbmcoYmFzZV9jbGFzcykge1xuICAgICAgICBpZiAoIU1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyB0byBjbGFzcyBvYmplY3QgaWYgbmVlZGVkXG4gICAgICAgIGxldCBiYXNlX2NsYXNzX29iamVjdCA9IGJhc2VfY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2YgYmFzZV9jbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGJhc2VfY2xhc3Nfb2JqZWN0ID0gTWFuaWZlc3QuZ2V0X2NsYXNzX2J5X25hbWUoYmFzZV9jbGFzcyk7XG4gICAgICAgICAgICBpZiAoIWJhc2VfY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBCYXNlIGNsYXNzIG5vdCBmb3VuZDogJHtiYXNlX2NsYXNzfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2xhc3NlcyA9IFtdO1xuXG4gICAgICAgIGZvciAobGV0IGNsYXNzX25hbWUgaW4gTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzZGF0YSA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICAgICAgaWYgKE1hbmlmZXN0LmpzX2lzX3N1YmNsYXNzX29mKGNsYXNzZGF0YS5jbGFzcywgYmFzZV9jbGFzc19vYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NfbmFtZTogY2xhc3NfbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgY2xhc3Nfb2JqZWN0OiBjbGFzc2RhdGEuY2xhc3MsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTb3J0IGFscGhhYmV0aWNhbGx5IGJ5IGNsYXNzIG5hbWUgdG8gZW5zdXJlIGRldGVybWluaXN0aWMgYmVoYXZpb3IgYW5kIHByZXZlbnQgcmFjZSBjb25kaXRpb24gYnVnc1xuICAgICAgICBjbGFzc2VzLnNvcnQoKGEsIGIpID0+IGEuY2xhc3NfbmFtZS5sb2NhbGVDb21wYXJlKGIuY2xhc3NfbmFtZSkpO1xuXG4gICAgICAgIHJldHVybiBjbGFzc2VzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgY2xhc3MgaXMgYSBzdWJjbGFzcyBvZiBhbm90aGVyIGNsYXNzXG4gICAgICogTWF0Y2hlcyBQSFAgTWFuaWZlc3Q6OmpzX2lzX3N1YmNsYXNzX29mKCkgc2lnbmF0dXJlIGFuZCBiZWhhdmlvclxuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBzdWJjbGFzcyAtIFRoZSBjaGlsZCBjbGFzcyAob2JqZWN0IG9yIG5hbWUpIHRvIGNoZWNrXG4gICAgICogQHBhcmFtIHtDbGFzc3xzdHJpbmd9IHN1cGVyY2xhc3MgLSBUaGUgcGFyZW50IGNsYXNzIChvYmplY3Qgb3IgbmFtZSkgdG8gY2hlY2sgYWdhaW5zdFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHN1YmNsYXNzIGV4dGVuZHMgc3VwZXJjbGFzcyAoZGlyZWN0bHkgb3IgaW5kaXJlY3RseSlcbiAgICAgKi9cbiAgICBzdGF0aWMganNfaXNfc3ViY2xhc3Nfb2Yoc3ViY2xhc3MsIHN1cGVyY2xhc3MpIHtcbiAgICAgICAgLy8gQ29udmVydCBzdHJpbmcgbmFtZXMgdG8gY2xhc3Mgb2JqZWN0c1xuICAgICAgICBsZXQgc3ViY2xhc3Nfb2JqZWN0ID0gc3ViY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2Ygc3ViY2xhc3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBzdWJjbGFzc19vYmplY3QgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShzdWJjbGFzcyk7XG4gICAgICAgICAgICBpZiAoIXN1YmNsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgICAgIC8vIENhbid0IHJlc29sdmUgc3ViY2xhc3MgLSByZXR1cm4gZmFsc2UgcGVyIHNwZWNcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgc3VwZXJjbGFzc19vYmplY3QgPSBzdXBlcmNsYXNzO1xuICAgICAgICBpZiAodHlwZW9mIHN1cGVyY2xhc3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBzdXBlcmNsYXNzX29iamVjdCA9IE1hbmlmZXN0LmdldF9jbGFzc19ieV9uYW1lKHN1cGVyY2xhc3MpO1xuICAgICAgICAgICAgaWYgKCFzdXBlcmNsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgICAgIC8vIENhbid0IHJlc29sdmUgc3VwZXJjbGFzcyAtIGZhaWwgbG91ZCBwZXIgc3BlY1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU3VwZXJjbGFzcyBub3QgZm91bmQgaW4gbWFuaWZlc3Q6ICR7c3VwZXJjbGFzc31gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENsYXNzZXMgYXJlIG5vdCBzdWJjbGFzc2VzIG9mIHRoZW1zZWx2ZXNcbiAgICAgICAgaWYgKHN1YmNsYXNzX29iamVjdCA9PT0gc3VwZXJjbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdhbGsgdXAgdGhlIGluaGVyaXRhbmNlIGNoYWluXG4gICAgICAgIGxldCBjdXJyZW50X2NsYXNzID0gc3ViY2xhc3Nfb2JqZWN0O1xuICAgICAgICB3aGlsZSAoY3VycmVudF9jbGFzcykge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRfY2xhc3MgPT09IHN1cGVyY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBNb3ZlIHVwIHRvIHBhcmVudCBjbGFzc1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRfY2xhc3MuX2V4dGVuZHMpIHtcbiAgICAgICAgICAgICAgICAvLyBfZXh0ZW5kcyBtYXkgYmUgYSBzdHJpbmcgb3IgY2xhc3MgcmVmZXJlbmNlXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjdXJyZW50X2NsYXNzLl9leHRlbmRzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzID0gTWFuaWZlc3QuZ2V0X2NsYXNzX2J5X25hbWUoY3VycmVudF9jbGFzcy5fZXh0ZW5kcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzcyA9IGN1cnJlbnRfY2xhc3MuX2V4dGVuZHM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBjbGFzcyBieSBpdHMgbmFtZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc19uYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGNsYXNzXG4gICAgICogQHJldHVybnMge0NsYXNzfG51bGx9IFRoZSBjbGFzcyBvYmplY3Qgb3IgbnVsbCBpZiBub3QgZm91bmRcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2NsYXNzX2J5X25hbWUoY2xhc3NfbmFtZSkge1xuICAgICAgICBpZiAoIU1hbmlmZXN0Ll9jbGFzc2VzIHx8ICFNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV0uY2xhc3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCByZWdpc3RlcmVkIGNsYXNzZXNcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIG9iamVjdHMgd2l0aCB7Y2xhc3NfbmFtZSwgY2xhc3Nfb2JqZWN0LCBleHRlbmRzfVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfYWxsX2NsYXNzZXMoKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICAgIGNsYXNzX25hbWU6IGNsYXNzZGF0YS5uYW1lLFxuICAgICAgICAgICAgICAgIGNsYXNzX29iamVjdDogY2xhc3NkYXRhLmNsYXNzLFxuICAgICAgICAgICAgICAgIGV4dGVuZHM6IGNsYXNzZGF0YS5leHRlbmRzLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTb3J0IGFscGhhYmV0aWNhbGx5IGJ5IGNsYXNzIG5hbWUgdG8gZW5zdXJlIGRldGVybWluaXN0aWMgYmVoYXZpb3IgYW5kIHByZXZlbnQgcmFjZSBjb25kaXRpb24gYnVnc1xuICAgICAgICByZXN1bHRzLnNvcnQoKGEsIGIpID0+IGEuY2xhc3NfbmFtZS5sb2NhbGVDb21wYXJlKGIuY2xhc3NfbmFtZSkpO1xuXG4gICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgYnVpbGQga2V5IGZyb20gdGhlIGFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYnVpbGQga2V5IG9yIFwiTk9CVUlMRFwiIGlmIG5vdCBhdmFpbGFibGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYnVpbGRfa2V5KCkge1xuICAgICAgICBpZiAod2luZG93LnJzeGFwcCAmJiB3aW5kb3cucnN4YXBwLmJ1aWxkX2tleSkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5yc3hhcHAuYnVpbGRfa2V5O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnTk9CVUlMRCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGRlY29yYXRvcnMgZm9yIGEgc3BlY2lmaWMgY2xhc3MgYW5kIG1ldGhvZFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfENsYXNzfSBjbGFzc19uYW1lIC0gVGhlIGNsYXNzIG5hbWUgb3IgY2xhc3Mgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZF9uYW1lIC0gVGhlIG1ldGhvZCBuYW1lXG4gICAgICogQHJldHVybnMge0FycmF5fG51bGx9IEFycmF5IG9mIGRlY29yYXRvciBvYmplY3RzIG9yIG51bGwgaWYgbm9uZSBmb3VuZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfZGVjb3JhdG9ycyhjbGFzc19uYW1lLCBtZXRob2RfbmFtZSkge1xuICAgICAgICAvLyBDb252ZXJ0IGNsYXNzIG9iamVjdCB0byBuYW1lIGlmIG5lZWRlZFxuICAgICAgICBpZiAodHlwZW9mIGNsYXNzX25hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjbGFzc19uYW1lID0gY2xhc3NfbmFtZS5fbmFtZSB8fCBjbGFzc19uYW1lLm5hbWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGFzc19pbmZvID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgIGlmICghY2xhc3NfaW5mbyB8fCAhY2xhc3NfaW5mby5kZWNvcmF0b3JzIHx8ICFjbGFzc19pbmZvLmRlY29yYXRvcnNbbWV0aG9kX25hbWVdKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYW5zZm9ybSBjb21wYWN0IGZvcm1hdCB0byBvYmplY3QgZm9ybWF0XG4gICAgICAgIHJldHVybiBNYW5pZmVzdC5fdHJhbnNmb3JtX2RlY29yYXRvcnMoY2xhc3NfaW5mby5kZWNvcmF0b3JzW21ldGhvZF9uYW1lXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBtZXRob2RzIHdpdGggZGVjb3JhdG9ycyBmb3IgYSBjbGFzc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfENsYXNzfSBjbGFzc19uYW1lIC0gVGhlIGNsYXNzIG5hbWUgb3IgY2xhc3Mgb2JqZWN0XG4gICAgICogQHJldHVybnMge09iamVjdH0gT2JqZWN0IHdpdGggbWV0aG9kIG5hbWVzIGFzIGtleXMgYW5kIGRlY29yYXRvciBhcnJheXMgYXMgdmFsdWVzXG4gICAgICovXG4gICAgc3RhdGljIGdldF9hbGxfZGVjb3JhdG9ycyhjbGFzc19uYW1lKSB7XG4gICAgICAgIC8vIENvbnZlcnQgY2xhc3Mgb2JqZWN0IHRvIG5hbWUgaWYgbmVlZGVkXG4gICAgICAgIGlmICh0eXBlb2YgY2xhc3NfbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNsYXNzX25hbWUgPSBjbGFzc19uYW1lLl9uYW1lIHx8IGNsYXNzX25hbWUubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsYXNzX2luZm8gPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgaWYgKCFjbGFzc19pbmZvIHx8ICFjbGFzc19pbmZvLmRlY29yYXRvcnMpIHtcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYW5zZm9ybSBhbGwgZGVjb3JhdG9ycyBmcm9tIGNvbXBhY3QgdG8gb2JqZWN0IGZvcm1hdFxuICAgICAgICBjb25zdCByZXN1bHQgPSB7fTtcbiAgICAgICAgZm9yIChsZXQgbWV0aG9kX25hbWUgaW4gY2xhc3NfaW5mby5kZWNvcmF0b3JzKSB7XG4gICAgICAgICAgICByZXN1bHRbbWV0aG9kX25hbWVdID0gTWFuaWZlc3QuX3RyYW5zZm9ybV9kZWNvcmF0b3JzKGNsYXNzX2luZm8uZGVjb3JhdG9yc1ttZXRob2RfbmFtZV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJhbnNmb3JtIGNvbXBhY3QgZGVjb3JhdG9yIGZvcm1hdCB0byBvYmplY3QgZm9ybWF0XG4gICAgICogQHBhcmFtIHtBcnJheX0gY29tcGFjdF9kZWNvcmF0b3JzIC0gQXJyYXkgb2YgW25hbWUsIFthcmdzXV0gdHVwbGVzXG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBkZWNvcmF0b3Igb2JqZWN0cyB3aXRoIG5hbWUgYW5kIGFyZ3VtZW50cyBwcm9wZXJ0aWVzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3RyYW5zZm9ybV9kZWNvcmF0b3JzKGNvbXBhY3RfZGVjb3JhdG9ycykge1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29tcGFjdF9kZWNvcmF0b3JzKSkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbXBhY3RfZGVjb3JhdG9ycy5tYXAoZGVjb3JhdG9yID0+IHtcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRlY29yYXRvcikgJiYgZGVjb3JhdG9yLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogZGVjb3JhdG9yWzBdLFxuICAgICAgICAgICAgICAgICAgICBhcmd1bWVudHM6IGRlY29yYXRvclsxXSB8fCBbXVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBIYW5kbGUgbWFsZm9ybWVkIGRlY29yYXRvciBkYXRhXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG5hbWU6ICd1bmtub3duJyxcbiAgICAgICAgICAgICAgICBhcmd1bWVudHM6IFtdXG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBhIG1ldGhvZCBoYXMgYSBzcGVjaWZpYyBkZWNvcmF0b3JcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xDbGFzc30gY2xhc3NfbmFtZSAtIFRoZSBjbGFzcyBuYW1lIG9yIGNsYXNzIG9iamVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RfbmFtZSAtIFRoZSBtZXRob2QgbmFtZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkZWNvcmF0b3JfbmFtZSAtIFRoZSBkZWNvcmF0b3IgbmFtZSB0byBjaGVjayBmb3JcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgbWV0aG9kIGhhcyB0aGUgZGVjb3JhdG9yXG4gICAgICovXG4gICAgc3RhdGljIGhhc19kZWNvcmF0b3IoY2xhc3NfbmFtZSwgbWV0aG9kX25hbWUsIGRlY29yYXRvcl9uYW1lKSB7XG4gICAgICAgIGNvbnN0IGRlY29yYXRvcnMgPSBNYW5pZmVzdC5nZXRfZGVjb3JhdG9ycyhjbGFzc19uYW1lLCBtZXRob2RfbmFtZSk7XG4gICAgICAgIGlmICghZGVjb3JhdG9ycykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRlY29yYXRvcnMuc29tZShkID0+IGQubmFtZSA9PT0gZGVjb3JhdG9yX25hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgc3ViY2xhc3NlcyBvZiBhIGdpdmVuIGNsYXNzIHVzaW5nIHRoZSBwcmUtYnVpbHQgaW5kZXhcbiAgICAgKiBUaGlzIGlzIHRoZSBKYXZhU2NyaXB0IGVxdWl2YWxlbnQgb2YgUEhQJ3MgTWFuaWZlc3Q6OmpzX2dldF9zdWJjbGFzc2VzX29mKClcbiAgICAgKiBAcGFyYW0ge0NsYXNzfHN0cmluZ30gYmFzZV9jbGFzcyAtIFRoZSBiYXNlIGNsYXNzIChvYmplY3Qgb3IgbmFtZSBzdHJpbmcpIHRvIGdldCBzdWJjbGFzc2VzIG9mXG4gICAgICogQHJldHVybnMge0FycmF5PENsYXNzPn0gQXJyYXkgb2YgYWN0dWFsIGNsYXNzIG9iamVjdHMgdGhhdCBhcmUgc3ViY2xhc3NlcyBvZiB0aGUgYmFzZSBjbGFzc1xuICAgICAqL1xuICAgIHN0YXRpYyBqc19nZXRfc3ViY2xhc3Nlc19vZihiYXNlX2NsYXNzKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgaW5kZXggaWYgbmVlZGVkXG4gICAgICAgIGlmICghTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4KSB7XG4gICAgICAgICAgICBNYW5pZmVzdC5fYnVpbGRfc3ViY2xhc3NfaW5kZXgoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgY2xhc3Mgb2JqZWN0IHRvIG5hbWUgaWYgbmVlZGVkXG4gICAgICAgIGxldCBiYXNlX2NsYXNzX25hbWUgPSBiYXNlX2NsYXNzO1xuICAgICAgICBpZiAodHlwZW9mIGJhc2VfY2xhc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBiYXNlX2NsYXNzX25hbWUgPSBiYXNlX2NsYXNzLl9uYW1lIHx8IGJhc2VfY2xhc3MubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBiYXNlIGNsYXNzIGV4aXN0c1xuICAgICAgICBpZiAoIU1hbmlmZXN0Ll9jbGFzc2VzW2Jhc2VfY2xhc3NfbmFtZV0pIHtcbiAgICAgICAgICAgIC8vIEJhc2UgY2xhc3Mgbm90IGluIG1hbmlmZXN0IC0gcmV0dXJuIGVtcHR5IGFycmF5XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZXQgc3ViY2xhc3MgbmFtZXMgZnJvbSB0aGUgaW5kZXhcbiAgICAgICAgY29uc3Qgc3ViY2xhc3NfbmFtZXMgPSBNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbYmFzZV9jbGFzc19uYW1lXSB8fCBbXTtcblxuICAgICAgICAvLyBDb252ZXJ0IG5hbWVzIHRvIGFjdHVhbCBjbGFzcyBvYmplY3RzXG4gICAgICAgIGNvbnN0IHN1YmNsYXNzX29iamVjdHMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgc3ViY2xhc3NfbmFtZSBvZiBzdWJjbGFzc19uYW1lcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbc3ViY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBzdWJjbGFzc19vYmplY3RzLnB1c2goY2xhc3NkYXRhLmNsYXNzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYnkgY2xhc3MgbmFtZSBmb3IgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvclxuICAgICAgICBzdWJjbGFzc19vYmplY3RzLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5hbWVfYSA9IGEuX25hbWUgfHwgYS5uYW1lO1xuICAgICAgICAgICAgY29uc3QgbmFtZV9iID0gYi5fbmFtZSB8fCBiLm5hbWU7XG4gICAgICAgICAgICByZXR1cm4gbmFtZV9hLmxvY2FsZUNvbXBhcmUobmFtZV9iKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHN1YmNsYXNzX29iamVjdHM7XG4gICAgfVxufVxuXG4vLyBSU1ggbWFuaWZlc3QgYXV0b21hdGljYWxseSBtYWtlcyBjbGFzc2VzIGdsb2JhbCAtIG5vIG1hbnVhbCBhc3NpZ25tZW50IG5lZWRlZFxuIiwiLyoqXG4gKiBSc3hfQmVoYXZpb3JzIC0gQ29yZSBGcmFtZXdvcmsgVXNlciBFeHBlcmllbmNlIEVuaGFuY2VtZW50c1xuICpcbiAqIFRoaXMgY2xhc3MgcHJvdmlkZXMgYXV0b21hdGljIHF1YWxpdHktb2YtbGlmZSBiZWhhdmlvcnMgdGhhdCBpbXByb3ZlIHRoZSBkZWZhdWx0XG4gKiBicm93c2VyIGV4cGVyaWVuY2UgZm9yIFJTWCBhcHBsaWNhdGlvbnMuIFRoZXNlIGJlaGF2aW9ycyBhcmUgdHJhbnNwYXJlbnQgdG9cbiAqIGFwcGxpY2F0aW9uIGRldmVsb3BlcnMgYW5kIHJ1biBhdXRvbWF0aWNhbGx5IG9uIGZyYW1ld29yayBpbml0aWFsaXphdGlvbi5cbiAqXG4gKiBUaGVzZSBiZWhhdmlvcnMgdXNlIGpRdWVyeSBldmVudCBkZWxlZ2F0aW9uIHRvIGhhbmRsZSBib3RoIGV4aXN0aW5nIGFuZCBkeW5hbWljYWxseVxuICogYWRkZWQgY29udGVudC4gVGhleSBhcmUgaW1wbGVtZW50ZWQgd2l0aCBsb3cgcHJpb3JpdHkgdG8gYWxsb3cgYXBwbGljYXRpb24gY29kZSB0b1xuICogb3ZlcnJpZGUgZGVmYXVsdCBiZWhhdmlvcnMgd2hlbiBuZWVkZWQuXG4gKlxuICogQGludGVybmFsIEZyYW1ld29yayB1c2Ugb25seSAtIG5vdCBwYXJ0IG9mIHB1YmxpYyBBUElcbiAqL1xuY2xhc3MgUnN4X0JlaGF2aW9ycyB7XG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfY29yZV9pbml0KCkge1xuICAgICAgICBSc3hfQmVoYXZpb3JzLl9pbml0X2lnbm9yZV9pbnZhbGlkX2FuY2hvcl9saW5rcygpO1xuICAgICAgICBSc3hfQmVoYXZpb3JzLl90cmltX2NvcGllZF90ZXh0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogLSBBbmNob3IgbGluayBoYW5kbGluZzogUHJldmVudHMgYnJva2VuIFwiI1wiIGxpbmtzIGZyb20gY2F1c2luZyBwYWdlIGp1bXBzIG9yIFVSTCBjaGFuZ2VzXG4gICAgICogLSBJZ25vcmVzIFwiI1wiIChlbXB0eSBoYXNoKSB0byBwcmV2ZW50IHNjcm9sbC10by10b3AgYmVoYXZpb3JcbiAgICAgKiAtIElnbm9yZXMgXCIjcGxhY2Vob2xkZXIqXCIgbGlua3MgdXNlZCBhcyByb3V0ZSBwbGFjZWhvbGRlcnMgZHVyaW5nIGRldmVsb3BtZW50XG4gICAgICogLSBWYWxpZGF0ZXMgYW5jaG9yIHRhcmdldHMgZXhpc3QgYmVmb3JlIGFsbG93aW5nIG5hdmlnYXRpb25cbiAgICAgKiAtIFByZXNlcnZlcyBub3JtYWwgYW5jaG9yIGJlaGF2aW9yIHdoZW4gdGFyZ2V0cyBleGlzdFxuICAgICAqL1xuICAgIHN0YXRpYyBfaW5pdF9pZ25vcmVfaW52YWxpZF9hbmNob3JfbGlua3MoKSB7XG4gICAgICAgIHJldHVybjsgLy8gZGlzYWJsZWQgZm9yIG5vdyAtIG1ha2UgdGhpcyBpbnRvIGEgY29uZmlndXJhYmxlIG9wdGlvblxuXG4gICAgICAgIC8vIFVzZSBldmVudCBkZWxlZ2F0aW9uIG9uIGRvY3VtZW50IHRvIGhhbmRsZSBhbGwgY3VycmVudCBhbmQgZnV0dXJlIGFuY2hvciBjbGlja3NcbiAgICAgICAgLy8gVXNlIG1vdXNlZG93biBpbnN0ZWFkIG9mIGNsaWNrIHRvIHJ1biBiZWZvcmUgbW9zdCBhcHBsaWNhdGlvbiBoYW5kbGVyc1xuICAgICAgICAkKGRvY3VtZW50KS5vbignbW91c2Vkb3duJywgJ2FbaHJlZl49XCIjXCJdJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGNvbnN0ICRsaW5rID0gJCh0aGlzKTtcbiAgICAgICAgICAgIGNvbnN0IGhyZWYgPSAkbGluay5hdHRyKCdocmVmJyk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGFub3RoZXIgaGFuZGxlciBoYXMgYWxyZWFkeSBwcmV2ZW50ZWQgZGVmYXVsdFxuICAgICAgICAgICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFsbG93IGRhdGEtcnN4LWFsbG93LWhhc2ggYXR0cmlidXRlIHRvIGJ5cGFzcyB0aGlzIGJlaGF2aW9yXG4gICAgICAgICAgICBpZiAoJGxpbmsuZGF0YSgncnN4LWFsbG93LWhhc2gnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSGFuZGxlIGVtcHR5IGhhc2ggLSBwcmV2ZW50IHNjcm9sbCB0byB0b3BcbiAgICAgICAgICAgIGlmIChocmVmID09PSAnIycpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEhhbmRsZSBwbGFjZWhvbGRlciBsaW5rcyB1c2VkIGR1cmluZyBkZXZlbG9wbWVudFxuICAgICAgICAgICAgaWYgKGhyZWYuc3RhcnRzV2l0aCgnI3BsYWNlaG9sZGVyJykpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZvciBvdGhlciBoYXNoIGxpbmtzLCBjaGVjayBpZiB0YXJnZXQgZXhpc3RzXG4gICAgICAgICAgICBjb25zdCB0YXJnZXRJZCA9IGhyZWYuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgaWYgKHRhcmdldElkKSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIGVsZW1lbnQgd2l0aCBtYXRjaGluZyBJRCBvciBuYW1lIGF0dHJpYnV0ZVxuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldEV4aXN0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdldElkKSAhPT0gbnVsbCB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBbbmFtZT1cIiR7dGFyZ2V0SWR9XCJdYCkgIT09IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRhcmdldEV4aXN0cykge1xuICAgICAgICAgICAgICAgICAgICAvLyBUYXJnZXQgZG9lc24ndCBleGlzdCAtIHByZXZlbnQgbmF2aWdhdGlvblxuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gVGFyZ2V0IGV4aXN0cyAtIGFsbG93IG5vcm1hbCBhbmNob3IgYmVoYXZpb3JcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogLSBDb3B5IHRleHQgdHJpbW1pbmc6IEF1dG9tYXRpY2FsbHkgcmVtb3ZlcyBsZWFkaW5nL3RyYWlsaW5nIHdoaXRlc3BhY2UgZnJvbSBjb3BpZWQgdGV4dFxuICAgICAqIC0gSG9sZCBTaGlmdCB0byBwcmVzZXJ2ZSB3aGl0ZXNwYWNlXG4gICAgICogLSBTa2lwcyB0cmltbWluZyBpbiBjb2RlIGJsb2NrcywgdGV4dGFyZWFzLCBhbmQgY29udGVudGVkaXRhYmxlIGVsZW1lbnRzXG4gICAgICovXG4gICAgc3RhdGljIF90cmltX2NvcGllZF90ZXh0KCkge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjb3B5JywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAvLyBEb24ndCB0cmltIGlmIHVzZXIgaXMgaG9sZGluZyBTaGlmdCAoYWxsb3dzIGNvcHlpbmcgd2l0aCB3aGl0ZXNwYWNlIGlmIG5lZWRlZClcbiAgICAgICAgICAgIGlmIChldmVudC5zaGlmdEtleSkgcmV0dXJuO1xuXG4gICAgICAgICAgICBsZXQgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgbGV0IHNlbGVjdGVkX3RleHQgPSBzZWxlY3Rpb24udG9TdHJpbmcoKTtcblxuICAgICAgICAgICAgLy8gRG9uJ3QgdHJpbSBpZiBzZWxlY3Rpb24gaXMgZW1wdHlcbiAgICAgICAgICAgIGlmICghc2VsZWN0ZWRfdGV4dCkgcmV0dXJuO1xuXG4gICAgICAgICAgICAvLyBEb24ndCB0cmltIGlmIGNvcHlpbmcgZnJvbSBjb2RlIGJsb2NrcywgdGV4dGFyZWFzLCBvciBjb250ZW50LWVkaXRhYmxlIChwcmVzZXJ2ZSBmb3JtYXR0aW5nKVxuICAgICAgICAgICAgbGV0IGNvbnRhaW5lciA9IHNlbGVjdGlvbi5nZXRSYW5nZUF0KDApLmNvbW1vbkFuY2VzdG9yQ29udGFpbmVyO1xuICAgICAgICAgICAgaWYgKGNvbnRhaW5lci5ub2RlVHlwZSA9PT0gMykgY29udGFpbmVyID0gY29udGFpbmVyLnBhcmVudE5vZGU7IC8vIFRleHQgbm9kZSB0byBlbGVtZW50XG4gICAgICAgICAgICBpZiAoY29udGFpbmVyLmNsb3Nlc3QoJ3ByZSwgY29kZSwgLmNvZGUtYmxvY2ssIHRleHRhcmVhLCBbY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiXScpKSByZXR1cm47XG5cbiAgICAgICAgICAgIGxldCB0cmltbWVkX3RleHQgPSBzZWxlY3RlZF90ZXh0LnRyaW0oKTtcblxuICAgICAgICAgICAgLy8gT25seSBtb2RpZnkgaWYgdGhlcmUncyBhY3R1YWxseSB3aGl0ZXNwYWNlIHRvIHRyaW1cbiAgICAgICAgICAgIGlmICh0cmltbWVkX3RleHQgIT09IHNlbGVjdGVkX3RleHQgJiYgdHJpbW1lZF90ZXh0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIGV2ZW50LmNsaXBib2FyZERhdGEuc2V0RGF0YSgndGV4dC9wbGFpbicsIHRyaW1tZWRfdGV4dCk7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ0NvcHk6IHRyaW1tZWQgd2hpdGVzcGFjZSBmcm9tIHNlbGVjdGlvbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59XG4iLCIvLyBTaW1wbGUga2V5IHZhbHVlIGNhY2hlLiAgQ2FuIG9ubHkgc3RvcmUgNTAwMCBlbnRyaWVzLCB3aWxsIHJlc2V0IGFmdGVyIDUwMDAgZW50cmllcy5cblxuLy8gVG9kbzoga2VlcCBsb2NhbCBjYWNoZSBjb25jZXB0IHRoZSBzYW1lLCByZXBsYWNlIGdsb2JhbCBjYWNoZSBjb25jZXB0IHdpdGggdGhlIG5vdiAyMDE5IHZlcnNpb24gb2Zcbi8vIHNlc3Npb24gY2FjaGUuICBVc2UgYSBzZXNzaW9uIGtleSAmIGJ1aWxkIGtleSB0byB0cmFjayBjYWNoZSBrZXlzIHNvIGNhY2hlZCB2YWx1ZXMgb25seSBsYXN0IHVudGlsIHVzZXIgbG9ncyBvdXQuXG4vLyByZXZpZXcgc2Vzc2lvbiBjb2RlIHRvIGVuc3VyZSB0aGF0IHNlc3Npb24ga2V5ICphbHdheXMqIHJvdGF0ZXMgb24gbG9nb3V0LiAgTWFrZSBzZXNzaW9uIGlkIGEgcHJvdGVjdGVkIHZhbHVlLlxuY2xhc3MgUnN4X0NhY2hlIHtcbiAgICBzdGF0aWMgb25fY29yZV9kZWZpbmUoKSB7XG4gICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlcyA9IHtcbiAgICAgICAgICAgIGdsb2JhbDoge30sXG4gICAgICAgICAgICBpbnN0YW5jZToge30sXG4gICAgICAgIH07XG5cbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzX3NldCA9IDA7XG4gICAgfVxuXG4gICAgLy8gQWxpYXMgZm9yIGdldF9pbnN0YW5jZVxuICAgIHN0YXRpYyBnZXQoa2V5KSB7XG4gICAgICAgIHJldHVybiBSc3hfQ2FjaGUuZ2V0X2luc3RhbmNlKGtleSk7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBmcm9tIHRoZSBwb29sIG9mIGNhY2hlZCBkYXRhIGZvciB0aGlzICdpbnN0YW5jZScuICBBbiBpbnN0YW5jZVxuICAgIC8vIGluIHRoaXMgY2FzZSBpcyBhIHZpcnR1YWwgcGFnZSBsb2FkIC8gbmF2aWdhdGlvbiBpbiB0aGUgU1BBLiAgQ2FsbCBNYWluLmxpYi5yZXNldCgpIHRvIHJlc2V0LlxuICAgIC8vIFJldHVybnMgbnVsbCBvbiBmYWlsdXJlXG4gICAgc3RhdGljIGdldF9pbnN0YW5jZShrZXkpIHtcbiAgICAgICAgaWYgKE1haW4uZGVidWcoJ25vX2FwaV9jYWNoZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBrZXlfZW5jb2RlZCA9IFJzeF9DYWNoZS5fZW5jb2Rla2V5KGtleSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBDb3JlX0NhY2hlLl9jYWNoZXMuaW5zdGFuY2Vba2V5X2VuY29kZWRdICE9IHVuZGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShDb3JlX0NhY2hlLl9jYWNoZXMuaW5zdGFuY2Vba2V5X2VuY29kZWRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgbnVsbCBvbiBmYWlsdXJlXG4gICAgLy8gUmV0dXJucyBhIGNhY2hlZCB2YWx1ZSBmcm9tIGdsb2JhbCBjYWNoZSAodW5pcXVlIHRvIHBhZ2UgbG9hZCwgc3Vydml2ZXMgcmVzZXQoKSlcbiAgICBzdGF0aWMgZ2V0X2dsb2JhbChrZXkpIHtcbiAgICAgICAgaWYgKE1haW4uZGVidWcoJ25vX2FwaV9jYWNoZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBrZXlfZW5jb2RlZCA9IFJzeF9DYWNoZS5fZW5jb2Rla2V5KGtleSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBDb3JlX0NhY2hlLl9jYWNoZXMuZ2xvYmFsW2tleV9lbmNvZGVkXSAhPSB1bmRlZikge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoQ29yZV9DYWNoZS5fY2FjaGVzLmdsb2JhbFtrZXlfZW5jb2RlZF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gU2V0cyBhIHZhbHVlIGluIGluc3RhbmNlIGFuZCBnbG9iYWwgY2FjaGUgKG5vdCBzaGFyZWQgYmV0d2VlbiBicm93c2VyIHRhYnMpXG4gICAgc3RhdGljIHNldChrZXksIHZhbHVlKSB7XG4gICAgICAgIGlmIChNYWluLmRlYnVnKCdub19hcGlfY2FjaGUnKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUubGVuZ3RoID4gNjQgKiAxMDI0KSB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKCdDQUNIRScsICdXYXJuaW5nIC0gbm90IGNhY2hpbmcgbGFyZ2UgY2FjaGUgZW50cnknLCBrZXkpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXMuZ2xvYmFsW2tleV9lbmNvZGVkXSA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzLmluc3RhbmNlW2tleV9lbmNvZGVkXSA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcblxuICAgICAgICAvLyBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKFwiQ0FDSEVcIiwgXCJTZXRcIiwga2V5LCB2YWx1ZSk7XG5cbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzX3NldCsrO1xuXG4gICAgICAgIC8vIFJlc2V0IGNhY2hlIGFmdGVyIDUwMDAgaXRlbXMgc2V0XG4gICAgICAgIGlmIChDb3JlX0NhY2hlLl9jYWNoZXNfc2V0ID4gNTAwMCkge1xuICAgICAgICAgICAgLy8gR2V0IGFuIGFjY3VyYXRlIGNvdW50XG4gICAgICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXNfc2V0ID0gY291bnQoQ29yZV9DYWNoZS5fY2FjaGVzLmdsb2JhbCk7XG5cbiAgICAgICAgICAgIGlmIChDb3JlX0NhY2hlLl9jYWNoZXNfc2V0ID4gNTAwMCkge1xuICAgICAgICAgICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgZ2xvYmFsOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgaW5zdGFuY2U6IHt9LFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzX3NldCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIG51bGwgb24gZmFpbHVyZVxuICAgIC8vIFJldHVybnMgYSBjYWNoZWQgdmFsdWUgZnJvbSBzZXNzaW9uIGNhY2hlIChzaGFyZWQgYmV0d2VlbiBicm93c2VyIHRhYnMpXG4gICAgc3RhdGljIGdldF9zZXNzaW9uKGtleSkge1xuICAgICAgICBpZiAoTWFpbi5kZWJ1Zygnbm9fYXBpX2NhY2hlJykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFSc3hfQ2FjaGUuX3N1cHBvcnRzU3RvcmFnZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBrZXlfZW5jb2RlZCA9IFJzeF9DYWNoZS5fZW5jb2Rla2V5KGtleSk7XG5cbiAgICAgICAgbGV0IHJzID0gc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbShrZXlfZW5jb2RlZCk7XG5cbiAgICAgICAgaWYgKCFlbXB0eShycykpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKHJzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2V0cyBhIHZhbHVlIGluIHNlc3Npb24gY2FjaGUgKHNoYXJlZCBiZXR3ZWVuIGJyb3dzZXIgdGFicylcbiAgICBzdGF0aWMgc2V0X3Nlc3Npb24oa2V5LCB2YWx1ZSwgX3RyeWFnYWluID0gdHJ1ZSkge1xuICAgICAgICBpZiAoTWFpbi5kZWJ1Zygnbm9fYXBpX2NhY2hlJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPiA2NCAqIDEwMjQpIHtcbiAgICAgICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoJ0NBQ0hFJywgJ1dhcm5pbmcgLSBub3QgY2FjaGluZyBsYXJnZSBjYWNoZSBlbnRyeScsIGtleSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVJzeF9DYWNoZS5fc3VwcG9ydHNTdG9yYWdlKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2UucmVtb3ZlSXRlbShrZXlfZW5jb2RlZCk7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKGtleV9lbmNvZGVkLCBKU09OLnN0cmluZ2lmeSh2YWx1ZSkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoUnN4X0NhY2hlLl9pc091dE9mU3BhY2UoZSkgJiYgc2Vzc2lvblN0b3JhZ2UubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2UuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICBpZiAoX3RyeWFnYWluKSB7XG4gICAgICAgICAgICAgICAgICAgIENvcmVfQ2FjaGUuc2V0X3Nlc3Npb24oa2V5LCB2YWx1ZSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBfcmVzZXQoKSB7XG4gICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlcy5pbnN0YW5jZSA9IHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvciBnaXZlbiBrZXkgb2YgYW55IHR5cGUgaW5jbHVkaW5nIGFuIG9iamVjdCwgcmV0dXJuIGEgc3RyaW5nIHJlcHJlc2VudGluZ1xuICAgICAqIHRoZSBrZXkgdGhhdCB0aGUgY2FjaGVkIHZhbHVlIHNob3VsZCBiZSBzdG9yZWQgYXMgaW4gc2Vzc2lvbnN0b3JhZ2VcbiAgICAgKi9cbiAgICBzdGF0aWMgX2VuY29kZWtleShrZXkpIHtcbiAgICAgICAgY29uc3QgcHJlZml4ID0gJ2NhY2hlXyc7XG5cbiAgICAgICAgLy8gU2Vzc2lvbiByZWltcGxlbWVudFxuICAgICAgICAvLyB2YXIgcHJlZml4ID0gXCJjYWNoZV9cIiArIFNwYS5zZXNzaW9uKCkudXNlcl9pZCgpICsgXCJfXCI7XG5cbiAgICAgICAgaWYgKGlzX3N0cmluZyhrZXkpICYmIGtleS5sZW5ndGggPCAxNTAgJiYga2V5LmluZGV4T2YoJyAnKSA9PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuIHByZWZpeCArIE1hbmlmZXN0LmJ1aWxkX2tleSgpICsgJ18nICsga2V5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHByZWZpeCArIGhhc2goW01hbmlmZXN0LmJ1aWxkX2tleSgpLCBrZXldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIERldGVybWluZXMgaWYgc2Vzc2lvblN0b3JhZ2UgaXMgc3VwcG9ydGVkIGluIHRoZSBicm93c2VyO1xuICAgIC8vIHJlc3VsdCBpcyBjYWNoZWQgZm9yIGJldHRlciBwZXJmb3JtYW5jZSBpbnN0ZWFkIG9mIGJlaW5nIHJ1biBlYWNoIHRpbWUuXG4gICAgLy8gRmVhdHVyZSBkZXRlY3Rpb24gaXMgYmFzZWQgb24gaG93IE1vZGVybml6ciBkb2VzIGl0O1xuICAgIC8vIGl0J3Mgbm90IHN0cmFpZ2h0Zm9yd2FyZCBkdWUgdG8gRkY0IGlzc3Vlcy5cbiAgICAvLyBJdCdzIG5vdCBydW4gYXQgcGFyc2UtdGltZSBhcyBpdCB0YWtlcyAyMDBtcyBpbiBBbmRyb2lkLlxuICAgIC8vIENvZGUgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vcGFtZWxhZm94L2xzY2FjaGUvYmxvYi9tYXN0ZXIvbHNjYWNoZS5qcywgQXBhY2hlIExpY2Vuc2UgUGFtZWxhZm94XG4gICAgc3RhdGljIF9zdXBwb3J0c1N0b3JhZ2UoKSB7XG4gICAgICAgIGxldCBrZXkgPSAnX19jYWNoZXRlc3RfXyc7XG4gICAgICAgIGxldCB2YWx1ZSA9IGtleTtcblxuICAgICAgICBpZiAoUnN4X0NhY2hlLl9fc3VwcG9ydHNTdG9yYWdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzb21lIGJyb3dzZXJzIHdpbGwgdGhyb3cgYW4gZXJyb3IgaWYgeW91IHRyeSB0byBhY2Nlc3MgbG9jYWwgc3RvcmFnZSAoZS5nLiBicmF2ZSBicm93c2VyKVxuICAgICAgICAvLyBoZW5jZSBjaGVjayBpcyBpbnNpZGUgYSB0cnkvY2F0Y2hcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICghc2Vzc2lvblN0b3JhZ2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0oa2V5KTtcbiAgICAgICAgICAgIFJzeF9DYWNoZS5fX3N1cHBvcnRzU3RvcmFnZSA9IHRydWU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIElmIHdlIGhpdCB0aGUgbGltaXQsIGFuZCB3ZSBkb24ndCBoYXZlIGFuIGVtcHR5IHNlc3Npb25TdG9yYWdlIHRoZW4gaXQgbWVhbnMgd2UgaGF2ZSBzdXBwb3J0XG4gICAgICAgICAgICBpZiAoUnN4X0NhY2hlLl9pc091dE9mU3BhY2UoZSkgJiYgc2Vzc2lvblN0b3JhZ2UubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgUnN4X0NhY2hlLl9fc3VwcG9ydHNTdG9yYWdlID0gdHJ1ZTsgLy8ganVzdCBtYXhlZCBpdCBvdXQgYW5kIGV2ZW4gdGhlIHNldCB0ZXN0IGZhaWxlZC5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgUnN4X0NhY2hlLl9fc3VwcG9ydHNTdG9yYWdlID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUnN4X0NhY2hlLl9fc3VwcG9ydHNTdG9yYWdlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIHRvIHNldCBpZiB0aGUgZXJyb3IgaXMgdXMgZGVhbGluZyB3aXRoIGJlaW5nIG91dCBvZiBzcGFjZVxuICAgIHN0YXRpYyBfaXNPdXRPZlNwYWNlKGUpIHtcbiAgICAgICAgcmV0dXJuIGUgJiYgKGUubmFtZSA9PT0gJ1FVT1RBX0VYQ0VFREVEX0VSUicgfHwgZS5uYW1lID09PSAnTlNfRVJST1JfRE9NX1FVT1RBX1JFQUNIRUQnIHx8IGUubmFtZSA9PT0gJ1F1b3RhRXhjZWVkZWRFcnJvcicpO1xuICAgIH1cbn1cbiIsIi8qKlxuICogUnN4X0luaXQgLSBDb3JlIGZyYW1ld29yayBpbml0aWFsaXphdGlvbiBhbmQgZW52aXJvbm1lbnQgdmFsaWRhdGlvblxuICovXG5jbGFzcyBSc3hfSW5pdCB7XG4gICAgLyoqXG4gICAgICogQ2FsbGVkIHZpYSBSc3guX3JzeF9jb3JlX2Jvb3RcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgY29yZSBlbnZpcm9ubWVudCBhbmQgcnVucyBiYXNpYyBzYW5pdHkgY2hlY2tzXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfY29yZV9pbml0KCkge1xuICAgICAgICBpZiAoIVJzeC5pc19wcm9kKCkpIHtcbiAgICAgICAgICAgIFJzeF9Jbml0Ll9fZW52aXJvbm1lbnRfY2hlY2tzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXZlbG9wbWVudCBlbnZpcm9ubWVudCBjaGVja3MgdG8gZW5zdXJlIHByb3BlciBjb25maWd1cmF0aW9uXG4gICAgICovXG4gICAgc3RhdGljIF9fZW52aXJvbm1lbnRfY2hlY2tzKCkge1xuICAgICAgICAvLyBGaW5kIGFsbCBzY3JpcHQgdGFncyBpbiB0aGUgRE9NXG4gICAgICAgIGNvbnN0IHNjcmlwdHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnc2NyaXB0Jyk7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzY3JpcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBzY3JpcHQgPSBzY3JpcHRzW2ldO1xuXG4gICAgICAgICAgICAvLyBTa2lwIGlubGluZSBzY3JpcHRzIChubyBzcmMgYXR0cmlidXRlKVxuICAgICAgICAgICAgaWYgKCFzY3JpcHQuc3JjKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHNjcmlwdCBoYXMgZGVmZXIgYXR0cmlidXRlXG4gICAgICAgICAgICBpZiAoIXNjcmlwdC5kZWZlcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNyYyA9IHNjcmlwdC5zcmMgfHwgJyhpbmxpbmUgc2NyaXB0KSc7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVhc29uID0gYEFsbCBzY3JpcHQgdGFncyB1c2VkIGluIGFuIFJTcGFkZSBwcm9qZWN0IG11c3QgaGF2ZSBkZWZlciBhdHRyaWJ1dGUuIEZvdW5kIHNjcmlwdCB3aXRob3V0IGRlZmVyOiAke3NyY31gO1xuXG4gICAgICAgICAgICAgICAgLy8gU3RvcCBmcmFtZXdvcmsgYm9vdCB3aXRoIHJlYXNvblxuICAgICAgICAgICAgICAgIFJzeC5fcnN4X2NvcmVfYm9vdF9zdG9wKHJlYXNvbik7XG5cbiAgICAgICAgICAgICAgICAvLyBBbHNvIGxvZyB0byBjb25zb2xlIGZvciB2aXNpYmlsaXR5XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgW1JTWCBCT09UIFNUT1BQRURdICR7cmVhc29ufWApO1xuXG4gICAgICAgICAgICAgICAgLy8gU3RvcCBjaGVja2luZyBhZnRlciBmaXJzdCB2aW9sYXRpb25cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59IiwiLy8gQEZJTEUtU1VCQ0xBU1MtMDEtRVhDRVBUSU9OXG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgSmF2YVNjcmlwdCBPUk0gbW9kZWxzXG4gKlxuICogUHJvdmlkZXMgY29yZSBmdW5jdGlvbmFsaXR5IGZvciBmZXRjaGluZyByZWNvcmRzIGZyb20gYmFja2VuZCBQSFAgbW9kZWxzLlxuICogQWxsIG1vZGVsIHN0dWJzIGdlbmVyYXRlZCBieSB0aGUgbWFuaWZlc3QgZXh0ZW5kIHRoaXMgYmFzZSBjbGFzcy5cbiAqXG4gKiBFeGFtcGxlIHVzYWdlOlxuICogICAvLyBGZXRjaCBzaW5nbGUgcmVjb3JkXG4gKiAgIGNvbnN0IHVzZXIgPSBhd2FpdCBVc2VyX01vZGVsLmZldGNoKDEyMyk7XG4gKlxuICogICAvLyBGZXRjaCBtdWx0aXBsZSByZWNvcmRzXG4gKiAgIGNvbnN0IHVzZXJzID0gYXdhaXQgVXNlcl9Nb2RlbC5mZXRjaChbMSwgMiwgM10pO1xuICpcbiAqICAgLy8gQ3JlYXRlIGluc3RhbmNlIHdpdGggZGF0YVxuICogICBjb25zdCB1c2VyID0gbmV3IFVzZXJfTW9kZWwoe2lkOiAxLCBuYW1lOiAnSm9obid9KTtcbiAqXG4gKiAgQEluc3RhbnRpYXRhYmxlXG4gKi9cbmNsYXNzIFJzeF9Kc19Nb2RlbCB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3IgLSBJbml0aWFsaXplIG1vZGVsIGluc3RhbmNlIHdpdGggZGF0YVxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGRhdGEgLSBLZXktdmFsdWUgcGFpcnMgdG8gcG9wdWxhdGUgdGhlIG1vZGVsXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZGF0YSA9IHt9KSB7XG4gICAgICAgIC8vIF9fTU9ERUwgU1lTVEVNOiBFbmFibGVzIGF1dG9tYXRpYyBPUk0gaW5zdGFudGlhdGlvbiB3aGVuIGZldGNoaW5nIGZyb20gUEhQIG1vZGVscy5cbiAgICAgICAgLy8gUEhQIG1vZGVscyBhZGQgXCJfX01PREVMXCI6IFwiQ2xhc3NOYW1lXCIgdG8gSlNPTiwgSmF2YVNjcmlwdCB1c2VzIGl0IHRvIGNyZWF0ZSBwcm9wZXIgaW5zdGFuY2VzLlxuICAgICAgICAvLyBUaGlzIHByb3ZpZGVzIHR5cGVkIG1vZGVsIG9iamVjdHMgaW5zdGVhZCBvZiBwbGFpbiBKU09OLCB3aXRoIG1ldGhvZHMgYW5kIHR5cGUgY2hlY2tpbmcuXG5cbiAgICAgICAgLy8gVGhpcyBjb25zdHJ1Y3RvciBmaWx0ZXJzIG91dCB0aGUgX19NT0RFTCBtYXJrZXIgdGhhdCB3YXMgdXNlZCB0byBpZGVudGlmeSB3aGljaCBjbGFzc1xuICAgICAgICAvLyB0byBpbnN0YW50aWF0ZSwga2VlcGluZyBvbmx5IHRoZSBhY3R1YWwgZGF0YSBwcm9wZXJ0aWVzIG9uIHRoZSBpbnN0YW5jZS5cbiAgICAgICAgY29uc3QgeyBfX01PREVMLCAuLi5tb2RlbERhdGEgfSA9IGRhdGE7XG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgbW9kZWxEYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaCByZWNvcmQocykgZnJvbSB0aGUgYmFja2VuZCBtb2RlbFxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgbWlycm9ycyB0aGUgUEhQIE1vZGVsOjpmZXRjaCgpIGZ1bmN0aW9uYWxpdHkuXG4gICAgICogVGhlIGJhY2tlbmQgbW9kZWwgbXVzdCBoYXZlIGEgZmV0Y2goKSBtZXRob2Qgd2l0aCB0aGVcbiAgICAgKiAjW0FqYXhfRW5kcG9pbnRfTW9kZWxfRmV0Y2hdIGFubm90YXRpb24gdG8gYmUgY2FsbGFibGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxBcnJheX0gaWQgLSBTaW5nbGUgSUQgb3IgYXJyYXkgb2YgSURzIHRvIGZldGNoXG4gICAgICogQHJldHVybnMge1Byb21pc2V9IC0gU2luZ2xlIG1vZGVsIGluc3RhbmNlLCBhcnJheSBvZiBpbnN0YW5jZXMsIG9yIGZhbHNlXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGZldGNoKGlkKSB7XG4gICAgICAgIGNvbnN0IEN1cnJlbnRDbGFzcyA9IHRoaXM7XG4gICAgICAgIC8vIEdldCB0aGUgbW9kZWwgY2xhc3MgbmFtZSBmcm9tIHRoZSBjdXJyZW50IGNsYXNzXG4gICAgICAgIGNvbnN0IG1vZGVsTmFtZSA9IEN1cnJlbnRDbGFzcy5uYW1lO1xuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogYC9fZmV0Y2gvJHttb2RlbE5hbWV9YCxcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgZGF0YTogeyBpZDogaWQgfSxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEhhbmRsZSByZXNwb25zZSBiYXNlZCBvbiB0eXBlXG4gICAgICAgIGlmIChyZXNwb25zZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVzZSBfaW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZSB0byBoYW5kbGUgT1JNIGluc3RhbnRpYXRpb25cbiAgICAgICAgLy8gVGhpcyB3aWxsIGF1dG9tYXRpY2FsbHkgZGV0ZWN0IF9fTU9ERUwgcHJvcGVydGllcyBhbmQgY3JlYXRlIGFwcHJvcHJpYXRlIGluc3RhbmNlc1xuICAgICAgICByZXR1cm4gUnN4X0pzX01vZGVsLl9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlKHJlc3BvbnNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIG1vZGVsIGNsYXNzIG5hbWVcbiAgICAgKiBVc2VkIGludGVybmFsbHkgZm9yIEFQSSBjYWxsc1xuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNsYXNzIG5hbWVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0TW9kZWxOYW1lKCkge1xuICAgICAgICBjb25zdCBDdXJyZW50Q2xhc3MgPSB0aGlzO1xuICAgICAgICByZXR1cm4gQ3VycmVudENsYXNzLm5hbWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVmcmVzaCB0aGlzIGluc3RhbmNlIHdpdGggbGF0ZXN0IGRhdGEgZnJvbSBzZXJ2ZXJcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSBVcGRhdGVkIGluc3RhbmNlIG9yIGZhbHNlIGlmIG5vdCBmb3VuZFxuICAgICAqL1xuICAgIGFzeW5jIHJlZnJlc2goKSB7XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoYXQuaWQpIHtcbiAgICAgICAgICAgIHNob3VsZG50X2hhcHBlbignQ2Fubm90IHJlZnJlc2ggbW9kZWwgd2l0aG91dCBpZCBwcm9wZXJ0eScpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZnJlc2ggPSBhd2FpdCB0aGF0LmNvbnN0cnVjdG9yLmZldGNoKHRoYXQuaWQpO1xuXG4gICAgICAgIGlmIChmcmVzaCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGlzIGluc3RhbmNlIHdpdGggZnJlc2ggZGF0YVxuICAgICAgICBPYmplY3QuYXNzaWduKHRoYXQsIGZyZXNoKTtcbiAgICAgICAgcmV0dXJuIHRoYXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCBtb2RlbCBpbnN0YW5jZSB0byBwbGFpbiBvYmplY3RcbiAgICAgKiBVc2VmdWwgZm9yIHNlcmlhbGl6YXRpb24gb3Igc2VuZGluZyB0byBBUElzXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBQbGFpbiBvYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICAgKi9cbiAgICB0b09iamVjdCgpIHtcbiAgICAgICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgICAgIGNvbnN0IG9iaiA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiB0aGF0KSB7XG4gICAgICAgICAgICBpZiAodGhhdC5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIHR5cGVvZiB0aGF0W2tleV0gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBvYmpba2V5XSA9IHRoYXRba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgbW9kZWwgaW5zdGFuY2UgdG8gSlNPTiBzdHJpbmdcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEpTT04gcmVwcmVzZW50YXRpb25cbiAgICAgKi9cbiAgICB0b0pTT04oKSB7XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhhdC50b09iamVjdCgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWN1cnNpdmVseSBpbnN0YW50aWF0ZSBPUk0gbW9kZWxzIGluIHJlc3BvbnNlIGRhdGFcbiAgICAgKlxuICAgICAqIExvb2tzIGZvciBvYmplY3RzIHdpdGggX19NT0RFTCBwcm9wZXJ0eSBhbmQgaW5zdGFudGlhdGVzIHRoZSBhcHByb3ByaWF0ZVxuICAgICAqIEphdmFTY3JpcHQgbW9kZWwgY2xhc3MgaWYgaXQgZXhpc3RzIGluIHRoZSBnbG9iYWwgc2NvcGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IGRhdGEgLSBUaGUgZGF0YSB0byBwcm9jZXNzIChjYW4gYmUgYW55IHR5cGUpXG4gICAgICogQHJldHVybnMgeyp9IFRoZSBkYXRhIHdpdGggT1JNIG9iamVjdHMgaW5zdGFudGlhdGVkXG4gICAgICovXG4gICAgc3RhdGljIF9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlKGRhdGEpIHtcbiAgICAgICAgLy8gX19NT0RFTCBTWVNURU06IEVuYWJsZXMgYXV0b21hdGljIE9STSBpbnN0YW50aWF0aW9uIHdoZW4gZmV0Y2hpbmcgZnJvbSBQSFAgbW9kZWxzLlxuICAgICAgICAvLyBQSFAgbW9kZWxzIGFkZCBcIl9fTU9ERUxcIjogXCJDbGFzc05hbWVcIiB0byBKU09OLCBKYXZhU2NyaXB0IHVzZXMgaXQgdG8gY3JlYXRlIHByb3BlciBpbnN0YW5jZXMuXG4gICAgICAgIC8vIFRoaXMgcHJvdmlkZXMgdHlwZWQgbW9kZWwgb2JqZWN0cyBpbnN0ZWFkIG9mIHBsYWluIEpTT04sIHdpdGggbWV0aG9kcyBhbmQgdHlwZSBjaGVja2luZy5cblxuICAgICAgICAvLyBUaGlzIHJlY3Vyc2l2ZSBwcm9jZXNzb3Igc2NhbnMgYWxsIEFQSSByZXNwb25zZSBkYXRhIGxvb2tpbmcgZm9yIF9fTU9ERUwgbWFya2Vycy5cbiAgICAgICAgLy8gV2hlbiBmb3VuZCwgaXQgYXR0ZW1wdHMgdG8gaW5zdGFudGlhdGUgdGhlIGFwcHJvcHJpYXRlIEphdmFTY3JpcHQgbW9kZWwgY2xhc3MsXG4gICAgICAgIC8vIGNvbnZlcnRpbmcge19fTU9ERUw6IFwiVXNlcl9Nb2RlbFwiLCBpZDogMSwgbmFtZTogXCJKb2huXCJ9IGludG8gbmV3IFVzZXJfTW9kZWwoey4uLn0pLlxuICAgICAgICAvLyBXb3JrcyByZWN1cnNpdmVseSB0aHJvdWdoIGFycmF5cyBhbmQgbmVzdGVkIG9iamVjdHMgdG8gaGFuZGxlIGNvbXBsZXggZGF0YSBzdHJ1Y3R1cmVzLlxuICAgICAgICAvLyBIYW5kbGUgbnVsbC91bmRlZmluZWRcbiAgICAgICAgaWYgKGRhdGEgPT09IG51bGwgfHwgZGF0YSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSBhcnJheXMgLSByZWN1cnNpdmVseSBwcm9jZXNzIGVhY2ggZWxlbWVudFxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGEubWFwKChpdGVtKSA9PiBSc3hfSnNfTW9kZWwuX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUoaXRlbSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIG9iamVjdHNcbiAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBvYmplY3QgaGFzIGEgX19NT0RFTCBwcm9wZXJ0eVxuICAgICAgICAgICAgaWYgKGRhdGEuX19NT0RFTCAmJiB0eXBlb2YgZGF0YS5fX01PREVMID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIC8vIFRyeSB0byBmaW5kIHRoZSBtb2RlbCBjbGFzcyBpbiB0aGUgZ2xvYmFsIHNjb3BlXG4gICAgICAgICAgICAgICAgY29uc3QgTW9kZWxDbGFzcyA9IHdpbmRvd1tkYXRhLl9fTU9ERUxdO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG1vZGVsIGNsYXNzIGV4aXN0cyBhbmQgZXh0ZW5kcyBSc3hfSnNfTW9kZWwsIGluc3RhbnRpYXRlIGl0XG4gICAgICAgICAgICAgICAgLy8gRHluYW1pYyBtb2RlbCByZXNvbHV0aW9uIHJlcXVpcmVzIGNoZWNraW5nIGNsYXNzIGV4aXN0ZW5jZSAtIEBKUy1ERUZFTlNJVkUtMDEtRVhDRVBUSU9OXG4gICAgICAgICAgICAgICAgaWYgKE1vZGVsQ2xhc3MgJiYgTW9kZWxDbGFzcy5wcm90b3R5cGUgaW5zdGFuY2VvZiBSc3hfSnNfTW9kZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBNb2RlbENsYXNzKGRhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmVjdXJzaXZlbHkgcHJvY2VzcyBhbGwgb2JqZWN0IHByb3BlcnRpZXNcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSBSc3hfSnNfTW9kZWwuX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUoZGF0YVtrZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0dXJuIHByaW1pdGl2ZSB2YWx1ZXMgYXMtaXNcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxufVxuIiwiLyoqXG4gKiBWaWV3X1RyYW5zaXRpb25zIC0gU21vb3RoIHBhZ2UtdG8tcGFnZSB0cmFuc2l0aW9ucyB1c2luZyBWaWV3IFRyYW5zaXRpb25zIEFQSVxuICpcbiAqIEVuYWJsZXMgY3Jvc3MtZG9jdW1lbnQgdmlldyB0cmFuc2l0aW9ucyBzbyB0aGUgYnJvd3NlciBkb2Vzbid0IHBhaW50IHRoZSBuZXcgcGFnZVxuICogdW50aWwgaXQncyByZWFkeSwgY3JlYXRpbmcgc21vb3RoIGFuaW1hdGlvbnMgYmV0d2VlbiBwYWdlcy5cbiAqXG4gKiBGYWxscyBiYWNrIGdyYWNlZnVsbHkgaWYgVmlldyBUcmFuc2l0aW9ucyBBUEkgaXMgbm90IGF2YWlsYWJsZS5cbiAqL1xuY2xhc3MgUnN4X1ZpZXdfVHJhbnNpdGlvbnMge1xuICAgIC8qKlxuICAgICAqIENhbGxlZCBkdXJpbmcgZnJhbWV3b3JrIGNvcmUgaW5pdCBwaGFzZVxuICAgICAqIENoZWNrcyBmb3IgVmlldyBUcmFuc2l0aW9ucyBBUEkgc3VwcG9ydCBhbmQgZW5hYmxlcyBpZiBhdmFpbGFibGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19jb3JlX2luaXQoKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIFZpZXcgVHJhbnNpdGlvbnMgQVBJIGlzIHN1cHBvcnRlZFxuICAgICAgICBpZiAoIWRvY3VtZW50LnN0YXJ0Vmlld1RyYW5zaXRpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGVfZGVidWcoJ1ZJRVdfVFJBTlNJVElPTlMnLCAnVmlldyBUcmFuc2l0aW9ucyBBUEkgbm90IHN1cHBvcnRlZCwgc2tpcHBpbmcnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVuYWJsZSBjcm9zcy1kb2N1bWVudCB2aWV3IHRyYW5zaXRpb25zIHZpYSBDU1NcbiAgICAgICAgUnN4X1ZpZXdfVHJhbnNpdGlvbnMuX2luamVjdF90cmFuc2l0aW9uX2NzcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluamVjdCBDU1MgdG8gZW5hYmxlIGNyb3NzLWRvY3VtZW50IHZpZXcgdHJhbnNpdGlvbnNcbiAgICAgKlxuICAgICAqIFRoZSBAdmlldy10cmFuc2l0aW9uIHsgbmF2aWdhdGlvbjogYXV0bzsgfSBydWxlIHRlbGxzIHRoZSBicm93c2VyIHRvOlxuICAgICAqIDEuIENhcHR1cmUgYSBzbmFwc2hvdCBvZiB0aGUgY3VycmVudCBwYWdlIGJlZm9yZSBuYXZpZ2F0aW9uXG4gICAgICogMi4gRmV0Y2ggdGhlIG5ldyBwYWdlXG4gICAgICogMy4gV2FpdCB1bnRpbCB0aGUgbmV3IHBhZ2UgaXMgZnVsbHkgbG9hZGVkIGFuZCBwYWludGVkIChkb2N1bWVudC5yZWFkeSlcbiAgICAgKiA0LiBBbmltYXRlIHNtb290aGx5IGJldHdlZW4gdGhlIHR3byBzdGF0ZXNcbiAgICAgKlxuICAgICAqIFRoaXMgcHJldmVudHMgdGhlIHdoaXRlIGZsYXNoIGR1cmluZyBuYXZpZ2F0aW9uIGFuZCBjcmVhdGVzIGFwcC1saWtlIHRyYW5zaXRpb25zLlxuICAgICAqL1xuICAgIHN0YXRpYyBfaW5qZWN0X3RyYW5zaXRpb25fY3NzKCkge1xuICAgICAgICBjb25zdCBzdHlsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XG5cbiAgICAgICAgc3R5bGUudGV4dENvbnRlbnQgPSBgXG4gICAgICAgICAgICBAdmlldy10cmFuc2l0aW9uIHtcbiAgICAgICAgICAgICAgICBuYXZpZ2F0aW9uOiBhdXRvO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKiBEaXNhYmxlIGFuaW1hdGlvbiAtIGluc3RhbnQgdHJhbnNpdGlvbiAqL1xuICAgICAgICAgICAgOjp2aWV3LXRyYW5zaXRpb24tZ3JvdXAoKiksXG4gICAgICAgICAgICA6OnZpZXctdHJhbnNpdGlvbi1vbGQoKiksXG4gICAgICAgICAgICA6OnZpZXctdHJhbnNpdGlvbi1uZXcoKikge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbi1kdXJhdGlvbjogMHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIGA7XG5cbiAgICAgICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzdHlsZSk7XG4gICAgfVxufVxuIiwiLyoqXG4gKiBSZWFkV3JpdGVMb2NrIGltcGxlbWVudGF0aW9uIGZvciBSU3BhZGUgZnJhbWV3b3JrXG4gKiBQcm92aWRlcyBleGNsdXNpdmUgKHdyaXRlKSBhbmQgc2hhcmVkIChyZWFkKSBsb2NraW5nIG1lY2hhbmlzbXMgZm9yIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zXG4gKi9cbmNsYXNzIFJlYWRXcml0ZUxvY2sge1xuICAgIHN0YXRpYyAjbG9ja3MgPSBuZXcgTWFwKCk7XG5cbiAgICAvKipcbiAgICAgKiBHZXQgb3IgY3JlYXRlIGEgbG9jayBvYmplY3QgZm9yIGEgZ2l2ZW4gbmFtZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljICNnZXRfbG9jayhuYW1lKSB7XG4gICAgICAgIGxldCBzID0gdGhpcy4jbG9ja3MuZ2V0KG5hbWUpO1xuICAgICAgICBpZiAoIXMpIHtcbiAgICAgICAgICAgIHMgPSB7IHJlYWRlcnM6IDAsIHdyaXRlcl9hY3RpdmU6IGZhbHNlLCByZWFkZXJfcTogW10sIHdyaXRlcl9xOiBbXSB9O1xuICAgICAgICAgICAgdGhpcy4jbG9ja3Muc2V0KG5hbWUsIHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjaGVkdWxlIHRoZSBuZXh0IG9wZXJhdGlvbiBmb3IgYSBsb2NrXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgI3NjaGVkdWxlKG5hbWUpIHtcbiAgICAgICAgY29uc3QgcyA9IHRoaXMuI2dldF9sb2NrKG5hbWUpO1xuICAgICAgICBpZiAocy53cml0ZXJfYWN0aXZlIHx8IHMucmVhZGVycyA+IDApIHJldHVybjtcblxuICAgICAgICAvLyBydW4gb25lIHdyaXRlciBpZiBxdWV1ZWRcbiAgICAgICAgaWYgKHMud3JpdGVyX3EubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgeyBjYiwgcmVzb2x2ZSwgcmVqZWN0IH0gPSBzLndyaXRlcl9xLnNoaWZ0KCk7XG4gICAgICAgICAgICBzLndyaXRlcl9hY3RpdmUgPSB0cnVlO1xuICAgICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAgICAgICAudGhlbihjYilcbiAgICAgICAgICAgICAgICAudGhlbihyZXNvbHZlLCByZWplY3QpXG4gICAgICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzLndyaXRlcl9hY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4jc2NoZWR1bGUobmFtZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBvdGhlcndpc2UgcnVuIGFsbCBxdWV1ZWQgcmVhZGVycyBpbiBwYXJhbGxlbFxuICAgICAgICBpZiAocy5yZWFkZXJfcS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBiYXRjaCA9IHMucmVhZGVyX3Euc3BsaWNlKDApO1xuICAgICAgICAgICAgcy5yZWFkZXJzICs9IGJhdGNoLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAoY29uc3QgeyBjYiwgcmVzb2x2ZSwgcmVqZWN0IH0gb2YgYmF0Y2gpIHtcbiAgICAgICAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbihjYilcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KVxuICAgICAgICAgICAgICAgICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzLnJlYWRlcnMgLT0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzLnJlYWRlcnMgPT09IDApIHRoaXMuI3NjaGVkdWxlKG5hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFjcXVpcmUgYW4gZXhjbHVzaXZlIG11dGV4IGxvY2sgYnkgbmFtZS5cbiAgICAgKiBPbmx5IG9uZSB3cml0ZXIgcnVucyBhdCBhIHRpbWU7IGJsb2NrcyByZWFkZXJzIHVudGlsIGZpbmlzaGVkLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICogQHBhcmFtIHsoKSA9PiBhbnl8UHJvbWlzZTxhbnk+fSBjYlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAgICovXG4gICAgc3RhdGljIGFjcXVpcmUobmFtZSwgY2IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHMgPSB0aGlzLiNnZXRfbG9jayhuYW1lKTtcbiAgICAgICAgICAgIHMud3JpdGVyX3EucHVzaCh7IGNiLCByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICB0aGlzLiNzY2hlZHVsZShuYW1lKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWNxdWlyZSBhIHNoYXJlZCByZWFkIGxvY2sgYnkgbmFtZS5cbiAgICAgKiBNdWx0aXBsZSByZWFkZXJzIGNhbiBydW4gaW4gcGFyYWxsZWw7IGJsb2NrcyB3aGVuIHdyaXRlciBpcyBhY3RpdmUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0geygpID0+IGFueXxQcm9taXNlPGFueT59IGNiXG4gICAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYWNxdWlyZV9yZWFkKG5hbWUsIGNiKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzID0gdGhpcy4jZ2V0X2xvY2sobmFtZSk7XG4gICAgICAgICAgICBpZiAocy53cml0ZXJfYWN0aXZlIHx8IHMud3JpdGVyX3EubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHMucmVhZGVyX3EucHVzaCh7IGNiLCByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuI3NjaGVkdWxlKG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcy5yZWFkZXJzICs9IDE7XG4gICAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgICAgIC50aGVuKGNiKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlc29sdmUsIHJlamVjdClcbiAgICAgICAgICAgICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHMucmVhZGVycyAtPSAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAocy5yZWFkZXJzID09PSAwKSB0aGlzLiNzY2hlZHVsZShuYW1lKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yY2UtdW5sb2NrIGEgbXV0ZXggKHVzZSB3aXRoIGNhdXRpb24pLlxuICAgICAqIENvbXBsZXRlbHkgcmVtb3ZlcyB0aGUgbG9jayBzdGF0ZSwgcG90ZW50aWFsbHkgYnJlYWtpbmcgd2FpdGluZyBvcGVyYXRpb25zLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICovXG4gICAgc3RhdGljIGZvcmNlX3VubG9jayhuYW1lKSB7XG4gICAgICAgIHRoaXMuI2xvY2tzLmRlbGV0ZShuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgaW5mb3JtYXRpb24gYWJvdXQgcGVuZGluZyBvcGVyYXRpb25zIG9uIGEgbXV0ZXguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcmV0dXJucyB7e3JlYWRlcnM6IG51bWJlciwgd3JpdGVyX2FjdGl2ZTogYm9vbGVhbiwgcmVhZGVyX3E6IG51bWJlciwgd3JpdGVyX3E6IG51bWJlcn19XG4gICAgICovXG4gICAgc3RhdGljIHBlbmRpbmcobmFtZSkge1xuICAgICAgICBjb25zdCBzID0gdGhpcy4jbG9ja3MuZ2V0KG5hbWUpO1xuICAgICAgICBpZiAoIXMpIHJldHVybiB7IHJlYWRlcnM6IDAsIHdyaXRlcl9hY3RpdmU6IGZhbHNlLCByZWFkZXJfcTogMCwgd3JpdGVyX3E6IDAgfTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlYWRlcnM6IHMucmVhZGVycyxcbiAgICAgICAgICAgIHdyaXRlcl9hY3RpdmU6IHMud3JpdGVyX2FjdGl2ZSxcbiAgICAgICAgICAgIHJlYWRlcl9xOiBzLnJlYWRlcl9xLmxlbmd0aCxcbiAgICAgICAgICAgIHdyaXRlcl9xOiBzLndyaXRlcl9xLmxlbmd0aFxuICAgICAgICB9O1xuICAgIH1cbn0iLCIvKipcbiAqIEZvcm0gdXRpbGl0aWVzIGZvciB2YWxpZGF0aW9uIGFuZCBlcnJvciBoYW5kbGluZ1xuICovXG5jbGFzcyBGb3JtX1V0aWxzIHtcbiAgICAvKipcbiAgICAgKiBGcmFtZXdvcmsgaW5pdGlhbGl6YXRpb24gaG9vayB0byByZWdpc3RlciBqUXVlcnkgcGx1Z2luXG4gICAgICogQ3JlYXRlcyAkLmZuLmFqYXhfc3VibWl0KCkgZm9yIGZvcm0gZWxlbWVudHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfZGVmaW5lKHBhcmFtcyA9IHt9KSB7XG4gICAgICAgICQuZm4uYWpheF9zdWJtaXQgPSBmdW5jdGlvbihvcHRpb25zID0ge30pIHtcbiAgICAgICAgICAgIGNvbnN0ICRlbGVtZW50ID0gJCh0aGlzKTtcblxuICAgICAgICAgICAgaWYgKCEkZWxlbWVudC5pcygnZm9ybScpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhamF4X3N1Ym1pdCgpIGNhbiBvbmx5IGJlIGNhbGxlZCBvbiBmb3JtIGVsZW1lbnRzJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9ICRlbGVtZW50LmF0dHIoJ2FjdGlvbicpO1xuICAgICAgICAgICAgaWYgKCF1cmwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Zvcm0gbXVzdCBoYXZlIGFuIGFjdGlvbiBhdHRyaWJ1dGUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgeyBjb250cm9sbGVyLCBhY3Rpb24gfSA9IEFqYXguYWpheF91cmxfdG9fY29udHJvbGxlcl9hY3Rpb24odXJsKTtcblxuICAgICAgICAgICAgcmV0dXJuIEZvcm1fVXRpbHMuYWpheF9zdWJtaXQoJGVsZW1lbnQsIGNvbnRyb2xsZXIsIGFjdGlvbiwgb3B0aW9ucyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvd3MgZm9ybSB2YWxpZGF0aW9uIGVycm9yc1xuICAgICAqXG4gICAgICogUkVRVUlSRUQgSFRNTCBTVFJVQ1RVUkU6XG4gICAgICogRm9yIGlubGluZSBmaWVsZCBlcnJvcnMgdG8gZGlzcGxheSBwcm9wZXJseSwgZm9ybSBmaWVsZHMgbXVzdCBmb2xsb3cgdGhpcyBzdHJ1Y3R1cmU6XG4gICAgICpcbiAgICAgKiA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAqICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiIGZvcj1cImZpZWxkLW5hbWVcIj5GaWVsZCBMYWJlbDwvbGFiZWw+XG4gICAgICogICA8aW5wdXQgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBpZD1cImZpZWxkLW5hbWVcIiBuYW1lPVwiZmllbGQtbmFtZVwiIHR5cGU9XCJ0ZXh0XCI+XG4gICAgICogPC9kaXY+XG4gICAgICpcbiAgICAgKiBLZXkgcmVxdWlyZW1lbnRzOlxuICAgICAqIC0gV3JhcCBlYWNoIGZpZWxkIGluIGEgY29udGFpbmVyIHdpdGggY2xhc3MgXCJmb3JtLWdyb3VwXCIgKG9yIFwiZm9ybS1jaGVja1wiIC8gXCJpbnB1dC1ncm91cFwiKVxuICAgICAqIC0gSW5wdXQgbXVzdCBoYXZlIGEgXCJuYW1lXCIgYXR0cmlidXRlIG1hdGNoaW5nIHRoZSBlcnJvciBrZXlcbiAgICAgKiAtIFVzZSBcImZvcm0tY29udHJvbFwiIGNsYXNzIG9uIGlucHV0cyBmb3IgQm9vdHN0cmFwIDUgc3R5bGluZ1xuICAgICAqXG4gICAgICogQWNjZXB0cyB0aHJlZSBmb3JtYXRzOlxuICAgICAqIC0gU3RyaW5nOiBTaW5nbGUgZXJyb3Igc2hvd24gYXMgYWxlcnRcbiAgICAgKiAtIEFycmF5IG9mIHN0cmluZ3M6IE11bHRpcGxlIGVycm9ycyBzaG93biBhcyBidWxsZXRlZCBhbGVydFxuICAgICAqIC0gT2JqZWN0OiBGaWVsZCBuYW1lcyBtYXBwZWQgdG8gZXJyb3JzLCBzaG93biBpbmxpbmUgKHVubWF0Y2hlZCBzaG93biBhcyBhbGVydClcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJlbnRfc2VsZWN0b3IgLSBqUXVlcnkgc2VsZWN0b3IgZm9yIHBhcmVudCBlbGVtZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmd8T2JqZWN0fEFycmF5fSBlcnJvcnMgLSBFcnJvciBtZXNzYWdlcyB0byBkaXNwbGF5XG4gICAgICogQHJldHVybnMge1Byb21pc2V9IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBhbmltYXRpb25zIGNvbXBsZXRlXG4gICAgICovXG4gICAgc3RhdGljIGFwcGx5X2Zvcm1fZXJyb3JzKHBhcmVudF9zZWxlY3RvciwgZXJyb3JzKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3JzKTtcblxuICAgICAgICBjb25zdCAkcGFyZW50ID0gJChwYXJlbnRfc2VsZWN0b3IpO1xuXG4gICAgICAgIC8vIFJlc2V0IHRoZSBmb3JtIGVycm9ycyBiZWZvcmUgYXBwbHlpbmcgbmV3IG9uZXNcbiAgICAgICAgRm9ybV9VdGlscy5yZXNldF9mb3JtX2Vycm9ycyhwYXJlbnRfc2VsZWN0b3IpO1xuXG4gICAgICAgIC8vIE5vcm1hbGl6ZSBpbnB1dCB0byBzdGFuZGFyZCBmb3JtYXRcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZCA9IEZvcm1fVXRpbHMuX25vcm1hbGl6ZV9lcnJvcnMoZXJyb3JzKTtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIGxldCBhbmltYXRpb25zID0gW107XG5cbiAgICAgICAgICAgIGlmIChub3JtYWxpemVkLnR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgLy8gU2luZ2xlIGVycm9yIG1lc3NhZ2VcbiAgICAgICAgICAgICAgICBhbmltYXRpb25zID0gRm9ybV9VdGlscy5fYXBwbHlfZ2VuZXJhbF9lcnJvcnMoJHBhcmVudCwgbm9ybWFsaXplZC5kYXRhKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobm9ybWFsaXplZC50eXBlID09PSAnYXJyYXknKSB7XG4gICAgICAgICAgICAgICAgLy8gQXJyYXkgb2YgZXJyb3IgbWVzc2FnZXNcbiAgICAgICAgICAgICAgICBjb25zdCBkZWR1cGxpY2F0ZWQgPSBGb3JtX1V0aWxzLl9kZWR1cGxpY2F0ZV9lcnJvcnMobm9ybWFsaXplZC5kYXRhKTtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25zID0gRm9ybV9VdGlscy5fYXBwbHlfZ2VuZXJhbF9lcnJvcnMoJHBhcmVudCwgZGVkdXBsaWNhdGVkKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobm9ybWFsaXplZC50eXBlID09PSAnZmllbGRzJykge1xuICAgICAgICAgICAgICAgIC8vIEZpZWxkLXNwZWNpZmljIGVycm9yc1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IEZvcm1fVXRpbHMuX2FwcGx5X2ZpZWxkX2Vycm9ycygkcGFyZW50LCBub3JtYWxpemVkLmRhdGEpO1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMgPSByZXN1bHQuYW5pbWF0aW9ucztcblxuICAgICAgICAgICAgICAgIC8vIENvdW50IG1hdGNoZWQgZmllbGRzXG4gICAgICAgICAgICAgICAgY29uc3QgbWF0Y2hlZF9jb3VudCA9IE9iamVjdC5rZXlzKG5vcm1hbGl6ZWQuZGF0YSkubGVuZ3RoIC0gT2JqZWN0LmtleXMocmVzdWx0LnVubWF0Y2hlZCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNvbnN0IHVubWF0Y2hlZF9kZWR1cGxpY2F0ZWQgPSBGb3JtX1V0aWxzLl9kZWR1cGxpY2F0ZV9lcnJvcnMocmVzdWx0LnVubWF0Y2hlZCk7XG4gICAgICAgICAgICAgICAgY29uc3QgdW5tYXRjaGVkX2NvdW50ID0gT2JqZWN0LmtleXModW5tYXRjaGVkX2RlZHVwbGljYXRlZCkubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgLy8gU2hvdyBzdW1tYXJ5IGFsZXJ0IGlmIHRoZXJlIGFyZSBhbnkgZmllbGQgZXJyb3JzIChtYXRjaGVkIG9yIHVubWF0Y2hlZClcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hlZF9jb3VudCA+IDAgfHwgdW5tYXRjaGVkX2NvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBCdWlsZCBzdW1tYXJ5IG1lc3NhZ2VcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN1bW1hcnlfbXNnID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaGVkX2NvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyeV9tc2cgPSBtYXRjaGVkX2NvdW50ID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAnUGxlYXNlIGNvcnJlY3QgdGhlIGVycm9yIGhpZ2hsaWdodGVkIGJlbG93LidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdQbGVhc2UgY29ycmVjdCB0aGUgZXJyb3JzIGhpZ2hsaWdodGVkIGJlbG93Lic7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgdW5tYXRjaGVkIGVycm9ycywgYWRkIHRoZW0gYXMgYSBidWxsZXRlZCBsaXN0XG4gICAgICAgICAgICAgICAgICAgIGlmICh1bm1hdGNoZWRfY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdW1tYXJ5X2FuaW1hdGlvbnMgPSBGb3JtX1V0aWxzLl9hcHBseV9jb21iaW5lZF9lcnJvcigkcGFyZW50LCBzdW1tYXJ5X21zZywgdW5tYXRjaGVkX2RlZHVwbGljYXRlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbmltYXRpb25zLnB1c2goLi4uc3VtbWFyeV9hbmltYXRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEp1c3QgdGhlIHN1bW1hcnkgbWVzc2FnZSwgbm8gdW5tYXRjaGVkIGVycm9yc1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3VtbWFyeV9hbmltYXRpb25zID0gRm9ybV9VdGlscy5fYXBwbHlfZ2VuZXJhbF9lcnJvcnMoJHBhcmVudCwgc3VtbWFyeV9tc2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKC4uLnN1bW1hcnlfYW5pbWF0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJlc29sdmUgdGhlIHByb21pc2Ugb25jZSBhbGwgYW5pbWF0aW9ucyBhcmUgY29tcGxldGVcbiAgICAgICAgICAgIFByb21pc2UuYWxsKGFuaW1hdGlvbnMpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFNjcm9sbCB0byBlcnJvciBjb250YWluZXIgaWYgaXQgZXhpc3RzXG4gICAgICAgICAgICAgICAgY29uc3QgJGVycm9yX2NvbnRhaW5lciA9ICRwYXJlbnQuZmluZCgnW2RhdGEtaWQ9XCJlcnJvcl9jb250YWluZXJcIl0nKS5maXJzdCgpO1xuICAgICAgICAgICAgICAgIGlmICgkZXJyb3JfY29udGFpbmVyLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGFpbmVyX3RvcCA9ICRlcnJvcl9jb250YWluZXIub2Zmc2V0KCkudG9wO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBmaXhlZCBoZWFkZXIgb2Zmc2V0XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpeGVkX2hlYWRlcl9oZWlnaHQgPSBGb3JtX1V0aWxzLl9nZXRfZml4ZWRfaGVhZGVyX2hlaWdodCgpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNjcm9sbCB0byBwb3NpdGlvbiBlcnJvciBjb250YWluZXIgMjBweCBiZWxvdyBhbnkgZml4ZWQgaGVhZGVyc1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXRfc2Nyb2xsID0gY29udGFpbmVyX3RvcCAtIGZpeGVkX2hlYWRlcl9oZWlnaHQgLSAyMDtcbiAgICAgICAgICAgICAgICAgICAgJCgnaHRtbCwgYm9keScpLmFuaW1hdGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsVG9wOiB0YXJnZXRfc2Nyb2xsXG4gICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFycyBmb3JtIHZhbGlkYXRpb24gZXJyb3JzIGFuZCByZXNldHMgYWxsIGZvcm0gdmFsdWVzIHRvIGRlZmF1bHRzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8alF1ZXJ5fSBmb3JtX3NlbGVjdG9yIC0galF1ZXJ5IHNlbGVjdG9yIG9yIGpRdWVyeSBvYmplY3QgZm9yIGZvcm0gZWxlbWVudFxuICAgICAqL1xuICAgIHN0YXRpYyByZXNldChmb3JtX3NlbGVjdG9yKSB7XG4gICAgICAgIGNvbnN0ICRmb3JtID0gdHlwZW9mIGZvcm1fc2VsZWN0b3IgPT09ICdzdHJpbmcnID8gJChmb3JtX3NlbGVjdG9yKSA6IGZvcm1fc2VsZWN0b3I7XG5cbiAgICAgICAgRm9ybV9VdGlscy5yZXNldF9mb3JtX2Vycm9ycyhmb3JtX3NlbGVjdG9yKTtcbiAgICAgICAgJGZvcm0udHJpZ2dlcigncmVzZXQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemVzIGZvcm0gZGF0YSBpbnRvIGtleS12YWx1ZSBvYmplY3RcbiAgICAgKiBSZXR1cm5zIGFsbCBpbnB1dCBlbGVtZW50cyB3aXRoIG5hbWUgYXR0cmlidXRlcyBhcyBvYmplY3QgcHJvcGVydGllc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfGpRdWVyeX0gZm9ybV9zZWxlY3RvciAtIGpRdWVyeSBzZWxlY3RvciBvciBqUXVlcnkgb2JqZWN0IGZvciBmb3JtIGVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBGb3JtIGRhdGEgYXMga2V5LXZhbHVlIHBhaXJzXG4gICAgICovXG4gICAgc3RhdGljIHNlcmlhbGl6ZShmb3JtX3NlbGVjdG9yKSB7XG4gICAgICAgIGNvbnN0ICRmb3JtID0gdHlwZW9mIGZvcm1fc2VsZWN0b3IgPT09ICdzdHJpbmcnID8gJChmb3JtX3NlbGVjdG9yKSA6IGZvcm1fc2VsZWN0b3I7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB7fTtcblxuICAgICAgICAkZm9ybS5zZXJpYWxpemVBcnJheSgpLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgICAgIGRhdGFbaXRlbS5uYW1lXSA9IGl0ZW0udmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1Ym1pdHMgZm9ybSB0byBSU1ggY29udHJvbGxlciBhY3Rpb24gdmlhIEFKQVhcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xqUXVlcnl9IGZvcm1fc2VsZWN0b3IgLSBqUXVlcnkgc2VsZWN0b3Igb3IgalF1ZXJ5IG9iamVjdCBmb3IgZm9ybSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNvbnRyb2xsZXIgLSBDb250cm9sbGVyIGNsYXNzIG5hbWUgKGUuZy4sICdVc2VyX0NvbnRyb2xsZXInKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24gLSBBY3Rpb24gbWV0aG9kIG5hbWUgKGUuZy4sICdzYXZlX3Byb2ZpbGUnKVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3B0aW9uYWwgY29uZmlndXJhdGlvbiB7b25fc3VjY2VzczogZm4sIG9uX2Vycm9yOiBmbn1cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggcmVzcG9uc2UgZGF0YVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBhamF4X3N1Ym1pdChmb3JtX3NlbGVjdG9yLCBjb250cm9sbGVyLCBhY3Rpb24sIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCAkZm9ybSA9IHR5cGVvZiBmb3JtX3NlbGVjdG9yID09PSAnc3RyaW5nJyA/ICQoZm9ybV9zZWxlY3RvcikgOiBmb3JtX3NlbGVjdG9yO1xuICAgICAgICBjb25zdCBmb3JtX2RhdGEgPSBGb3JtX1V0aWxzLnNlcmlhbGl6ZSgkZm9ybSk7XG5cbiAgICAgICAgRm9ybV9VdGlscy5yZXNldF9mb3JtX2Vycm9ycyhmb3JtX3NlbGVjdG9yKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBBamF4LmNhbGwoY29udHJvbGxlciwgYWN0aW9uLCBmb3JtX2RhdGEpO1xuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5vbl9zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy5vbl9zdWNjZXNzKHJlc3BvbnNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgaWYgKGVycm9yLnR5cGUgPT09ICdmb3JtX2Vycm9yJyAmJiBlcnJvci5kZXRhaWxzKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgRm9ybV9VdGlscy5hcHBseV9mb3JtX2Vycm9ycyhmb3JtX3NlbGVjdG9yLCBlcnJvci5kZXRhaWxzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgRm9ybV9VdGlscy5hcHBseV9mb3JtX2Vycm9ycyhmb3JtX3NlbGVjdG9yLCBlcnJvci5tZXNzYWdlIHx8ICdBbiBlcnJvciBvY2N1cnJlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5vbl9lcnJvcikge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMub25fZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgZm9ybSB2YWxpZGF0aW9uIGVycm9yc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJlbnRfc2VsZWN0b3IgLSBqUXVlcnkgc2VsZWN0b3IgZm9yIHBhcmVudCBlbGVtZW50XG4gICAgICovXG4gICAgc3RhdGljIHJlc2V0X2Zvcm1fZXJyb3JzKHBhcmVudF9zZWxlY3Rvcikge1xuICAgICAgICBjb25zdCAkcGFyZW50ID0gJChwYXJlbnRfc2VsZWN0b3IpO1xuXG4gICAgICAgIC8vIFJlbW92ZSBmbGFzaCBtZXNzYWdlc1xuICAgICAgICAkKCcuZmxhc2gtbWVzc2FnZXMnKS5yZW1vdmUoKTtcblxuICAgICAgICAvLyBSZW1vdmUgYWxlcnQtZGFuZ2VyIG1lc3NhZ2VzXG4gICAgICAgICRwYXJlbnQuZmluZCgnLmFsZXJ0LWRhbmdlcicpLnJlbW92ZSgpO1xuXG4gICAgICAgIC8vIFJlbW92ZSB2YWxpZGF0aW9uIGVycm9yIGNsYXNzZXMgYW5kIHRleHQgZnJvbSBmb3JtIGVsZW1lbnRzXG4gICAgICAgICRwYXJlbnQuZmluZCgnLmlzLWludmFsaWQnKS5yZW1vdmVDbGFzcygnaXMtaW52YWxpZCcpO1xuICAgICAgICAkcGFyZW50LmZpbmQoJy5pbnZhbGlkLWZlZWRiYWNrJykucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgICAvKipcbiAgICAgKiBOb3JtYWxpemVzIGVycm9yIGlucHV0IGludG8gc3RhbmRhcmQgZm9ybWF0c1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfE9iamVjdHxBcnJheX0gZXJyb3JzIC0gUmF3IGVycm9yIGlucHV0XG4gICAgICogQHJldHVybnMge09iamVjdH0gTm9ybWFsaXplZCBlcnJvcnMgYXMge3R5cGU6ICdzdHJpbmcnfCdhcnJheSd8J2ZpZWxkcycsIGRhdGE6IC4uLn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfbm9ybWFsaXplX2Vycm9ycyhlcnJvcnMpIHtcbiAgICAgICAgLy8gSGFuZGxlIG51bGwvdW5kZWZpbmVkXG4gICAgICAgIGlmICghZXJyb3JzKSB7XG4gICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnc3RyaW5nJywgZGF0YTogJ0FuIGVycm9yIGhhcyBvY2N1cnJlZCcgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSBzdHJpbmdcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvcnMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnc3RyaW5nJywgZGF0YTogZXJyb3JzIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIYW5kbGUgYXJyYXlcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZXJyb3JzKSkge1xuICAgICAgICAgICAgLy8gQXJyYXkgb2Ygc3RyaW5ncyAtIGdlbmVyYWwgZXJyb3JzXG4gICAgICAgICAgICBpZiAoZXJyb3JzLmV2ZXJ5KChlKSA9PiB0eXBlb2YgZSA9PT0gJ3N0cmluZycpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2FycmF5JywgZGF0YTogZXJyb3JzIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBcnJheSB3aXRoIG9iamVjdCBhcyBmaXJzdCBlbGVtZW50IC0gZXh0cmFjdCBpdFxuICAgICAgICAgICAgaWYgKGVycm9ycy5sZW5ndGggPiAwICYmIHR5cGVvZiBlcnJvcnNbMF0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZvcm1fVXRpbHMuX25vcm1hbGl6ZV9lcnJvcnMoZXJyb3JzWzBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEVtcHR5IG9yIG1peGVkIGFycmF5XG4gICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnYXJyYXknLCBkYXRhOiBbXSB9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIG9iamVjdCAtIGNoZWNrIGZvciBMYXJhdmVsIHJlc3BvbnNlIHdyYXBwZXJcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBVbndyYXAge2Vycm9yczogey4uLn19IG9yIHtlcnJvcjogey4uLn19XG4gICAgICAgICAgICBjb25zdCB1bndyYXBwZWQgPSBlcnJvcnMuZXJyb3JzIHx8IGVycm9ycy5lcnJvcjtcbiAgICAgICAgICAgIGlmICh1bndyYXBwZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRm9ybV9VdGlscy5fbm9ybWFsaXplX2Vycm9ycyh1bndyYXBwZWQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDb252ZXJ0IExhcmF2ZWwgdmFsaWRhdG9yIGZvcm1hdCB7ZmllbGQ6IFttc2cxLCBtc2cyXX0gdG8ge2ZpZWxkOiBtc2cxfVxuICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZCA9IHt9O1xuICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBlcnJvcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3JzLmhhc093blByb3BlcnR5KGZpZWxkKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGVycm9yc1tmaWVsZF07XG4gICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVkW2ZpZWxkXSA9IHZhbHVlWzBdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRbZmllbGRdID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVkW2ZpZWxkXSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdmaWVsZHMnLCBkYXRhOiBub3JtYWxpemVkIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaW5hbCBjYXRjaC1hbGwqXG4gICAgICAgIHJldHVybiB7IHR5cGU6ICdzdHJpbmcnLCBkYXRhOiBTdHJpbmcoZXJyb3JzKSB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgZHVwbGljYXRlIGVycm9yIG1lc3NhZ2VzIGZyb20gYXJyYXkgb3Igb2JqZWN0IHZhbHVlc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBlcnJvcnMgLSBFcnJvcnMgdG8gZGVkdXBsaWNhdGVcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fSBEZWR1cGxpY2F0ZWQgZXJyb3JzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2RlZHVwbGljYXRlX2Vycm9ycyhlcnJvcnMpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZXJyb3JzKSkge1xuICAgICAgICAgICAgcmV0dXJuIFsuLi5uZXcgU2V0KGVycm9ycyldO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBjb25zdCBzZWVuID0gbmV3IFNldCgpO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBlcnJvcnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGVycm9yc1trZXldO1xuICAgICAgICAgICAgICAgIGlmICghc2Vlbi5oYXModmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlZW4uYWRkKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVycm9ycztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcHBsaWVzIGZpZWxkLXNwZWNpZmljIHZhbGlkYXRpb24gZXJyb3JzIHRvIGZvcm0gaW5wdXRzXG4gICAgICogQHBhcmFtIHtqUXVlcnl9ICRwYXJlbnQgLSBQYXJlbnQgZWxlbWVudCBjb250YWluaW5nIGZvcm1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZmllbGRfZXJyb3JzIC0gT2JqZWN0IG1hcHBpbmcgZmllbGQgbmFtZXMgdG8gZXJyb3IgbWVzc2FnZXNcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBPYmplY3QgY29udGFpbmluZyB7YW5pbWF0aW9uczogQXJyYXksIHVubWF0Y2hlZDogT2JqZWN0fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9hcHBseV9maWVsZF9lcnJvcnMoJHBhcmVudCwgZmllbGRfZXJyb3JzKSB7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBbXTtcbiAgICAgICAgY29uc3QgdW5tYXRjaGVkID0ge307XG5cbiAgICAgICAgZm9yIChjb25zdCBmaWVsZF9uYW1lIGluIGZpZWxkX2Vycm9ycykge1xuICAgICAgICAgICAgY29uc3QgZXJyb3JfbWVzc2FnZSA9IGZpZWxkX2Vycm9yc1tmaWVsZF9uYW1lXTtcbiAgICAgICAgICAgIGNvbnN0ICRpbnB1dCA9ICRwYXJlbnQuZmluZChgW25hbWU9XCIke2ZpZWxkX25hbWV9XCJdYCk7XG5cbiAgICAgICAgICAgIGlmICghJGlucHV0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHVubWF0Y2hlZFtmaWVsZF9uYW1lXSA9IGVycm9yX21lc3NhZ2U7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0ICRlcnJvciA9ICQoJzxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCI+PC9kaXY+JykuaHRtbChlcnJvcl9tZXNzYWdlKTtcbiAgICAgICAgICAgIGNvbnN0ICR0YXJnZXQgPSAkaW5wdXQuY2xvc2VzdCgnLmZvcm0tZ3JvdXAsIC5mb3JtLWNoZWNrLCAuaW5wdXQtZ3JvdXAnKTtcblxuICAgICAgICAgICAgaWYgKCEkdGFyZ2V0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHVubWF0Y2hlZFtmaWVsZF9uYW1lXSA9IGVycm9yX21lc3NhZ2U7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICRpbnB1dC5hZGRDbGFzcygnaXMtaW52YWxpZCcpO1xuICAgICAgICAgICAgJGVycm9yLmFwcGVuZFRvKCR0YXJnZXQpO1xuICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKCRlcnJvci5oaWRlKCkuZmFkZUluKDMwMCkucHJvbWlzZSgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGFuaW1hdGlvbnMsIHVubWF0Y2hlZCB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgY29tYmluZWQgZXJyb3IgbWVzc2FnZSB3aXRoIHN1bW1hcnkgYW5kIHVubWF0Y2hlZCBmaWVsZCBlcnJvcnNcbiAgICAgKiBAcGFyYW0ge2pRdWVyeX0gJHBhcmVudCAtIFBhcmVudCBlbGVtZW50IGNvbnRhaW5pbmcgZm9ybVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdW1tYXJ5X21zZyAtIFN1bW1hcnkgbWVzc2FnZSAoZS5nLiwgXCJQbGVhc2UgY29ycmVjdCB0aGUgZXJyb3JzIGJlbG93XCIpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHVubWF0Y2hlZF9lcnJvcnMgLSBPYmplY3Qgb2YgZmllbGQgZXJyb3JzIHRoYXQgY291bGRuJ3QgYmUgbWF0Y2hlZCB0byBmaWVsZHNcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIGFuaW1hdGlvbiBwcm9taXNlc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9hcHBseV9jb21iaW5lZF9lcnJvcigkcGFyZW50LCBzdW1tYXJ5X21zZywgdW5tYXRjaGVkX2Vycm9ycykge1xuICAgICAgICBjb25zdCBhbmltYXRpb25zID0gW107XG4gICAgICAgIGNvbnN0ICRlcnJvcl9jb250YWluZXIgPSAkcGFyZW50LmZpbmQoJ1tkYXRhLWlkPVwiZXJyb3JfY29udGFpbmVyXCJdJykuZmlyc3QoKTtcbiAgICAgICAgY29uc3QgJHRhcmdldCA9ICRlcnJvcl9jb250YWluZXIubGVuZ3RoID4gMCA/ICRlcnJvcl9jb250YWluZXIgOiAkcGFyZW50O1xuXG4gICAgICAgIC8vIENyZWF0ZSBhbGVydCB3aXRoIHN1bW1hcnkgbWVzc2FnZSBhbmQgYnVsbGV0ZWQgbGlzdCBvZiB1bm1hdGNoZWQgZXJyb3JzXG4gICAgICAgIGNvbnN0ICRhbGVydCA9ICQoJzxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj48L2Rpdj4nKTtcblxuICAgICAgICAvLyBBZGQgc3VtbWFyeSBtZXNzYWdlIGlmIHByb3ZpZGVkXG4gICAgICAgIGlmIChzdW1tYXJ5X21zZykge1xuICAgICAgICAgICAgJCgnPHAgY2xhc3M9XCJtYi0yXCI+PC9wPicpLnRleHQoc3VtbWFyeV9tc2cpLmFwcGVuZFRvKCRhbGVydCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdW5tYXRjaGVkIGVycm9ycyBhcyBidWxsZXRlZCBsaXN0XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyh1bm1hdGNoZWRfZXJyb3JzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCAkbGlzdCA9ICQoJzx1bCBjbGFzcz1cIm1iLTBcIj48L3VsPicpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZF9uYW1lIGluIHVubWF0Y2hlZF9lcnJvcnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBlcnJvcl9tc2cgPSB1bm1hdGNoZWRfZXJyb3JzW2ZpZWxkX25hbWVdO1xuICAgICAgICAgICAgICAgICQoJzxsaT48L2xpPicpLmh0bWwoZXJyb3JfbXNnKS5hcHBlbmRUbygkbGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkbGlzdC5hcHBlbmRUbygkYWxlcnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCRlcnJvcl9jb250YWluZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKCRhbGVydC5oaWRlKCkuYXBwZW5kVG8oJHRhcmdldCkuZmFkZUluKDMwMCkucHJvbWlzZSgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCgkYWxlcnQuaGlkZSgpLnByZXBlbmRUbygkdGFyZ2V0KS5mYWRlSW4oMzAwKS5wcm9taXNlKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFuaW1hdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyBnZW5lcmFsIGVycm9yIG1lc3NhZ2VzIGFzIGFsZXJ0IGJveFxuICAgICAqIEBwYXJhbSB7alF1ZXJ5fSAkcGFyZW50IC0gUGFyZW50IGVsZW1lbnQgdG8gcHJlcGVuZCBhbGVydCB0b1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfEFycmF5fSBtZXNzYWdlcyAtIEVycm9yIG1lc3NhZ2UocykgdG8gZGlzcGxheVxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2YgYW5pbWF0aW9uIHByb21pc2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2FwcGx5X2dlbmVyYWxfZXJyb3JzKCRwYXJlbnQsIG1lc3NhZ2VzKSB7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBbXTtcblxuICAgICAgICAvLyBMb29rIGZvciBhIHNwZWNpZmljIGVycm9yIGNvbnRhaW5lciBkaXYgKGUuZy4sIGluIFJzeF9Gb3JtIGNvbXBvbmVudClcbiAgICAgICAgY29uc3QgJGVycm9yX2NvbnRhaW5lciA9ICRwYXJlbnQuZmluZCgnW2RhdGEtaWQ9XCJlcnJvcl9jb250YWluZXJcIl0nKS5maXJzdCgpO1xuICAgICAgICBjb25zdCAkdGFyZ2V0ID0gJGVycm9yX2NvbnRhaW5lci5sZW5ndGggPiAwID8gJGVycm9yX2NvbnRhaW5lciA6ICRwYXJlbnQ7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIFNpbmdsZSBlcnJvciAtIHNpbXBsZSBhbGVydCB3aXRob3V0IGxpc3RcbiAgICAgICAgICAgIGNvbnN0ICRhbGVydCA9ICQoJzxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj48L2Rpdj4nKS50ZXh0KG1lc3NhZ2VzKTtcbiAgICAgICAgICAgIGlmICgkZXJyb3JfY29udGFpbmVyLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25zLnB1c2goJGFsZXJ0LmhpZGUoKS5hcHBlbmRUbygkdGFyZ2V0KS5mYWRlSW4oMzAwKS5wcm9taXNlKCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25zLnB1c2goJGFsZXJ0LmhpZGUoKS5wcmVwZW5kVG8oJHRhcmdldCkuZmFkZUluKDMwMCkucHJvbWlzZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG1lc3NhZ2VzKSAmJiBtZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAvLyBNdWx0aXBsZSBlcnJvcnMgLSBidWxsZXRlZCBsaXN0XG4gICAgICAgICAgICBjb25zdCAkYWxlcnQgPSAkKCc8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCIgcm9sZT1cImFsZXJ0XCI+PHVsIGNsYXNzPVwibWItMFwiPjwvdWw+PC9kaXY+Jyk7XG4gICAgICAgICAgICBjb25zdCAkbGlzdCA9ICRhbGVydC5maW5kKCd1bCcpO1xuXG4gICAgICAgICAgICBtZXNzYWdlcy5mb3JFYWNoKChtc2cpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZXh0ID0gKG1zZyArICcnKS50cmltKCkgfHwgJ0FuIGVycm9yIGhhcyBvY2N1cnJlZCc7XG4gICAgICAgICAgICAgICAgJCgnPGxpPjwvbGk+JykuaHRtbCh0ZXh0KS5hcHBlbmRUbygkbGlzdCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKCRlcnJvcl9jb250YWluZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCgkYWxlcnQuaGlkZSgpLmFwcGVuZFRvKCR0YXJnZXQpLmZhZGVJbigzMDApLnByb21pc2UoKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCgkYWxlcnQuaGlkZSgpLnByZXBlbmRUbygkdGFyZ2V0KS5mYWRlSW4oMzAwKS5wcm9taXNlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBtZXNzYWdlcyA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkobWVzc2FnZXMpKSB7XG4gICAgICAgICAgICAvLyBPYmplY3Qgb2YgdW5tYXRjaGVkIGZpZWxkIGVycm9ycyAtIGNvbnZlcnQgdG8gYXJyYXlcbiAgICAgICAgICAgIGNvbnN0IGVycm9yX2xpc3QgPSBPYmplY3QudmFsdWVzKG1lc3NhZ2VzKVxuICAgICAgICAgICAgICAgIC5tYXAoKHYpID0+IFN0cmluZyh2KS50cmltKCkpXG4gICAgICAgICAgICAgICAgLmZpbHRlcigodikgPT4gdik7XG4gICAgICAgICAgICBpZiAoZXJyb3JfbGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZvcm1fVXRpbHMuX2FwcGx5X2dlbmVyYWxfZXJyb3JzKCRwYXJlbnQsIGVycm9yX2xpc3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFuaW1hdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgdG90YWwgaGVpZ2h0IG9mIGZpeGVkL3N0aWNreSBoZWFkZXJzIGF0IHRoZSB0b3Agb2YgdGhlIHBhZ2VcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUb3RhbCBoZWlnaHQgaW4gcGl4ZWxzIG9mIGZpeGVkIHRvcCBlbGVtZW50c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZXRfZml4ZWRfaGVhZGVyX2hlaWdodCgpIHtcbiAgICAgICAgbGV0IHRvdGFsX2hlaWdodCA9IDA7XG5cbiAgICAgICAgLy8gRmluZCBhbGwgZml4ZWQgb3Igc3RpY2t5IHBvc2l0aW9uZWQgZWxlbWVudHNcbiAgICAgICAgJCgnKicpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjb25zdCAkZWwgPSAkKHRoaXMpO1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSAkZWwuY3NzKCdwb3NpdGlvbicpO1xuXG4gICAgICAgICAgICAvLyBPbmx5IGNoZWNrIGZpeGVkIG9yIHN0aWNreSBlbGVtZW50c1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uICE9PSAnZml4ZWQnICYmIHBvc2l0aW9uICE9PSAnc3RpY2t5Jykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgZWxlbWVudCBpcyBwb3NpdGlvbmVkIGF0IG9yIG5lYXIgdGhlIHRvcFxuICAgICAgICAgICAgY29uc3QgdG9wID0gcGFyc2VJbnQoJGVsLmNzcygndG9wJykpIHx8IDA7XG4gICAgICAgICAgICBpZiAodG9wID4gNTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIE5vdCBhIHRvcCBoZWFkZXJcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgZWxlbWVudCBpcyB2aXNpYmxlXG4gICAgICAgICAgICBpZiAoISRlbC5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgZWxlbWVudCBzcGFucyBzaWduaWZpY2FudCB3aWR0aCAobGlrZWx5IGEgaGVhZGVyL25hdmJhcilcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gJGVsLm91dGVyV2lkdGgoKTtcbiAgICAgICAgICAgIGNvbnN0IHZpZXdwb3J0X3dpZHRoID0gJCh3aW5kb3cpLndpZHRoKCk7XG4gICAgICAgICAgICBpZiAod2lkdGggPCB2aWV3cG9ydF93aWR0aCAqIDAuNSkge1xuICAgICAgICAgICAgICAgIHJldHVybjsgLy8gVG9vIG5hcnJvdyB0byBiZSBhIGhlYWRlclxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBZGQgdGhpcyBlbGVtZW50J3MgaGVpZ2h0XG4gICAgICAgICAgICB0b3RhbF9oZWlnaHQgKz0gJGVsLm91dGVySGVpZ2h0KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0b3RhbF9oZWlnaHQ7XG4gICAgfVxufVxuIiwiLyoqXG4gKiBEZWJ1Z2dlciBjbGFzcyBmb3IgY29uc29sZV9kZWJ1ZyBhbmQgYnJvd3NlciBlcnJvciBsb2dnaW5nXG4gKiBIYW5kbGVzIGJhdGNoZWQgc3VibWlzc2lvbiB0byBzZXJ2ZXIgd2hlbiBjb25maWd1cmVkXG4gKi9cbmNsYXNzIERlYnVnZ2VyIHtcbiAgICAvLyBCYXRjaGluZyBzdGF0ZSBmb3IgY29uc29sZV9kZWJ1ZyBtZXNzYWdlc1xuICAgIHN0YXRpYyBfY29uc29sZV9iYXRjaCA9IFtdO1xuICAgIHN0YXRpYyBfY29uc29sZV90aW1lciA9IG51bGw7XG4gICAgc3RhdGljIF9jb25zb2xlX2JhdGNoX2NvdW50ID0gMDtcblxuICAgIC8vIEJhdGNoaW5nIHN0YXRlIGZvciBlcnJvciBtZXNzYWdlc1xuICAgIHN0YXRpYyBfZXJyb3JfYmF0Y2ggPSBbXTtcbiAgICBzdGF0aWMgX2Vycm9yX3RpbWVyID0gbnVsbDtcbiAgICBzdGF0aWMgX2Vycm9yX2NvdW50ID0gMDtcbiAgICBzdGF0aWMgX2Vycm9yX2JhdGNoX2NvdW50ID0gMDtcblxuICAgIC8vIENvbnN0YW50c1xuICAgIHN0YXRpYyBERUJPVU5DRV9NUyA9IDIwMDA7XG4gICAgc3RhdGljIE1BWF9FUlJPUlNfUEVSX1BBR0UgPSAyMDtcbiAgICBzdGF0aWMgTUFYX0VSUk9SX0JBVENIRVMgPSA1O1xuXG4gICAgLy8gU3RvcmUgc3RhcnQgdGltZSBmb3IgYmVuY2htYXJraW5nXG4gICAgc3RhdGljIF9zdGFydF90aW1lID0gbnVsbDtcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgZnJhbWV3b3JrIGVycm9yIGhhbmRsaW5nXG4gICAgICogQ2FsbGVkIGR1cmluZyBmcmFtZXdvcmsgaW5pdGlhbGl6YXRpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19jb3JlX2luaXQoKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIGJyb3dzZXIgZXJyb3IgbG9nZ2luZyBpcyBlbmFibGVkXG4gICAgICAgIGlmICh3aW5kb3cucnN4YXBwICYmIHdpbmRvdy5yc3hhcHAubG9nX2Jyb3dzZXJfZXJyb3JzKSB7XG4gICAgICAgICAgICAvLyBSZWdpc3RlciBnbG9iYWwgZXJyb3IgaGFuZGxlclxuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgRGVidWdnZXIuX2hhbmRsZV9icm93c2VyX2Vycm9yKHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXZlbnQubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWU6IGV2ZW50LmZpbGVuYW1lLFxuICAgICAgICAgICAgICAgICAgICBsaW5lbm86IGV2ZW50LmxpbmVubyxcbiAgICAgICAgICAgICAgICAgICAgY29sbm86IGV2ZW50LmNvbG5vLFxuICAgICAgICAgICAgICAgICAgICBzdGFjazogZXZlbnQuZXJyb3IgPyBldmVudC5lcnJvci5zdGFjayA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gUmVnaXN0ZXIgdW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9uIGhhbmRsZXJcbiAgICAgICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd1bmhhbmRsZWRyZWplY3Rpb24nLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBEZWJ1Z2dlci5faGFuZGxlX2Jyb3dzZXJfZXJyb3Ioe1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBldmVudC5yZWFzb24gPyBldmVudC5yZWFzb24ubWVzc2FnZSB8fCBTdHJpbmcoZXZlbnQucmVhc29uKSA6ICdVbmhhbmRsZWQgcHJvbWlzZSByZWplY3Rpb24nLFxuICAgICAgICAgICAgICAgICAgICBzdGFjazogZXZlbnQucmVhc29uICYmIGV2ZW50LnJlYXNvbi5zdGFjayA/IGV2ZW50LnJlYXNvbi5zdGFjayA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICd1bmhhbmRsZWRyZWplY3Rpb24nLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWdpc3RlciB1aSByZWZyZXNoIGhhbmRsZXJcbiAgICAgICAgUnN4Lm9uKCdyZWZyZXNoJywgRGVidWdnZXIub25fcmVmcmVzaCk7XG4gICAgfVxuXG4gICAgLy8gSW4gZGV2IG1vZGUsIHNvbWUgdWkgZWxlbWVudHMgY2FuIGJlIGF1dG9tYXRpY2FsbHkgYXBwbGllZCB0byBhc3Npc3Qgd2l0aCBkZXZlbG9wbWVudFxuICAgIHN0YXRpYyBvbl9yZWZyZXNoKCkge1xuICAgICAgICBpZiAoIVJzeC5pc19wcm9kKCkpIHtcbiAgICAgICAgICAgIC8vIEFkZCBhbiB1bmRlcmxpbmUgMiBweCBibHVlIHRvIGFsbCBhIHRhZ3Mgd2l0aCBocmVmID09PSBcIiNcIiB1c2luZyBqcXVlcnlcbiAgICAgICAgICAgIC8vIFRvZG86IG1heWJlIHRoaXMgc2hvdWxkIGJlIGEgY29uZmlndXJhYmxlIGRlYnVnIG9wdGlvbj9cbiAgICAgICAgICAgIC8vICQoJ2FbaHJlZj1cIiNcIl0nKS5jc3Moe1xuICAgICAgICAgICAgLy8gICAgICdib3JkZXItYm90dG9tJzogJzJweCBzb2xpZCBibHVlJyxcbiAgICAgICAgICAgIC8vICAgICAndGV4dC1kZWNvcmF0aW9uJzogJ25vbmUnXG4gICAgICAgICAgICAvLyB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb24gb2YgY29uc29sZV9kZWJ1Z1xuICAgICAqIE1pcnJvcnMgUEhQIGZ1bmN0aW9uYWxpdHkgd2l0aCBiYXRjaGluZyBmb3IgTGFyYXZlbCBsb2dcbiAgICAgKi9cbiAgICBzdGF0aWMgY29uc29sZV9kZWJ1ZyhjaGFubmVsLCAuLi52YWx1ZXMpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgY29uc29sZV9kZWJ1ZyBpcyBlbmFibGVkXG4gICAgICAgIGlmICghd2luZG93LnJzeGFwcCB8fCAhd2luZG93LnJzeGFwcC5jb25zb2xlX2RlYnVnIHx8ICF3aW5kb3cucnN4YXBwLmNvbnNvbGVfZGVidWcuZW5hYmxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29uZmlnID0gd2luZG93LnJzeGFwcC5jb25zb2xlX2RlYnVnO1xuXG4gICAgICAgIC8vIE5vcm1hbGl6ZSBjaGFubmVsIG5hbWVcbiAgICAgICAgY2hhbm5lbCA9IFN0cmluZyhjaGFubmVsKVxuICAgICAgICAgICAgLnRvVXBwZXJDYXNlKClcbiAgICAgICAgICAgIC5yZXBsYWNlKC9bXFxbXFxdXS9nLCAnJyk7XG5cbiAgICAgICAgLy8gQXBwbHkgZmlsdGVyaW5nXG4gICAgICAgIGlmIChjb25maWcuZmlsdGVyX21vZGUgPT09ICdzcGVjaWZpYycpIHtcbiAgICAgICAgICAgIGNvbnN0IHNwZWNpZmljID0gY29uZmlnLnNwZWNpZmljX2NoYW5uZWw7XG4gICAgICAgICAgICBpZiAoc3BlY2lmaWMpIHtcbiAgICAgICAgICAgICAgICAvLyBTcGxpdCBjb21tYS1zZXBhcmF0ZWQgdmFsdWVzIGFuZCBub3JtYWxpemVcbiAgICAgICAgICAgICAgICBjb25zdCBjaGFubmVscyA9IHNwZWNpZmljLnNwbGl0KCcsJykubWFwKChjKSA9PiBjLnRyaW0oKS50b1VwcGVyQ2FzZSgpKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNoYW5uZWxzLmluY2x1ZGVzKGNoYW5uZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoY29uZmlnLmZpbHRlcl9tb2RlID09PSAnd2hpdGVsaXN0Jykge1xuICAgICAgICAgICAgY29uc3Qgd2hpdGVsaXN0ID0gKGNvbmZpZy5maWx0ZXJfY2hhbm5lbHMgfHwgW10pLm1hcCgoYykgPT4gYy50b1VwcGVyQ2FzZSgpKTtcbiAgICAgICAgICAgIGlmICghd2hpdGVsaXN0LmluY2x1ZGVzKGNoYW5uZWwpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGNvbmZpZy5maWx0ZXJfbW9kZSA9PT0gJ2JsYWNrbGlzdCcpIHtcbiAgICAgICAgICAgIGNvbnN0IGJsYWNrbGlzdCA9IChjb25maWcuZmlsdGVyX2NoYW5uZWxzIHx8IFtdKS5tYXAoKGMpID0+IGMudG9VcHBlckNhc2UoKSk7XG4gICAgICAgICAgICBpZiAoYmxhY2tsaXN0LmluY2x1ZGVzKGNoYW5uZWwpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJlcGFyZSB0aGUgbWVzc2FnZVxuICAgICAgICBsZXQgbWVzc2FnZSA9IHtcbiAgICAgICAgICAgIGNoYW5uZWw6IGNoYW5uZWwsXG4gICAgICAgICAgICB2YWx1ZXM6IHZhbHVlcyxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEFkZCBsb2NhdGlvbiBpZiBjb25maWd1cmVkXG4gICAgICAgIGlmIChjb25maWcuaW5jbHVkZV9sb2NhdGlvbiB8fCBjb25maWcuaW5jbHVkZV9iYWNrdHJhY2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKCk7XG4gICAgICAgICAgICBjb25zdCBzdGFjayA9IGVycm9yLnN0YWNrIHx8ICcnO1xuICAgICAgICAgICAgY29uc3Qgc3RhY2tMaW5lcyA9IHN0YWNrLnNwbGl0KCdcXG4nKTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5pbmNsdWRlX2xvY2F0aW9uICYmIHN0YWNrTGluZXMubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgICAgIC8vIFNraXAgRXJyb3IgbGluZSBhbmQgdGhpcyBmdW5jdGlvblxuICAgICAgICAgICAgICAgIGNvbnN0IGNhbGxlckxpbmUgPSBzdGFja0xpbmVzWzJdIHx8ICcnO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gY2FsbGVyTGluZS5tYXRjaCgvYXRcXHMrLio/XFxzK1xcKCguKj8pOihcXGQrKTooXFxkKylcXCkvKSB8fCBjYWxsZXJMaW5lLm1hdGNoKC9hdFxccysoLio/KTooXFxkKyk6KFxcZCspLyk7XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubG9jYXRpb24gPSBgJHttYXRjaFsxXX06JHttYXRjaFsyXX1gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5pbmNsdWRlX2JhY2t0cmFjZSkge1xuICAgICAgICAgICAgICAgIC8vIEluY2x1ZGUgZmlyc3QgNSBzdGFjayBmcmFtZXMsIHNraXBwaW5nIHRoaXMgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICBtZXNzYWdlLmJhY2t0cmFjZSA9IHN0YWNrTGluZXNcbiAgICAgICAgICAgICAgICAgICAgLnNsaWNlKDIsIDcpXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoKGxpbmUpID0+IGxpbmUudHJpbSgpKVxuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKChsaW5lKSA9PiBsaW5lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE91dHB1dCB0byBicm93c2VyIGNvbnNvbGUgaWYgZW5hYmxlZFxuICAgICAgICBpZiAoY29uZmlnLm91dHB1dHMgJiYgY29uZmlnLm91dHB1dHMuYnJvd3Nlcikge1xuICAgICAgICAgICAgY29uc3QgcHJlZml4ID0gY29uZmlnLmluY2x1ZGVfYmVuY2htYXJrID8gYFske0RlYnVnZ2VyLl9nZXRfdGltZV9wcmVmaXgoKX1dIGAgOiAnJztcbiAgICAgICAgICAgIGNvbnN0IGNoYW5uZWxQcmVmaXggPSBgWyR7Y2hhbm5lbH1dYDtcblxuICAgICAgICAgICAgLy8gVXNlIGFwcHJvcHJpYXRlIGNvbnNvbGUgbWV0aG9kIGJhc2VkIG9uIGNoYW5uZWxcbiAgICAgICAgICAgIGxldCBjb25zb2xlTWV0aG9kID0gJ2xvZyc7XG4gICAgICAgICAgICBpZiAoY2hhbm5lbC5pbmNsdWRlcygnRVJST1InKSkgY29uc29sZU1ldGhvZCA9ICdlcnJvcic7XG4gICAgICAgICAgICBlbHNlIGlmIChjaGFubmVsLmluY2x1ZGVzKCdXQVJOJykpIGNvbnNvbGVNZXRob2QgPSAnd2Fybic7XG4gICAgICAgICAgICBlbHNlIGlmIChjaGFubmVsLmluY2x1ZGVzKCdJTkZPJykpIGNvbnNvbGVNZXRob2QgPSAnaW5mbyc7XG5cbiAgICAgICAgICAgIGNvbnNvbGVbY29uc29sZU1ldGhvZF0ocHJlZml4ICsgY2hhbm5lbFByZWZpeCwgLi4udmFsdWVzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJhdGNoIGZvciBMYXJhdmVsIGxvZyBpZiBlbmFibGVkXG4gICAgICAgIGlmIChjb25maWcub3V0cHV0cyAmJiBjb25maWcub3V0cHV0cy5sYXJhdmVsX2xvZykge1xuICAgICAgICAgICAgRGVidWdnZXIuX2JhdGNoX2NvbnNvbGVfbWVzc2FnZShtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvZyBhbiBlcnJvciB0byB0aGUgc2VydmVyXG4gICAgICogVXNlZCBtYW51YWxseSBvciBieSBBamF4IGVycm9yIGhhbmRsaW5nXG4gICAgICovXG4gICAgc3RhdGljIGxvZ19lcnJvcihlcnJvcikge1xuICAgICAgICAvLyBDaGVjayBpZiBicm93c2VyIGVycm9yIGxvZ2dpbmcgaXMgZW5hYmxlZFxuICAgICAgICBpZiAoIXdpbmRvdy5yc3hhcHAgfHwgIXdpbmRvdy5yc3hhcHAubG9nX2Jyb3dzZXJfZXJyb3JzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOb3JtYWxpemUgZXJyb3IgZm9ybWF0XG4gICAgICAgIGxldCBlcnJvckRhdGEgPSB7fTtcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGVycm9yRGF0YS5tZXNzYWdlID0gZXJyb3I7XG4gICAgICAgICAgICBlcnJvckRhdGEudHlwZSA9ICdtYW51YWwnO1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgIGVycm9yRGF0YS5tZXNzYWdlID0gZXJyb3IubWVzc2FnZTtcbiAgICAgICAgICAgIGVycm9yRGF0YS5zdGFjayA9IGVycm9yLnN0YWNrO1xuICAgICAgICAgICAgZXJyb3JEYXRhLnR5cGUgPSAnZXhjZXB0aW9uJztcbiAgICAgICAgfSBlbHNlIGlmIChlcnJvciAmJiB0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBlcnJvckRhdGEgPSBlcnJvcjtcbiAgICAgICAgICAgIGlmICghZXJyb3JEYXRhLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBlcnJvckRhdGEudHlwZSA9ICdtYW51YWwnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgRGVidWdnZXIuX2hhbmRsZV9icm93c2VyX2Vycm9yKGVycm9yRGF0YSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IEhhbmRsZSBicm93c2VyIGVycm9ycyB3aXRoIGJhdGNoaW5nXG4gICAgICovXG4gICAgc3RhdGljIF9oYW5kbGVfYnJvd3Nlcl9lcnJvcihlcnJvckRhdGEpIHtcbiAgICAgICAgLy8gQ2hlY2sgbGltaXRzXG4gICAgICAgIGlmIChEZWJ1Z2dlci5fZXJyb3JfY291bnQgPj0gRGVidWdnZXIuTUFYX0VSUk9SU19QRVJfUEFHRSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChEZWJ1Z2dlci5fZXJyb3JfYmF0Y2hfY291bnQgPj0gRGVidWdnZXIuTUFYX0VSUk9SX0JBVENIRVMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIERlYnVnZ2VyLl9lcnJvcl9jb3VudCsrO1xuXG4gICAgICAgIC8vIEFkZCBtZXRhZGF0YVxuICAgICAgICBlcnJvckRhdGEudXJsID0gd2luZG93LmxvY2F0aW9uLmhyZWY7XG4gICAgICAgIGVycm9yRGF0YS51c2VyQWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICAgICAgICBlcnJvckRhdGEudGltZXN0YW1wID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuXG4gICAgICAgIC8vIEFkZCB0byBiYXRjaFxuICAgICAgICBEZWJ1Z2dlci5fZXJyb3JfYmF0Y2gucHVzaChlcnJvckRhdGEpO1xuXG4gICAgICAgIC8vIENsZWFyIGV4aXN0aW5nIHRpbWVyXG4gICAgICAgIGlmIChEZWJ1Z2dlci5fZXJyb3JfdGltZXIpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dChEZWJ1Z2dlci5fZXJyb3JfdGltZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2V0IGRlYm91bmNlIHRpbWVyXG4gICAgICAgIERlYnVnZ2VyLl9lcnJvcl90aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgRGVidWdnZXIuX2ZsdXNoX2Vycm9yX2JhdGNoKCk7XG4gICAgICAgIH0sIERlYnVnZ2VyLkRFQk9VTkNFX01TKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogQmF0Y2ggY29uc29sZV9kZWJ1ZyBtZXNzYWdlcyBmb3IgTGFyYXZlbCBsb2dcbiAgICAgKi9cbiAgICBzdGF0aWMgX2JhdGNoX2NvbnNvbGVfbWVzc2FnZShtZXNzYWdlKSB7XG4gICAgICAgIERlYnVnZ2VyLl9jb25zb2xlX2JhdGNoLnB1c2gobWVzc2FnZSk7XG5cbiAgICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgdGltZXJcbiAgICAgICAgaWYgKERlYnVnZ2VyLl9jb25zb2xlX3RpbWVyKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQoRGVidWdnZXIuX2NvbnNvbGVfdGltZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2V0IGRlYm91bmNlIHRpbWVyXG4gICAgICAgIERlYnVnZ2VyLl9jb25zb2xlX3RpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5fZmx1c2hfY29uc29sZV9iYXRjaCgpO1xuICAgICAgICB9LCBEZWJ1Z2dlci5ERUJPVU5DRV9NUyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IEZsdXNoIGNvbnNvbGVfZGVidWcgYmF0Y2ggdG8gc2VydmVyXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9mbHVzaF9jb25zb2xlX2JhdGNoKCkge1xuICAgICAgICBpZiAoRGVidWdnZXIuX2NvbnNvbGVfYmF0Y2gubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBtZXNzYWdlcyA9IERlYnVnZ2VyLl9jb25zb2xlX2JhdGNoO1xuICAgICAgICBEZWJ1Z2dlci5fY29uc29sZV9iYXRjaCA9IFtdO1xuICAgICAgICBEZWJ1Z2dlci5fY29uc29sZV90aW1lciA9IG51bGw7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBBamF4LmNhbGwoUnN4LlJvdXRlKCdEZWJ1Z2dlcl9Db250cm9sbGVyJywgJ2xvZ19jb25zb2xlX21lc3NhZ2VzJyksIHsgbWVzc2FnZXM6IG1lc3NhZ2VzIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgLy8gU2lsZW50bHkgZmFpbCAtIGRvbid0IGNyZWF0ZSBlcnJvciBsb29wXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gc2VuZCBjb25zb2xlX2RlYnVnIG1lc3NhZ2VzIHRvIHNlcnZlcjonLCBlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogRmx1c2ggZXJyb3IgYmF0Y2ggdG8gc2VydmVyXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9mbHVzaF9lcnJvcl9iYXRjaCgpIHtcbiAgICAgICAgaWYgKERlYnVnZ2VyLl9lcnJvcl9iYXRjaC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGVycm9ycyA9IERlYnVnZ2VyLl9lcnJvcl9iYXRjaDtcbiAgICAgICAgRGVidWdnZXIuX2Vycm9yX2JhdGNoID0gW107XG4gICAgICAgIERlYnVnZ2VyLl9lcnJvcl90aW1lciA9IG51bGw7XG4gICAgICAgIERlYnVnZ2VyLl9lcnJvcl9iYXRjaF9jb3VudCsrO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gQWpheC5jYWxsKFJzeC5Sb3V0ZSgnRGVidWdnZXJfQ29udHJvbGxlcicsICdsb2dfYnJvd3Nlcl9lcnJvcnMnKSwgeyBlcnJvcnM6IGVycm9ycyB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIFNpbGVudGx5IGZhaWwgLSBkb24ndCBjcmVhdGUgZXJyb3IgbG9vcFxuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIHNlbmQgYnJvd3NlciBlcnJvcnMgdG8gc2VydmVyOicsIGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBHZXQgdGltZSBwcmVmaXggZm9yIGJlbmNobWFya2luZ1xuICAgICAqL1xuICAgIHN0YXRpYyBfZ2V0X3RpbWVfcHJlZml4KCkge1xuICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICBpZiAoIURlYnVnZ2VyLl9zdGFydF90aW1lKSB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5fc3RhcnRfdGltZSA9IG5vdztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBlbGFwc2VkID0gbm93IC0gRGVidWdnZXIuX3N0YXJ0X3RpbWU7XG4gICAgICAgIHJldHVybiAoZWxhcHNlZCAvIDEwMDApLnRvRml4ZWQoMykgKyAncyc7XG4gICAgfVxufVxuIiwiLy8gQEpTLVRISVMtMDEtRVhDRVBUSU9OXG4vKipcbiAqIGpRdWVyeSBoZWxwZXIgZXh0ZW5zaW9ucyBmb3IgdGhlIFJTWCBmcmFtZXdvcmtcbiAqIFRoZXNlIGV4dGVuc2lvbnMgYWRkIHV0aWxpdHkgbWV0aG9kcyB0byBqUXVlcnkncyBwcm90b3R5cGVcbiAqIE5vdGU6ICd0aGlzJyByZWZlcmVuY2VzIGluIGpRdWVyeSBleHRlbnNpb25zIHJlZmVyIHRvIGpRdWVyeSBvYmplY3RzIGJ5IGRlc2lnblxuICovXG5jbGFzcyBSc3hfSnFfSGVscGVycyB7XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSBqUXVlcnkgZXh0ZW5zaW9ucyB3aGVuIHRoZSBmcmFtZXdvcmsgY29yZSBpcyBkZWZpbmVkXG4gICAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGR1cmluZyBmcmFtZXdvcmsgaW5pdGlhbGl6YXRpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19jb3JlX2RlZmluZSgpIHtcbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIGpxdWVyeSBzZWxlY3RvciBtYXRjaGVkIGFuIGVsZW1lbnRcbiAgICAgICAgJC5mbi5leGlzdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sZW5ndGggPiAwO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiBqcXVlcnkgZWxlbWVudCBpcyB2aXNpYmxlXG4gICAgICAgICQuZm4uaXNfdmlzaWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmlzKCc6dmlzaWJsZScpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFNjcm9sbHMgdG8gdGhlIHRhcmdldCBlbGVtZW50LCBvbmx5IHNjcm9sbHMgdXAuICBUb2RvOiBDcmVhdGUgYSB2ZXJzaW9uXG4gICAgICAgIC8vIG9mIHRoaXMgdGhhdCBhbHNvIHNjcm9sbHMgb25seSBkb3duLCBvciBib3RoXG4gICAgICAgICQuZm4uc2Nyb2xsX3VwX3RvID0gZnVuY3Rpb24gKHNwZWVkID0gMCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmV4aXN0cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS53YXJuKFwiQ291bGQgbm90IGZpbmQgdGFyZ2V0IGVsZW1lbnQgdG8gc2Nyb2xsIHRvXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLmlzX2luX2RvbSgpKSB7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS53YXJuKFwiVGFyZ2V0IGVsZW1lbnQgZm9yIHNjcm9sbCBpcyBub3Qgb24gZG9tXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IGVfdG9wID0gTWF0aC5yb3VuZCh0aGlzLm9mZnNldCgpLnRvcCk7XG4gICAgICAgICAgICBsZXQgc190b3AgPSAkKCdib2R5Jykuc2Nyb2xsVG9wKCk7XG4gICAgICAgICAgICBpZiAoZV90b3AgPCAwKSB7XG4gICAgICAgICAgICAgICAgbGV0IHRhcmdldCA9IHNfdG9wICsgZV90b3A7XG4gICAgICAgICAgICAgICAgJCgnaHRtbCwgYm9keScpLmFuaW1hdGUoXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFRvcDogdGFyZ2V0LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBzcGVlZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gJCgpLmlzKFwiOmZvY3VzXCIpIC0gY2hlY2sgaWYgZWxlbWVudCBoYXMgZm9jdXNcbiAgICAgICAgJC5leHByWyc6J10uZm9jdXMgPSBmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICAgICAgcmV0dXJuIGVsZW0gPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgJiYgKGVsZW0udHlwZSB8fCBlbGVtLmhyZWYpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFNhdmUgbmF0aXZlIGNsaWNrIGJlaGF2aW9yIGJlZm9yZSBvdmVycmlkZVxuICAgICAgICAkLmZuLl9jbGlja19uYXRpdmUgPSAkLmZuLmNsaWNrO1xuXG4gICAgICAgIC8vIE92ZXJyaWRlIC5jbGljaygpIHRvIGNhbGwgcHJldmVudERlZmF1bHQgYnkgZGVmYXVsdFxuICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFjY2lkZW50YWwgcGFnZSBuYXZpZ2F0aW9uL2Zvcm0gc3VibWlzc2lvbiAtIHRoZSBjb3JyZWN0IGJlaGF2aW9yIDk1JSBvZiB0aGUgdGltZVxuICAgICAgICAkLmZuLmNsaWNrID0gZnVuY3Rpb24gKGhhbmRsZXIpIHtcbiAgICAgICAgICAgIC8vIElmIG5vIGhhbmRsZXIgcHJvdmlkZWQsIHRyaWdnZXIgY2xpY2sgZXZlbnQgKGpRdWVyeSAuY2xpY2soKSB3aXRoIG5vIGFyZ3MpXG4gICAgICAgICAgICBpZiAodHlwZW9mIGhhbmRsZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NsaWNrX25hdGl2ZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBdHRhY2ggY2xpY2sgaGFuZGxlciB3aXRoIGF1dG9tYXRpYyBwcmV2ZW50RGVmYXVsdFxuICAgICAgICAgICAgcmV0dXJuIHRoaXMub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBTYXZlIG9yaWdpbmFsIHByZXZlbnREZWZhdWx0XG4gICAgICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxfcHJldmVudERlZmF1bHQgPSBlLnByZXZlbnREZWZhdWx0LmJpbmQoZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBPdmVycmlkZSBwcmV2ZW50RGVmYXVsdCB0byBzaG93IHdhcm5pbmcgd2hlbiBjYWxsZWQgZXhwbGljaXRseVxuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdldmVudC5wcmV2ZW50RGVmYXVsdCgpIGlzIGNhbGxlZCBhdXRvbWF0aWNhbGx5IGJ5IFJTcGFkZSAuY2xpY2soKSBoYW5kbGVycyBhbmQgY2FuIGJlIHJlbW92ZWQuJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbF9wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAvLyBDYWxsIHByZXZlbnREZWZhdWx0IGJlZm9yZSBoYW5kbGVyXG4gICAgICAgICAgICAgICAgb3JpZ2luYWxfcHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyLmNhbGwodGhpcywgZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBFc2NhcGUgaGF0Y2g6IGNsaWNrIGhhbmRsZXIgd2l0aG91dCBwcmV2ZW50RGVmYXVsdCBmb3IgdGhlIDUlIGNhc2VcbiAgICAgICAgJC5mbi5jbGlja19hbGxvd19kZWZhdWx0ID0gZnVuY3Rpb24gKGhhbmRsZXIpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fY2xpY2tfbmF0aXZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fY2xpY2tfbmF0aXZlKGhhbmRsZXIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiB0aGUganF1ZXJ5IGVsZW1lbnQgZXhpc3RzIGluIGFuZCBpcyBhdHRhY2hlZCB0byB0aGUgRE9NXG4gICAgICAgICQuZm4uaXNfaW5fZG9tID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbGV0ICRlbGVtZW50ID0gdGhpcztcbiAgICAgICAgICAgIGxldCBfYW5jZXN0b3IgPSBmdW5jdGlvbiAoSFRNTG9iaikge1xuICAgICAgICAgICAgICAgIHdoaWxlIChIVE1Mb2JqLnBhcmVudEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgSFRNTG9iaiA9IEhUTUxvYmoucGFyZW50RWxlbWVudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIEhUTUxvYmo7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIF9hbmNlc3RvcigkZWxlbWVudFswXSkgPT09IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhlIGVsZW1lbnQgaXMgdmlzaWJsZSBpbiB0aGUgdmlld3BvcnRcbiAgICAgICAgJC5mbi5pc19pbl92aWV3cG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGxldCBzY3JvbGx0b3AgPSAkKHdpbmRvdykuc2Nyb2xsVG9wKCkgPiAwID8gJCh3aW5kb3cpLnNjcm9sbFRvcCgpIDogJCgnYm9keScpLnNjcm9sbFRvcCgpO1xuXG4gICAgICAgICAgICBsZXQgJGVsZW1lbnQgPSB0aGlzO1xuXG4gICAgICAgICAgICBjb25zdCB0b3Bfb2ZfZWxlbWVudCA9ICRlbGVtZW50Lm9mZnNldCgpLnRvcDtcbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbV9vZl9lbGVtZW50ID0gJGVsZW1lbnQub2Zmc2V0KCkudG9wICsgJGVsZW1lbnQub3V0ZXJIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IGJvdHRvbV9vZl9zY3JlZW4gPSBzY3JvbGx0b3AgKyAkKHdpbmRvdykuaW5uZXJIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHRvcF9vZl9zY3JlZW4gPSBzY3JvbGx0b3A7XG5cbiAgICAgICAgICAgIGlmIChib3R0b21fb2Zfc2NyZWVuID4gdG9wX29mX2VsZW1lbnQgJiYgdG9wX29mX3NjcmVlbiA8IGJvdHRvbV9vZl9lbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXRzIHRoZSB0YWduYW1lIG9mIGEganF1ZXJ5IGVsZW1lbnRcbiAgICAgICAgJC5mbi50YWduYW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvcCgndGFnTmFtZScpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIGEgaHJlZiBpcyBub3Qgc2FtZSBkb21haW5cbiAgICAgICAgJC5mbi5pc19leHRlcm5hbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNvbnN0IGhvc3QgPSB3aW5kb3cubG9jYXRpb24uaG9zdDtcbiAgICAgICAgICAgIGNvbnN0IGxpbmsgPSAkKCc8YT4nLCB7XG4gICAgICAgICAgICAgICAgaHJlZjogdGhpcy5hdHRyKCdocmVmJyksXG4gICAgICAgICAgICB9KVswXS5ob3N0bmFtZTtcbiAgICAgICAgICAgIHJldHVybiBsaW5rICE9PSBob3N0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEhUTUw1IGZvcm0gdmFsaWRhdGlvbiB3cmFwcGVyc1xuICAgICAgICAkLmZuLmNoZWNrVmFsaWRpdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzWzBdLmNoZWNrVmFsaWRpdHkoKTtcbiAgICAgICAgfTtcblxuICAgICAgICAkLmZuLnJlcG9ydFZhbGlkaXR5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1swXS5yZXBvcnRWYWxpZGl0eSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgICQuZm4ucmVxdWVzdFN1Ym1pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB0aGlzWzBdLnJlcXVlc3RTdWJtaXQoKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEZpbmQgcmVsYXRlZCBjb21wb25lbnRzIGJ5IHNlYXJjaGluZyB1cCB0aGUgYW5jZXN0b3IgdHJlZVxuICAgICAgICAvLyBMaWtlIC5jbG9zZXN0KCkgYnV0IHNlYXJjaGVzIHdpdGhpbiBhbmNlc3RvcnMgaW5zdGVhZCBvZiBtYXRjaGluZyB0aGVtXG4gICAgICAgICQuZm4uY2xvc2VzdF9zaWJsaW5nID0gZnVuY3Rpb24gKHNlbGVjdG9yKSB7XG4gICAgICAgICAgICBsZXQgJGN1cnJlbnQgPSB0aGlzO1xuICAgICAgICAgICAgbGV0ICRwYXJlbnQgPSAkY3VycmVudC5wYXJlbnQoKTtcblxuICAgICAgICAgICAgLy8gS2VlcCBnb2luZyB1cCB0aGUgdHJlZSB1bnRpbCB3ZSBoaXQgYm9keVxuICAgICAgICAgICAgd2hpbGUgKCRwYXJlbnQubGVuZ3RoID4gMCAmJiAhJHBhcmVudC5pcygnYm9keScpKSB7XG4gICAgICAgICAgICAgICAgLy8gU2VhcmNoIHdpdGhpbiB0aGlzIHBhcmVudCBmb3IgdGhlIHNlbGVjdG9yXG4gICAgICAgICAgICAgICAgbGV0ICRmb3VuZCA9ICRwYXJlbnQuZmluZChzZWxlY3Rvcik7XG4gICAgICAgICAgICAgICAgaWYgKCRmb3VuZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkZm91bmQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTW92ZSB1cCBvbmUgbGV2ZWxcbiAgICAgICAgICAgICAgICAkcGFyZW50ID0gJHBhcmVudC5wYXJlbnQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgd2UgcmVhY2hlZCBib2R5LCBzZWFyY2ggd2l0aGluIGJvZHkgYXMgd2VsbFxuICAgICAgICAgICAgaWYgKCRwYXJlbnQuaXMoJ2JvZHknKSkge1xuICAgICAgICAgICAgICAgIGxldCAkZm91bmQgPSAkcGFyZW50LmZpbmQoc2VsZWN0b3IpO1xuICAgICAgICAgICAgICAgIGlmICgkZm91bmQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGZvdW5kO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmV0dXJuIGVtcHR5IGpRdWVyeSBvYmplY3QgaWYgbm90aGluZyBmb3VuZFxuICAgICAgICAgICAgcmV0dXJuICQoKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBPdmVycmlkZSAkLmFqYXggdG8gcHJldmVudCBkaXJlY3QgQUpBWCBjYWxscyB0byBsb2NhbCBzZXJ2ZXJcbiAgICAgICAgLy8gRGV2ZWxvcGVycyBtdXN0IHVzZSB0aGUgQWpheCBlbmRwb2ludCBwYXR0ZXJuOiBhd2FpdCBDb250cm9sbGVyLm1ldGhvZChwYXJhbXMpXG4gICAgICAgIGNvbnN0IG5hdGl2ZV9hamF4ID0gJC5hamF4O1xuICAgICAgICAkLmFqYXggPSBmdW5jdGlvbiAodXJsLCBvcHRpb25zKSB7XG4gICAgICAgICAgICAvLyBIYW5kbGUgYm90aCAkLmFqYXgodXJsLCBvcHRpb25zKSBhbmQgJC5hamF4KG9wdGlvbnMpIHNpZ25hdHVyZXNcbiAgICAgICAgICAgIGxldCBzZXR0aW5ncztcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdXJsID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy51cmwgPSB1cmw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzID0gdXJsIHx8IHt9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGEgbG9jYWwgcmVxdWVzdCAocmVsYXRpdmUgVVJMIG9yIHNhbWUgZG9tYWluKVxuICAgICAgICAgICAgY29uc3QgcmVxdWVzdF91cmwgPSBzZXR0aW5ncy51cmwgfHwgJyc7XG4gICAgICAgICAgICBjb25zdCBpc19yZWxhdGl2ZSA9ICFyZXF1ZXN0X3VybC5tYXRjaCgvXmh0dHBzPzpcXC9cXC8vKTtcbiAgICAgICAgICAgIGNvbnN0IGlzX3NhbWVfZG9tYWluID0gcmVxdWVzdF91cmwuc3RhcnRzV2l0aCh3aW5kb3cubG9jYXRpb24ub3JpZ2luKTtcbiAgICAgICAgICAgIGNvbnN0IGlzX2xvY2FsX3JlcXVlc3QgPSBpc19yZWxhdGl2ZSB8fCBpc19zYW1lX2RvbWFpbjtcblxuICAgICAgICAgICAgLy8gQWxsb3cgZnJhbWV3b3JrIEFqYXguY2FsbCgpIHRvIGZ1bmN0aW9uXG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MuX19sb2NhbF9pbnRlZ3JhdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVfYWpheC5jYWxsKHRoaXMsIHNldHRpbmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWxsb3cgZmlsZSB1cGxvYWQgZW5kcG9pbnQgLSByZXF1aXJlcyBuYXRpdmUgJC5hamF4IGZvciBGb3JtRGF0YSBzdXBwb3J0XG4gICAgICAgICAgICBjb25zdCBpc19maWxlX3VwbG9hZCA9IHJlcXVlc3RfdXJsID09PSAnL191cGxvYWQnIHx8IHJlcXVlc3RfdXJsLmVuZHNXaXRoKCcvX3VwbG9hZCcpO1xuICAgICAgICAgICAgaWYgKGlzX2ZpbGVfdXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZV9hamF4LmNhbGwodGhpcywgc2V0dGluZ3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCbG9jayBsb2NhbCBBSkFYIHJlcXVlc3RzIHRoYXQgZG9uJ3QgdXNlIHRoZSBBamF4IGVuZHBvaW50IHBhdHRlcm5cbiAgICAgICAgICAgIGlmIChpc19sb2NhbF9yZXF1ZXN0KSB7XG4gICAgICAgICAgICAgICAgLy8gVHJ5IHRvIHBhcnNlIGNvbnRyb2xsZXIgYW5kIGFjdGlvbiBmcm9tIFVSTFxuICAgICAgICAgICAgICAgIGxldCBjb250cm9sbGVyX25hbWUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGxldCBhY3Rpb25fbmFtZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgY29uc3QgdXJsX21hdGNoID0gcmVxdWVzdF91cmwubWF0Y2goL1xcL19yc3hfYXBpXFwvKFteXFwvXSspXFwvKFteXFwvXFw/XSspLyk7XG4gICAgICAgICAgICAgICAgaWYgKHVybF9tYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVyX25hbWUgPSB1cmxfbWF0Y2hbMV07XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbl9uYW1lID0gdXJsX21hdGNoWzJdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBlcnJvcl9tZXNzYWdlID0gJ0FKQVggcmVxdWVzdHMgdG8gbG9jYWxob3N0IHZpYSAkLmFqYXgoKSBhcmUgcHJvaGliaXRlZC5cXG5cXG4nO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRyb2xsZXJfbmFtZSAmJiBhY3Rpb25fbmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGBJbnN0ZWFkIG9mOlxcbmA7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYCAgJC5hamF4KHt1cmw6ICcke3JlcXVlc3RfdXJsfScsIC4uLn0pXFxuXFxuYDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgVXNlOlxcbmA7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYCAgYXdhaXQgJHtjb250cm9sbGVyX25hbWV9LiR7YWN0aW9uX25hbWV9KHBhcmFtZXRlcnMpXFxuXFxuYDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGBVc2UgdGhlIEFqYXggZW5kcG9pbnQgcGF0dGVybjpcXG5gO1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGAgIGF3YWl0IENvbnRyb2xsZXJfTmFtZS5hY3Rpb25fbmFtZShwYXJhbWV0ZXJzKVxcblxcbmA7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgVGhlIGNvbnRyb2xsZXIgbWV0aG9kIG11c3QgaGF2ZSB0aGUgI1tBamF4X0VuZHBvaW50XSBhdHRyaWJ1dGUuYDtcblxuICAgICAgICAgICAgICAgIHNob3VsZG50X2hhcHBlbihlcnJvcl9tZXNzYWdlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWxsb3cgZXh0ZXJuYWwgcmVxdWVzdHMgKGRpZmZlcmVudCBkb21haW4pXG4gICAgICAgICAgICByZXR1cm4gbmF0aXZlX2FqYXguY2FsbCh0aGlzLCBzZXR0aW5ncyk7XG4gICAgICAgIH07XG4gICAgfVxufSIsIi8vIEBST1VURS1FWElTVFMtMDEtRVhDRVBUSU9OIC0gVGhpcyBmaWxlIGNvbnRhaW5zIGRvY3VtZW50YXRpb24gZXhhbXBsZXMgd2l0aCBmaWN0aW9uYWwgcm91dGUgbmFtZXNcblxuLyoqXG4gKiBSc3ggLSBDb3JlIEphdmFTY3JpcHQgUnVudGltZSBTeXN0ZW1cbiAqXG4gKiBUaGUgUnN4IGNsYXNzIGlzIHRoZSBjZW50cmFsIGh1YiBmb3IgdGhlIFJTWCBKYXZhU2NyaXB0IHJ1bnRpbWUsIHByb3ZpZGluZyBlc3NlbnRpYWxcbiAqIHN5c3RlbS1sZXZlbCB1dGlsaXRpZXMgdGhhdCBhbGwgb3RoZXIgZnJhbWV3b3JrIGNvbXBvbmVudHMgZGVwZW5kIG9uLiBJdCBzZXJ2ZXMgYXMgdGhlXG4gKiBmb3VuZGF0aW9uIGZvciB0aGUgY2xpZW50LXNpZGUgZnJhbWV3b3JrLCBoYW5kbGluZyBjb3JlIG9wZXJhdGlvbnMgdGhhdCBtdXN0IGJlIGdsb2JhbGx5XG4gKiBhY2Nlc3NpYmxlIGFuZCBjb25zaXN0ZW50bHkgYXZhaWxhYmxlLlxuICpcbiAqIENvcmUgUmVzcG9uc2liaWxpdGllczpcbiAqIC0gRXZlbnQgU3lzdGVtOiBBcHBsaWNhdGlvbi13aWRlIGV2ZW50IGJ1cyBmb3IgZnJhbWV3b3JrIGxpZmVjeWNsZSBhbmQgY3VzdG9tIGV2ZW50c1xuICogLSBFbnZpcm9ubWVudCBEZXRlY3Rpb246IFJ1bnRpbWUgZW52aXJvbm1lbnQgaWRlbnRpZmljYXRpb24gKGRldi9wcm9kdWN0aW9uKVxuICogLSBSb3V0ZSBNYW5hZ2VtZW50OiBUeXBlLXNhZmUgcm91dGUgZ2VuZXJhdGlvbiBhbmQgVVJMIGJ1aWxkaW5nXG4gKiAtIFVuaXF1ZSBJRCBHZW5lcmF0aW9uOiBDbGllbnQtc2lkZSB1bmlxdWUgaWRlbnRpZmllciBnZW5lcmF0aW9uXG4gKiAtIEZyYW1ld29yayBCb290c3RyYXA6IE11bHRpLXBoYXNlIGluaXRpYWxpemF0aW9uIG9yY2hlc3RyYXRpb25cbiAqIC0gTG9nZ2luZzogQ2VudHJhbGl6ZWQgbG9nZ2luZyBpbnRlcmZhY2UgKGRlbGVnYXRlcyB0byBjb25zb2xlX2RlYnVnKVxuICpcbiAqIFRoZSBSc3ggY2xhc3MgZGVsaWJlcmF0ZWx5IGtlZXBzIGl0cyBzY29wZSBsaW1pdGVkIHRvIGNvcmUgdXRpbGl0aWVzLiBBZHZhbmNlZCBmZWF0dXJlc1xuICogYXJlIGRlbGVnYXRlZCB0byBzcGVjaWFsaXplZCBjbGFzc2VzOlxuICogLSBNYW5pZmVzdCBvcGVyYXRpb25zIOKGkiBNYW5pZmVzdCBjbGFzc1xuICogLSBDYWNoaW5nIOKGkiBSc3hfQ2FjaGUgY2xhc3NcbiAqIC0gQUpBWC9BUEkgY2FsbHMg4oaSIEFqYXhfKiBjbGFzc2VzXG4gKiAtIFJvdXRlIHByb3hpZXMg4oaSIFJzeF9Sb3V0ZV9Qcm94eSBjbGFzc1xuICogLSBCZWhhdmlvcnMg4oaSIFJzeF9CZWhhdmlvcnMgY2xhc3NcbiAqXG4gKiBBbGwgbWV0aG9kcyBhcmUgc3RhdGljIC0gUnN4IGlzIG5ldmVyIGluc3RhbnRpYXRlZC4gSXQncyBhdmFpbGFibGUgZ2xvYmFsbHkgZnJvbSB0aGVcbiAqIG1vbWVudCBidW5kbGVzIGxvYWQgYW5kIHJlbWFpbnMgY29uc3RhbnQgdGhyb3VnaG91dCB0aGUgYXBwbGljYXRpb24gbGlmZWN5Y2xlLlxuICpcbiAqIFVzYWdlIEV4YW1wbGVzOlxuICogYGBgamF2YXNjcmlwdFxuICogLy8gRXZlbnQgc3lzdGVtXG4gKiBSc3gub24oJ2FwcF9yZWFkeScsICgpID0+IGNvbnNvbGUubG9nKCdBcHAgaW5pdGlhbGl6ZWQnKSk7XG4gKiBSc3gudHJpZ2dlcignY3VzdG9tX2V2ZW50Jywge2RhdGE6ICd2YWx1ZSd9KTtcbiAqXG4gKiAvLyBFbnZpcm9ubWVudCBkZXRlY3Rpb25cbiAqIGlmIChSc3guaXNfZGV2KCkpIHsgY29uc29sZS5sb2coJ0RldmVsb3BtZW50IG1vZGUnKTsgfVxuICpcbiAqIC8vIFJvdXRlIGdlbmVyYXRpb25cbiAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnQ29udHJvbGxlcicsICdhY3Rpb24nKS51cmwoKTtcbiAqXG4gKiAvLyBVbmlxdWUgSURzXG4gKiBjb25zdCB1bmlxdWVJZCA9IFJzeC51aWQoKTsgLy8gZS5nLiwgXCJyc3hfMTIzNDU2Nzg5MF8xXCJcbiAqIGBgYFxuICpcbiAqIEBzdGF0aWNcbiAqIEBnbG9iYWxcbiAqL1xuY2xhc3MgUnN4IHtcbiAgICAvLyBHZXRzIHNldCB0byB0cnVlIHRvIGludGVydXB0IHN0YXJ0dXAgc2VxdWVuY2VcbiAgICBzdGF0aWMgX19zdG9wcGVkID0gZmFsc2U7XG5cbiAgICAvLyBJbml0aWFsaXplIGV2ZW50IGhhbmRsZXJzIHN0b3JhZ2VcbiAgICBzdGF0aWMgX2luaXRfZXZlbnRzKCkge1xuICAgICAgICBpZiAodHlwZW9mIFJzeC5fZXZlbnRfaGFuZGxlcnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBSc3guX2V2ZW50X2hhbmRsZXJzID0ge307XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBSc3guX3RyaWdnZXJlZF9ldmVudHMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBSc3guX3RyaWdnZXJlZF9ldmVudHMgPSB7fTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlZ2lzdGVyIGFuIGV2ZW50IGhhbmRsZXJcbiAgICBzdGF0aWMgb24oZXZlbnQsIGNhbGxiYWNrKSB7XG4gICAgICAgIFJzeC5faW5pdF9ldmVudHMoKTtcblxuICAgICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XSkge1xuICAgICAgICAgICAgUnN4Ll9ldmVudF9oYW5kbGVyc1tldmVudF0gPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIFJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdLnB1c2goY2FsbGJhY2spO1xuXG4gICAgICAgIC8vIElmIHRoaXMgZXZlbnQgd2FzIGFscmVhZHkgdHJpZ2dlcmVkLCBjYWxsIHRoZSBjYWxsYmFjayBpbW1lZGlhdGVseVxuICAgICAgICBpZiAoUnN4Ll90cmlnZ2VyZWRfZXZlbnRzW2V2ZW50XSkge1xuICAgICAgICAgICAgY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCAnVHJpZ2dlcmluZyAnICsgZXZlbnQgKyAnIGZvciBsYXRlIHJlZ2lzdGVyZWQgY2FsbGJhY2snKTtcbiAgICAgICAgICAgIGNhbGxiYWNrKFJzeC5fdHJpZ2dlcmVkX2V2ZW50c1tldmVudF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVHJpZ2dlciBhbiBldmVudCB3aXRoIG9wdGlvbmFsIGRhdGFcbiAgICBzdGF0aWMgdHJpZ2dlcihldmVudCwgZGF0YSA9IHt9KSB7XG4gICAgICAgIFJzeC5faW5pdF9ldmVudHMoKTtcblxuICAgICAgICAvLyBSZWNvcmQgdGhhdCB0aGlzIGV2ZW50IHdhcyB0cmlnZ2VyZWRcbiAgICAgICAgUnN4Ll90cmlnZ2VyZWRfZXZlbnRzW2V2ZW50XSA9IGRhdGE7XG5cbiAgICAgICAgaWYgKCFSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCAnVHJpZ2dlcmluZyAnICsgZXZlbnQgKyAnIGZvciAnICsgUnN4Ll9ldmVudF9oYW5kbGVyc1tldmVudF0ubGVuZ3RoICsgJyBjYWxsYmFja3MnKTtcblxuICAgICAgICAvLyBDYWxsIGFsbCByZWdpc3RlcmVkIGhhbmRsZXJzIGZvciB0aGlzIGV2ZW50IGluIG9yZGVyXG4gICAgICAgIGZvciAoY29uc3QgY2FsbGJhY2sgb2YgUnN4Ll9ldmVudF9oYW5kbGVyc1tldmVudF0pIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGRhdGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQWxpYXMgZm9yIHRyaWdnZXIucmVmcmVzaCgnJyksIHNob3VsZCBiZSBjYWxsZWQgYWZ0ZXIgbWFqb3IgVUkgdXBkYXRlcyB0byBhcHBseSBzdWNoIGVmZmVjdHMgYXNcbiAgICAvLyB1bmRlcmxpbmluZyBsaW5rcyB0byB1bmltcGxlbWVudGVkICMgcm91dGVzXG4gICAgc3RhdGljIHRyaWdnZXJfcmVmcmVzaCgpIHtcbiAgICAgICAgLy8gVXNlIFJzeC5vbigncmVmcmVzaCcsIGNhbGxiYWNrKTsgdG8gcmVnaXN0ZXIgYSBjYWxsYmFjayBmb3IgcmVmcmVzaFxuICAgICAgICB0aGlzLnRyaWdnZXIoJ3JlZnJlc2gnKTtcbiAgICB9XG5cbiAgICAvLyBMb2cgdG8gc2VydmVyIHRoYXQgYW4gZXZlbnQgaGFwcGVuZWRcbiAgICBzdGF0aWMgbG9nKHR5cGUsIG1lc3NhZ2UgPSAnbm90aWNlJykge1xuICAgICAgICBDb3JlX0xvZy5sb2codHlwZSwgbWVzc2FnZSk7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoZSBhcHAgaXMgYmVpbmcgcnVuIGluIGRldiBtb2RlXG4gICAgLy8gVGhpcyBzaG91bGQgYWZmZWN0IGNhY2hpbmcgYW5kIHNvbWUgZGVidWcgY2hlY2tzXG4gICAgc3RhdGljIGlzX2RldigpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5yc3hhcHAuZGVidWc7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzX3Byb2QoKSB7XG4gICAgICAgIHJldHVybiAhd2luZG93LnJzeGFwcC5kZWJ1ZztcbiAgICB9XG5cbiAgICAvLyBHZW5lcmF0ZXMgYSB1bmlxdWUgbnVtYmVyIGZvciB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2VcbiAgICBzdGF0aWMgdWlkKCkge1xuICAgICAgICBpZiAodHlwZW9mIFJzeC5fdWlkID09IHVuZGVmKSB7XG4gICAgICAgICAgICBSc3guX3VpZCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFJzeC5fdWlkKys7XG4gICAgfVxuXG4gICAgLy8gU3RvcmFnZSBmb3Igcm91dGUgZGVmaW5pdGlvbnMgbG9hZGVkIGZyb20gYnVuZGxlc1xuICAgIHN0YXRpYyBfcm91dGVzID0ge307XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmUgcm91dGVzIGZyb20gYnVuZGxlZCBkYXRhXG4gICAgICogQ2FsbGVkIGJ5IGdlbmVyYXRlZCBKYXZhU2NyaXB0IGluIGJ1bmRsZXNcbiAgICAgKi9cbiAgICBzdGF0aWMgX2RlZmluZV9yb3V0ZXMocm91dGVzKSB7XG4gICAgICAgIC8vIE1lcmdlIHJvdXRlcyBpbnRvIHRoZSBnbG9iYWwgcm91dGUgc3RvcmFnZVxuICAgICAgICBmb3IgKGNvbnN0IGNsYXNzX25hbWUgaW4gcm91dGVzKSB7XG4gICAgICAgICAgICBpZiAoIVJzeC5fcm91dGVzW2NsYXNzX25hbWVdKSB7XG4gICAgICAgICAgICAgICAgUnN4Ll9yb3V0ZXNbY2xhc3NfbmFtZV0gPSB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoY29uc3QgbWV0aG9kX25hbWUgaW4gcm91dGVzW2NsYXNzX25hbWVdKSB7XG4gICAgICAgICAgICAgICAgUnN4Ll9yb3V0ZXNbY2xhc3NfbmFtZV1bbWV0aG9kX25hbWVdID0gcm91dGVzW2NsYXNzX25hbWVdW21ldGhvZF9uYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIFVSTCBmb3IgYSBjb250cm9sbGVyIHJvdXRlXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBnZW5lcmF0ZXMgVVJMcyBmb3IgY29udHJvbGxlciBhY3Rpb25zIGJ5IGxvb2tpbmcgdXAgcm91dGUgcGF0dGVybnNcbiAgICAgKiBhbmQgcmVwbGFjaW5nIHBhcmFtZXRlcnMuIEl0IGhhbmRsZXMgYm90aCByZWd1bGFyIHJvdXRlcyBhbmQgQWpheCBlbmRwb2ludHMuXG4gICAgICpcbiAgICAgKiBJZiB0aGUgcm91dGUgaXMgbm90IGZvdW5kIGluIHRoZSByb3V0ZSBkZWZpbml0aW9ucywgYSBkZWZhdWx0IHBhdHRlcm4gaXMgdXNlZDpcbiAgICAgKiBgL18ve2NvbnRyb2xsZXJ9L3thY3Rpb259YCB3aXRoIGFsbCBwYXJhbWV0ZXJzIGFwcGVuZGVkIGFzIHF1ZXJ5IHN0cmluZ3MuXG4gICAgICpcbiAgICAgKiBVc2FnZSBleGFtcGxlczpcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogLy8gU2ltcGxlIHJvdXRlIHdpdGhvdXQgcGFyYW1ldGVycyAoZGVmYXVsdHMgdG8gJ2luZGV4JyBhY3Rpb24pXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdGcm9udGVuZF9JbmRleF9Db250cm9sbGVyJyk7XG4gICAgICogLy8gUmV0dXJuczogL2Rhc2hib2FyZFxuICAgICAqXG4gICAgICogLy8gUm91dGUgd2l0aCBleHBsaWNpdCBhY3Rpb25cbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0luZGV4X0NvbnRyb2xsZXInLCAnaW5kZXgnKTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvZGFzaGJvYXJkXG4gICAgICpcbiAgICAgKiAvLyBSb3V0ZSB3aXRoIGludGVnZXIgcGFyYW1ldGVyIChzZXRzICdpZCcpXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdGcm9udGVuZF9DbGllbnRfVmlld19Db250cm9sbGVyJywgJ3ZpZXcnLCAxMjMpO1xuICAgICAqIC8vIFJldHVybnM6IC9jbGllbnRzL3ZpZXcvMTIzXG4gICAgICpcbiAgICAgKiAvLyBSb3V0ZSB3aXRoIG5hbWVkIHBhcmFtZXRlcnMgKG9iamVjdClcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0NsaWVudF9WaWV3X0NvbnRyb2xsZXInLCAndmlldycsIHtpZDogJ0MwMDEnfSk7XG4gICAgICogLy8gUmV0dXJuczogL2NsaWVudHMvdmlldy9DMDAxXG4gICAgICpcbiAgICAgKiAvLyBSb3V0ZSB3aXRoIHJlcXVpcmVkIGFuZCBxdWVyeSBwYXJhbWV0ZXJzXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdGcm9udGVuZF9DbGllbnRfVmlld19Db250cm9sbGVyJywgJ3ZpZXcnLCB7XG4gICAgICogICAgIGlkOiAnQzAwMScsXG4gICAgICogICAgIHRhYjogJ2hpc3RvcnknXG4gICAgICogfSk7XG4gICAgICogLy8gUmV0dXJuczogL2NsaWVudHMvdmlldy9DMDAxP3RhYj1oaXN0b3J5XG4gICAgICpcbiAgICAgKiAvLyBSb3V0ZSBub3QgZm91bmQgLSB1c2VzIGRlZmF1bHQgcGF0dGVyblxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnVW5pbXBsZW1lbnRlZF9Db250cm9sbGVyJywgJ3NvbWVfYWN0aW9uJywge2ZvbzogJ2Jhcid9KTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvXy9VbmltcGxlbWVudGVkX0NvbnRyb2xsZXIvc29tZV9hY3Rpb24/Zm9vPWJhclxuICAgICAqXG4gICAgICogLy8gUGxhY2Vob2xkZXIgcm91dGVcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Z1dHVyZV9Db250cm9sbGVyJywgJyNpbmRleCcpO1xuICAgICAqIC8vIFJldHVybnM6ICNcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjbGFzc19uYW1lIFRoZSBjb250cm9sbGVyIGNsYXNzIG5hbWUgKGUuZy4sICdVc2VyX0NvbnRyb2xsZXInKVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbYWN0aW9uX25hbWU9J2luZGV4J10gVGhlIGFjdGlvbi9tZXRob2QgbmFtZSAoZGVmYXVsdHMgdG8gJ2luZGV4JykuIFVzZSAnI2FjdGlvbicgZm9yIHBsYWNlaG9sZGVycy5cbiAgICAgKiBAcGFyYW0ge251bWJlcnxPYmplY3R9IFtwYXJhbXM9bnVsbF0gUm91dGUgcGFyYW1ldGVycy4gSW50ZWdlciBzZXRzICdpZCcsIG9iamVjdCBwcm92aWRlcyBuYW1lZCBwYXJhbXMuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGdlbmVyYXRlZCBVUkxcbiAgICAgKi9cbiAgICBzdGF0aWMgUm91dGUoY2xhc3NfbmFtZSwgYWN0aW9uX25hbWUgPSAnaW5kZXgnLCBwYXJhbXMgPSBudWxsKSB7XG4gICAgICAgIC8vIE5vcm1hbGl6ZSBwYXJhbXMgdG8gb2JqZWN0XG4gICAgICAgIGxldCBwYXJhbXNfb2JqID0ge307XG4gICAgICAgIGlmICh0eXBlb2YgcGFyYW1zID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgcGFyYW1zX29iaiA9IHsgaWQ6IHBhcmFtcyB9O1xuICAgICAgICB9IGVsc2UgaWYgKHBhcmFtcyAmJiB0eXBlb2YgcGFyYW1zID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcGFyYW1zX29iaiA9IHBhcmFtcztcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMgIT09IG51bGwgJiYgcGFyYW1zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGFyYW1zIG11c3QgYmUgbnVtYmVyLCBvYmplY3QsIG9yIG51bGwnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFBsYWNlaG9sZGVyIHJvdXRlOiBhY3Rpb24gc3RhcnRzIHdpdGggIyBtZWFucyB1bmltcGxlbWVudGVkL3NjYWZmb2xkaW5nXG4gICAgICAgIGlmIChhY3Rpb25fbmFtZS5zdGFydHNXaXRoKCcjJykpIHtcbiAgICAgICAgICAgIHJldHVybiAnIyc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBpZiByb3V0ZSBleGlzdHMgaW4gZGVmaW5pdGlvbnNcbiAgICAgICAgbGV0IHBhdHRlcm47XG4gICAgICAgIGlmIChSc3guX3JvdXRlc1tjbGFzc19uYW1lXSAmJiBSc3guX3JvdXRlc1tjbGFzc19uYW1lXVthY3Rpb25fbmFtZV0pIHtcbiAgICAgICAgICAgIHBhdHRlcm4gPSBSc3guX3JvdXRlc1tjbGFzc19uYW1lXVthY3Rpb25fbmFtZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBSb3V0ZSBub3QgZm91bmQgLSB1c2UgZGVmYXVsdCBwYXR0ZXJuIC9fL3tjb250cm9sbGVyfS97YWN0aW9ufVxuICAgICAgICAgICAgcGF0dGVybiA9IGAvXy8ke2NsYXNzX25hbWV9LyR7YWN0aW9uX25hbWV9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdlbmVyYXRlIFVSTCBmcm9tIHBhdHRlcm5cbiAgICAgICAgcmV0dXJuIFJzeC5fZ2VuZXJhdGVfdXJsX2Zyb21fcGF0dGVybihwYXR0ZXJuLCBwYXJhbXNfb2JqKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBVUkwgZnJvbSByb3V0ZSBwYXR0ZXJuIGJ5IHJlcGxhY2luZyBwYXJhbWV0ZXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0dGVybiBUaGUgcm91dGUgcGF0dGVybiAoZS5nLiwgJy91c2Vycy86aWQvdmlldycpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtcyBQYXJhbWV0ZXJzIHRvIGZpbGwgaW50byB0aGUgcm91dGVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZ2VuZXJhdGVkIFVSTFxuICAgICAqL1xuICAgIHN0YXRpYyBfZ2VuZXJhdGVfdXJsX2Zyb21fcGF0dGVybihwYXR0ZXJuLCBwYXJhbXMpIHtcbiAgICAgICAgLy8gRXh0cmFjdCByZXF1aXJlZCBwYXJhbWV0ZXJzIGZyb20gdGhlIHBhdHRlcm5cbiAgICAgICAgY29uc3QgcmVxdWlyZWRfcGFyYW1zID0gW107XG4gICAgICAgIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hdGNoKC86KFthLXpBLVpfXVthLXpBLVowLTlfXSopL2cpO1xuICAgICAgICBpZiAobWF0Y2hlcykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIHRoZSA6IHByZWZpeCBmcm9tIGVhY2ggbWF0Y2hcbiAgICAgICAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2YgbWF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHJlcXVpcmVkX3BhcmFtcy5wdXNoKG1hdGNoLnN1YnN0cmluZygxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBmb3IgcmVxdWlyZWQgcGFyYW1ldGVyc1xuICAgICAgICBjb25zdCBtaXNzaW5nID0gW107XG4gICAgICAgIGZvciAoY29uc3QgcmVxdWlyZWQgb2YgcmVxdWlyZWRfcGFyYW1zKSB7XG4gICAgICAgICAgICBpZiAoIShyZXF1aXJlZCBpbiBwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZy5wdXNoKHJlcXVpcmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtaXNzaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUmVxdWlyZWQgcGFyYW1ldGVycyBbJHttaXNzaW5nLmpvaW4oJywgJyl9XSBhcmUgbWlzc2luZyBmb3Igcm91dGUgJHtwYXR0ZXJufWApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQnVpbGQgdGhlIFVSTCBieSByZXBsYWNpbmcgcGFyYW1ldGVyc1xuICAgICAgICBsZXQgdXJsID0gcGF0dGVybjtcbiAgICAgICAgY29uc3QgdXNlZF9wYXJhbXMgPSB7fTtcblxuICAgICAgICBmb3IgKGNvbnN0IHBhcmFtX25hbWUgb2YgcmVxdWlyZWRfcGFyYW1zKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHBhcmFtc1twYXJhbV9uYW1lXTtcbiAgICAgICAgICAgIC8vIFVSTCBlbmNvZGUgdGhlIHZhbHVlXG4gICAgICAgICAgICBjb25zdCBlbmNvZGVkX3ZhbHVlID0gZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKTtcbiAgICAgICAgICAgIHVybCA9IHVybC5yZXBsYWNlKCc6JyArIHBhcmFtX25hbWUsIGVuY29kZWRfdmFsdWUpO1xuICAgICAgICAgICAgdXNlZF9wYXJhbXNbcGFyYW1fbmFtZV0gPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29sbGVjdCBhbnkgZXh0cmEgcGFyYW1ldGVycyBmb3IgcXVlcnkgc3RyaW5nXG4gICAgICAgIGNvbnN0IHF1ZXJ5X3BhcmFtcyA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBwYXJhbXMpIHtcbiAgICAgICAgICAgIGlmICghdXNlZF9wYXJhbXNba2V5XSkge1xuICAgICAgICAgICAgICAgIHF1ZXJ5X3BhcmFtc1trZXldID0gcGFyYW1zW2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBcHBlbmQgcXVlcnkgc3RyaW5nIGlmIHRoZXJlIGFyZSBleHRyYSBwYXJhbWV0ZXJzXG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhxdWVyeV9wYXJhbXMpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IHF1ZXJ5X3N0cmluZyA9IE9iamVjdC5lbnRyaWVzKHF1ZXJ5X3BhcmFtcylcbiAgICAgICAgICAgICAgICAubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke2VuY29kZVVSSUNvbXBvbmVudChrZXkpfT0ke2VuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSl9YClcbiAgICAgICAgICAgICAgICAuam9pbignJicpO1xuICAgICAgICAgICAgdXJsICs9ICc/JyArIHF1ZXJ5X3N0cmluZztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1cmw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IENhbGwgYSBzcGVjaWZpYyBtZXRob2Qgb24gYWxsIGNsYXNzZXMgdGhhdCBoYXZlIGl0XG4gICAgICogQ29sbGVjdHMgcHJvbWlzZXMgZnJvbSByZXR1cm4gdmFsdWVzIGFuZCB3YWl0cyBmb3IgYWxsIHRvIHJlc29sdmVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kX25hbWUgVGhlIG1ldGhvZCBuYW1lIHRvIGNhbGwgb24gYWxsIGNsYXNzZXNcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIG1ldGhvZCBjYWxscyBjb21wbGV0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfcnN4X2NhbGxfYWxsX2NsYXNzZXMobWV0aG9kX25hbWUpIHtcbiAgICAgICAgY29uc3QgYWxsX2NsYXNzZXMgPSBNYW5pZmVzdC5nZXRfYWxsX2NsYXNzZXMoKTtcbiAgICAgICAgY29uc3QgY2xhc3Nlc193aXRoX21ldGhvZCA9IFtdO1xuICAgICAgICBjb25zdCBwcm9taXNlX3BpbGUgPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IGNsYXNzX2luZm8gb2YgYWxsX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzX29iamVjdCA9IGNsYXNzX2luZm8uY2xhc3Nfb2JqZWN0O1xuICAgICAgICAgICAgY29uc3QgY2xhc3NfbmFtZSA9IGNsYXNzX2luZm8uY2xhc3NfbmFtZTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBjbGFzcyBoYXMgdGhlIG1ldGhvZCAoc3RhdGljIG1ldGhvZHMgYXJlIG9uIHRoZSBjbGFzcyBpdHNlbGYpXG4gICAgICAgICAgICBpZiAodHlwZW9mIGNsYXNzX29iamVjdFttZXRob2RfbmFtZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzX3dpdGhfbWV0aG9kLnB1c2goY2xhc3NfbmFtZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmV0dXJuX3ZhbHVlID0gYXdhaXQgY2xhc3Nfb2JqZWN0W21ldGhvZF9uYW1lXSgpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ29sbGVjdCBwcm9taXNlcyBmcm9tIHJldHVybiB2YWx1ZVxuICAgICAgICAgICAgICAgIGlmIChyZXR1cm5fdmFsdWUgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb21pc2VfcGlsZS5wdXNoKHJldHVybl92YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHJldHVybl92YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHJldHVybl92YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0gaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZV9waWxlLnB1c2goaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoUnN4Ll9fc3RvcHBlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNsYXNzZXNfd2l0aF9tZXRob2QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCBgJHttZXRob2RfbmFtZX06ICR7Y2xhc3Nlc193aXRoX21ldGhvZC5sZW5ndGh9IGNsYXNzZXNgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEF3YWl0IGFsbCBwcm9taXNlcyBiZWZvcmUgcmV0dXJuaW5nXG4gICAgICAgIGlmIChwcm9taXNlX3BpbGUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCBgJHttZXRob2RfbmFtZX06IEF3YWl0aW5nICR7cHJvbWlzZV9waWxlLmxlbmd0aH0gcHJvbWlzZXNgKTtcbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VfcGlsZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogRXhlY3V0ZSBtdWx0aS1waGFzZSBpbml0aWFsaXphdGlvbiBmb3IgYWxsIHJlZ2lzdGVyZWQgY2xhc3Nlc1xuICAgICAqIFRoaXMgcnVucyB2YXJpb3VzIGluaXRpYWxpemF0aW9uIHBoYXNlcyBpbiBvcmRlciB0byBwcm9wZXJseSBzZXQgdXAgdGhlIGFwcGxpY2F0aW9uXG4gICAgICogQHJldHVybnMge1Byb21pc2V9IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBpbml0aWFsaXphdGlvbiBwaGFzZXMgY29tcGxldGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgX3JzeF9jb3JlX2Jvb3QoKSB7XG4gICAgICAgIGlmIChSc3guX19ib290ZWQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1JzeC5fcnN4X2NvcmVfYm9vdCBjYWxsZWQgbW9yZSB0aGFuIG9uY2UnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIFJzeC5fX2Jvb3RlZCA9IHRydWU7XG5cbiAgICAgICAgLy8gR2V0IGFsbCByZWdpc3RlcmVkIGNsYXNzZXMgZnJvbSB0aGUgbWFuaWZlc3RcbiAgICAgICAgY29uc3QgYWxsX2NsYXNzZXMgPSBNYW5pZmVzdC5nZXRfYWxsX2NsYXNzZXMoKTtcblxuICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsIGBTdGFydGluZyBfcnN4X2NvcmVfYm9vdCB3aXRoICR7YWxsX2NsYXNzZXMubGVuZ3RofSBjbGFzc2VzYCk7XG5cbiAgICAgICAgaWYgKCFhbGxfY2xhc3NlcyB8fCBhbGxfY2xhc3Nlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIC8vIE5vIGNsYXNzZXMgdG8gaW5pdGlhbGl6ZVxuICAgICAgICAgICAgc2hvdWxkbnRfaGFwcGVuKCdObyBjbGFzc2VzIHJlZ2lzdGVyZWQgaW4ganMgLSB0aGVyZSBzaG91bGQgYmUgYXQgbGVhc3QgdGhlIGNvcmUgZnJhbWV3b3JrIGNsYXNzZXMnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlZmluZSBpbml0aWFsaXphdGlvbiBwaGFzZXMgaW4gb3JkZXJcbiAgICAgICAgY29uc3QgcGhhc2VzID0gW1xuICAgICAgICAgICAgeyBldmVudDogJ2ZyYW1ld29ya19jb3JlX2RlZmluZScsIG1ldGhvZDogJ19vbl9mcmFtZXdvcmtfY29yZV9kZWZpbmUnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnZnJhbWV3b3JrX21vZHVsZXNfZGVmaW5lJywgbWV0aG9kOiAnX29uX2ZyYW1ld29ya19tb2R1bGVzX2RlZmluZScgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdmcmFtZXdvcmtfY29yZV9pbml0JywgbWV0aG9kOiAnX29uX2ZyYW1ld29ya19jb3JlX2luaXQnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnYXBwX21vZHVsZXNfZGVmaW5lJywgbWV0aG9kOiAnb25fYXBwX21vZHVsZXNfZGVmaW5lJyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2FwcF9kZWZpbmUnLCBtZXRob2Q6ICdvbl9hcHBfZGVmaW5lJyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2ZyYW1ld29ya19tb2R1bGVzX2luaXQnLCBtZXRob2Q6ICdfb25fZnJhbWV3b3JrX21vZHVsZXNfaW5pdCcgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdhcHBfbW9kdWxlc19pbml0JywgbWV0aG9kOiAnb25fYXBwX21vZHVsZXNfaW5pdCcgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdhcHBfaW5pdCcsIG1ldGhvZDogJ29uX2FwcF9pbml0JyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2FwcF9yZWFkeScsIG1ldGhvZDogJ29uX2FwcF9yZWFkeScgfSxcbiAgICAgICAgXTtcblxuICAgICAgICAvLyBFeGVjdXRlIGVhY2ggcGhhc2UgaW4gb3JkZXJcbiAgICAgICAgZm9yIChjb25zdCBwaGFzZSBvZiBwaGFzZXMpIHtcbiAgICAgICAgICAgIGF3YWl0IFJzeC5fcnN4X2NhbGxfYWxsX2NsYXNzZXMocGhhc2UubWV0aG9kKTtcblxuICAgICAgICAgICAgaWYgKFJzeC5fX3N0b3BwZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFJzeC50cmlnZ2VyKHBoYXNlLmV2ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVpIHJlZnJlc2ggY2FsbGJhY2tzXG4gICAgICAgIFJzeC50cmlnZ2VyX3JlZnJlc2goKTtcblxuICAgICAgICAvLyBBbGwgcGhhc2VzIGNvbXBsZXRlXG4gICAgICAgIGNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgJ0luaXRpYWxpemF0aW9uIGNvbXBsZXRlJyk7XG5cbiAgICAgICAgLy8gVE9ETzogRmluZCBhIGdvb2Qgd2FpdCB0byB3YWl0IGZvciBhbGwganFodG1sIGNvbXBvbmVudHMgdG8gbG9hZCwgdGhlbiB0cmlnZ2VyIG9uX3JlYWR5IGFuZCBvbigncmVhZHknKSBlbXVsYXRpbmcgdGhlIHRvcCBsZXZlbCBsYXN0IHN5bnRheCB0aGF0IGpxaHRtbCBjb21wb25lbnRzIG9wZXJhdGVhcywgYnV0IGFzIGEgc3RhbmRhcmQganMgY2xhc3MgKHN1Y2ggYXMgYSBwYWdlIGNsYXNzKS4gIFRoZSBiaWdnZXN0IHF1ZXN0aW9uIGlzLCBob3cgZG8gd2UgZWZmaWNpZW50bHkgY2hvb3NlIG9ubHkgdGhlIHRvcCBsZXZlbCBqcWh0bWwgY29tcG9uZW50cy4gIGRvIHdlIG9ubHkgY29uc2lkZXIgY29tcG9uZW50cyBjcmV0YWVkIGRpcmVjdGx5IG9uIGJsYWRlIHRlbXBsYXRlcz8gdGhhdCBzZWFtcyByZWFzb25hYmxlLi4uXG5cbiAgICAgICAgLy8gVHJpZ2dlciBfZGVidWdfcmVhZHkgZXZlbnQgLSB0aGlzIGlzIE9OTFkgZm9yIHRvb2xpbmcgbGlrZSByc3g6ZGVidWdcbiAgICAgICAgLy8gRE8gTk9UIHVzZSB0aGlzIGluIGFwcGxpY2F0aW9uIGNvZGUgLSB1c2Ugb25fYXBwX3JlYWR5KCkgcGhhc2UgaW5zdGVhZFxuICAgICAgICAvLyBUaGlzIGV2ZW50IGV4aXN0cyBzb2xlbHkgZm9yIGRlYnVnZ2luZyB0b29scyB0aGF0IG5lZWQgdG8gcnVuIGFmdGVyIGZ1bGwgaW5pdGlhbGl6YXRpb25cbiAgICAgICAgUnN4LnRyaWdnZXIoJ19kZWJ1Z19yZWFkeScpO1xuICAgIH1cblxuICAgIC8qIENhbGxpbmcgdGhpcyBzdG9wcyB0aGUgYm9vdCBwcm9jZXNzLiAqL1xuICAgIHN0YXRpYyBhc3luYyBfcnN4X2NvcmVfYm9vdF9zdG9wKHJlYXNvbikge1xuICAgICAgICBjb25zb2xlLmVycm9yKHJlYXNvbik7XG4gICAgICAgIFJzeC5fX3N0b3BwZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhcnNlIFVSTCBoYXNoIGludG8ga2V5LXZhbHVlIG9iamVjdFxuICAgICAqIEhhbmRsZXMgZm9ybWF0OiAja2V5PXZhbHVlJmtleTI9dmFsdWUyXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBQYXJzZWQgaGFzaCBwYXJhbWV0ZXJzXG4gICAgICovXG4gICAgc3RhdGljIF9wYXJzZV9oYXNoKCkge1xuICAgICAgICBjb25zdCBoYXNoID0gd2luZG93LmxvY2F0aW9uLmhhc2g7XG4gICAgICAgIGlmICghaGFzaCB8fCBoYXNoID09PSAnIycpIHtcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSBsZWFkaW5nICMgYW5kIHBhcnNlIGFzIHF1ZXJ5IHN0cmluZ1xuICAgICAgICBjb25zdCBoYXNoX3N0cmluZyA9IGhhc2guc3Vic3RyaW5nKDEpO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7fTtcblxuICAgICAgICBjb25zdCBwYWlycyA9IGhhc2hfc3RyaW5nLnNwbGl0KCcmJyk7XG4gICAgICAgIGZvciAoY29uc3QgcGFpciBvZiBwYWlycykge1xuICAgICAgICAgICAgY29uc3QgW2tleSwgdmFsdWVdID0gcGFpci5zcGxpdCgnPScpO1xuICAgICAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgICAgIHBhcmFtc1tkZWNvZGVVUklDb21wb25lbnQoa2V5KV0gPSB2YWx1ZSA/IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSkgOiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXJhbXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VyaWFsaXplIG9iamVjdCBpbnRvIFVSTCBoYXNoIGZvcm1hdFxuICAgICAqIFByb2R1Y2VzIGZvcm1hdDogI2tleT12YWx1ZSZrZXkyPXZhbHVlMlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtcyBLZXktdmFsdWUgcGFpcnMgdG8gZW5jb2RlXG4gICAgICogQHJldHVybnMge3N0cmluZ30gRW5jb2RlZCBoYXNoIHN0cmluZyAod2l0aCBsZWFkaW5nICMsIG9yIGVtcHR5IHN0cmluZylcbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZV9oYXNoKHBhcmFtcykge1xuICAgICAgICBjb25zdCBwYWlycyA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBwYXJhbXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcGFyYW1zW2tleV07XG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gJycpIHtcbiAgICAgICAgICAgICAgICBwYWlycy5wdXNoKGAke2VuY29kZVVSSUNvbXBvbmVudChrZXkpfT0ke2VuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSl9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGFpcnMubGVuZ3RoID4gMCA/ICcjJyArIHBhaXJzLmpvaW4oJyYnKSA6ICcnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgcGFnZSBzdGF0ZSBmcm9tIFVSTCBoYXNoXG4gICAgICpcbiAgICAgKiBVc2FnZTpcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogY29uc3Qgc3RhdGUgPSBSc3guZ2V0X2FsbF9wYWdlX3N0YXRlKCk7XG4gICAgICogLy8gUmV0dXJuczoge2RnX3BhZ2U6ICcyJywgZGdfc29ydDogJ25hbWUnfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHJldHVybnMge09iamVjdH0gQWxsIGhhc2ggcGFyYW1ldGVycyBhcyBrZXktdmFsdWUgcGFpcnNcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2FsbF9wYWdlX3N0YXRlKCkge1xuICAgICAgICByZXR1cm4gUnN4Ll9wYXJzZV9oYXNoKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHNpbmdsZSB2YWx1ZSBmcm9tIFVSTCBoYXNoIHN0YXRlXG4gICAgICpcbiAgICAgKiBVc2FnZTpcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogY29uc3QgcGFnZSA9IFJzeC5nZXRfcGFnZV9zdGF0ZSgnZGdfcGFnZScpO1xuICAgICAqIC8vIFJldHVybnM6ICcyJyBvciBudWxsIGlmIG5vdCBzZXRcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSB0byByZXRyaWV2ZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gVGhlIHZhbHVlIG9yIG51bGwgaWYgbm90IGZvdW5kXG4gICAgICovXG4gICAgc3RhdGljIGdldF9wYWdlX3N0YXRlKGtleSkge1xuICAgICAgICBjb25zdCBzdGF0ZSA9IFJzeC5fcGFyc2VfaGFzaCgpO1xuICAgICAgICByZXR1cm4gc3RhdGVba2V5XSA/PyBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCBzaW5nbGUgdmFsdWUgaW4gVVJMIGhhc2ggc3RhdGUgKHJlcGxhY2VzIGhpc3RvcnksIGRvZXNuJ3QgYWRkKVxuICAgICAqXG4gICAgICogVXNhZ2U6XG4gICAgICogYGBgamF2YXNjcmlwdFxuICAgICAqIFJzeC5zZXRfcGFnZV9zdGF0ZSgnZGdfcGFnZScsIDIpO1xuICAgICAqIC8vIFVSTCBiZWNvbWVzOiBodHRwOi8vZXhhbXBsZS5jb20vcGFnZSNkZ19wYWdlPTJcbiAgICAgKlxuICAgICAqIFJzeC5zZXRfcGFnZV9zdGF0ZSgnZGdfcGFnZScsIG51bGwpOyAvLyBSZW1vdmUga2V5XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgdG8gc2V0XG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfG51bGx9IHZhbHVlIFRoZSB2YWx1ZSAobnVsbC9lbXB0eSByZW1vdmVzIHRoZSBrZXkpXG4gICAgICovXG4gICAgc3RhdGljIHNldF9wYWdlX3N0YXRlKGtleSwgdmFsdWUpIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBSc3guX3BhcnNlX2hhc2goKTtcblxuICAgICAgICAvLyBVcGRhdGUgb3IgcmVtb3ZlIHRoZSBrZXlcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICBkZWxldGUgc3RhdGVba2V5XTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXRlW2tleV0gPSBTdHJpbmcodmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIFVSTCB3aXRob3V0IGFkZGluZyBoaXN0b3J5XG4gICAgICAgIGNvbnN0IG5ld19oYXNoID0gUnN4Ll9zZXJpYWxpemVfaGFzaChzdGF0ZSk7XG4gICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSArIHdpbmRvdy5sb2NhdGlvbi5zZWFyY2ggKyBuZXdfaGFzaDtcbiAgICAgICAgaGlzdG9yeS5yZXBsYWNlU3RhdGUobnVsbCwgJycsIHVybCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IG11bHRpcGxlIHZhbHVlcyBpbiBVUkwgaGFzaCBzdGF0ZSBhdCBvbmNlXG4gICAgICpcbiAgICAgKiBVc2FnZTpcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogUnN4LnNldF9hbGxfcGFnZV9zdGF0ZSh7ZGdfcGFnZTogMiwgZGdfc29ydDogJ25hbWUnfSk7XG4gICAgICogLy8gVVJMIGJlY29tZXM6IGh0dHA6Ly9leGFtcGxlLmNvbS9wYWdlI2RnX3BhZ2U9MiZkZ19zb3J0PW5hbWVcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBuZXdfc3RhdGUgT2JqZWN0IHdpdGgga2V5LXZhbHVlIHBhaXJzIHRvIHNldFxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRfYWxsX3BhZ2Vfc3RhdGUobmV3X3N0YXRlKSB7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gUnN4Ll9wYXJzZV9oYXNoKCk7XG5cbiAgICAgICAgLy8gTWVyZ2UgbmV3IHN0YXRlXG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIG5ld19zdGF0ZSkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBuZXdfc3RhdGVba2V5XTtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBzdGF0ZVtrZXldO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdGF0ZVtrZXldID0gU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZSBVUkwgd2l0aG91dCBhZGRpbmcgaGlzdG9yeVxuICAgICAgICBjb25zdCBuZXdfaGFzaCA9IFJzeC5fc2VyaWFsaXplX2hhc2goc3RhdGUpO1xuICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUgKyB3aW5kb3cubG9jYXRpb24uc2VhcmNoICsgbmV3X2hhc2g7XG4gICAgICAgIGhpc3RvcnkucmVwbGFjZVN0YXRlKG51bGwsICcnLCB1cmwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlciBhbiBlcnJvciBpbiBhIERPTSBlbGVtZW50XG4gICAgICpcbiAgICAgKiBEaXNwbGF5cyBlcnJvcnMgZnJvbSBBamF4IGNhbGxzIGluIGEgc3RhbmRhcmRpemVkIGZvcm1hdC4gSGFuZGxlcyBkaWZmZXJlbnRcbiAgICAgKiBlcnJvciB0eXBlcyAoZmF0YWwsIHZhbGlkYXRpb24sIGF1dGgsIGdlbmVyaWMpIHdpdGggYXBwcm9wcmlhdGUgZm9ybWF0dGluZy5cbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiB0cnkge1xuICAgICAqICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBDb250cm9sbGVyLm1ldGhvZCgpO1xuICAgICAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICogICAgIFJzeC5yZW5kZXJfZXJyb3IoZXJyb3IsICcjZXJyb3JfY29udGFpbmVyJyk7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtFcnJvcnxPYmplY3R9IGVycm9yIC0gRXJyb3Igb2JqZWN0IGZyb20gQWpheCBjYWxsXG4gICAgICogQHBhcmFtIHtqUXVlcnl8c3RyaW5nfSBjb250YWluZXIgLSBqUXVlcnkgZWxlbWVudCBvciBzZWxlY3RvciBmb3IgZXJyb3IgZGlzcGxheVxuICAgICAqL1xuICAgIHN0YXRpYyByZW5kZXJfZXJyb3IoZXJyb3IsIGNvbnRhaW5lcikge1xuICAgICAgICBjb25zdCAkY29udGFpbmVyID0gJChjb250YWluZXIpO1xuXG4gICAgICAgIGlmICghJGNvbnRhaW5lci5leGlzdHMoKSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignUnN4LnJlbmRlcl9lcnJvcjogQ29udGFpbmVyIG5vdCBmb3VuZCcsIGNvbnRhaW5lcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDbGVhciBleGlzdGluZyBjb250ZW50XG4gICAgICAgICRjb250YWluZXIuZW1wdHkoKTtcblxuICAgICAgICBsZXQgaHRtbCA9ICcnO1xuXG4gICAgICAgIC8vIEhhbmRsZSBkaWZmZXJlbnQgZXJyb3IgdHlwZXNcbiAgICAgICAgaWYgKGVycm9yLnR5cGUgPT09ICdmYXRhbCcgJiYgZXJyb3IuZGV0YWlscykge1xuICAgICAgICAgICAgLy8gRmF0YWwgUEhQIGVycm9yIHdpdGggZmlsZS9saW5lL2Vycm9yXG4gICAgICAgICAgICBjb25zdCBkZXRhaWxzID0gZXJyb3IuZGV0YWlscztcbiAgICAgICAgICAgIGNvbnN0IGZpbGUgPSBkZXRhaWxzLmZpbGUgfHwgJ1Vua25vd24gZmlsZSc7XG4gICAgICAgICAgICBjb25zdCBsaW5lID0gZGV0YWlscy5saW5lIHx8ICc/JztcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBkZXRhaWxzLmVycm9yIHx8IGVycm9yLm1lc3NhZ2UgfHwgJ0ZhdGFsIGVycm9yIG9jY3VycmVkJztcblxuICAgICAgICAgICAgaHRtbCA9IGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxoNT5VbmNhdWdodCBGYXRhbCBFcnJvciBpbiAke2ZpbGV9OiR7bGluZX06PC9oNT5cbiAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+JHtSc3guX2VzY2FwZV9odG1sKG1lc3NhZ2UpfTwvcD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIGA7XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3IudHlwZSA9PT0gJ2Zvcm1fZXJyb3InICYmIGVycm9yLmRldGFpbHMpIHtcbiAgICAgICAgICAgIC8vIFZhbGlkYXRpb24gZXJyb3JzIC0gc2hvdyB1bm1hdGNoZWQgZXJyb3JzIG9ubHlcbiAgICAgICAgICAgIC8vIChtYXRjaGVkIGVycm9ycyBzaG91bGQgYmUgaGFuZGxlZCBieSBGb3JtX1V0aWxzLmFwcGx5X2Zvcm1fZXJyb3JzKVxuICAgICAgICAgICAgY29uc3QgZXJyb3JzID0gZXJyb3IuZGV0YWlscztcbiAgICAgICAgICAgIGNvbnN0IGVycm9yX2xpc3QgPSBbXTtcblxuICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBlcnJvcnMpIHtcbiAgICAgICAgICAgICAgICBlcnJvcl9saXN0LnB1c2goZXJyb3JzW2ZpZWxkXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChlcnJvcl9saXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiIHJvbGU9XCJhbGVydFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGg1PlZhbGlkYXRpb24gRXJyb3JzOjwvaDU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJtYi0wXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHtlcnJvcl9saXN0Lm1hcChlcnIgPT4gYDxsaT4ke1JzeC5fZXNjYXBlX2h0bWwoZXJyKX08L2xpPmApLmpvaW4oJycpfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC91bD5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChlcnJvci50eXBlID09PSAnYXV0aF9yZXF1aXJlZCcgfHwgZXJyb3IudHlwZSA9PT0gJ3VuYXV0aG9yaXplZCcpIHtcbiAgICAgICAgICAgIC8vIEF1dGhlbnRpY2F0aW9uL2F1dGhvcml6YXRpb24gZXJyb3JzXG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IubWVzc2FnZSB8fCAnQXV0aGVudGljYXRpb24gcmVxdWlyZWQnO1xuICAgICAgICAgICAgaHRtbCA9IGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiIHJvbGU9XCJhbGVydFwiPlxuICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj4ke1JzeC5fZXNjYXBlX2h0bWwobWVzc2FnZSl9PC9wPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgYDtcbiAgICAgICAgfSBlbHNlIGlmIChlcnJvci50eXBlID09PSAnbmV0d29yaycpIHtcbiAgICAgICAgICAgIC8vIE5ldHdvcmsgZXJyb3JzXG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IubWVzc2FnZSB8fCAnVW5hYmxlIHRvIHJlYWNoIHNlcnZlci4gUGxlYXNlIGNoZWNrIHlvdXIgY29ubmVjdGlvbi4nO1xuICAgICAgICAgICAgaHRtbCA9IGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMFwiPiR7UnN4Ll9lc2NhcGVfaHRtbChtZXNzYWdlKX08L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gR2VuZXJpYy91bmtub3duIGVycm9yXG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IubWVzc2FnZSB8fCBlcnJvci50b1N0cmluZygpIHx8ICdBbiB1bmtub3duIGVycm9yIG9jY3VycmVkJztcbiAgICAgICAgICAgIGh0bWwgPSBgXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiIHJvbGU9XCJhbGVydFwiPlxuICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj4ke1JzeC5fZXNjYXBlX2h0bWwobWVzc2FnZSl9PC9wPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgYDtcbiAgICAgICAgfVxuXG4gICAgICAgICRjb250YWluZXIuaHRtbChodG1sKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFc2NhcGUgSFRNTCB0byBwcmV2ZW50IFhTUyBpbiBlcnJvciBtZXNzYWdlc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9lc2NhcGVfaHRtbCh0ZXh0KSB7XG4gICAgICAgIGNvbnN0IGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBkaXYudGV4dENvbnRlbnQgPSB0ZXh0O1xuICAgICAgICByZXR1cm4gZGl2LmlubmVySFRNTDtcbiAgICB9XG59XG4iLCIvLyBARklMRS1TVUJDTEFTUy0wMS1FWENFUFRJT05cblxuLyoqXG4gKiBDbGllbnQtc2lkZSBBamF4IGNsYXNzIGZvciBtYWtpbmcgQVBJIGNhbGxzIHRvIFJTWCBjb250cm9sbGVyc1xuICpcbiAqIEF1dG9tYXRpY2FsbHkgYmF0Y2hlcyBtdWx0aXBsZSBjYWxscyBpbnRvIHNpbmdsZSBIVFRQIHJlcXVlc3RzIHRvIHJlZHVjZSBuZXR3b3JrIG92ZXJoZWFkLlxuICogQmF0Y2hlcyB1cCB0byAyMCBjYWxscyBvciBmbHVzaGVzIGFmdGVyIHNldFRpbWVvdXQoMCkgZGVib3VuY2UuXG4gKi9cbmNsYXNzIEFqYXgge1xuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgQWpheCBzeXN0ZW1cbiAgICAgKiBDYWxsZWQgYXV0b21hdGljYWxseSB3aGVuIGNsYXNzIGlzIGxvYWRlZFxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCgpIHtcbiAgICAgICAgLy8gUXVldWUgb2YgcGVuZGluZyBjYWxscyB3YWl0aW5nIHRvIGJlIGJhdGNoZWRcbiAgICAgICAgQWpheC5fcGVuZGluZ19jYWxscyA9IHt9O1xuXG4gICAgICAgIC8vIFRpbWVyIGZvciBiYXRjaGluZyBmbHVzaFxuICAgICAgICBBamF4Ll9mbHVzaF90aW1lb3V0ID0gbnVsbDtcblxuICAgICAgICAvLyBDYWxsIGNvdW50ZXIgZm9yIGdlbmVyYXRpbmcgdW5pcXVlIGNhbGwgSURzXG4gICAgICAgIEFqYXguX2NhbGxfY291bnRlciA9IDA7XG5cbiAgICAgICAgLy8gTWF4aW11bSBiYXRjaCBzaXplIGJlZm9yZSBmb3JjaW5nIGltbWVkaWF0ZSBmbHVzaFxuICAgICAgICBBamF4Lk1BWF9CQVRDSF9TSVpFID0gMjA7XG5cbiAgICAgICAgLy8gRGVib3VuY2UgdGltZSBpbiBtaWxsaXNlY29uZHNcbiAgICAgICAgQWpheC5ERUJPVU5DRV9NUyA9IDA7XG5cbiAgICAgICAgLy8gVHJhY2sgcHJvbWlzZXMgZnJvbSBBamF4IGNhbGxzIHRvIGRldGVjdCB1bmNhdWdodCByZWplY3Rpb25zXG4gICAgICAgIEFqYXguX3RyYWNrZWRfcHJvbWlzZXMgPSBuZXcgV2Vha1NldCgpO1xuXG4gICAgICAgIC8vIFNldCB1cCBnbG9iYWwgdW5oYW5kbGVkIHJlamVjdGlvbiBoYW5kbGVyIGZvciBBamF4IGVycm9yc1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigndW5oYW5kbGVkcmVqZWN0aW9uJywgYXN5bmMgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAvLyBPbmx5IGhhbmRsZSByZWplY3Rpb25zIGZyb20gQWpheCBwcm9taXNlc1xuICAgICAgICAgICAgaWYgKEFqYXguX3RyYWNrZWRfcHJvbWlzZXMuaGFzKGV2ZW50LnByb21pc2UpKSB7XG4gICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gUHJldmVudCBicm93c2VyJ3MgZGVmYXVsdCBcIlVuY2F1Z2h0IChpbiBwcm9taXNlKVwiIGVycm9yXG5cbiAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IGV2ZW50LnJlYXNvbjtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdVbmNhdWdodCBBamF4IGVycm9yOicsIGVycm9yKTtcblxuICAgICAgICAgICAgICAgIC8vIFNob3cgTW9kYWwuZXJyb3IoKSBmb3IgdW5jYXVnaHQgQWpheCBlcnJvcnNcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1vZGFsICE9PSAndW5kZWZpbmVkJyAmJiBNb2RhbC5lcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBNb2RhbC5lcnJvcihlcnJvciwgJ1VuY2F1Z2h0IEFqYXggRXJyb3InKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2UgYW4gQUpBWCBjYWxsIHRvIGFuIFJTWCBjb250cm9sbGVyIGFjdGlvblxuICAgICAqXG4gICAgICogQWxsIGNhbGxzIGFyZSBhdXRvbWF0aWNhbGx5IGJhdGNoZWQgdW5sZXNzIHdpbmRvdy5yc3hhcHAuYWpheF9kaXNhYmxlX2JhdGNoaW5nIGlzIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xvYmplY3R8ZnVuY3Rpb259IHVybCAtIFRoZSBBamF4IFVSTCAoZS5nLiwgJy9fYWpheC9Db250cm9sbGVyX05hbWUvYWN0aW9uX25hbWUnKSBvciBhbiBvYmplY3QvZnVuY3Rpb24gd2l0aCBhIC5wYXRoIHByb3BlcnR5XG4gICAgICogQHBhcmFtIHtvYmplY3R9IHBhcmFtcyAtIFBhcmFtZXRlcnMgdG8gc2VuZCB0byB0aGUgYWN0aW9uXG4gICAgICogQHJldHVybnMge1Byb21pc2V9IC0gUmVzb2x2ZXMgd2l0aCB0aGUgcmV0dXJuIHZhbHVlLCByZWplY3RzIHdpdGggZXJyb3JcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgY2FsbCh1cmwsIHBhcmFtcyA9IHt9KSB7XG4gICAgICAgIC8vIElmIHVybCBpcyBhbiBvYmplY3Qgb3IgZnVuY3Rpb24gd2l0aCBhIC5wYXRoIHByb3BlcnR5LCB1c2UgdGhhdCBhcyB0aGUgVVJMXG4gICAgICAgIGlmICh1cmwgJiYgdHlwZW9mIHVybCA9PT0gJ29iamVjdCcgJiYgdXJsLnBhdGgpIHtcbiAgICAgICAgICAgIHVybCA9IHVybC5wYXRoO1xuICAgICAgICB9IGVsc2UgaWYgKHVybCAmJiB0eXBlb2YgdXJsID09PSAnZnVuY3Rpb24nICYmIHVybC5wYXRoKSB7XG4gICAgICAgICAgICB1cmwgPSB1cmwucGF0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFZhbGlkYXRlIHVybCBpcyBhIG5vbi1lbXB0eSBzdHJpbmdcbiAgICAgICAgaWYgKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnIHx8IHVybC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQWpheC5jYWxsKCkgcmVxdWlyZXMgYSBub24tZW1wdHkgc3RyaW5nIFVSTCBvciBhbiBvYmplY3QvZnVuY3Rpb24gd2l0aCBhIC5wYXRoIHByb3BlcnR5Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFeHRyYWN0IGNvbnRyb2xsZXIgYW5kIGFjdGlvbiBmcm9tIFVSTFxuICAgICAgICBjb25zdCB7IGNvbnRyb2xsZXIsIGFjdGlvbiB9ID0gQWpheC5hamF4X3VybF90b19jb250cm9sbGVyX2FjdGlvbih1cmwpO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCdBamF4OicsIGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zKTtcblxuICAgICAgICAvLyBDaGVjayBpZiBiYXRjaGluZyBpcyBkaXNhYmxlZCBmb3IgZGVidWdnaW5nXG4gICAgICAgIGxldCBwcm9taXNlO1xuICAgICAgICBpZiAod2luZG93LnJzeGFwcCAmJiB3aW5kb3cucnN4YXBwLmFqYXhfZGlzYWJsZV9iYXRjaGluZykge1xuICAgICAgICAgICAgcHJvbWlzZSA9IEFqYXguX2NhbGxfZGlyZWN0KGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb21pc2UgPSBBamF4Ll9jYWxsX2JhdGNoKGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYWNrIHRoaXMgcHJvbWlzZSBmb3IgdW5oYW5kbGVkIHJlamVjdGlvbiBkZXRlY3Rpb25cbiAgICAgICAgQWpheC5fdHJhY2tlZF9wcm9taXNlcy5hZGQocHJvbWlzZSk7XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZSBhIGJhdGNoZWQgQWpheCBjYWxsXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NhbGxfYmF0Y2goY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMgPSB7fSkge1xuICAgICAgICBjb25zb2xlLmxvZygnQWpheCBCYXRjaDonLCBjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcyk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIC8vIEdlbmVyYXRlIGNhbGwga2V5IGZvciBkZWR1cGxpY2F0aW9uXG4gICAgICAgICAgICBjb25zdCBjYWxsX2tleSA9IEFqYXguX2dlbmVyYXRlX2NhbGxfa2V5KGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zKTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBleGFjdCBjYWxsIGlzIGFscmVhZHkgcGVuZGluZ1xuICAgICAgICAgICAgaWYgKEFqYXguX3BlbmRpbmdfY2FsbHNbY2FsbF9rZXldKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdfY2FsbCA9IEFqYXguX3BlbmRpbmdfY2FsbHNbY2FsbF9rZXldO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgY2FsbCBhbHJlYWR5IGNvbXBsZXRlZCAoY2FjaGVkKSwgcmV0dXJuIGltbWVkaWF0ZWx5XG4gICAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nX2NhbGwuaXNfY29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nX2NhbGwuaXNfZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChleGlzdGluZ19jYWxsLmVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoZXhpc3RpbmdfY2FsbC5yZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBDYWxsIGlzIHBlbmRpbmcsIGFkZCB0aGlzIHByb21pc2UgdG8gY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgZXhpc3RpbmdfY2FsbC5jYWxsYmFja3MucHVzaCh7IHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgcGVuZGluZyBjYWxsXG4gICAgICAgICAgICBjb25zdCBjYWxsX2lkID0gQWpheC5fY2FsbF9jb3VudGVyKys7XG4gICAgICAgICAgICBjb25zdCBwZW5kaW5nX2NhbGwgPSB7XG4gICAgICAgICAgICAgICAgY2FsbF9pZDogY2FsbF9pZCxcbiAgICAgICAgICAgICAgICBjYWxsX2tleTogY2FsbF9rZXksXG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogY29udHJvbGxlcixcbiAgICAgICAgICAgICAgICBhY3Rpb246IGFjdGlvbixcbiAgICAgICAgICAgICAgICBwYXJhbXM6IHBhcmFtcyxcbiAgICAgICAgICAgICAgICBjYWxsYmFja3M6IFt7IHJlc29sdmUsIHJlamVjdCB9XSxcbiAgICAgICAgICAgICAgICBpc19jb21wbGV0ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgaXNfZXJyb3I6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHJlc3VsdDogbnVsbCxcbiAgICAgICAgICAgICAgICBlcnJvcjogbnVsbCxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8vIEFkZCB0byBwZW5kaW5nIHF1ZXVlXG4gICAgICAgICAgICBBamF4Ll9wZW5kaW5nX2NhbGxzW2NhbGxfa2V5XSA9IHBlbmRpbmdfY2FsbDtcblxuICAgICAgICAgICAgLy8gQ291bnQgcGVuZGluZyBjYWxsc1xuICAgICAgICAgICAgY29uc3QgcGVuZGluZ19jb3VudCA9IE9iamVjdC5rZXlzKEFqYXguX3BlbmRpbmdfY2FsbHMpLmZpbHRlcigoa2V5KSA9PiAhQWpheC5fcGVuZGluZ19jYWxsc1trZXldLmlzX2NvbXBsZXRlKS5sZW5ndGg7XG5cbiAgICAgICAgICAgIC8vIElmIHdlJ3ZlIGhpdCB0aGUgYmF0Y2ggc2l6ZSBsaW1pdCwgZmx1c2ggaW1tZWRpYXRlbHlcbiAgICAgICAgICAgIGlmIChwZW5kaW5nX2NvdW50ID49IEFqYXguTUFYX0JBVENIX1NJWkUpIHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoQWpheC5fZmx1c2hfdGltZW91dCk7XG4gICAgICAgICAgICAgICAgQWpheC5fZmx1c2hfdGltZW91dCA9IG51bGw7XG4gICAgICAgICAgICAgICAgQWpheC5fZmx1c2hfcGVuZGluZ19jYWxscygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBTY2hlZHVsZSBiYXRjaCBmbHVzaCB3aXRoIGRlYm91bmNlXG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KEFqYXguX2ZsdXNoX3RpbWVvdXQpO1xuICAgICAgICAgICAgICAgIEFqYXguX2ZsdXNoX3RpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgQWpheC5fZmx1c2hfcGVuZGluZ19jYWxscygpO1xuICAgICAgICAgICAgICAgIH0sIEFqYXguREVCT1VOQ0VfTVMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlIGEgZGlyZWN0IChub24tYmF0Y2hlZCkgQWpheCBjYWxsXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgX2NhbGxfZGlyZWN0KGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zID0ge30pIHtcbiAgICAgICAgLy8gQ29uc3RydWN0IFVSTCBmcm9tIGNvbnRyb2xsZXIgYW5kIGFjdGlvblxuICAgICAgICBjb25zdCB1cmwgPSBgL19hamF4LyR7Y29udHJvbGxlcn0vJHthY3Rpb259YDtcblxuICAgICAgICAvLyBMb2cgdGhlIEFKQVggY2FsbCB1c2luZyBjb25zb2xlX2RlYnVnXG4gICAgICAgIGlmICh0eXBlb2YgRGVidWdnZXIgIT09ICd1bmRlZmluZWQnICYmIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcpIHtcbiAgICAgICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoJ0FKQVgnLCBgQ2FsbGluZyAke2NvbnRyb2xsZXJ9LiR7YWN0aW9ufSAodW5iYXRjaGVkKWAsIHBhcmFtcyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgICAgICB1cmw6IHVybCxcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICBkYXRhOiBwYXJhbXMsXG4gICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgICAgICBfX2xvY2FsX2ludGVncmF0aW9uOiB0cnVlLCAvLyBCeXBhc3MgJC5hamF4IG92ZXJyaWRlXG4gICAgICAgICAgICAgICAgc3VjY2VzczogKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBjb25zb2xlX2RlYnVnIG1lc3NhZ2VzXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5jb25zb2xlX2RlYnVnICYmIEFycmF5LmlzQXJyYXkocmVzcG9uc2UuY29uc29sZV9kZWJ1ZykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlLmNvbnNvbGVfZGVidWcuZm9yRWFjaCgobXNnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1zZykgfHwgbXNnLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29uc29sZV9kZWJ1ZyBtZXNzYWdlIGZvcm1hdCAtIGV4cGVjdGVkIFtjaGFubmVsLCBbYXJndW1lbnRzXV0nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW2NoYW5uZWwsIGFyZ3NdID0gbXNnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGNoYW5uZWwsIC4uLmFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVzcG9uc2Ugd2FzIHN1Y2Nlc3NmdWxcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLl9zdWNjZXNzID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBASlMtQUpBWC0wMi1FWENFUFRJT04gLSBVbndyYXAgc2VydmVyIHJlc3BvbnNlcyB3aXRoIF9hamF4X3JldHVybl92YWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJvY2Vzc2VkX3ZhbHVlID0gUnN4X0pzX01vZGVsLl9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlKHJlc3BvbnNlLl9hamF4X3JldHVybl92YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgZXJyb3IgcmVzcG9uc2VzXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvcl90eXBlID0gcmVzcG9uc2UuZXJyb3JfdHlwZSB8fCAndW5rbm93bl9lcnJvcic7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFzb24gPSByZXNwb25zZS5yZWFzb24gfHwgJ1Vua25vd24gZXJyb3Igb2NjdXJyZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGV0YWlscyA9IHJlc3BvbnNlLmRldGFpbHMgfHwge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBzcGVjaWZpYyBlcnJvciB0eXBlc1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvcl90eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZmF0YWwnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGYXRhbCBQSFAgZXJyb3Igd2l0aCBmdWxsIGVycm9yIGRldGFpbHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmF0YWxfZXJyb3JfZGF0YSA9IHJlc3BvbnNlLmVycm9yIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvcl9tZXNzYWdlID0gZmF0YWxfZXJyb3JfZGF0YS5lcnJvciB8fCAnRmF0YWwgZXJyb3Igb2NjdXJyZWQnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FqYXggZXJyb3IgcmVzcG9uc2UgZnJvbSBzZXJ2ZXI6JywgcmVzcG9uc2UuZXJyb3IpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZhdGFsX2Vycm9yID0gbmV3IEVycm9yKGVycm9yX21lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYXRhbF9lcnJvci50eXBlID0gJ2ZhdGFsJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmF0YWxfZXJyb3IuZGV0YWlscyA9IHJlc3BvbnNlLmVycm9yO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExvZyB0byBzZXJ2ZXIgaWYgYnJvd3NlciBlcnJvciBsb2dnaW5nIGlzIGVuYWJsZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVidWdnZXIubG9nX2Vycm9yKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBBamF4IEZhdGFsIEVycm9yOiAke2Vycm9yX21lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdhamF4X2ZhdGFsJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZHBvaW50OiB1cmwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRhaWxzOiByZXNwb25zZS5lcnJvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGZhdGFsX2Vycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdyZXNwb25zZV9hdXRoX3JlcXVpcmVkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdUaGUgdXNlciBpcyBubyBsb25nZXIgYXV0aGVudGljYXRlZCwgdGhpcyBpcyBhIHBsYWNlaG9sZGVyIGZvciBmdXR1cmUgY29kZSB3aGljaCBoYW5kbGVzIHRoaXMgc2NlbmFyaW8uJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhdXRoX2Vycm9yID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dGhfZXJyb3IudHlwZSA9ICdhdXRoX3JlcXVpcmVkJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0aF9lcnJvci5kZXRhaWxzID0gZGV0YWlscztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGF1dGhfZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3Jlc3BvbnNlX3VuYXV0aG9yaXplZCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVGhlIHVzZXIgaXMgdW5hdXRob3JpemVkIHRvIHBlcmZvcm0gdGhpcyBhY3Rpb24sIHRoaXMgaXMgYSBwbGFjZWhvbGRlciBmb3IgZnV0dXJlIGNvZGUgd2hpY2ggaGFuZGxlcyB0aGlzIHNjZW5hcmlvLidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5hdXRoX2Vycm9yID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuYXV0aF9lcnJvci50eXBlID0gJ3VuYXV0aG9yaXplZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuYXV0aF9lcnJvci5kZXRhaWxzID0gZGV0YWlscztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KHVuYXV0aF9lcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAncmVzcG9uc2VfZm9ybV9lcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvcm1fZXJyb3IgPSBuZXcgRXJyb3IocmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybV9lcnJvci50eXBlID0gJ2Zvcm1fZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtX2Vycm9yLmRldGFpbHMgPSBkZXRhaWxzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZm9ybV9lcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZ2VuZXJpY19lcnJvciA9IG5ldyBFcnJvcihyZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcmljX2Vycm9yLnR5cGUgPSBlcnJvcl90eXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcmljX2Vycm9yLmRldGFpbHMgPSBkZXRhaWxzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZ2VuZXJpY19lcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBlcnJvcjogKHhociwgc3RhdHVzLCBlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvcl9tZXNzYWdlID0gQWpheC5fZXh0cmFjdF9lcnJvcl9tZXNzYWdlKHhocik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ldHdvcmtfZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3JfbWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgIG5ldHdvcmtfZXJyb3IudHlwZSA9ICduZXR3b3JrX2Vycm9yJztcbiAgICAgICAgICAgICAgICAgICAgbmV0d29ya19lcnJvci5zdGF0dXMgPSB4aHIuc3RhdHVzO1xuICAgICAgICAgICAgICAgICAgICBuZXR3b3JrX2Vycm9yLnN0YXR1c1RleHQgPSBzdGF0dXM7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTG9nIHNlcnZlciBlcnJvcnMgKDUwMCspIHRvIHRoZSBzZXJ2ZXIgaWYgYnJvd3NlciBlcnJvciBsb2dnaW5nIGlzIGVuYWJsZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gNTAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBEZWJ1Z2dlci5sb2dfZXJyb3Ioe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBBamF4IFNlcnZlciBFcnJvciAke3hoci5zdGF0dXN9OiAke2Vycm9yX21lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnYWpheF9zZXJ2ZXJfZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZHBvaW50OiB1cmwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiB4aHIuc3RhdHVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1c1RleHQ6IHN0YXR1cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldHdvcmtfZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmx1c2ggYWxsIHBlbmRpbmcgY2FsbHMgYnkgc2VuZGluZyBiYXRjaCByZXF1ZXN0XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgX2ZsdXNoX3BlbmRpbmdfY2FsbHMoKSB7XG4gICAgICAgIC8vIENvbGxlY3QgYWxsIHBlbmRpbmcgY2FsbHNcbiAgICAgICAgY29uc3QgY2FsbHNfdG9fc2VuZCA9IFtdO1xuICAgICAgICBjb25zdCBjYWxsX21hcCA9IHt9OyAvLyBNYXAgY2FsbF9pZCB0byBwZW5kaW5nX2NhbGwgb2JqZWN0XG5cbiAgICAgICAgZm9yIChjb25zdCBjYWxsX2tleSBpbiBBamF4Ll9wZW5kaW5nX2NhbGxzKSB7XG4gICAgICAgICAgICBjb25zdCBwZW5kaW5nX2NhbGwgPSBBamF4Ll9wZW5kaW5nX2NhbGxzW2NhbGxfa2V5XTtcblxuICAgICAgICAgICAgaWYgKCFwZW5kaW5nX2NhbGwuaXNfY29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICBjYWxsc190b19zZW5kLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjYWxsX2lkOiBwZW5kaW5nX2NhbGwuY2FsbF9pZCxcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlcjogcGVuZGluZ19jYWxsLmNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogcGVuZGluZ19jYWxsLmFjdGlvbixcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zOiBwZW5kaW5nX2NhbGwucGFyYW1zLFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY2FsbF9tYXBbcGVuZGluZ19jYWxsLmNhbGxfaWRdID0gcGVuZGluZ19jYWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTm90aGluZyB0byBzZW5kXG4gICAgICAgIGlmIChjYWxsc190b19zZW5kLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTG9nIGJhdGNoIGZvciBkZWJ1Z2dpbmdcbiAgICAgICAgaWYgKHR5cGVvZiBEZWJ1Z2dlciAhPT0gJ3VuZGVmaW5lZCcgJiYgRGVidWdnZXIuY29uc29sZV9kZWJ1Zykge1xuICAgICAgICAgICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZyhcbiAgICAgICAgICAgICAgICAnQUpBWF9CQVRDSCcsXG4gICAgICAgICAgICAgICAgYFNlbmRpbmcgYmF0Y2ggb2YgJHtjYWxsc190b19zZW5kLmxlbmd0aH0gY2FsbHNgLFxuICAgICAgICAgICAgICAgIGNhbGxzX3RvX3NlbmQubWFwKChjKSA9PiBgJHtjLmNvbnRyb2xsZXJ9LiR7Yy5hY3Rpb259YClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gU2VuZCBiYXRjaCByZXF1ZXN0XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0ICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdXJsOiAnL19hamF4L19iYXRjaCcsXG4gICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgZGF0YTogeyBiYXRjaF9jYWxsczogSlNPTi5zdHJpbmdpZnkoY2FsbHNfdG9fc2VuZCkgfSxcbiAgICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgICAgIF9fbG9jYWxfaW50ZWdyYXRpb246IHRydWUsIC8vIEJ5cGFzcyAkLmFqYXggb3ZlcnJpZGVcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBQcm9jZXNzIGJhdGNoIHJlc3BvbnNlXG4gICAgICAgICAgICAvLyBSZXNwb25zZSBmb3JtYXQ6IHsgQ18wOiB7c3VjY2VzcywgX2FqYXhfcmV0dXJuX3ZhbHVlfSwgQ18xOiB7Li4ufSwgLi4uIH1cbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVzcG9uc2Vfa2V5IGluIHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFyZXNwb25zZV9rZXkuc3RhcnRzV2l0aCgnQ18nKSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBjYWxsX2lkID0gcGFyc2VJbnQocmVzcG9uc2Vfa2V5LnN1YnN0cmluZygyKSwgMTApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhbGxfcmVzcG9uc2UgPSByZXNwb25zZVtyZXNwb25zZV9rZXldO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdfY2FsbCA9IGNhbGxfbWFwW2NhbGxfaWRdO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFwZW5kaW5nX2NhbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignUmVjZWl2ZWQgcmVzcG9uc2UgZm9yIHVua25vd24gY2FsbF9pZDonLCBjYWxsX2lkKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSGFuZGxlIGNvbnNvbGVfZGVidWcgbWVzc2FnZXMgaWYgcHJlc2VudFxuICAgICAgICAgICAgICAgIGlmIChjYWxsX3Jlc3BvbnNlLmNvbnNvbGVfZGVidWcgJiYgQXJyYXkuaXNBcnJheShjYWxsX3Jlc3BvbnNlLmNvbnNvbGVfZGVidWcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxfcmVzcG9uc2UuY29uc29sZV9kZWJ1Zy5mb3JFYWNoKChtc2cpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtc2cpIHx8IG1zZy5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29uc29sZV9kZWJ1ZyBtZXNzYWdlIGZvcm1hdCAtIGV4cGVjdGVkIFtjaGFubmVsLCBbYXJndW1lbnRzXV0nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtjaGFubmVsLCBhcmdzXSA9IG1zZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGNoYW5uZWwsIC4uLmFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBNYXJrIGNhbGwgYXMgY29tcGxldGVcbiAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuaXNfY29tcGxldGUgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgc3VjY2Vzc2Z1bFxuICAgICAgICAgICAgICAgIGlmIChjYWxsX3Jlc3BvbnNlLl9zdWNjZXNzID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEBKUy1BSkFYLTAyLUVYQ0VQVElPTiAtIEJhdGNoIHN5c3RlbSB1bndyYXBzIHNlcnZlciByZXNwb25zZXMgd2l0aCBfYWpheF9yZXR1cm5fdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJvY2Vzc2VkX3ZhbHVlID0gUnN4X0pzX01vZGVsLl9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlKGNhbGxfcmVzcG9uc2UuX2FqYXhfcmV0dXJuX3ZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLnJlc3VsdCA9IHByb2Nlc3NlZF92YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGFsbCBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmNhbGxiYWNrcy5mb3JFYWNoKCh7IHJlc29sdmUgfSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JfdHlwZSA9IGNhbGxfcmVzcG9uc2UuZXJyb3JfdHlwZSB8fCAndW5rbm93bl9lcnJvcic7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnJvcl9tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3JfZGV0YWlscztcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3JfdHlwZSA9PT0gJ2ZhdGFsJyAmJiBjYWxsX3Jlc3BvbnNlLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGYXRhbCBQSFAgZXJyb3Igd2l0aCBmdWxsIGVycm9yIGRldGFpbHNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZhdGFsX2Vycm9yX2RhdGEgPSBjYWxsX3Jlc3BvbnNlLmVycm9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSA9IGZhdGFsX2Vycm9yX2RhdGEuZXJyb3IgfHwgJ0ZhdGFsIGVycm9yIG9jY3VycmVkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX2RldGFpbHMgPSBjYWxsX3Jlc3BvbnNlLmVycm9yO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBamF4IGVycm9yIHJlc3BvbnNlIGZyb20gc2VydmVyOicsIGNhbGxfcmVzcG9uc2UuZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXIgZXJyb3IgdHlwZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgPSBjYWxsX3Jlc3BvbnNlLnJlYXNvbiB8fCAnVW5rbm93biBlcnJvciBvY2N1cnJlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl9kZXRhaWxzID0gY2FsbF9yZXNwb25zZS5kZXRhaWxzIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3JfbWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yLnR5cGUgPSBlcnJvcl90eXBlO1xuICAgICAgICAgICAgICAgICAgICBlcnJvci5kZXRhaWxzID0gZXJyb3JfZGV0YWlscztcblxuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuaXNfZXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuZXJyb3IgPSBlcnJvcjtcblxuICAgICAgICAgICAgICAgICAgICAvLyBSZWplY3QgYWxsIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuY2FsbGJhY2tzLmZvckVhY2goKHsgcmVqZWN0IH0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoeGhyX2Vycm9yKSB7XG4gICAgICAgICAgICAvLyBOZXR3b3JrIG9yIHNlcnZlciBlcnJvciAtIHJlamVjdCBhbGwgcGVuZGluZyBjYWxsc1xuICAgICAgICAgICAgY29uc3QgZXJyb3JfbWVzc2FnZSA9IEFqYXguX2V4dHJhY3RfZXJyb3JfbWVzc2FnZSh4aHJfZXJyb3IpO1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3JfbWVzc2FnZSk7XG4gICAgICAgICAgICBlcnJvci50eXBlID0gJ25ldHdvcmtfZXJyb3InO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNhbGxfaWQgaW4gY2FsbF9tYXApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwZW5kaW5nX2NhbGwgPSBjYWxsX21hcFtjYWxsX2lkXTtcbiAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuaXNfY29tcGxldGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5pc19lcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmVycm9yID0gZXJyb3I7XG5cbiAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuY2FsbGJhY2tzLmZvckVhY2goKHsgcmVqZWN0IH0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc29sZS5lcnJvcignQmF0Y2ggQWpheCByZXF1ZXN0IGZhaWxlZDonLCBlcnJvcl9tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgdW5pcXVlIGtleSBmb3IgZGVkdXBsaWNhdGluZyBjYWxsc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZW5lcmF0ZV9jYWxsX2tleShjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcykge1xuICAgICAgICAvLyBDcmVhdGUgYSBzdGFibGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjYWxsXG4gICAgICAgIC8vIFNvcnQgcGFyYW1zIGtleXMgZm9yIGNvbnNpc3RlbnQgaGFzaGluZ1xuICAgICAgICBjb25zdCBzb3J0ZWRfcGFyYW1zID0ge307XG4gICAgICAgIE9iamVjdC5rZXlzKHBhcmFtcylcbiAgICAgICAgICAgIC5zb3J0KClcbiAgICAgICAgICAgIC5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgICAgICAgICBzb3J0ZWRfcGFyYW1zW2tleV0gPSBwYXJhbXNba2V5XTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBgJHtjb250cm9sbGVyfTo6JHthY3Rpb259Ojoke0pTT04uc3RyaW5naWZ5KHNvcnRlZF9wYXJhbXMpfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXh0cmFjdCBlcnJvciBtZXNzYWdlIGZyb20galF1ZXJ5IFhIUiBvYmplY3RcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZXh0cmFjdF9lcnJvcl9tZXNzYWdlKHhocikge1xuICAgICAgICBpZiAoeGhyLnJlc3BvbnNlSlNPTiAmJiB4aHIucmVzcG9uc2VKU09OLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiB4aHIucmVzcG9uc2VKU09OLm1lc3NhZ2U7XG4gICAgICAgIH0gZWxzZSBpZiAoeGhyLnJlc3BvbnNlVGV4dCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IEpTT04ucGFyc2UoeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLm1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIC8vIE5vdCBKU09OXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYCR7eGhyLnN0YXR1c306ICR7eGhyLnN0YXR1c1RleHQgfHwgJ1Vua25vd24gZXJyb3InfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2VzIGFuIEFKQVggVVJMIGludG8gY29udHJvbGxlciBhbmQgYWN0aW9uXG4gICAgICogU3VwcG9ydHMgYm90aCAvX2FqYXgvIGFuZCAvXy8gVVJMIHByZWZpeGVzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8b2JqZWN0fGZ1bmN0aW9ufSB1cmwgLSBVUkwgaW4gZm9ybWF0ICcvX2FqYXgvQ29udHJvbGxlcl9OYW1lL2FjdGlvbl9uYW1lJyBvciAnL18vQ29udHJvbGxlcl9OYW1lL2FjdGlvbl9uYW1lJywgb3IgYW4gb2JqZWN0L2Z1bmN0aW9uIHdpdGggYSAucGF0aCBwcm9wZXJ0eVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IE9iamVjdCB3aXRoIHtjb250cm9sbGVyOiBzdHJpbmcsIGFjdGlvbjogc3RyaW5nfVxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiBVUkwgZG9lc24ndCBzdGFydCB3aXRoIC9fYWpheCBvciAvXyBvciBoYXMgaW52YWxpZCBzdHJ1Y3R1cmVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWpheF91cmxfdG9fY29udHJvbGxlcl9hY3Rpb24odXJsKSB7XG4gICAgICAgIC8vIElmIHVybCBpcyBhbiBvYmplY3Qgb3IgZnVuY3Rpb24gd2l0aCBhIC5wYXRoIHByb3BlcnR5LCB1c2UgdGhhdCBhcyB0aGUgVVJMXG4gICAgICAgIGlmICh1cmwgJiYgdHlwZW9mIHVybCA9PT0gJ29iamVjdCcgJiYgdXJsLnBhdGgpIHtcbiAgICAgICAgICAgIHVybCA9IHVybC5wYXRoO1xuICAgICAgICB9IGVsc2UgaWYgKHVybCAmJiB0eXBlb2YgdXJsID09PSAnZnVuY3Rpb24nICYmIHVybC5wYXRoKSB7XG4gICAgICAgICAgICB1cmwgPSB1cmwucGF0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFZhbGlkYXRlIHVybCBpcyBhIHN0cmluZ1xuICAgICAgICBpZiAodHlwZW9mIHVybCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVVJMIG11c3QgYmUgYSBzdHJpbmcgb3IgaGF2ZSBhIC5wYXRoIHByb3BlcnR5LCBnb3Q6ICR7dHlwZW9mIHVybH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdXJsLnN0YXJ0c1dpdGgoJy9fYWpheCcpICYmICF1cmwuc3RhcnRzV2l0aCgnL18vJykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVVJMIG11c3Qgc3RhcnQgd2l0aCAvX2FqYXggb3IgL18sIGdvdDogJHt1cmx9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXJ0cyA9IHVybC5zcGxpdCgnLycpLmZpbHRlcigocGFydCkgPT4gcGFydCAhPT0gJycpO1xuXG4gICAgICAgIGlmIChwYXJ0cy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgQUpBWCBVUkwgc3RydWN0dXJlOiAke3VybH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJ0cy5sZW5ndGggPiAzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFKQVggVVJMIGhhcyB0b28gbWFueSBzZWdtZW50czogJHt1cmx9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjb250cm9sbGVyID0gcGFydHNbMV07XG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IHBhcnRzWzJdIHx8ICdpbmRleCc7XG5cbiAgICAgICAgcmV0dXJuIHsgY29udHJvbGxlciwgYWN0aW9uIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXV0by1pbml0aWFsaXplIHN0YXRpYyBwcm9wZXJ0aWVzIHdoZW4gY2xhc3MgaXMgZmlyc3QgbG9hZGVkXG4gICAgICovXG4gICAgc3RhdGljIG9uX2NvcmVfZGVmaW5lKCkge1xuICAgICAgICBBamF4Ll9vbl9mcmFtZXdvcmtfY29yZV9pbml0KCk7XG4gICAgfVxufVxuIiwiLyoqXG4gKiBKcWh0bWxfQ29tcG9uZW50IC0gQmFzZSBjbGFzcyBmb3IgSlFIVE1MIGNvbXBvbmVudHMgaW4gUlNYIGZyYW1ld29ya1xuICpcbiAqIFRoaXMgY2xhc3Mgd3JhcHMgdGhlIGpxaHRtbC5Db21wb25lbnQgZnJvbSB0aGUgbnBtIHBhY2thZ2UgYW5kIHByb3ZpZGVzXG4gKiB0aGUgc3RhbmRhcmQgaW50ZXJmYWNlIGZvciBSU1ggY29tcG9uZW50cyBmb2xsb3dpbmcgdGhlIFVwcGVyX0Nhc2UgbmFtaW5nIGNvbnZlbnRpb24uXG4gKlxuICogX0Jhc2VfSnFodG1sX0NvbXBvbmVudCBpcyBpbXBvcnRlZCBmcm9tIG5wbSB2aWEgSnFodG1sX0J1bmRsZS5cbiAqXG4gKiBASW5zdGFudGlhdGFibGVcbiAqL1xuY2xhc3MgSnFodG1sX0NvbXBvbmVudCBleHRlbmRzIF9CYXNlX0pxaHRtbF9Db21wb25lbnQge31cblxuLy8gUlNYIG1hbmlmZXN0IGF1dG9tYXRpY2FsbHkgbWFrZXMgY2xhc3NlcyBnbG9iYWwgLSBubyBtYW51YWwgYXNzaWdubWVudCBuZWVkZWRcbiIsIi8qKlxuICogSlFIVE1MIEludGVncmF0aW9uIC0gQXV0b21hdGljIGNvbXBvbmVudCByZWdpc3RyYXRpb24gYW5kIGJpbmRpbmdcbiAqXG4gKiBUaGlzIG1vZHVsZSBhdXRvbWF0aWNhbGx5OlxuICogMS4gUmVnaXN0ZXJzIGNvbXBvbmVudCBjbGFzc2VzIHRoYXQgZXh0ZW5kIEpxaHRtbF9Db21wb25lbnRcbiAqIDIuIEJpbmRzIHRlbXBsYXRlcyB0byBjb21wb25lbnQgY2xhc3NlcyB3aGVuIG5hbWVzIG1hdGNoXG4gKiAzLiBFbmFibGVzICQoc2VsZWN0b3IpLmNvbXBvbmVudChcIkNvbXBvbmVudF9OYW1lXCIpIHN5bnRheFxuICovXG5jbGFzcyBKcWh0bWxfSW50ZWdyYXRpb24ge1xuICAgIC8qKlxuICAgICAqIENvbXBpbGVkIEpxaHRtbCB0ZW1wbGF0ZXMgc2VsZi1yZWdpc3Rlci4gIFRoZSBkZXZlbG9wZXIgKHRoZSBmcmFtZXdvcmsgaW4gdGhpcyBjYXNlKSBpcyBzdGlsbFxuICAgICAqIHJlc3BvbnNpYmxlIGZvciByZWdpc3RlcmluZyBlczYgY29tcG9uZW50IGNsYXNzZXMgd2l0aCBqcWh0bWwuICBUaGlzIGRvZXMgc28gYXQgYW4gZWFybHkgc3RhZ2VcbiAgICAgKiBvZiBmcmFtZXdvcmsgaW5pdC5cbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19tb2R1bGVzX2RlZmluZSgpIHtcbiAgICAgICAgbGV0IGpxaHRtbF9jb21wb25lbnRzID0gTWFuaWZlc3QuZ2V0X2V4dGVuZGluZygnSnFodG1sX0NvbXBvbmVudCcpO1xuXG4gICAgICAgIGNvbnNvbGVfZGVidWcoJ0pRSFRNTF9JTklUJywgJ1JlZ2lzdGVyaW5nICcgKyBqcWh0bWxfY29tcG9uZW50cy5sZW5ndGggKyAnIEpxaHRtbCBDb21wb25lbnRzJyk7XG5cbiAgICAgICAgZm9yIChsZXQgY29tcG9uZW50IG9mIGpxaHRtbF9jb21wb25lbnRzKSB7XG4gICAgICAgICAgICBqcWh0bWwucmVnaXN0ZXJfY29tcG9uZW50KGNvbXBvbmVudC5jbGFzc19uYW1lLCBjb21wb25lbnQuY2xhc3Nfb2JqZWN0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZyYW1ld29yayBtb2R1bGVzIGluaXQgcGhhc2UgLSBCaW5kIGNvbXBvbmVudHMgYW5kIGluaXRpYWxpemUgRE9NXG4gICAgICogVGhpcyBydW5zIGFmdGVyIHRlbXBsYXRlcyBhcmUgcmVnaXN0ZXJlZCB0byBiaW5kIGNvbXBvbmVudCBjbGFzc2VzXG4gICAgICogQHBhcmFtIHtqUXVlcnl9IFskc2NvcGVdIE9wdGlvbmFsIHNjb3BlIHRvIHNlYXJjaCB3aXRoaW4gKGRlZmF1bHRzIHRvIGJvZHkpXG4gICAgICogQHJldHVybnMge0FycmF5PFByb21pc2U+fHVuZGVmaW5lZH0gQXJyYXkgb2YgcHJvbWlzZXMgZm9yIHJlY3Vyc2l2ZSBjYWxscywgdW5kZWZpbmVkIGZvciB0b3AtbGV2ZWxcbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19tb2R1bGVzX2luaXQoJHNjb3BlKSB7XG4gICAgICAgIGNvbnN0IGlzX3RvcF9sZXZlbCA9ICEkc2NvcGU7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudHNfbmVlZGluZ19pbml0ID0gKCRzY29wZSB8fCAkKCdib2R5JykpLmZpbmQoJy5KcWh0bWxfQ29tcG9uZW50X0luaXQnKTtcbiAgICAgICAgaWYgKGNvbXBvbmVudHNfbmVlZGluZ19pbml0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnNvbGVfZGVidWcoJ0pRSFRNTF9JTklUJywgYEluaXRpYWxpemluZyAke2NvbXBvbmVudHNfbmVlZGluZ19pbml0Lmxlbmd0aH0gRE9NIGNvbXBvbmVudHNgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbXBvbmVudHNfbmVlZGluZ19pbml0LmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3QgJGVsZW1lbnQgPSAkKHRoaXMpO1xuXG4gICAgICAgICAgICAvLyBTa2lwIGlmIGVsZW1lbnQgaXMgbm8gbG9uZ2VyIGF0dGFjaGVkIHRvIHRoZSBkb2N1bWVudFxuICAgICAgICAgICAgLy8gKG1heSBoYXZlIGJlZW4gcmVtb3ZlZCBieSBhIHBhcmVudCBjb21wb25lbnQncyAuZW1wdHkoKSBjYWxsKVxuICAgICAgICAgICAgaWYgKCFkb2N1bWVudC5jb250YWlucygkZWxlbWVudFswXSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGFueSBwYXJlbnQgaGFzIEpxaHRtbF9Db21wb25lbnRfSW5pdCBjbGFzcyAtIHNraXAgbmVzdGVkIGNvbXBvbmVudHNcbiAgICAgICAgICAgIGxldCBwYXJlbnQgPSAkZWxlbWVudFswXS5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgd2hpbGUgKHBhcmVudCkge1xuICAgICAgICAgICAgICAgIGlmIChwYXJlbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdKcWh0bWxfQ29tcG9uZW50X0luaXQnKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47IC8vIFNraXAgdGhpcyBlbGVtZW50LCBpdCdzIG5lc3RlZFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50RWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29tcG9uZW50X25hbWUgPSAkZWxlbWVudC5hdHRyKCdkYXRhLWNvbXBvbmVudC1pbml0LW5hbWUnKTtcblxuICAgICAgICAgICAgLy8galF1ZXJ5J3MgLmRhdGEoKSBkb2Vzbid0IGF1dG8tcGFyc2UgSlNPTiAtIHdlIG5lZWQgdG8gcGFyc2UgaXQgbWFudWFsbHlcbiAgICAgICAgICAgIGxldCBjb21wb25lbnRfYXJncyA9IHt9O1xuICAgICAgICAgICAgY29uc3QgYXJnc19zdHJpbmcgPSAkZWxlbWVudC5hdHRyKCdkYXRhLWNvbXBvbmVudC1hcmdzJyk7XG5cbiAgICAgICAgICAgIC8vIFVuc2V0IGNvbXBvbmVudC0gcGhwIHNpZGUgaW5pdGlhbGl6YXRpb24gYXJncywgaXQgaXMgbm8gbG9uZ2VyIG5lZWRlZCBhcyBhIGNvbXBpb25lbnQgYXR0cmlidXRlXG4gICAgICAgICAgICAvLyBVbnNldHRpbmcgYWxzbyBwcmV2ZW50cyB1bmRlc2lyZWQgYWNjZXNzIHRvIHRoaXMgY29kZSBpbiBvdGhlciBwYXJ0cyBvZiB0aGUgcHJvZ3JhbSwgcHJldmVuaW5nIGFuXG4gICAgICAgICAgICAvLyB1bndhbnRlZCBmdXR1cmUgZGVwZW5kZW5jeSBvbiB0aGlzIHBhcmFkaWdtXG4gICAgICAgICAgICAkZWxlbWVudC5yZW1vdmVBdHRyKCdkYXRhLWNvbXBvbmVudC1pbml0LW5hbWUnKTtcbiAgICAgICAgICAgICRlbGVtZW50LnJlbW92ZUF0dHIoJ2RhdGEtY29tcG9uZW50LWFyZ3MnKTtcbiAgICAgICAgICAgICRlbGVtZW50LnJlbW92ZURhdGEoJ2NvbXBvbmVudC1pbml0LW5hbWUnKTtcbiAgICAgICAgICAgICRlbGVtZW50LnJlbW92ZURhdGEoJ2NvbXBvbmVudC1hcmdzJyk7XG5cbiAgICAgICAgICAgIGlmIChhcmdzX3N0cmluZykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudF9hcmdzID0gSlNPTi5wYXJzZShhcmdzX3N0cmluZyk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbSlFIVE1MIEludGVncmF0aW9uXSBGYWlsZWQgdG8gcGFyc2UgY29tcG9uZW50IGFyZ3MgZm9yICR7Y29tcG9uZW50X25hbWV9OmAsIGUpO1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRfYXJncyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbXBvbmVudF9uYW1lKSB7XG4gICAgICAgICAgICAgICAgLy8gVHJhbnNmb3JtICQgcHJlZml4ZWQga2V5cyB0byBkYXRhLSBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgbGV0IGNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkID0ge307XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoY29tcG9uZW50X2FyZ3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIChrZXkuc3RhcnRzV2l0aCgnJCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkW2tleS5zdWJzdHJpbmcoMSldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIC8vIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5LnN0YXJ0c1dpdGgoJ2RhdGEtJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkW2tleS5zdWJzdHJpbmcoNSldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRfYXJnc19maWx0ZXJlZFtrZXldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdG9yZSBpbm5lciBIVE1MIGFzIHN0cmluZyBmb3IgbmVzdGVkIGNvbXBvbmVudCBwcm9jZXNzaW5nXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkLl9pbm5lcl9odG1sID0gJGVsZW1lbnQuaHRtbCgpO1xuICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5lbXB0eSgpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgaW5pdCBjbGFzcyBiZWZvcmUgaW5zdGFudGlhdGlvbiB0byBwcmV2ZW50IHJlLWluaXRpYWxpemF0aW9uXG4gICAgICAgICAgICAgICAgICAgICRlbGVtZW50LnJlbW92ZUNsYXNzKCdKcWh0bWxfQ29tcG9uZW50X0luaXQnKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBDcmVhdGUgcHJvbWlzZSBmb3IgdGhpcyBjb21wb25lbnQncyBpbml0aWFsaXphdGlvblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wb25lbnRfcHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgalF1ZXJ5IGNvbXBvbmVudCBwbHVnaW4gdG8gY3JlYXRlIHRoZSBjb21wb25lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsdWdpbiBoYW5kbGVzIGVsZW1lbnQgaW50ZXJuYWxseSwganVzdCBwYXNzIGFyZ3NcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgdXBkYXRlZCAkZWxlbWVudCBmcm9tXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29tcG9uZW50ID0gJGVsZW1lbnQuY29tcG9uZW50KGNvbXBvbmVudF9uYW1lLCBjb21wb25lbnRfYXJnc19maWx0ZXJlZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudC5vbigncmVuZGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbGxlY3QgcHJvbWlzZXMgZnJvbSBuZXN0ZWQgY29tcG9uZW50c1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2V0dGluZyB0aGUgdXBkYXRlZCBjb21wb25lbnQgaGVyZSAtIGlmIHRoZSB0YWcgbmFtZSB3YXMgbm90IGRpdiwgdGhlIGVsZW1lbnQgd291bGQgaGF2ZSBiZWVuIHJlY3JlYXRlZCwgc28gd2UgbmVlZCB0byBnZXQgdGhlIGVsZW1lbnQgc2V0IG9uIHRoZSBjb21wb25lbnQsIG5vdCBmcm9tIG91ciBlYXJsaWVyIHNlbGVjdG9yXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXN0ZWRfcHJvbWlzZXMgPSBKcWh0bWxfSW50ZWdyYXRpb24uX29uX2ZyYW1ld29ya19tb2R1bGVzX2luaXQoY29tcG9uZW50LiQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goLi4ubmVzdGVkX3Byb21pc2VzKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgdGhpcyBjb21wb25lbnQncyBwcm9taXNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkuJDtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChjb21wb25lbnRfcHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgW0pRSFRNTCBJbnRlZ3JhdGlvbl0gRmFpbGVkIHRvIGluaXRpYWxpemUgY29tcG9uZW50ICR7Y29tcG9uZW50X25hbWV9OmAsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZGV0YWlsczonLCBlcnJvci5zdGFjayB8fCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUb3AtbGV2ZWwgY2FsbDogc3Bhd24gYXN5bmMgaGFuZGxlciB0byB3YWl0IGZvciBhbGwgcHJvbWlzZXMsIHRoZW4gdHJpZ2dlciBldmVudFxuICAgICAgICBpZiAoaXNfdG9wX2xldmVsKSB7XG4gICAgICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBSc3guX3JzeF9jYWxsX2FsbF9jbGFzc2VzKCdvbl9qcWh0bWxfcmVhZHknKTtcbiAgICAgICAgICAgICAgICBSc3gudHJpZ2dlcignanFodG1sX3JlYWR5Jyk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVjdXJzaXZlIGNhbGw6IHJldHVybiBwcm9taXNlcyBmb3IgcGFyZW50IHRvIGNvbGxlY3RcbiAgICAgICAgcmV0dXJuIHByb21pc2VzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgcmVnaXN0ZXJlZCBjb21wb25lbnQgbmFtZXNcbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gQXJyYXkgb2YgY29tcG9uZW50IG5hbWVzXG4gICAgICovXG4gICAgc3RhdGljIGdldF9jb21wb25lbnRfbmFtZXMoKSB7XG4gICAgICAgIHJldHVybiBqcWh0bWwuZ2V0X2NvbXBvbmVudF9uYW1lcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgY29tcG9uZW50IGlzIHJlZ2lzdGVyZWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBDb21wb25lbnQgbmFtZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIGNvbXBvbmVudCBpcyByZWdpc3RlcmVkXG4gICAgICovXG4gICAgc3RhdGljIGhhc19jb21wb25lbnQobmFtZSkge1xuICAgICAgICByZXR1cm4ganFodG1sLmhhc19jb21wb25lbnQobmFtZSk7XG4gICAgfVxufVxuXG4vLyBSU1ggbWFuaWZlc3QgYXV0b21hdGljYWxseSBtYWtlcyBjbGFzc2VzIGdsb2JhbCAtIG5vIG1hbnVhbCBhc3NpZ25tZW50IG5lZWRlZFxuIiwiLy8gSmF2YVNjcmlwdCBNYW5pZmVzdCAtIEdlbmVyYXRlZCBieSBCdW5kbGVDb21waWxlclxuLy8gUmVnaXN0ZXJzIGFsbCBjbGFzc2VzIGluIHRoaXMgYnVuZGxlIGZvciBydW50aW1lIGludHJvc3BlY3Rpb25cbk1hbmlmZXN0Ll9kZWZpbmUoW1xuICAgIFtNYW5pZmVzdCwgXCJNYW5pZmVzdFwiLCBudWxsXSxcbiAgICBbUnN4X0JlaGF2aW9ycywgXCJSc3hfQmVoYXZpb3JzXCIsIG51bGxdLFxuICAgIFtSc3hfQ2FjaGUsIFwiUnN4X0NhY2hlXCIsIG51bGxdLFxuICAgIFtSc3hfSW5pdCwgXCJSc3hfSW5pdFwiLCBudWxsXSxcbiAgICBbUnN4X0pzX01vZGVsLCBcIlJzeF9Kc19Nb2RlbFwiLCBudWxsXSxcbiAgICBbUnN4X1ZpZXdfVHJhbnNpdGlvbnMsIFwiUnN4X1ZpZXdfVHJhbnNpdGlvbnNcIiwgbnVsbF0sXG4gICAgW1JlYWRXcml0ZUxvY2ssIFwiUmVhZFdyaXRlTG9ja1wiLCBudWxsXSxcbiAgICBbRm9ybV9VdGlscywgXCJGb3JtX1V0aWxzXCIsIG51bGxdLFxuICAgIFtEZWJ1Z2dlciwgXCJEZWJ1Z2dlclwiLCBudWxsXSxcbiAgICBbUnN4X0pxX0hlbHBlcnMsIFwiUnN4X0pxX0hlbHBlcnNcIiwgbnVsbF0sXG4gICAgW1JzeCwgXCJSc3hcIiwgbnVsbF0sXG4gICAgW0FqYXgsIFwiQWpheFwiLCBudWxsXSxcbiAgICBbSnFodG1sX0NvbXBvbmVudCwgXCJKcWh0bWxfQ29tcG9uZW50XCIsIF9CYXNlX0pxaHRtbF9Db21wb25lbnRdLFxuICAgIFtKcWh0bWxfSW50ZWdyYXRpb24sIFwiSnFodG1sX0ludGVncmF0aW9uXCIsIG51bGxdXG5dKTtcblxuIiwiJChkb2N1bWVudCkucmVhZHkoYXN5bmMgZnVuY3Rpb24oKSB7XG50cnkge1xuY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCAnRG9jdW1lbnQgcmVhZHksIHN0YXJ0aW5nIFJzeC5fcnN4X2NvcmVfYm9vdCcpO1xuYXdhaXQgUnN4Ll9yc3hfY29yZV9ib290KCk7XG5jb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdJbml0aWFsaXphdGlvbiBjb21wbGV0ZScpO1xufSBjYXRjaCAoZXJyb3IpIHtcbmNvbnNvbGUuZXJyb3IoJ1tSU1hfSU5JVF0gSW5pdGlhbGl6YXRpb24gZmFpbGVkOicsIGVycm9yKTtcbmNvbnNvbGUuZXJyb3IoJ1tSU1hfSU5JVF0gU3RhY2s6JywgZXJyb3Iuc3RhY2spO1xudGhyb3cgZXJyb3I7XG59XG59KTsiXSwic291cmNlUm9vdCI6IiJ9