PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
11.9 11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 All 205 releases
booking / includes / page-form-builder / admin-page-tpl / _out / bfb-templates.js

bfb-templates.js in Booking Calendar 11.9, at includes/page-form-builder/admin-page-tpl/_out/bfb-templates.js

308 lines 34.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 "use strict";
2
3 /**
4 * Booking Calendar — WP template helpers (BFB Admin)
5 *
6 * Provides a tiny wrapper around wp.template() and a safe "ensure in DOM" helper
7 * for templates that produce modal markup or other admin UI.
8 *
9 * Exposes under:
10 * WPBC_BFB_Core.UI.Templates:
11 * - render_wp_template( template_id, data )
12 * - ensure_dom_from_wp_template( template_id, dom_id?, data? )
13 * - ensure_dom_ref_from_wp_template( template_id, dom_id?, data? )
14 *
15 * Back-compat aliases (optional):
16 * - render()
17 * - ensure_dom()
18 * - ensure_dom_ref()
19 * @file ../includes/page-form-builder/admin-page-tpl/_out/bfb-templates.js
20 */
21 (function (w, d) {
22 'use strict';
23
24 const Core = w.WPBC_BFB_Core = w.WPBC_BFB_Core || {};
25 const UI = Core.UI = Core.UI || {};
26
27 /**
28 * Namespace for template helpers.
29 */
30 const Templates = UI.Templates = UI.Templates || {};
31
32 /**
33 * Escape an id for querySelector usage.
34 *
35 * @param {string} s
36 * @returns {string}
37 */
38 function css_escape(s) {
39 s = String(s || '');
40 if (w.CSS && typeof w.CSS.escape === 'function') {
41 return w.CSS.escape(s);
42 }
43 return s.replace(/([^\w-])/g, '\\$1');
44 }
45
46 /**
47 * Try to obtain wp.template render function.
48 *
49 * @param {string} template_id
50 * @returns {Function|null}
51 */
52 function get_wp_template_fn(template_id) {
53 try {
54 if (!w.wp || typeof w.wp.template !== 'function') {
55 return null;
56 }
57 const fn = w.wp.template(String(template_id || ''));
58 return typeof fn === 'function' ? fn : null;
59 } catch (_e) {
60 return null;
61 }
62 }
63
64 /**
65 * Render wp.template() safely.
66 *
67 * Note: template_id is the id WITHOUT the "tmpl-" prefix.
68 *
69 * @param {string} template_id
70 * @param {Object} [data]
71 * @returns {string} HTML string or empty string on failure
72 */
73 function render_wp_template(template_id, data) {
74 const fn = get_wp_template_fn(template_id);
75 if (!fn) {
76 return '';
77 }
78 try {
79 return String(fn(data || {}));
80 } catch (_e) {
81 return '';
82 }
83 }
84
85 /**
86 * Parse arguments for ensure_dom_from_wp_template() supporting both signatures:
87 * - (template_id, dom_id, data)
88 * - (template_id, data) // dom_id omitted
89 *
90 * @param {string|Object} dom_id_or_data
91 * @param {Object} data
92 * @returns {{dom_id:string, tpl_data:Object}}
93 */
94 function normalize_dom_args(dom_id_or_data, data) {
95 // If 2nd arg is plain object => treat as data, no explicit dom_id.
96 if (dom_id_or_data && typeof dom_id_or_data === 'object' && !Array.isArray(dom_id_or_data)) {
97 return {
98 dom_id: '',
99 tpl_data: dom_id_or_data || {}
100 };
101 }
102 return {
103 dom_id: String(dom_id_or_data || ''),
104 tpl_data: data || {}
105 };
106 }
107
108 /**
109 * Find an id on the root element or inside its subtree.
110 * Used to avoid inserting duplicates when template HTML already has an id.
111 *
112 * @param {HTMLElement} root
113 * @returns {string}
114 */
115 function detect_first_id(root) {
116 try {
117 const direct = String(root.id || root.getAttribute('id') || '');
118 if (direct) {
119 return direct;
120 }
121 const first_with_id = root.querySelector ? root.querySelector('[id]') : null;
122 return first_with_id ? String(first_with_id.id || '') : '';
123 } catch (_e) {
124 return '';
125 }
126 }
127
128 /**
129 * Ensure the returned node has a stable id (only if it doesn't have one).
130 *
131 * @param {HTMLElement} el
132 * @param {string} preferred_id
133 * @param {string} fallback_id
134 * @returns {void}
135 */
136 function ensure_element_id(el, preferred_id, fallback_id) {
137 if (!el || el.id) {
138 return;
139 }
140 const base = String(preferred_id || fallback_id || '');
141 if (!base) {
142 return;
143 }
144 let candidate = base;
145 let i = 2;
146 while (d.getElementById(candidate) && d.getElementById(candidate) !== el) {
147 candidate = base + '-' + i++;
148 }
149 try {
150 el.id = candidate;
151 } catch (_e) {}
152 }
153
154 /**
155 * Ensure a rendered template element exists in DOM (lazy insert).
156 *
157 * Behavior:
158 * - If dom_id is provided and exists => returns that existing node.
159 * - Otherwise renders the template and inserts its first root node into DOM.
160 * - If the rendered root (or its subtree) already has an id that exists in DOM,
161 * return the existing element instead of inserting a duplicate.
162 * - Returns the requested dom_id element if possible, else the inserted root.
163 *
164 * @param {string} template_id
165 * @param {string|Object} [dom_id_or_data]
166 * @param {Object} [data]
167 * @returns {HTMLElement|null}
168 */
169 function ensure_dom_from_wp_template(template_id, dom_id_or_data, data) {
170 const args = normalize_dom_args(dom_id_or_data, data);
171 const dom_id = args.dom_id;
172 const tpl_data = args.tpl_data;
173
174 // 1) If caller asked for a specific dom_id and it's already in DOM, return it.
175 if (dom_id) {
176 const existing = d.getElementById(dom_id);
177 if (existing) {
178 return existing;
179 }
180 }
181
182 // 2) Render template HTML.
183 const html = render_wp_template(template_id, tpl_data);
184 if (!html) {
185 return null;
186 }
187
188 // 3) Convert HTML -> element (first root node).
189 const wrap = d.createElement('div');
190 wrap.innerHTML = String(html).trim();
191 const root = wrap.firstElementChild;
192 if (!root) {
193 return null;
194 }
195
196 // 4) Avoid duplicate IDs:
197 // If template contains an id (root or subtree) and that id already exists in DOM,
198 // return the existing element instead of inserting a duplicate.
199 const detected_id = detect_first_id(root);
200 if (!dom_id && detected_id) {
201 const existing_by_detected = d.getElementById(detected_id);
202 if (existing_by_detected) return existing_by_detected;
203 }
204
205 // 5) Insert into DOM.
206 (d.body || d.documentElement).appendChild(root);
207
208 // 6) Return requested target:
209 // - If dom_id provided: try getElementById(dom_id), else try querySelector inside root, else root.
210 let ret = root;
211 if (dom_id) {
212 ret = d.getElementById(dom_id) || root;
213 if (ret === root) {
214 try {
215 const inside = root.querySelector('#' + css_escape(dom_id));
216 if (inside) ret = inside;
217 } catch (_e) {}
218 }
219 }
220
221 // 7) Make sure returned node has an id (useful for modal show/hide).
222 ensure_element_id(ret, dom_id, detected_id || 'wpbc_tpl_' + String(template_id || 'tpl'));
223
224 // 8) Post-render normalizers (safe no-op if not defined yet).
225 try {
226 if (UI.apply_post_render) {
227 UI.apply_post_render(ret);
228 }
229 } catch (_e) {}
230 return ret;
231 }
232
233 /**
234 * Same as ensure_dom_from_wp_template(), but returns both element and resolved id.
235 *
236 * @param {string} template_id
237 * @param {string|Object} [dom_id_or_data]
238 * @param {Object} [data]
239 * @returns {{id:string, el:HTMLElement}|null}
240 */
241 function ensure_dom_ref_from_wp_template(template_id, dom_id_or_data, data) {
242 const el = ensure_dom_from_wp_template(template_id, dom_id_or_data, data);
243 if (!el) return null;
244 return {
245 id: String(el.id || ''),
246 el
247 };
248 }
249
250 // -------------------------------------------------------------------------
251 // Public API (clear names)
252 // -------------------------------------------------------------------------
253
254 Templates.render_wp_template = render_wp_template;
255 Templates.ensure_dom_from_wp_template = ensure_dom_from_wp_template;
256 Templates.ensure_dom_ref_from_wp_template = ensure_dom_ref_from_wp_template;
257
258 // Keep escape available (useful for callers that need selector-safe ids).
259 Templates.css_escape = css_escape;
260
261 // Also keep your existing UI.* aliases if other files already call these:.
262 UI.render_wp_template = Templates.render_wp_template;
263 UI.ensure_dom_from_wp_template = Templates.ensure_dom_from_wp_template;
264 UI.ensure_dom_ref_from_wp_template = Templates.ensure_dom_ref_from_wp_template;
265
266 // -------------------------------------------------------------------------
267 // UI.Modals (admin helper)
268 // - Optional dependency: jQuery.fn.wpbc_my_modal
269 // - Safe fallback: toggles display style
270 // -------------------------------------------------------------------------
271
272 const Modals = UI.Modals = UI.Modals || {};
273
274 // Reuse the same escape helper everywhere.
275 Modals.css_escape = Modals.css_escape || Templates.css_escape || css_escape;
276 Modals.show = Modals.show || function (modal_el_or_id) {
277 const modal_id = typeof modal_el_or_id === 'string' ? String(modal_el_or_id || '') : String(modal_el_or_id && modal_el_or_id.id ? modal_el_or_id.id : '');
278 const modal_el = typeof modal_el_or_id === 'string' ? d.getElementById(modal_id) : modal_el_or_id;
279 if (!modal_el) return;
280 try {
281 if (w.jQuery && w.jQuery.fn && w.jQuery.fn.wpbc_my_modal) {
282 const $m = modal_id ? w.jQuery('#' + Modals.css_escape(modal_id)) : w.jQuery(modal_el);
283 if ($m && $m.wpbc_my_modal) {
284 $m.wpbc_my_modal('show');
285 return;
286 }
287 }
288 } catch (_e) {}
289 modal_el.style.display = 'block';
290 };
291 Modals.hide = Modals.hide || function (modal_el_or_id) {
292 const modal_id = typeof modal_el_or_id === 'string' ? String(modal_el_or_id || '') : String(modal_el_or_id && modal_el_or_id.id ? modal_el_or_id.id : '');
293 const modal_el = typeof modal_el_or_id === 'string' ? d.getElementById(modal_id) : modal_el_or_id;
294 if (!modal_el) return;
295 try {
296 if (w.jQuery && w.jQuery.fn && w.jQuery.fn.wpbc_my_modal) {
297 const $m = modal_id ? w.jQuery('#' + Modals.css_escape(modal_id)) : w.jQuery(modal_el);
298 if ($m && $m.wpbc_my_modal) {
299 $m.wpbc_my_modal('hide');
300 return;
301 }
302 }
303 } catch (_e) {}
304 modal_el.style.display = 'none';
305 };
306 })(window, document);
307 //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5jbHVkZXMvcGFnZS1mb3JtLWJ1aWxkZXIvYWRtaW4tcGFnZS10cGwvX291dC9iZmItdGVtcGxhdGVzLmpzIiwibmFtZXMiOlsidyIsImQiLCJDb3JlIiwiV1BCQ19CRkJfQ29yZSIsIlVJIiwiVGVtcGxhdGVzIiwiY3NzX2VzY2FwZSIsInMiLCJTdHJpbmciLCJDU1MiLCJlc2NhcGUiLCJyZXBsYWNlIiwiZ2V0X3dwX3RlbXBsYXRlX2ZuIiwidGVtcGxhdGVfaWQiLCJ3cCIsInRlbXBsYXRlIiwiZm4iLCJfZSIsInJlbmRlcl93cF90ZW1wbGF0ZSIsImRhdGEiLCJub3JtYWxpemVfZG9tX2FyZ3MiLCJkb21faWRfb3JfZGF0YSIsIkFycmF5IiwiaXNBcnJheSIsImRvbV9pZCIsInRwbF9kYXRhIiwiZGV0ZWN0X2ZpcnN0X2lkIiwicm9vdCIsImRpcmVjdCIsImlkIiwiZ2V0QXR0cmlidXRlIiwiZmlyc3Rfd2l0aF9pZCIsInF1ZXJ5U2VsZWN0b3IiLCJlbnN1cmVfZWxlbWVudF9pZCIsImVsIiwicHJlZmVycmVkX2lkIiwiZmFsbGJhY2tfaWQiLCJiYXNlIiwiY2FuZGlkYXRlIiwiaSIsImdldEVsZW1lbnRCeUlkIiwiZW5zdXJlX2RvbV9mcm9tX3dwX3RlbXBsYXRlIiwiYXJncyIsImV4aXN0aW5nIiwiaHRtbCIsIndyYXAiLCJjcmVhdGVFbGVtZW50IiwiaW5uZXJIVE1MIiwidHJpbSIsImZpcnN0RWxlbWVudENoaWxkIiwiZGV0ZWN0ZWRfaWQiLCJleGlzdGluZ19ieV9kZXRlY3RlZCIsImJvZHkiLCJkb2N1bWVudEVsZW1lbnQiLCJhcHBlbmRDaGlsZCIsInJldCIsImluc2lkZSIsImFwcGx5X3Bvc3RfcmVuZGVyIiwiZW5zdXJlX2RvbV9yZWZfZnJvbV93cF90ZW1wbGF0ZSIsIk1vZGFscyIsInNob3ciLCJtb2RhbF9lbF9vcl9pZCIsIm1vZGFsX2lkIiwibW9kYWxfZWwiLCJqUXVlcnkiLCJ3cGJjX215X21vZGFsIiwiJG0iLCJzdHlsZSIsImRpc3BsYXkiLCJoaWRlIiwid2luZG93IiwiZG9jdW1lbnQiXSwic291cmNlcyI6WyJpbmNsdWRlcy9wYWdlLWZvcm0tYnVpbGRlci9hZG1pbi1wYWdlLXRwbC9fc3JjL2JmYi10ZW1wbGF0ZXMuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIEJvb2tpbmcgQ2FsZW5kYXIg4oCUIFdQIHRlbXBsYXRlIGhlbHBlcnMgKEJGQiBBZG1pbilcclxuICpcclxuICogUHJvdmlkZXMgYSB0aW55IHdyYXBwZXIgYXJvdW5kIHdwLnRlbXBsYXRlKCkgYW5kIGEgc2FmZSBcImVuc3VyZSBpbiBET01cIiBoZWxwZXJcclxuICogZm9yIHRlbXBsYXRlcyB0aGF0IHByb2R1Y2UgbW9kYWwgbWFya3VwIG9yIG90aGVyIGFkbWluIFVJLlxyXG4gKlxyXG4gKiBFeHBvc2VzIHVuZGVyOlxyXG4gKiAgIFdQQkNfQkZCX0NvcmUuVUkuVGVtcGxhdGVzOlxyXG4gKiAgICAgLSByZW5kZXJfd3BfdGVtcGxhdGUoIHRlbXBsYXRlX2lkLCBkYXRhIClcclxuICogICAgIC0gZW5zdXJlX2RvbV9mcm9tX3dwX3RlbXBsYXRlKCB0ZW1wbGF0ZV9pZCwgZG9tX2lkPywgZGF0YT8gKVxyXG4gKiAgICAgLSBlbnN1cmVfZG9tX3JlZl9mcm9tX3dwX3RlbXBsYXRlKCB0ZW1wbGF0ZV9pZCwgZG9tX2lkPywgZGF0YT8gKVxyXG4gKlxyXG4gKiBCYWNrLWNvbXBhdCBhbGlhc2VzIChvcHRpb25hbCk6XHJcbiAqICAgICAtIHJlbmRlcigpXHJcbiAqICAgICAtIGVuc3VyZV9kb20oKVxyXG4gKiAgICAgLSBlbnN1cmVfZG9tX3JlZigpXHJcbiAqIEBmaWxlIC4uL2luY2x1ZGVzL3BhZ2UtZm9ybS1idWlsZGVyL2FkbWluLXBhZ2UtdHBsL19vdXQvYmZiLXRlbXBsYXRlcy5qc1xyXG4gKi9cclxuKGZ1bmN0aW9uICh3LCBkKSB7XHJcblx0J3VzZSBzdHJpY3QnO1xyXG5cclxuXHRjb25zdCBDb3JlID0gKHcuV1BCQ19CRkJfQ29yZSA9IHcuV1BCQ19CRkJfQ29yZSB8fCB7fSk7XHJcblx0Y29uc3QgVUkgICA9IChDb3JlLlVJID0gQ29yZS5VSSB8fCB7fSk7XHJcblxyXG5cdC8qKlxyXG5cdCAqIE5hbWVzcGFjZSBmb3IgdGVtcGxhdGUgaGVscGVycy5cclxuXHQgKi9cclxuXHRjb25zdCBUZW1wbGF0ZXMgPSAoVUkuVGVtcGxhdGVzID0gVUkuVGVtcGxhdGVzIHx8IHt9KTtcclxuXHJcblx0LyoqXHJcblx0ICogRXNjYXBlIGFuIGlkIGZvciBxdWVyeVNlbGVjdG9yIHVzYWdlLlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd9IHNcclxuXHQgKiBAcmV0dXJucyB7c3RyaW5nfVxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIGNzc19lc2NhcGUocykge1xyXG5cdFx0cyA9IFN0cmluZyggcyB8fCAnJyApO1xyXG5cdFx0aWYgKCB3LkNTUyAmJiB0eXBlb2Ygdy5DU1MuZXNjYXBlID09PSAnZnVuY3Rpb24nICkge1xyXG5cdFx0XHRyZXR1cm4gdy5DU1MuZXNjYXBlKCBzICk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gcy5yZXBsYWNlKCAvKFteXFx3LV0pL2csICdcXFxcJDEnICk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBUcnkgdG8gb2J0YWluIHdwLnRlbXBsYXRlIHJlbmRlciBmdW5jdGlvbi5cclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB0ZW1wbGF0ZV9pZFxyXG5cdCAqIEByZXR1cm5zIHtGdW5jdGlvbnxudWxsfVxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIGdldF93cF90ZW1wbGF0ZV9mbih0ZW1wbGF0ZV9pZCkge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0aWYgKCAhIHcud3AgfHwgdHlwZW9mIHcud3AudGVtcGxhdGUgIT09ICdmdW5jdGlvbicgKSB7XHJcblx0XHRcdFx0cmV0dXJuIG51bGw7XHJcblx0XHRcdH1cclxuXHRcdFx0Y29uc3QgZm4gPSB3LndwLnRlbXBsYXRlKCBTdHJpbmcoIHRlbXBsYXRlX2lkIHx8ICcnICkgKTtcclxuXHRcdFx0cmV0dXJuICh0eXBlb2YgZm4gPT09ICdmdW5jdGlvbicpID8gZm4gOiBudWxsO1xyXG5cdFx0fSBjYXRjaCAoIF9lICkge1xyXG5cdFx0XHRyZXR1cm4gbnVsbDtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFJlbmRlciB3cC50ZW1wbGF0ZSgpIHNhZmVseS5cclxuXHQgKlxyXG5cdCAqIE5vdGU6IHRlbXBsYXRlX2lkIGlzIHRoZSBpZCBXSVRIT1VUIHRoZSBcInRtcGwtXCIgcHJlZml4LlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd9IHRlbXBsYXRlX2lkXHJcblx0ICogQHBhcmFtIHtPYmplY3R9IFtkYXRhXVxyXG5cdCAqIEByZXR1cm5zIHtzdHJpbmd9IEhUTUwgc3RyaW5nIG9yIGVtcHR5IHN0cmluZyBvbiBmYWlsdXJlXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gcmVuZGVyX3dwX3RlbXBsYXRlKHRlbXBsYXRlX2lkLCBkYXRhKSB7XHJcblx0XHRjb25zdCBmbiA9IGdldF93cF90ZW1wbGF0ZV9mbiggdGVtcGxhdGVfaWQgKTtcclxuXHRcdGlmICggISBmbiApIHtcclxuXHRcdFx0cmV0dXJuICcnO1xyXG5cdFx0fVxyXG5cdFx0dHJ5IHtcclxuXHRcdFx0cmV0dXJuIFN0cmluZyggZm4oIGRhdGEgfHwge30gKSApO1xyXG5cdFx0fSBjYXRjaCAoIF9lICkge1xyXG5cdFx0XHRyZXR1cm4gJyc7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBQYXJzZSBhcmd1bWVudHMgZm9yIGVuc3VyZV9kb21fZnJvbV93cF90ZW1wbGF0ZSgpIHN1cHBvcnRpbmcgYm90aCBzaWduYXR1cmVzOlxyXG5cdCAqICAgLSAodGVtcGxhdGVfaWQsIGRvbV9pZCwgZGF0YSlcclxuXHQgKiAgIC0gKHRlbXBsYXRlX2lkLCBkYXRhKSAgICAgICAgICAvLyBkb21faWQgb21pdHRlZFxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8T2JqZWN0fSBkb21faWRfb3JfZGF0YVxyXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhXHJcblx0ICogQHJldHVybnMge3tkb21faWQ6c3RyaW5nLCB0cGxfZGF0YTpPYmplY3R9fVxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIG5vcm1hbGl6ZV9kb21fYXJncyhkb21faWRfb3JfZGF0YSwgZGF0YSkge1xyXG5cdFx0Ly8gSWYgMm5kIGFyZyBpcyBwbGFpbiBvYmplY3QgPT4gdHJlYXQgYXMgZGF0YSwgbm8gZXhwbGljaXQgZG9tX2lkLlxyXG5cdFx0aWYgKCBkb21faWRfb3JfZGF0YSAmJiB0eXBlb2YgZG9tX2lkX29yX2RhdGEgPT09ICdvYmplY3QnICYmICEgQXJyYXkuaXNBcnJheSggZG9tX2lkX29yX2RhdGEgKSApIHtcclxuXHRcdFx0cmV0dXJuIHsgZG9tX2lkOiAnJywgdHBsX2RhdGE6IGRvbV9pZF9vcl9kYXRhIHx8IHt9IH07XHJcblx0XHR9XHJcblx0XHRyZXR1cm4geyBkb21faWQ6IFN0cmluZyggZG9tX2lkX29yX2RhdGEgfHwgJycgKSwgdHBsX2RhdGE6IGRhdGEgfHwge30gfTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEZpbmQgYW4gaWQgb24gdGhlIHJvb3QgZWxlbWVudCBvciBpbnNpZGUgaXRzIHN1YnRyZWUuXHJcblx0ICogVXNlZCB0byBhdm9pZCBpbnNlcnRpbmcgZHVwbGljYXRlcyB3aGVuIHRlbXBsYXRlIEhUTUwgYWxyZWFkeSBoYXMgYW4gaWQuXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSByb290XHJcblx0ICogQHJldHVybnMge3N0cmluZ31cclxuXHQgKi9cclxuXHRmdW5jdGlvbiBkZXRlY3RfZmlyc3RfaWQocm9vdCkge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Y29uc3QgZGlyZWN0ID0gU3RyaW5nKCByb290LmlkIHx8IHJvb3QuZ2V0QXR0cmlidXRlKCAnaWQnICkgfHwgJycgKTtcclxuXHRcdFx0aWYgKCBkaXJlY3QgKSB7XHJcblx0XHRcdFx0cmV0dXJuIGRpcmVjdDtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Y29uc3QgZmlyc3Rfd2l0aF9pZCA9IHJvb3QucXVlcnlTZWxlY3RvciA/IHJvb3QucXVlcnlTZWxlY3RvciggJ1tpZF0nICkgOiBudWxsO1xyXG5cdFx0XHRyZXR1cm4gZmlyc3Rfd2l0aF9pZCA/IFN0cmluZyggZmlyc3Rfd2l0aF9pZC5pZCB8fCAnJyApIDogJyc7XHJcblx0XHR9IGNhdGNoICggX2UgKSB7XHJcblx0XHRcdHJldHVybiAnJztcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEVuc3VyZSB0aGUgcmV0dXJuZWQgbm9kZSBoYXMgYSBzdGFibGUgaWQgKG9ubHkgaWYgaXQgZG9lc24ndCBoYXZlIG9uZSkuXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbFxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBwcmVmZXJyZWRfaWRcclxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZmFsbGJhY2tfaWRcclxuXHQgKiBAcmV0dXJucyB7dm9pZH1cclxuXHQgKi9cclxuXHRmdW5jdGlvbiBlbnN1cmVfZWxlbWVudF9pZChlbCwgcHJlZmVycmVkX2lkLCBmYWxsYmFja19pZCkge1xyXG5cdFx0aWYgKCAhIGVsIHx8IGVsLmlkICkge1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgYmFzZSA9IFN0cmluZyggcHJlZmVycmVkX2lkIHx8IGZhbGxiYWNrX2lkIHx8ICcnICk7XHJcblx0XHRpZiAoICEgYmFzZSApIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGxldCBjYW5kaWRhdGUgPSBiYXNlO1xyXG5cdFx0bGV0IGkgICAgICAgICA9IDI7XHJcblxyXG5cdFx0d2hpbGUgKCBkLmdldEVsZW1lbnRCeUlkKCBjYW5kaWRhdGUgKSAmJiBkLmdldEVsZW1lbnRCeUlkKCBjYW5kaWRhdGUgKSAhPT0gZWwgKSB7XHJcblx0XHRcdGNhbmRpZGF0ZSA9IGJhc2UgKyAnLScgKyAoaSsrKTtcclxuXHRcdH1cclxuXHJcblx0XHR0cnkge1xyXG5cdFx0XHRlbC5pZCA9IGNhbmRpZGF0ZTtcclxuXHRcdH0gY2F0Y2ggKCBfZSApIHtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEVuc3VyZSBhIHJlbmRlcmVkIHRlbXBsYXRlIGVsZW1lbnQgZXhpc3RzIGluIERPTSAobGF6eSBpbnNlcnQpLlxyXG5cdCAqXHJcblx0ICogQmVoYXZpb3I6XHJcblx0ICogLSBJZiBkb21faWQgaXMgcHJvdmlkZWQgYW5kIGV4aXN0cyA9PiByZXR1cm5zIHRoYXQgZXhpc3Rpbmcgbm9kZS5cclxuXHQgKiAtIE90aGVyd2lzZSByZW5kZXJzIHRoZSB0ZW1wbGF0ZSBhbmQgaW5zZXJ0cyBpdHMgZmlyc3Qgcm9vdCBub2RlIGludG8gRE9NLlxyXG5cdCAqIC0gSWYgdGhlIHJlbmRlcmVkIHJvb3QgKG9yIGl0cyBzdWJ0cmVlKSBhbHJlYWR5IGhhcyBhbiBpZCB0aGF0IGV4aXN0cyBpbiBET00sXHJcblx0ICogICByZXR1cm4gdGhlIGV4aXN0aW5nIGVsZW1lbnQgaW5zdGVhZCBvZiBpbnNlcnRpbmcgYSBkdXBsaWNhdGUuXHJcblx0ICogLSBSZXR1cm5zIHRoZSByZXF1ZXN0ZWQgZG9tX2lkIGVsZW1lbnQgaWYgcG9zc2libGUsIGVsc2UgdGhlIGluc2VydGVkIHJvb3QuXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdGVtcGxhdGVfaWRcclxuXHQgKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R9IFtkb21faWRfb3JfZGF0YV1cclxuXHQgKiBAcGFyYW0ge09iamVjdH0gW2RhdGFdXHJcblx0ICogQHJldHVybnMge0hUTUxFbGVtZW50fG51bGx9XHJcblx0ICovXHJcblx0ZnVuY3Rpb24gZW5zdXJlX2RvbV9mcm9tX3dwX3RlbXBsYXRlKHRlbXBsYXRlX2lkLCBkb21faWRfb3JfZGF0YSwgZGF0YSkge1xyXG5cdFx0Y29uc3QgYXJncyAgICAgPSBub3JtYWxpemVfZG9tX2FyZ3MoIGRvbV9pZF9vcl9kYXRhLCBkYXRhICk7XHJcblx0XHRjb25zdCBkb21faWQgICA9IGFyZ3MuZG9tX2lkO1xyXG5cdFx0Y29uc3QgdHBsX2RhdGEgPSBhcmdzLnRwbF9kYXRhO1xyXG5cclxuXHRcdC8vIDEpIElmIGNhbGxlciBhc2tlZCBmb3IgYSBzcGVjaWZpYyBkb21faWQgYW5kIGl0J3MgYWxyZWFkeSBpbiBET00sIHJldHVybiBpdC5cclxuXHRcdGlmICggZG9tX2lkICkge1xyXG5cdFx0XHRjb25zdCBleGlzdGluZyA9IGQuZ2V0RWxlbWVudEJ5SWQoIGRvbV9pZCApO1xyXG5cdFx0XHRpZiAoIGV4aXN0aW5nICkge1xyXG5cdFx0XHRcdHJldHVybiBleGlzdGluZztcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIDIpIFJlbmRlciB0ZW1wbGF0ZSBIVE1MLlxyXG5cdFx0Y29uc3QgaHRtbCA9IHJlbmRlcl93cF90ZW1wbGF0ZSggdGVtcGxhdGVfaWQsIHRwbF9kYXRhICk7XHJcblx0XHRpZiAoICEgaHRtbCApIHtcclxuXHRcdFx0cmV0dXJuIG51bGw7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gMykgQ29udmVydCBIVE1MIC0+IGVsZW1lbnQgKGZpcnN0IHJvb3Qgbm9kZSkuXHJcblx0XHRjb25zdCB3cmFwICAgICA9IGQuY3JlYXRlRWxlbWVudCggJ2RpdicgKTtcclxuXHRcdHdyYXAuaW5uZXJIVE1MID0gU3RyaW5nKCBodG1sICkudHJpbSgpO1xyXG5cclxuXHRcdGNvbnN0IHJvb3QgPSB3cmFwLmZpcnN0RWxlbWVudENoaWxkO1xyXG5cdFx0aWYgKCAhIHJvb3QgKSB7XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIDQpIEF2b2lkIGR1cGxpY2F0ZSBJRHM6XHJcblx0XHQvLyAgICBJZiB0ZW1wbGF0ZSBjb250YWlucyBhbiBpZCAocm9vdCBvciBzdWJ0cmVlKSBhbmQgdGhhdCBpZCBhbHJlYWR5IGV4aXN0cyBpbiBET00sXHJcblx0XHQvLyAgICByZXR1cm4gdGhlIGV4aXN0aW5nIGVsZW1lbnQgaW5zdGVhZCBvZiBpbnNlcnRpbmcgYSBkdXBsaWNhdGUuXHJcblx0XHRjb25zdCBkZXRlY3RlZF9pZCA9IGRldGVjdF9maXJzdF9pZCggcm9vdCApO1xyXG5cdFx0aWYgKCAhZG9tX2lkICYmIGRldGVjdGVkX2lkICkge1xyXG5cdFx0XHRjb25zdCBleGlzdGluZ19ieV9kZXRlY3RlZCA9IGQuZ2V0RWxlbWVudEJ5SWQoIGRldGVjdGVkX2lkICk7XHJcblx0XHRcdGlmICggZXhpc3RpbmdfYnlfZGV0ZWN0ZWQgKSByZXR1cm4gZXhpc3RpbmdfYnlfZGV0ZWN0ZWQ7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gNSkgSW5zZXJ0IGludG8gRE9NLlxyXG5cdFx0KGQuYm9keSB8fCBkLmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoIHJvb3QgKTtcclxuXHJcblx0XHQvLyA2KSBSZXR1cm4gcmVxdWVzdGVkIHRhcmdldDpcclxuXHRcdC8vICAgIC0gSWYgZG9tX2lkIHByb3ZpZGVkOiB0cnkgZ2V0RWxlbWVudEJ5SWQoZG9tX2lkKSwgZWxzZSB0cnkgcXVlcnlTZWxlY3RvciBpbnNpZGUgcm9vdCwgZWxzZSByb290LlxyXG5cdFx0bGV0IHJldCA9IHJvb3Q7XHJcblxyXG5cdFx0aWYgKCBkb21faWQgKSB7XHJcblx0XHRcdHJldCA9IGQuZ2V0RWxlbWVudEJ5SWQoIGRvbV9pZCApIHx8IHJvb3Q7XHJcblx0XHRcdGlmICggcmV0ID09PSByb290ICkge1xyXG5cdFx0XHRcdHRyeSB7XHJcblx0XHRcdFx0XHRjb25zdCBpbnNpZGUgPSByb290LnF1ZXJ5U2VsZWN0b3IoICcjJyArIGNzc19lc2NhcGUoIGRvbV9pZCApICk7XHJcblx0XHRcdFx0XHRpZiAoIGluc2lkZSApIHJldCA9IGluc2lkZTtcclxuXHRcdFx0XHR9IGNhdGNoICggX2UgKSB7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gNykgTWFrZSBzdXJlIHJldHVybmVkIG5vZGUgaGFzIGFuIGlkICh1c2VmdWwgZm9yIG1vZGFsIHNob3cvaGlkZSkuXHJcblx0XHRlbnN1cmVfZWxlbWVudF9pZCggcmV0LCBkb21faWQsIGRldGVjdGVkX2lkIHx8ICgnd3BiY190cGxfJyArIFN0cmluZyggdGVtcGxhdGVfaWQgfHwgJ3RwbCcgKSkgKTtcclxuXHJcblx0XHQvLyA4KSBQb3N0LXJlbmRlciBub3JtYWxpemVycyAoc2FmZSBuby1vcCBpZiBub3QgZGVmaW5lZCB5ZXQpLlxyXG5cdFx0dHJ5IHtcclxuXHRcdFx0aWYgKCBVSS5hcHBseV9wb3N0X3JlbmRlciApIHtcclxuXHRcdFx0XHRVSS5hcHBseV9wb3N0X3JlbmRlciggcmV0ICk7XHJcblx0XHRcdH1cclxuXHRcdH0gY2F0Y2ggKCBfZSApIHtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gcmV0O1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogU2FtZSBhcyBlbnN1cmVfZG9tX2Zyb21fd3BfdGVtcGxhdGUoKSwgYnV0IHJldHVybnMgYm90aCBlbGVtZW50IGFuZCByZXNvbHZlZCBpZC5cclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSB0ZW1wbGF0ZV9pZFxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfE9iamVjdH0gW2RvbV9pZF9vcl9kYXRhXVxyXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBbZGF0YV1cclxuXHQgKiBAcmV0dXJucyB7e2lkOnN0cmluZywgZWw6SFRNTEVsZW1lbnR9fG51bGx9XHJcblx0ICovXHJcblx0ZnVuY3Rpb24gZW5zdXJlX2RvbV9yZWZfZnJvbV93cF90ZW1wbGF0ZSh0ZW1wbGF0ZV9pZCwgZG9tX2lkX29yX2RhdGEsIGRhdGEpIHtcclxuXHRcdGNvbnN0IGVsID0gZW5zdXJlX2RvbV9mcm9tX3dwX3RlbXBsYXRlKCB0ZW1wbGF0ZV9pZCwgZG9tX2lkX29yX2RhdGEsIGRhdGEgKTtcclxuXHRcdGlmICggIWVsICkgcmV0dXJuIG51bGw7XHJcblx0XHRyZXR1cm4geyBpZDogU3RyaW5nKCBlbC5pZCB8fCAnJyApLCBlbCB9O1xyXG5cdH1cclxuXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIFB1YmxpYyBBUEkgKGNsZWFyIG5hbWVzKVxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblx0VGVtcGxhdGVzLnJlbmRlcl93cF90ZW1wbGF0ZSAgICAgICAgICAgICAgPSByZW5kZXJfd3BfdGVtcGxhdGU7XHJcblx0VGVtcGxhdGVzLmVuc3VyZV9kb21fZnJvbV93cF90ZW1wbGF0ZSAgICAgPSBlbnN1cmVfZG9tX2Zyb21fd3BfdGVtcGxhdGU7XHJcblx0VGVtcGxhdGVzLmVuc3VyZV9kb21fcmVmX2Zyb21fd3BfdGVtcGxhdGUgPSBlbnN1cmVfZG9tX3JlZl9mcm9tX3dwX3RlbXBsYXRlO1xyXG5cclxuXHQvLyBLZWVwIGVzY2FwZSBhdmFpbGFibGUgKHVzZWZ1bCBmb3IgY2FsbGVycyB0aGF0IG5lZWQgc2VsZWN0b3Itc2FmZSBpZHMpLlxyXG5cdFRlbXBsYXRlcy5jc3NfZXNjYXBlID0gY3NzX2VzY2FwZTtcclxuXHJcblx0Ly8gQWxzbyBrZWVwIHlvdXIgZXhpc3RpbmcgVUkuKiBhbGlhc2VzIGlmIG90aGVyIGZpbGVzIGFscmVhZHkgY2FsbCB0aGVzZTouXHJcblx0VUkucmVuZGVyX3dwX3RlbXBsYXRlICAgICAgICAgICAgICA9IFRlbXBsYXRlcy5yZW5kZXJfd3BfdGVtcGxhdGU7XHJcblx0VUkuZW5zdXJlX2RvbV9mcm9tX3dwX3RlbXBsYXRlICAgICA9IFRlbXBsYXRlcy5lbnN1cmVfZG9tX2Zyb21fd3BfdGVtcGxhdGU7XHJcblx0VUkuZW5zdXJlX2RvbV9yZWZfZnJvbV93cF90ZW1wbGF0ZSA9IFRlbXBsYXRlcy5lbnN1cmVfZG9tX3JlZl9mcm9tX3dwX3RlbXBsYXRlO1xyXG5cclxuXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIFVJLk1vZGFscyAoYWRtaW4gaGVscGVyKVxyXG5cdC8vIC0gT3B0aW9uYWwgZGVwZW5kZW5jeTogalF1ZXJ5LmZuLndwYmNfbXlfbW9kYWxcclxuXHQvLyAtIFNhZmUgZmFsbGJhY2s6IHRvZ2dsZXMgZGlzcGxheSBzdHlsZVxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcblx0Y29uc3QgTW9kYWxzID0gKFVJLk1vZGFscyA9IFVJLk1vZGFscyB8fCB7fSk7XHJcblxyXG5cdC8vIFJldXNlIHRoZSBzYW1lIGVzY2FwZSBoZWxwZXIgZXZlcnl3aGVyZS5cclxuXHRNb2RhbHMuY3NzX2VzY2FwZSA9IE1vZGFscy5jc3NfZXNjYXBlIHx8IFRlbXBsYXRlcy5jc3NfZXNjYXBlIHx8IGNzc19lc2NhcGU7XHJcblxyXG5cdE1vZGFscy5zaG93ID0gTW9kYWxzLnNob3cgfHwgZnVuY3Rpb24gKG1vZGFsX2VsX29yX2lkKSB7XHJcblxyXG5cdFx0Y29uc3QgbW9kYWxfaWQgPSAodHlwZW9mIG1vZGFsX2VsX29yX2lkID09PSAnc3RyaW5nJylcclxuXHRcdFx0PyBTdHJpbmcoIG1vZGFsX2VsX29yX2lkIHx8ICcnIClcclxuXHRcdFx0OiBTdHJpbmcoIChtb2RhbF9lbF9vcl9pZCAmJiBtb2RhbF9lbF9vcl9pZC5pZCkgPyBtb2RhbF9lbF9vcl9pZC5pZCA6ICcnICk7XHJcblxyXG5cdFx0Y29uc3QgbW9kYWxfZWwgPSAodHlwZW9mIG1vZGFsX2VsX29yX2lkID09PSAnc3RyaW5nJylcclxuXHRcdFx0PyBkLmdldEVsZW1lbnRCeUlkKCBtb2RhbF9pZCApXHJcblx0XHRcdDogbW9kYWxfZWxfb3JfaWQ7XHJcblxyXG5cdFx0aWYgKCAhbW9kYWxfZWwgKSByZXR1cm47XHJcblxyXG5cdFx0dHJ5IHtcclxuXHRcdFx0aWYgKCB3LmpRdWVyeSAmJiB3LmpRdWVyeS5mbiAmJiB3LmpRdWVyeS5mbi53cGJjX215X21vZGFsICkge1xyXG5cclxuXHRcdFx0XHRjb25zdCAkbSA9IG1vZGFsX2lkXHJcblx0XHRcdFx0XHQ/IHcualF1ZXJ5KCAnIycgKyBNb2RhbHMuY3NzX2VzY2FwZSggbW9kYWxfaWQgKSApXHJcblx0XHRcdFx0XHQ6IHcualF1ZXJ5KCBtb2RhbF9lbCApO1xyXG5cclxuXHRcdFx0XHRpZiAoICRtICYmICRtLndwYmNfbXlfbW9kYWwgKSB7XHJcblx0XHRcdFx0XHQkbS53cGJjX215X21vZGFsKCAnc2hvdycgKTtcclxuXHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH0gY2F0Y2ggKCBfZSApIHtcclxuXHRcdH1cclxuXHJcblx0XHRtb2RhbF9lbC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcclxuXHR9O1xyXG5cclxuXHRNb2RhbHMuaGlkZSA9IE1vZGFscy5oaWRlIHx8IGZ1bmN0aW9uIChtb2RhbF9lbF9vcl9pZCkge1xyXG5cclxuXHRcdGNvbnN0IG1vZGFsX2lkID0gKHR5cGVvZiBtb2RhbF9lbF9vcl9pZCA9PT0gJ3N0cmluZycpXHJcblx0XHRcdD8gU3RyaW5nKCBtb2RhbF9lbF9vcl9pZCB8fCAnJyApXHJcblx0XHRcdDogU3RyaW5nKCAobW9kYWxfZWxfb3JfaWQgJiYgbW9kYWxfZWxfb3JfaWQuaWQpID8gbW9kYWxfZWxfb3JfaWQuaWQgOiAnJyApO1xyXG5cclxuXHRcdGNvbnN0IG1vZGFsX2VsID0gKHR5cGVvZiBtb2RhbF9lbF9vcl9pZCA9PT0gJ3N0cmluZycpXHJcblx0XHRcdD8gZC5nZXRFbGVtZW50QnlJZCggbW9kYWxfaWQgKVxyXG5cdFx0XHQ6IG1vZGFsX2VsX29yX2lkO1xyXG5cclxuXHRcdGlmICggIW1vZGFsX2VsICkgcmV0dXJuO1xyXG5cclxuXHRcdHRyeSB7XHJcblx0XHRcdGlmICggdy5qUXVlcnkgJiYgdy5qUXVlcnkuZm4gJiYgdy5qUXVlcnkuZm4ud3BiY19teV9tb2RhbCApIHtcclxuXHJcblx0XHRcdFx0Y29uc3QgJG0gPSBtb2RhbF9pZFxyXG5cdFx0XHRcdFx0PyB3LmpRdWVyeSggJyMnICsgTW9kYWxzLmNzc19lc2NhcGUoIG1vZGFsX2lkICkgKVxyXG5cdFx0XHRcdFx0OiB3LmpRdWVyeSggbW9kYWxfZWwgKTtcclxuXHJcblx0XHRcdFx0aWYgKCAkbSAmJiAkbS53cGJjX215X21vZGFsICkge1xyXG5cdFx0XHRcdFx0JG0ud3BiY19teV9tb2RhbCggJ2hpZGUnICk7XHJcblx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9IGNhdGNoICggX2UgKSB7XHJcblx0XHR9XHJcblxyXG5cdFx0bW9kYWxfZWwuc3R5bGUuZGlzcGxheSA9ICdub25lJztcclxuXHR9O1xyXG5cclxufSggd2luZG93LCBkb2N1bWVudCApKTtcclxuIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNDLFdBQVVBLENBQUMsRUFBRUMsQ0FBQyxFQUFFO0VBQ2hCLFlBQVk7O0VBRVosTUFBTUMsSUFBSSxHQUFJRixDQUFDLENBQUNHLGFBQWEsR0FBR0gsQ0FBQyxDQUFDRyxhQUFhLElBQUksQ0FBQyxDQUFFO0VBQ3RELE1BQU1DLEVBQUUsR0FBTUYsSUFBSSxDQUFDRSxFQUFFLEdBQUdGLElBQUksQ0FBQ0UsRUFBRSxJQUFJLENBQUMsQ0FBRTs7RUFFdEM7QUFDRDtBQUNBO0VBQ0MsTUFBTUMsU0FBUyxHQUFJRCxFQUFFLENBQUNDLFNBQVMsR0FBR0QsRUFBRSxDQUFDQyxTQUFT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
308